1 /*
2 * Copyright 2010 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 "pc/session_description.h"
12
13 #include "absl/algorithm/container.h"
14 #include "absl/memory/memory.h"
15 #include "rtc_base/checks.h"
16 #include "rtc_base/strings/string_builder.h"
17
18 namespace cricket {
19 namespace {
20
FindContentInfoByName(ContentInfos * contents,const std::string & name)21 ContentInfo* FindContentInfoByName(ContentInfos* contents,
22 const std::string& name) {
23 RTC_DCHECK(contents);
24 for (ContentInfo& content : *contents) {
25 if (content.name == name) {
26 return &content;
27 }
28 }
29 return nullptr;
30 }
31
32 } // namespace
33
FindContentInfoByName(const ContentInfos & contents,const std::string & name)34 const ContentInfo* FindContentInfoByName(const ContentInfos& contents,
35 const std::string& name) {
36 for (ContentInfos::const_iterator content = contents.begin();
37 content != contents.end(); ++content) {
38 if (content->name == name) {
39 return &(*content);
40 }
41 }
42 return NULL;
43 }
44
FindContentInfoByType(const ContentInfos & contents,MediaProtocolType type)45 const ContentInfo* FindContentInfoByType(const ContentInfos& contents,
46 MediaProtocolType type) {
47 for (const auto& content : contents) {
48 if (content.type == type) {
49 return &content;
50 }
51 }
52 return nullptr;
53 }
54
ContentGroup(const std::string & semantics)55 ContentGroup::ContentGroup(const std::string& semantics)
56 : semantics_(semantics) {}
57
58 ContentGroup::ContentGroup(const ContentGroup&) = default;
59 ContentGroup::ContentGroup(ContentGroup&&) = default;
60 ContentGroup& ContentGroup::operator=(const ContentGroup&) = default;
61 ContentGroup& ContentGroup::operator=(ContentGroup&&) = default;
62 ContentGroup::~ContentGroup() = default;
63
FirstContentName() const64 const std::string* ContentGroup::FirstContentName() const {
65 return (!content_names_.empty()) ? &(*content_names_.begin()) : NULL;
66 }
67
HasContentName(absl::string_view content_name) const68 bool ContentGroup::HasContentName(absl::string_view content_name) const {
69 return absl::c_linear_search(content_names_, content_name);
70 }
71
AddContentName(absl::string_view content_name)72 void ContentGroup::AddContentName(absl::string_view content_name) {
73 if (!HasContentName(content_name)) {
74 content_names_.emplace_back(content_name);
75 }
76 }
77
RemoveContentName(absl::string_view content_name)78 bool ContentGroup::RemoveContentName(absl::string_view content_name) {
79 ContentNames::iterator iter = absl::c_find(content_names_, content_name);
80 if (iter == content_names_.end()) {
81 return false;
82 }
83 content_names_.erase(iter);
84 return true;
85 }
86
ToString() const87 std::string ContentGroup::ToString() const {
88 rtc::StringBuilder acc;
89 acc << semantics_ << "(";
90 if (!content_names_.empty()) {
91 for (const auto& name : content_names_) {
92 acc << name << " ";
93 }
94 }
95 acc << ")";
96 return acc.Release();
97 }
98
99 SessionDescription::SessionDescription() = default;
100 SessionDescription::SessionDescription(const SessionDescription&) = default;
101
~SessionDescription()102 SessionDescription::~SessionDescription() {}
103
Clone() const104 std::unique_ptr<SessionDescription> SessionDescription::Clone() const {
105 // Copy using the private copy constructor.
106 // This will clone the descriptions using ContentInfo's copy constructor.
107 return absl::WrapUnique(new SessionDescription(*this));
108 }
109
GetContentByName(const std::string & name) const110 const ContentInfo* SessionDescription::GetContentByName(
111 const std::string& name) const {
112 return FindContentInfoByName(contents_, name);
113 }
114
GetContentByName(const std::string & name)115 ContentInfo* SessionDescription::GetContentByName(const std::string& name) {
116 return FindContentInfoByName(&contents_, name);
117 }
118
GetContentDescriptionByName(const std::string & name) const119 const MediaContentDescription* SessionDescription::GetContentDescriptionByName(
120 const std::string& name) const {
121 const ContentInfo* cinfo = FindContentInfoByName(contents_, name);
122 if (cinfo == NULL) {
123 return NULL;
124 }
125
126 return cinfo->media_description();
127 }
128
GetContentDescriptionByName(const std::string & name)129 MediaContentDescription* SessionDescription::GetContentDescriptionByName(
130 const std::string& name) {
131 ContentInfo* cinfo = FindContentInfoByName(&contents_, name);
132 if (cinfo == NULL) {
133 return NULL;
134 }
135
136 return cinfo->media_description();
137 }
138
FirstContentByType(MediaProtocolType type) const139 const ContentInfo* SessionDescription::FirstContentByType(
140 MediaProtocolType type) const {
141 return FindContentInfoByType(contents_, type);
142 }
143
FirstContent() const144 const ContentInfo* SessionDescription::FirstContent() const {
145 return (contents_.empty()) ? NULL : &(*contents_.begin());
146 }
147
AddContent(const std::string & name,MediaProtocolType type,std::unique_ptr<MediaContentDescription> description)148 void SessionDescription::AddContent(
149 const std::string& name,
150 MediaProtocolType type,
151 std::unique_ptr<MediaContentDescription> description) {
152 ContentInfo content(type);
153 content.name = name;
154 content.set_media_description(std::move(description));
155 AddContent(std::move(content));
156 }
157
AddContent(const std::string & name,MediaProtocolType type,bool rejected,std::unique_ptr<MediaContentDescription> description)158 void SessionDescription::AddContent(
159 const std::string& name,
160 MediaProtocolType type,
161 bool rejected,
162 std::unique_ptr<MediaContentDescription> description) {
163 ContentInfo content(type);
164 content.name = name;
165 content.rejected = rejected;
166 content.set_media_description(std::move(description));
167 AddContent(std::move(content));
168 }
169
AddContent(const std::string & name,MediaProtocolType type,bool rejected,bool bundle_only,std::unique_ptr<MediaContentDescription> description)170 void SessionDescription::AddContent(
171 const std::string& name,
172 MediaProtocolType type,
173 bool rejected,
174 bool bundle_only,
175 std::unique_ptr<MediaContentDescription> description) {
176 ContentInfo content(type);
177 content.name = name;
178 content.rejected = rejected;
179 content.bundle_only = bundle_only;
180 content.set_media_description(std::move(description));
181 AddContent(std::move(content));
182 }
183
AddContent(ContentInfo && content)184 void SessionDescription::AddContent(ContentInfo&& content) {
185 if (extmap_allow_mixed()) {
186 // Mixed support on session level overrides setting on media level.
187 content.media_description()->set_extmap_allow_mixed_enum(
188 MediaContentDescription::kSession);
189 }
190 contents_.push_back(std::move(content));
191 }
192
RemoveContentByName(const std::string & name)193 bool SessionDescription::RemoveContentByName(const std::string& name) {
194 for (ContentInfos::iterator content = contents_.begin();
195 content != contents_.end(); ++content) {
196 if (content->name == name) {
197 contents_.erase(content);
198 return true;
199 }
200 }
201
202 return false;
203 }
204
AddTransportInfo(const TransportInfo & transport_info)205 void SessionDescription::AddTransportInfo(const TransportInfo& transport_info) {
206 transport_infos_.push_back(transport_info);
207 }
208
RemoveTransportInfoByName(const std::string & name)209 bool SessionDescription::RemoveTransportInfoByName(const std::string& name) {
210 for (TransportInfos::iterator transport_info = transport_infos_.begin();
211 transport_info != transport_infos_.end(); ++transport_info) {
212 if (transport_info->content_name == name) {
213 transport_infos_.erase(transport_info);
214 return true;
215 }
216 }
217 return false;
218 }
219
GetTransportInfoByName(const std::string & name) const220 const TransportInfo* SessionDescription::GetTransportInfoByName(
221 const std::string& name) const {
222 for (TransportInfos::const_iterator iter = transport_infos_.begin();
223 iter != transport_infos_.end(); ++iter) {
224 if (iter->content_name == name) {
225 return &(*iter);
226 }
227 }
228 return NULL;
229 }
230
GetTransportInfoByName(const std::string & name)231 TransportInfo* SessionDescription::GetTransportInfoByName(
232 const std::string& name) {
233 for (TransportInfos::iterator iter = transport_infos_.begin();
234 iter != transport_infos_.end(); ++iter) {
235 if (iter->content_name == name) {
236 return &(*iter);
237 }
238 }
239 return NULL;
240 }
241
RemoveGroupByName(const std::string & name)242 void SessionDescription::RemoveGroupByName(const std::string& name) {
243 for (ContentGroups::iterator iter = content_groups_.begin();
244 iter != content_groups_.end(); ++iter) {
245 if (iter->semantics() == name) {
246 content_groups_.erase(iter);
247 break;
248 }
249 }
250 }
251
HasGroup(const std::string & name) const252 bool SessionDescription::HasGroup(const std::string& name) const {
253 for (ContentGroups::const_iterator iter = content_groups_.begin();
254 iter != content_groups_.end(); ++iter) {
255 if (iter->semantics() == name) {
256 return true;
257 }
258 }
259 return false;
260 }
261
GetGroupByName(const std::string & name) const262 const ContentGroup* SessionDescription::GetGroupByName(
263 const std::string& name) const {
264 for (ContentGroups::const_iterator iter = content_groups_.begin();
265 iter != content_groups_.end(); ++iter) {
266 if (iter->semantics() == name) {
267 return &(*iter);
268 }
269 }
270 return NULL;
271 }
272
GetGroupsByName(const std::string & name) const273 std::vector<const ContentGroup*> SessionDescription::GetGroupsByName(
274 const std::string& name) const {
275 std::vector<const ContentGroup*> content_groups;
276 for (const ContentGroup& content_group : content_groups_) {
277 if (content_group.semantics() == name) {
278 content_groups.push_back(&content_group);
279 }
280 }
281 return content_groups;
282 }
283
~ContentInfo()284 ContentInfo::~ContentInfo() {
285 }
286
287 // Copy operator.
ContentInfo(const ContentInfo & o)288 ContentInfo::ContentInfo(const ContentInfo& o)
289 : name(o.name),
290 type(o.type),
291 rejected(o.rejected),
292 bundle_only(o.bundle_only),
293 description_(o.description_->Clone()) {}
294
operator =(const ContentInfo & o)295 ContentInfo& ContentInfo::operator=(const ContentInfo& o) {
296 name = o.name;
297 type = o.type;
298 rejected = o.rejected;
299 bundle_only = o.bundle_only;
300 description_ = o.description_->Clone();
301 return *this;
302 }
303
media_description() const304 const MediaContentDescription* ContentInfo::media_description() const {
305 return description_.get();
306 }
307
media_description()308 MediaContentDescription* ContentInfo::media_description() {
309 return description_.get();
310 }
311
312 } // namespace cricket
313