blob: 07ab7dbff5e8143f468af7b7a4a26360262fff95 [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
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
Steve Anton10542f22019-01-11 09:11:00 -080011#include "pc/session_description.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000012
Harald Alvestrand4d7160e2019-04-12 07:01:29 +020013#include <algorithm>
Steve Anton5adfafd2017-12-20 16:34:00 -080014#include <utility>
15
Steve Anton64b626b2019-01-28 17:25:26 -080016#include "absl/algorithm/container.h"
Harald Alvestrand4d7160e2019-04-12 07:01:29 +020017#include "absl/memory/memory.h"
Harald Alvestrand5fc28b12019-05-13 13:36:16 +020018#include "pc/media_protocol_names.h"
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "rtc_base/checks.h"
20
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000021namespace cricket {
Steve Anton4ab68ee2017-12-19 14:26:11 -080022namespace {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000023
Steve Anton4ab68ee2017-12-19 14:26:11 -080024ContentInfo* FindContentInfoByName(ContentInfos* contents,
25 const std::string& name) {
26 RTC_DCHECK(contents);
27 for (ContentInfo& content : *contents) {
28 if (content.name == name) {
29 return &content;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000030 }
31 }
Steve Anton4ab68ee2017-12-19 14:26:11 -080032 return nullptr;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000033}
34
Steve Anton4ab68ee2017-12-19 14:26:11 -080035} // namespace
36
37const ContentInfo* FindContentInfoByName(const ContentInfos& contents,
38 const std::string& name) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000039 for (ContentInfos::const_iterator content = contents.begin();
40 content != contents.end(); ++content) {
41 if (content->name == name) {
42 return &(*content);
43 }
44 }
45 return NULL;
46}
47
Steve Anton4ab68ee2017-12-19 14:26:11 -080048const ContentInfo* FindContentInfoByType(const ContentInfos& contents,
Steve Anton5adfafd2017-12-20 16:34:00 -080049 MediaProtocolType type) {
50 for (const auto& content : contents) {
51 if (content.type == type) {
52 return &content;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000053 }
54 }
Steve Anton5adfafd2017-12-20 16:34:00 -080055 return nullptr;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000056}
57
Steve Antond3ea9992017-10-31 12:38:23 -070058ContentGroup::ContentGroup(const std::string& semantics)
59 : semantics_(semantics) {}
60
61ContentGroup::ContentGroup(const ContentGroup&) = default;
62ContentGroup::ContentGroup(ContentGroup&&) = default;
63ContentGroup& ContentGroup::operator=(const ContentGroup&) = default;
64ContentGroup& ContentGroup::operator=(ContentGroup&&) = default;
65ContentGroup::~ContentGroup() = default;
66
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000067const std::string* ContentGroup::FirstContentName() const {
68 return (!content_names_.empty()) ? &(*content_names_.begin()) : NULL;
69}
70
71bool ContentGroup::HasContentName(const std::string& content_name) const {
Steve Anton64b626b2019-01-28 17:25:26 -080072 return absl::c_linear_search(content_names_, content_name);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000073}
74
75void ContentGroup::AddContentName(const std::string& content_name) {
76 if (!HasContentName(content_name)) {
77 content_names_.push_back(content_name);
78 }
79}
80
81bool ContentGroup::RemoveContentName(const std::string& content_name) {
Steve Anton64b626b2019-01-28 17:25:26 -080082 ContentNames::iterator iter = absl::c_find(content_names_, content_name);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000083 if (iter == content_names_.end()) {
84 return false;
85 }
86 content_names_.erase(iter);
87 return true;
88}
89
Steve Antond3ea9992017-10-31 12:38:23 -070090SessionDescription::SessionDescription() = default;
Steve Antond3ea9992017-10-31 12:38:23 -070091SessionDescription::SessionDescription(const SessionDescription&) = default;
92
Jonas Olssona4d87372019-07-05 19:08:33 +020093SessionDescription::~SessionDescription() {}
Steve Antond3ea9992017-10-31 12:38:23 -070094
Harald Alvestrand4d7160e2019-04-12 07:01:29 +020095std::unique_ptr<SessionDescription> SessionDescription::Clone() const {
Harald Alvestrand1716d392019-06-03 20:35:45 +020096 // Copy using the private copy constructor.
97 // This will clone the descriptions using ContentInfo's copy constructor.
98 return absl::WrapUnique(new SessionDescription(*this));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000099}
100
101const ContentInfo* SessionDescription::GetContentByName(
102 const std::string& name) const {
103 return FindContentInfoByName(contents_, name);
104}
105
Steve Anton4ab68ee2017-12-19 14:26:11 -0800106ContentInfo* SessionDescription::GetContentByName(const std::string& name) {
107 return FindContentInfoByName(&contents_, name);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000108}
109
Steve Antonb1c1de12017-12-21 15:14:30 -0800110const MediaContentDescription* SessionDescription::GetContentDescriptionByName(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000111 const std::string& name) const {
112 const ContentInfo* cinfo = FindContentInfoByName(contents_, name);
113 if (cinfo == NULL) {
114 return NULL;
115 }
116
Steve Antonb1c1de12017-12-21 15:14:30 -0800117 return cinfo->media_description();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000118}
119
Steve Antonb1c1de12017-12-21 15:14:30 -0800120MediaContentDescription* SessionDescription::GetContentDescriptionByName(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000121 const std::string& name) {
Steve Anton4ab68ee2017-12-19 14:26:11 -0800122 ContentInfo* cinfo = FindContentInfoByName(&contents_, name);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000123 if (cinfo == NULL) {
124 return NULL;
125 }
126
Steve Antonb1c1de12017-12-21 15:14:30 -0800127 return cinfo->media_description();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000128}
129
130const ContentInfo* SessionDescription::FirstContentByType(
Steve Anton5adfafd2017-12-20 16:34:00 -0800131 MediaProtocolType type) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000132 return FindContentInfoByType(contents_, type);
133}
134
135const ContentInfo* SessionDescription::FirstContent() const {
136 return (contents_.empty()) ? NULL : &(*contents_.begin());
137}
138
Harald Alvestrand1716d392019-06-03 20:35:45 +0200139void SessionDescription::AddContent(
140 const std::string& name,
141 MediaProtocolType type,
142 std::unique_ptr<MediaContentDescription> description) {
Steve Anton5adfafd2017-12-20 16:34:00 -0800143 ContentInfo content(type);
144 content.name = name;
Harald Alvestrand1716d392019-06-03 20:35:45 +0200145 content.set_media_description(std::move(description));
146 AddContent(std::move(content));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000147}
148
Harald Alvestrand1716d392019-06-03 20:35:45 +0200149void SessionDescription::AddContent(
150 const std::string& name,
151 MediaProtocolType type,
152 bool rejected,
153 std::unique_ptr<MediaContentDescription> description) {
Steve Anton5adfafd2017-12-20 16:34:00 -0800154 ContentInfo content(type);
155 content.name = name;
156 content.rejected = rejected;
Harald Alvestrand1716d392019-06-03 20:35:45 +0200157 content.set_media_description(std::move(description));
158 AddContent(std::move(content));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000159}
160
Harald Alvestrand1716d392019-06-03 20:35:45 +0200161void SessionDescription::AddContent(
162 const std::string& name,
163 MediaProtocolType type,
164 bool rejected,
165 bool bundle_only,
166 std::unique_ptr<MediaContentDescription> description) {
Steve Anton5adfafd2017-12-20 16:34:00 -0800167 ContentInfo content(type);
168 content.name = name;
169 content.rejected = rejected;
170 content.bundle_only = bundle_only;
Harald Alvestrand1716d392019-06-03 20:35:45 +0200171 content.set_media_description(std::move(description));
172 AddContent(std::move(content));
Johannes Kron9ac3c912018-10-12 10:54:26 +0200173}
174
Harald Alvestrand1716d392019-06-03 20:35:45 +0200175void SessionDescription::AddContent(ContentInfo&& content) {
Johannes Kron9581bc42018-10-23 10:17:39 +0200176 if (extmap_allow_mixed()) {
Johannes Kron9ac3c912018-10-12 10:54:26 +0200177 // Mixed support on session level overrides setting on media level.
Harald Alvestrand1716d392019-06-03 20:35:45 +0200178 content.media_description()->set_extmap_allow_mixed_enum(
Johannes Kron9ac3c912018-10-12 10:54:26 +0200179 MediaContentDescription::kSession);
180 }
Harald Alvestrand1716d392019-06-03 20:35:45 +0200181 contents_.push_back(std::move(content));
deadbeef25ed4352016-12-12 18:37:36 -0800182}
183
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000184bool SessionDescription::RemoveContentByName(const std::string& name) {
185 for (ContentInfos::iterator content = contents_.begin();
186 content != contents_.end(); ++content) {
187 if (content->name == name) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000188 contents_.erase(content);
189 return true;
190 }
191 }
192
193 return false;
194}
195
Steve Anton06817cd2018-12-18 15:55:30 -0800196void SessionDescription::AddTransportInfo(const TransportInfo& transport_info) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000197 transport_infos_.push_back(transport_info);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000198}
199
200bool SessionDescription::RemoveTransportInfoByName(const std::string& name) {
201 for (TransportInfos::iterator transport_info = transport_infos_.begin();
202 transport_info != transport_infos_.end(); ++transport_info) {
203 if (transport_info->content_name == name) {
204 transport_infos_.erase(transport_info);
205 return true;
206 }
207 }
208 return false;
209}
210
211const TransportInfo* SessionDescription::GetTransportInfoByName(
212 const std::string& name) const {
213 for (TransportInfos::const_iterator iter = transport_infos_.begin();
214 iter != transport_infos_.end(); ++iter) {
215 if (iter->content_name == name) {
216 return &(*iter);
217 }
218 }
219 return NULL;
220}
221
222TransportInfo* SessionDescription::GetTransportInfoByName(
223 const std::string& name) {
224 for (TransportInfos::iterator iter = transport_infos_.begin();
225 iter != transport_infos_.end(); ++iter) {
226 if (iter->content_name == name) {
227 return &(*iter);
228 }
229 }
230 return NULL;
231}
232
233void SessionDescription::RemoveGroupByName(const std::string& name) {
234 for (ContentGroups::iterator iter = content_groups_.begin();
235 iter != content_groups_.end(); ++iter) {
236 if (iter->semantics() == name) {
237 content_groups_.erase(iter);
238 break;
239 }
240 }
241}
242
243bool SessionDescription::HasGroup(const std::string& name) const {
244 for (ContentGroups::const_iterator iter = content_groups_.begin();
245 iter != content_groups_.end(); ++iter) {
246 if (iter->semantics() == name) {
247 return true;
248 }
249 }
250 return false;
251}
252
253const ContentGroup* SessionDescription::GetGroupByName(
254 const std::string& name) const {
255 for (ContentGroups::const_iterator iter = content_groups_.begin();
256 iter != content_groups_.end(); ++iter) {
257 if (iter->semantics() == name) {
258 return &(*iter);
259 }
260 }
261 return NULL;
262}
263
Harald Alvestrand1716d392019-06-03 20:35:45 +0200264ContentInfo::~ContentInfo() {
265 if (description_ && description_.get() != description) {
266 // If description_ is null, we assume that a move operator
267 // has been applied.
268 RTC_LOG(LS_ERROR) << "ContentInfo::description has been updated by "
269 << "assignment. This usage is deprecated.";
270 description_.reset(description); // ensure that it is destroyed.
271 }
272}
273
274// Copy operator.
275ContentInfo::ContentInfo(const ContentInfo& o)
276 : name(o.name),
277 type(o.type),
278 rejected(o.rejected),
279 bundle_only(o.bundle_only),
280 description_(o.description_->Clone()),
281 description(description_.get()) {}
282
283ContentInfo& ContentInfo::operator=(const ContentInfo& o) {
284 name = o.name;
285 type = o.type;
286 rejected = o.rejected;
287 bundle_only = o.bundle_only;
288 description_ = o.description_->Clone();
289 description = description_.get();
290 return *this;
291}
292
293const MediaContentDescription* ContentInfo::media_description() const {
294 if (description_.get() != description) {
295 // Someone's updated |description|, or used a move operator
296 // on the record.
297 RTC_LOG(LS_ERROR) << "ContentInfo::description has been updated by "
298 << "assignment. This usage is deprecated.";
299 const_cast<ContentInfo*>(this)->description_.reset(description);
300 }
301 return description_.get();
302}
303
304MediaContentDescription* ContentInfo::media_description() {
305 if (description_.get() != description) {
306 // Someone's updated |description|, or used a move operator
307 // on the record.
308 RTC_LOG(LS_ERROR) << "ContentInfo::description has been updated by "
309 << "assignment. This usage is deprecated.";
310 description_.reset(description);
311 }
312 return description_.get();
313}
314
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000315} // namespace cricket