OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/api/jsepsessiondescription.h" | |
12 | |
13 #include <memory> | |
14 | |
15 #include "webrtc/api/webrtcsdp.h" | |
16 #include "webrtc/base/arraysize.h" | |
17 #include "webrtc/base/stringencode.h" | |
18 #include "webrtc/pc/mediasession.h" | |
19 | |
20 using cricket::SessionDescription; | |
21 | |
22 namespace webrtc { | |
23 | |
24 static const char* kSupportedTypes[] = { | |
25 JsepSessionDescription::kOffer, | |
26 JsepSessionDescription::kPrAnswer, | |
27 JsepSessionDescription::kAnswer | |
28 }; | |
29 | |
30 static bool IsTypeSupported(const std::string& type) { | |
31 bool type_supported = false; | |
32 for (size_t i = 0; i < arraysize(kSupportedTypes); ++i) { | |
33 if (kSupportedTypes[i] == type) { | |
34 type_supported = true; | |
35 break; | |
36 } | |
37 } | |
38 return type_supported; | |
39 } | |
40 | |
41 const char SessionDescriptionInterface::kOffer[] = "offer"; | |
42 const char SessionDescriptionInterface::kPrAnswer[] = "pranswer"; | |
43 const char SessionDescriptionInterface::kAnswer[] = "answer"; | |
44 | |
45 const int JsepSessionDescription::kDefaultVideoCodecId = 100; | |
46 const char JsepSessionDescription::kDefaultVideoCodecName[] = "VP8"; | |
47 | |
48 SessionDescriptionInterface* CreateSessionDescription(const std::string& type, | |
49 const std::string& sdp, | |
50 SdpParseError* error) { | |
51 if (!IsTypeSupported(type)) { | |
52 return NULL; | |
53 } | |
54 | |
55 JsepSessionDescription* jsep_desc = new JsepSessionDescription(type); | |
56 if (!jsep_desc->Initialize(sdp, error)) { | |
57 delete jsep_desc; | |
58 return NULL; | |
59 } | |
60 return jsep_desc; | |
61 } | |
62 | |
63 JsepSessionDescription::JsepSessionDescription(const std::string& type) | |
64 : type_(type) { | |
65 } | |
66 | |
67 JsepSessionDescription::~JsepSessionDescription() {} | |
68 | |
69 bool JsepSessionDescription::Initialize( | |
70 cricket::SessionDescription* description, | |
71 const std::string& session_id, | |
72 const std::string& session_version) { | |
73 if (!description) | |
74 return false; | |
75 | |
76 session_id_ = session_id; | |
77 session_version_ = session_version; | |
78 description_.reset(description); | |
79 candidate_collection_.resize(number_of_mediasections()); | |
80 return true; | |
81 } | |
82 | |
83 bool JsepSessionDescription::Initialize(const std::string& sdp, | |
84 SdpParseError* error) { | |
85 return SdpDeserialize(sdp, this, error); | |
86 } | |
87 | |
88 bool JsepSessionDescription::AddCandidate( | |
89 const IceCandidateInterface* candidate) { | |
90 if (!candidate || candidate->sdp_mline_index() < 0) | |
91 return false; | |
92 size_t mediasection_index = 0; | |
93 if (!GetMediasectionIndex(candidate, &mediasection_index)) { | |
94 return false; | |
95 } | |
96 if (mediasection_index >= number_of_mediasections()) | |
97 return false; | |
98 const std::string& content_name = | |
99 description_->contents()[mediasection_index].name; | |
100 const cricket::TransportInfo* transport_info = | |
101 description_->GetTransportInfoByName(content_name); | |
102 if (!transport_info) { | |
103 return false; | |
104 } | |
105 | |
106 cricket::Candidate updated_candidate = candidate->candidate(); | |
107 if (updated_candidate.username().empty()) { | |
108 updated_candidate.set_username(transport_info->description.ice_ufrag); | |
109 } | |
110 if (updated_candidate.password().empty()) { | |
111 updated_candidate.set_password(transport_info->description.ice_pwd); | |
112 } | |
113 | |
114 std::unique_ptr<JsepIceCandidate> updated_candidate_wrapper( | |
115 new JsepIceCandidate(candidate->sdp_mid(), | |
116 static_cast<int>(mediasection_index), | |
117 updated_candidate)); | |
118 if (!candidate_collection_[mediasection_index].HasCandidate( | |
119 updated_candidate_wrapper.get())) | |
120 candidate_collection_[mediasection_index].add( | |
121 updated_candidate_wrapper.release()); | |
122 | |
123 return true; | |
124 } | |
125 | |
126 size_t JsepSessionDescription::RemoveCandidates( | |
127 const std::vector<cricket::Candidate>& candidates) { | |
128 size_t num_removed = 0; | |
129 for (auto& candidate : candidates) { | |
130 int mediasection_index = GetMediasectionIndex(candidate); | |
131 if (mediasection_index < 0) { | |
132 // Not found. | |
133 continue; | |
134 } | |
135 num_removed += candidate_collection_[mediasection_index].remove(candidate); | |
136 } | |
137 return num_removed; | |
138 } | |
139 | |
140 size_t JsepSessionDescription::number_of_mediasections() const { | |
141 if (!description_) | |
142 return 0; | |
143 return description_->contents().size(); | |
144 } | |
145 | |
146 const IceCandidateCollection* JsepSessionDescription::candidates( | |
147 size_t mediasection_index) const { | |
148 if (mediasection_index >= candidate_collection_.size()) | |
149 return NULL; | |
150 return &candidate_collection_[mediasection_index]; | |
151 } | |
152 | |
153 bool JsepSessionDescription::ToString(std::string* out) const { | |
154 if (!description_ || !out) { | |
155 return false; | |
156 } | |
157 *out = SdpSerialize(*this, false); | |
158 return !out->empty(); | |
159 } | |
160 | |
161 bool JsepSessionDescription::GetMediasectionIndex( | |
162 const IceCandidateInterface* candidate, | |
163 size_t* index) { | |
164 if (!candidate || !index) { | |
165 return false; | |
166 } | |
167 *index = static_cast<size_t>(candidate->sdp_mline_index()); | |
168 if (description_ && !candidate->sdp_mid().empty()) { | |
169 bool found = false; | |
170 // Try to match the sdp_mid with content name. | |
171 for (size_t i = 0; i < description_->contents().size(); ++i) { | |
172 if (candidate->sdp_mid() == description_->contents().at(i).name) { | |
173 *index = i; | |
174 found = true; | |
175 break; | |
176 } | |
177 } | |
178 if (!found) { | |
179 // If the sdp_mid is presented but we can't find a match, we consider | |
180 // this as an error. | |
181 return false; | |
182 } | |
183 } | |
184 return true; | |
185 } | |
186 | |
187 int JsepSessionDescription::GetMediasectionIndex( | |
188 const cricket::Candidate& candidate) { | |
189 // Find the description with a matching transport name of the candidate. | |
190 const std::string& transport_name = candidate.transport_name(); | |
191 for (size_t i = 0; i < description_->contents().size(); ++i) { | |
192 if (transport_name == description_->contents().at(i).name) { | |
193 return static_cast<int>(i); | |
194 } | |
195 } | |
196 return -1; | |
197 } | |
198 | |
199 } // namespace webrtc | |
OLD | NEW |