Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 : * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "signaling/src/sdp/SipccSdpAttributeList.h"
8 :
9 : #include <ostream>
10 : #include "mozilla/Assertions.h"
11 : #include "signaling/src/sdp/SdpErrorHolder.h"
12 :
13 : extern "C" {
14 : #include "signaling/src/sdp/sipcc/sdp_private.h"
15 : }
16 :
17 : namespace mozilla
18 : {
19 :
20 3 : /* static */ const std::string SipccSdpAttributeList::kEmptyString = "";
21 :
22 0 : SipccSdpAttributeList::SipccSdpAttributeList(
23 0 : const SipccSdpAttributeList* sessionLevel)
24 0 : : mSessionLevel(sessionLevel)
25 : {
26 0 : memset(&mAttributes, 0, sizeof(mAttributes));
27 0 : }
28 :
29 0 : SipccSdpAttributeList::~SipccSdpAttributeList()
30 : {
31 0 : for (size_t i = 0; i < kNumAttributeTypes; ++i) {
32 0 : delete mAttributes[i];
33 : }
34 0 : }
35 :
36 : bool
37 0 : SipccSdpAttributeList::HasAttribute(AttributeType type,
38 : bool sessionFallback) const
39 : {
40 0 : return !!GetAttribute(type, sessionFallback);
41 : }
42 :
43 : const SdpAttribute*
44 0 : SipccSdpAttributeList::GetAttribute(AttributeType type,
45 : bool sessionFallback) const
46 : {
47 0 : const SdpAttribute* value = mAttributes[static_cast<size_t>(type)];
48 : // Only do fallback when the attribute can appear at both the media and
49 : // session level
50 0 : if (!value && !AtSessionLevel() && sessionFallback &&
51 0 : SdpAttribute::IsAllowedAtSessionLevel(type) &&
52 0 : SdpAttribute::IsAllowedAtMediaLevel(type)) {
53 0 : return mSessionLevel->GetAttribute(type, false);
54 : }
55 0 : return value;
56 : }
57 :
58 : void
59 0 : SipccSdpAttributeList::RemoveAttribute(AttributeType type)
60 : {
61 0 : delete mAttributes[static_cast<size_t>(type)];
62 0 : mAttributes[static_cast<size_t>(type)] = nullptr;
63 0 : }
64 :
65 : void
66 0 : SipccSdpAttributeList::Clear()
67 : {
68 0 : for (size_t i = 0; i < kNumAttributeTypes; ++i) {
69 0 : RemoveAttribute(static_cast<AttributeType>(i));
70 : }
71 0 : }
72 :
73 : void
74 0 : SipccSdpAttributeList::SetAttribute(SdpAttribute* attr)
75 : {
76 0 : if (!IsAllowedHere(attr->GetType())) {
77 0 : MOZ_ASSERT(false, "This type of attribute is not allowed here");
78 : return;
79 : }
80 0 : RemoveAttribute(attr->GetType());
81 0 : mAttributes[attr->GetType()] = attr;
82 0 : }
83 :
84 : void
85 0 : SipccSdpAttributeList::LoadSimpleString(sdp_t* sdp, uint16_t level,
86 : sdp_attr_e attr,
87 : AttributeType targetType,
88 : SdpErrorHolder& errorHolder)
89 : {
90 0 : const char* value = sdp_attr_get_simple_string(sdp, attr, level, 0, 1);
91 0 : if (value) {
92 0 : if (!IsAllowedHere(targetType)) {
93 0 : uint32_t lineNumber = sdp_attr_line_number(sdp, attr, level, 0, 1);
94 0 : WarnAboutMisplacedAttribute(targetType, lineNumber, errorHolder);
95 : } else {
96 0 : SetAttribute(new SdpStringAttribute(targetType, std::string(value)));
97 : }
98 : }
99 0 : }
100 :
101 : void
102 0 : SipccSdpAttributeList::LoadSimpleStrings(sdp_t* sdp, uint16_t level,
103 : SdpErrorHolder& errorHolder)
104 : {
105 0 : LoadSimpleString(sdp, level, SDP_ATTR_MID, SdpAttribute::kMidAttribute,
106 0 : errorHolder);
107 0 : LoadSimpleString(sdp, level, SDP_ATTR_LABEL, SdpAttribute::kLabelAttribute,
108 0 : errorHolder);
109 0 : }
110 :
111 : void
112 0 : SipccSdpAttributeList::LoadSimpleNumber(sdp_t* sdp, uint16_t level,
113 : sdp_attr_e attr,
114 : AttributeType targetType,
115 : SdpErrorHolder& errorHolder)
116 : {
117 0 : if (sdp_attr_valid(sdp, attr, level, 0, 1)) {
118 0 : if (!IsAllowedHere(targetType)) {
119 0 : uint32_t lineNumber = sdp_attr_line_number(sdp, attr, level, 0, 1);
120 0 : WarnAboutMisplacedAttribute(targetType, lineNumber, errorHolder);
121 : } else {
122 0 : uint32_t value = sdp_attr_get_simple_u32(sdp, attr, level, 0, 1);
123 0 : SetAttribute(new SdpNumberAttribute(targetType, value));
124 : }
125 : }
126 0 : }
127 :
128 : void
129 0 : SipccSdpAttributeList::LoadSimpleNumbers(sdp_t* sdp, uint16_t level,
130 : SdpErrorHolder& errorHolder)
131 : {
132 0 : LoadSimpleNumber(sdp, level, SDP_ATTR_PTIME, SdpAttribute::kPtimeAttribute,
133 0 : errorHolder);
134 0 : LoadSimpleNumber(sdp, level, SDP_ATTR_MAXPTIME,
135 0 : SdpAttribute::kMaxptimeAttribute, errorHolder);
136 0 : LoadSimpleNumber(sdp, level, SDP_ATTR_SCTPPORT,
137 0 : SdpAttribute::kSctpPortAttribute, errorHolder);
138 0 : LoadSimpleNumber(sdp, level, SDP_ATTR_MAXMESSAGESIZE,
139 0 : SdpAttribute::kMaxMessageSizeAttribute, errorHolder);
140 0 : }
141 :
142 : void
143 0 : SipccSdpAttributeList::LoadFlags(sdp_t* sdp, uint16_t level)
144 : {
145 0 : if (AtSessionLevel()) {
146 0 : if (sdp_attr_valid(sdp, SDP_ATTR_ICE_LITE, level, 0, 1)) {
147 0 : SetAttribute(new SdpFlagAttribute(SdpAttribute::kIceLiteAttribute));
148 : }
149 : } else { // media-level
150 0 : if (sdp_attr_valid(sdp, SDP_ATTR_RTCP_MUX, level, 0, 1)) {
151 0 : SetAttribute(new SdpFlagAttribute(SdpAttribute::kRtcpMuxAttribute));
152 : }
153 0 : if (sdp_attr_valid(sdp, SDP_ATTR_END_OF_CANDIDATES, level, 0, 1)) {
154 : SetAttribute(
155 0 : new SdpFlagAttribute(SdpAttribute::kEndOfCandidatesAttribute));
156 : }
157 0 : if (sdp_attr_valid(sdp, SDP_ATTR_BUNDLE_ONLY, level, 0, 1)) {
158 0 : SetAttribute(new SdpFlagAttribute(SdpAttribute::kBundleOnlyAttribute));
159 : }
160 : }
161 0 : }
162 :
163 : static void
164 0 : ConvertDirection(sdp_direction_e sipcc_direction,
165 : SdpDirectionAttribute::Direction* dir_outparam)
166 : {
167 0 : switch (sipcc_direction) {
168 : case SDP_DIRECTION_SENDRECV:
169 0 : *dir_outparam = SdpDirectionAttribute::kSendrecv;
170 0 : return;
171 : case SDP_DIRECTION_SENDONLY:
172 0 : *dir_outparam = SdpDirectionAttribute::kSendonly;
173 0 : return;
174 : case SDP_DIRECTION_RECVONLY:
175 0 : *dir_outparam = SdpDirectionAttribute::kRecvonly;
176 0 : return;
177 : case SDP_DIRECTION_INACTIVE:
178 0 : *dir_outparam = SdpDirectionAttribute::kInactive;
179 0 : return;
180 : case SDP_MAX_QOS_DIRECTIONS:
181 : // Nothing actually sets this value.
182 : // Fall through to MOZ_CRASH below.
183 : {
184 : }
185 : }
186 :
187 0 : MOZ_CRASH("Invalid direction from sipcc; this is probably corruption");
188 : }
189 :
190 : void
191 0 : SipccSdpAttributeList::LoadDirection(sdp_t* sdp, uint16_t level,
192 : SdpErrorHolder& errorHolder)
193 : {
194 : SdpDirectionAttribute::Direction dir;
195 0 : ConvertDirection(sdp_get_media_direction(sdp, level, 0), &dir);
196 0 : SetAttribute(new SdpDirectionAttribute(dir));
197 0 : }
198 :
199 : void
200 0 : SipccSdpAttributeList::LoadIceAttributes(sdp_t* sdp, uint16_t level)
201 : {
202 : char* value;
203 : sdp_result_e sdpres =
204 0 : sdp_attr_get_ice_attribute(sdp, level, 0, SDP_ATTR_ICE_UFRAG, 1, &value);
205 0 : if (sdpres == SDP_SUCCESS) {
206 0 : SetAttribute(new SdpStringAttribute(SdpAttribute::kIceUfragAttribute,
207 0 : std::string(value)));
208 : }
209 : sdpres =
210 0 : sdp_attr_get_ice_attribute(sdp, level, 0, SDP_ATTR_ICE_PWD, 1, &value);
211 0 : if (sdpres == SDP_SUCCESS) {
212 0 : SetAttribute(new SdpStringAttribute(SdpAttribute::kIcePwdAttribute,
213 0 : std::string(value)));
214 : }
215 :
216 : const char* iceOptVal =
217 0 : sdp_attr_get_simple_string(sdp, SDP_ATTR_ICE_OPTIONS, level, 0, 1);
218 0 : if (iceOptVal) {
219 : auto* iceOptions =
220 0 : new SdpOptionsAttribute(SdpAttribute::kIceOptionsAttribute);
221 0 : iceOptions->Load(iceOptVal);
222 0 : SetAttribute(iceOptions);
223 : }
224 0 : }
225 :
226 : bool
227 0 : SipccSdpAttributeList::LoadFingerprint(sdp_t* sdp, uint16_t level,
228 : SdpErrorHolder& errorHolder)
229 : {
230 : char* value;
231 0 : UniquePtr<SdpFingerprintAttributeList> fingerprintAttrs;
232 :
233 0 : for (uint16_t i = 1; i < UINT16_MAX; ++i) {
234 0 : sdp_result_e result = sdp_attr_get_dtls_fingerprint_attribute(
235 0 : sdp, level, 0, SDP_ATTR_DTLS_FINGERPRINT, i, &value);
236 :
237 0 : if (result != SDP_SUCCESS) {
238 0 : break;
239 : }
240 :
241 0 : std::string fingerprintAttr(value);
242 : uint32_t lineNumber =
243 0 : sdp_attr_line_number(sdp, SDP_ATTR_DTLS_FINGERPRINT, level, 0, i);
244 :
245 : // sipcc does not expose parse code for this
246 0 : size_t start = fingerprintAttr.find_first_not_of(" \t");
247 0 : if (start == std::string::npos) {
248 0 : errorHolder.AddParseError(lineNumber, "Empty fingerprint attribute");
249 0 : return false;
250 : }
251 :
252 0 : size_t end = fingerprintAttr.find_first_of(" \t", start);
253 0 : if (end == std::string::npos) {
254 : // One token, no trailing ws
255 0 : errorHolder.AddParseError(lineNumber,
256 0 : "Only one token in fingerprint attribute");
257 0 : return false;
258 : }
259 :
260 0 : std::string algorithmToken(fingerprintAttr.substr(start, end - start));
261 :
262 0 : start = fingerprintAttr.find_first_not_of(" \t", end);
263 0 : if (start == std::string::npos) {
264 : // One token, trailing ws
265 0 : errorHolder.AddParseError(lineNumber,
266 0 : "Only one token in fingerprint attribute");
267 0 : return false;
268 : }
269 :
270 0 : std::string fingerprintToken(fingerprintAttr.substr(start));
271 :
272 : std::vector<uint8_t> fingerprint =
273 0 : SdpFingerprintAttributeList::ParseFingerprint(fingerprintToken);
274 0 : if (fingerprint.size() == 0) {
275 0 : errorHolder.AddParseError(lineNumber, "Malformed fingerprint token");
276 0 : return false;
277 : }
278 :
279 0 : if (!fingerprintAttrs) {
280 0 : fingerprintAttrs.reset(new SdpFingerprintAttributeList);
281 : }
282 :
283 : // Don't assert on unknown algorithm, just skip
284 0 : fingerprintAttrs->PushEntry(algorithmToken, fingerprint, false);
285 : }
286 :
287 0 : if (fingerprintAttrs) {
288 0 : SetAttribute(fingerprintAttrs.release());
289 : }
290 :
291 0 : return true;
292 : }
293 :
294 : void
295 0 : SipccSdpAttributeList::LoadCandidate(sdp_t* sdp, uint16_t level)
296 : {
297 : char* value;
298 : auto candidates =
299 0 : MakeUnique<SdpMultiStringAttribute>(SdpAttribute::kCandidateAttribute);
300 :
301 0 : for (uint16_t i = 1; i < UINT16_MAX; ++i) {
302 0 : sdp_result_e result = sdp_attr_get_ice_attribute(
303 0 : sdp, level, 0, SDP_ATTR_ICE_CANDIDATE, i, &value);
304 :
305 0 : if (result != SDP_SUCCESS) {
306 0 : break;
307 : }
308 :
309 0 : candidates->mValues.push_back(value);
310 : }
311 :
312 0 : if (!candidates->mValues.empty()) {
313 0 : SetAttribute(candidates.release());
314 : }
315 0 : }
316 :
317 : bool
318 0 : SipccSdpAttributeList::LoadSctpmap(sdp_t* sdp, uint16_t level,
319 : SdpErrorHolder& errorHolder)
320 : {
321 0 : auto sctpmap = MakeUnique<SdpSctpmapAttributeList>();
322 0 : for (uint16_t i = 0; i < UINT16_MAX; ++i) {
323 0 : sdp_attr_t* attr = sdp_find_attr(sdp, level, 0, SDP_ATTR_SCTPMAP, i + 1);
324 :
325 0 : if (!attr) {
326 0 : break;
327 : }
328 :
329 : // Yeah, this is a little weird, but for now we'll just store this as a
330 : // payload type.
331 0 : uint16_t payloadType = attr->attr.sctpmap.port;
332 0 : uint16_t streams = attr->attr.sctpmap.streams;
333 0 : const char* name = attr->attr.sctpmap.protocol;
334 :
335 0 : std::ostringstream osPayloadType;
336 0 : osPayloadType << payloadType;
337 0 : sctpmap->PushEntry(osPayloadType.str(), name, streams);
338 : }
339 :
340 0 : if (!sctpmap->mSctpmaps.empty()) {
341 0 : SetAttribute(sctpmap.release());
342 : }
343 :
344 0 : return true;
345 : }
346 :
347 : SdpRtpmapAttributeList::CodecType
348 0 : SipccSdpAttributeList::GetCodecType(rtp_ptype type)
349 : {
350 0 : switch (type) {
351 : case RTP_PCMU:
352 0 : return SdpRtpmapAttributeList::kPCMU;
353 : case RTP_PCMA:
354 0 : return SdpRtpmapAttributeList::kPCMA;
355 : case RTP_G722:
356 0 : return SdpRtpmapAttributeList::kG722;
357 : case RTP_H264_P0:
358 : case RTP_H264_P1:
359 0 : return SdpRtpmapAttributeList::kH264;
360 : case RTP_OPUS:
361 0 : return SdpRtpmapAttributeList::kOpus;
362 : case RTP_VP8:
363 0 : return SdpRtpmapAttributeList::kVP8;
364 : case RTP_VP9:
365 0 : return SdpRtpmapAttributeList::kVP9;
366 : case RTP_RED:
367 0 : return SdpRtpmapAttributeList::kRed;
368 : case RTP_ULPFEC:
369 0 : return SdpRtpmapAttributeList::kUlpfec;
370 : case RTP_TELEPHONE_EVENT:
371 0 : return SdpRtpmapAttributeList::kTelephoneEvent;
372 : case RTP_NONE:
373 : // Happens when sipcc doesn't know how to translate to the enum
374 : case RTP_CELP:
375 : case RTP_G726:
376 : case RTP_GSM:
377 : case RTP_G723:
378 : case RTP_DVI4:
379 : case RTP_DVI4_II:
380 : case RTP_LPC:
381 : case RTP_G728:
382 : case RTP_G729:
383 : case RTP_JPEG:
384 : case RTP_NV:
385 : case RTP_H261:
386 : case RTP_L16:
387 : case RTP_H263:
388 : case RTP_ILBC:
389 : case RTP_I420:
390 0 : return SdpRtpmapAttributeList::kOtherCodec;
391 : }
392 0 : MOZ_CRASH("Invalid codec type from sipcc. Probably corruption.");
393 : }
394 :
395 : bool
396 0 : SipccSdpAttributeList::LoadRtpmap(sdp_t* sdp, uint16_t level,
397 : SdpErrorHolder& errorHolder)
398 : {
399 0 : auto rtpmap = MakeUnique<SdpRtpmapAttributeList>();
400 : uint16_t count;
401 : sdp_result_e result =
402 0 : sdp_attr_num_instances(sdp, level, 0, SDP_ATTR_RTPMAP, &count);
403 0 : if (result != SDP_SUCCESS) {
404 0 : MOZ_ASSERT(false, "Unable to get rtpmap size");
405 : errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
406 : "Unable to get rtpmap size");
407 : return false;
408 : }
409 0 : for (uint16_t i = 0; i < count; ++i) {
410 0 : uint16_t pt = sdp_attr_get_rtpmap_payload_type(sdp, level, 0, i + 1);
411 0 : const char* ccName = sdp_attr_get_rtpmap_encname(sdp, level, 0, i + 1);
412 :
413 0 : if (!ccName) {
414 : // Probably no rtpmap attribute for a pt in an m-line
415 0 : errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
416 0 : "No rtpmap attribute for payload type");
417 0 : continue;
418 : }
419 :
420 0 : std::string name(ccName);
421 :
422 : SdpRtpmapAttributeList::CodecType codec =
423 0 : GetCodecType(sdp_get_known_payload_type(sdp, level, pt));
424 :
425 0 : uint32_t clock = sdp_attr_get_rtpmap_clockrate(sdp, level, 0, i + 1);
426 0 : uint16_t channels = 0;
427 :
428 : // sipcc gives us a channels value of "1" for video
429 0 : if (sdp_get_media_type(sdp, level) == SDP_MEDIA_AUDIO) {
430 0 : channels = sdp_attr_get_rtpmap_num_chan(sdp, level, 0, i + 1);
431 : }
432 :
433 0 : std::ostringstream osPayloadType;
434 0 : osPayloadType << pt;
435 0 : rtpmap->PushEntry(osPayloadType.str(), codec, name, clock, channels);
436 : }
437 :
438 0 : if (!rtpmap->mRtpmaps.empty()) {
439 0 : SetAttribute(rtpmap.release());
440 : }
441 :
442 0 : return true;
443 : }
444 :
445 : void
446 0 : SipccSdpAttributeList::LoadSetup(sdp_t* sdp, uint16_t level)
447 : {
448 : sdp_setup_type_e setupType;
449 0 : auto sdpres = sdp_attr_get_setup_attribute(sdp, level, 0, 1, &setupType);
450 :
451 0 : if (sdpres != SDP_SUCCESS) {
452 0 : return;
453 : }
454 :
455 0 : switch (setupType) {
456 : case SDP_SETUP_ACTIVE:
457 0 : SetAttribute(new SdpSetupAttribute(SdpSetupAttribute::kActive));
458 0 : return;
459 : case SDP_SETUP_PASSIVE:
460 0 : SetAttribute(new SdpSetupAttribute(SdpSetupAttribute::kPassive));
461 0 : return;
462 : case SDP_SETUP_ACTPASS:
463 0 : SetAttribute(new SdpSetupAttribute(SdpSetupAttribute::kActpass));
464 0 : return;
465 : case SDP_SETUP_HOLDCONN:
466 0 : SetAttribute(new SdpSetupAttribute(SdpSetupAttribute::kHoldconn));
467 0 : return;
468 : case SDP_SETUP_UNKNOWN:
469 0 : return;
470 : case SDP_SETUP_NOT_FOUND:
471 : case SDP_MAX_SETUP:
472 : // There is no code that will set these.
473 : // Fall through to MOZ_CRASH() below.
474 : {
475 : }
476 : }
477 :
478 0 : MOZ_CRASH("Invalid setup type from sipcc. This is probably corruption.");
479 : }
480 :
481 : void
482 0 : SipccSdpAttributeList::LoadSsrc(sdp_t* sdp, uint16_t level)
483 : {
484 0 : auto ssrcs = MakeUnique<SdpSsrcAttributeList>();
485 :
486 0 : for (uint16_t i = 1; i < UINT16_MAX; ++i) {
487 0 : sdp_attr_t* attr = sdp_find_attr(sdp, level, 0, SDP_ATTR_SSRC, i);
488 :
489 0 : if (!attr) {
490 0 : break;
491 : }
492 :
493 0 : sdp_ssrc_t* ssrc = &(attr->attr.ssrc);
494 0 : ssrcs->PushEntry(ssrc->ssrc, ssrc->attribute);
495 : }
496 :
497 0 : if (!ssrcs->mSsrcs.empty()) {
498 0 : SetAttribute(ssrcs.release());
499 : }
500 0 : }
501 :
502 : bool
503 0 : SipccSdpAttributeList::LoadImageattr(sdp_t* sdp,
504 : uint16_t level,
505 : SdpErrorHolder& errorHolder)
506 : {
507 : UniquePtr<SdpImageattrAttributeList> imageattrs(
508 0 : new SdpImageattrAttributeList);
509 :
510 0 : for (uint16_t i = 1; i < UINT16_MAX; ++i) {
511 0 : const char* imageattrRaw = sdp_attr_get_simple_string(sdp,
512 : SDP_ATTR_IMAGEATTR,
513 : level,
514 : 0,
515 0 : i);
516 0 : if (!imageattrRaw) {
517 0 : break;
518 : }
519 :
520 0 : std::string error;
521 : size_t errorPos;
522 0 : if (!imageattrs->PushEntry(imageattrRaw, &error, &errorPos)) {
523 0 : std::ostringstream fullError;
524 0 : fullError << error << " at column " << errorPos;
525 0 : errorHolder.AddParseError(
526 0 : sdp_attr_line_number(sdp, SDP_ATTR_IMAGEATTR, level, 0, i),
527 0 : fullError.str());
528 0 : return false;
529 : }
530 : }
531 :
532 0 : if (!imageattrs->mImageattrs.empty()) {
533 0 : SetAttribute(imageattrs.release());
534 : }
535 0 : return true;
536 : }
537 :
538 : bool
539 0 : SipccSdpAttributeList::LoadSimulcast(sdp_t* sdp,
540 : uint16_t level,
541 : SdpErrorHolder& errorHolder)
542 : {
543 0 : const char* simulcastRaw = sdp_attr_get_simple_string(sdp,
544 : SDP_ATTR_SIMULCAST,
545 : level,
546 : 0,
547 0 : 1);
548 0 : if (!simulcastRaw) {
549 0 : return true;
550 : }
551 :
552 : UniquePtr<SdpSimulcastAttribute> simulcast(
553 0 : new SdpSimulcastAttribute);
554 :
555 0 : std::istringstream is(simulcastRaw);
556 0 : std::string error;
557 0 : if (!simulcast->Parse(is, &error)) {
558 0 : std::ostringstream fullError;
559 0 : fullError << error << " at column " << is.tellg();
560 0 : errorHolder.AddParseError(
561 0 : sdp_attr_line_number(sdp, SDP_ATTR_SIMULCAST, level, 0, 1),
562 0 : fullError.str());
563 0 : return false;
564 : }
565 :
566 0 : SetAttribute(simulcast.release());
567 0 : return true;
568 : }
569 :
570 : bool
571 0 : SipccSdpAttributeList::LoadGroups(sdp_t* sdp, uint16_t level,
572 : SdpErrorHolder& errorHolder)
573 : {
574 0 : uint16_t attrCount = 0;
575 0 : if (sdp_attr_num_instances(sdp, level, 0, SDP_ATTR_GROUP, &attrCount) !=
576 : SDP_SUCCESS) {
577 0 : MOZ_ASSERT(false, "Could not get count of group attributes");
578 : errorHolder.AddParseError(0, "Could not get count of group attributes");
579 : return false;
580 : }
581 :
582 0 : UniquePtr<SdpGroupAttributeList> groups = MakeUnique<SdpGroupAttributeList>();
583 0 : for (uint16_t attr = 1; attr <= attrCount; ++attr) {
584 : SdpGroupAttributeList::Semantics semantics;
585 0 : std::vector<std::string> tags;
586 :
587 0 : switch (sdp_get_group_attr(sdp, level, 0, attr)) {
588 : case SDP_GROUP_ATTR_FID:
589 0 : semantics = SdpGroupAttributeList::kFid;
590 0 : break;
591 : case SDP_GROUP_ATTR_LS:
592 0 : semantics = SdpGroupAttributeList::kLs;
593 0 : break;
594 : case SDP_GROUP_ATTR_ANAT:
595 0 : semantics = SdpGroupAttributeList::kAnat;
596 0 : break;
597 : case SDP_GROUP_ATTR_BUNDLE:
598 0 : semantics = SdpGroupAttributeList::kBundle;
599 0 : break;
600 : default:
601 0 : continue;
602 : }
603 :
604 0 : uint16_t idCount = sdp_get_group_num_id(sdp, level, 0, attr);
605 0 : for (uint16_t id = 1; id <= idCount; ++id) {
606 0 : const char* idStr = sdp_get_group_id(sdp, level, 0, attr, id);
607 0 : if (!idStr) {
608 0 : std::ostringstream os;
609 0 : os << "bad a=group identifier at " << (attr - 1) << ", " << (id - 1);
610 0 : errorHolder.AddParseError(0, os.str());
611 0 : return false;
612 : }
613 0 : tags.push_back(std::string(idStr));
614 : }
615 0 : groups->PushEntry(semantics, tags);
616 : }
617 :
618 0 : if (!groups->mGroups.empty()) {
619 0 : SetAttribute(groups.release());
620 : }
621 :
622 0 : return true;
623 : }
624 :
625 : bool
626 0 : SipccSdpAttributeList::LoadMsidSemantics(sdp_t* sdp, uint16_t level,
627 : SdpErrorHolder& errorHolder)
628 : {
629 0 : auto msidSemantics = MakeUnique<SdpMsidSemanticAttributeList>();
630 :
631 0 : for (uint16_t i = 1; i < UINT16_MAX; ++i) {
632 0 : sdp_attr_t* attr = sdp_find_attr(sdp, level, 0, SDP_ATTR_MSID_SEMANTIC, i);
633 :
634 0 : if (!attr) {
635 0 : break;
636 : }
637 :
638 0 : sdp_msid_semantic_t* msid_semantic = &(attr->attr.msid_semantic);
639 0 : std::vector<std::string> msids;
640 0 : for (size_t i = 0; i < SDP_MAX_MEDIA_STREAMS; ++i) {
641 0 : if (!msid_semantic->msids[i]) {
642 0 : break;
643 : }
644 :
645 0 : msids.push_back(msid_semantic->msids[i]);
646 : }
647 :
648 0 : msidSemantics->PushEntry(msid_semantic->semantic, msids);
649 : }
650 :
651 0 : if (!msidSemantics->mMsidSemantics.empty()) {
652 0 : SetAttribute(msidSemantics.release());
653 : }
654 0 : return true;
655 : }
656 :
657 : void
658 0 : SipccSdpAttributeList::LoadIdentity(sdp_t* sdp, uint16_t level)
659 : {
660 0 : const char* val = sdp_attr_get_long_string(sdp, SDP_ATTR_IDENTITY, level, 0, 1);
661 0 : if (val) {
662 0 : SetAttribute(new SdpStringAttribute(SdpAttribute::kIdentityAttribute,
663 0 : std::string(val)));
664 : }
665 0 : }
666 :
667 : void
668 0 : SipccSdpAttributeList::LoadDtlsMessage(sdp_t* sdp, uint16_t level)
669 : {
670 0 : const char* val = sdp_attr_get_long_string(sdp, SDP_ATTR_DTLS_MESSAGE, level,
671 0 : 0, 1);
672 0 : if (val) {
673 : // sipcc does not expose parse code for this, so we use a SDParta-provided
674 : // parser
675 0 : std::string strval(val);
676 0 : SetAttribute(new SdpDtlsMessageAttribute(strval));
677 : }
678 0 : }
679 :
680 : void
681 0 : SipccSdpAttributeList::LoadFmtp(sdp_t* sdp, uint16_t level)
682 : {
683 0 : auto fmtps = MakeUnique<SdpFmtpAttributeList>();
684 :
685 0 : for (uint16_t i = 1; i < UINT16_MAX; ++i) {
686 0 : sdp_attr_t* attr = sdp_find_attr(sdp, level, 0, SDP_ATTR_FMTP, i);
687 :
688 0 : if (!attr) {
689 0 : break;
690 : }
691 :
692 0 : sdp_fmtp_t* fmtp = &(attr->attr.fmtp);
693 :
694 : // Get the payload type
695 0 : std::stringstream osPayloadType;
696 : // payload_num is the number in the fmtp attribute, verbatim
697 0 : osPayloadType << fmtp->payload_num;
698 :
699 : // Get parsed form of parameters, if supported
700 0 : UniquePtr<SdpFmtpAttributeList::Parameters> parameters;
701 :
702 0 : rtp_ptype codec = sdp_get_known_payload_type(sdp, level, fmtp->payload_num);
703 :
704 0 : switch (codec) {
705 : case RTP_H264_P0:
706 : case RTP_H264_P1: {
707 : SdpFmtpAttributeList::H264Parameters* h264Parameters(
708 0 : new SdpFmtpAttributeList::H264Parameters);
709 :
710 0 : sstrncpy(h264Parameters->sprop_parameter_sets, fmtp->parameter_sets,
711 0 : sizeof(h264Parameters->sprop_parameter_sets));
712 :
713 0 : h264Parameters->level_asymmetry_allowed =
714 0 : !!(fmtp->level_asymmetry_allowed);
715 :
716 0 : h264Parameters->packetization_mode = fmtp->packetization_mode;
717 0 : sscanf(fmtp->profile_level_id, "%x", &h264Parameters->profile_level_id);
718 0 : h264Parameters->max_mbps = fmtp->max_mbps;
719 0 : h264Parameters->max_fs = fmtp->max_fs;
720 0 : h264Parameters->max_cpb = fmtp->max_cpb;
721 0 : h264Parameters->max_dpb = fmtp->max_dpb;
722 0 : h264Parameters->max_br = fmtp->max_br;
723 :
724 0 : parameters.reset(h264Parameters);
725 0 : } break;
726 : case RTP_VP9: {
727 : SdpFmtpAttributeList::VP8Parameters* vp9Parameters(
728 : new SdpFmtpAttributeList::VP8Parameters(
729 0 : SdpRtpmapAttributeList::kVP9));
730 :
731 0 : vp9Parameters->max_fs = fmtp->max_fs;
732 0 : vp9Parameters->max_fr = fmtp->max_fr;
733 :
734 0 : parameters.reset(vp9Parameters);
735 0 : } break;
736 : case RTP_VP8: {
737 : SdpFmtpAttributeList::VP8Parameters* vp8Parameters(
738 : new SdpFmtpAttributeList::VP8Parameters(
739 0 : SdpRtpmapAttributeList::kVP8));
740 :
741 0 : vp8Parameters->max_fs = fmtp->max_fs;
742 0 : vp8Parameters->max_fr = fmtp->max_fr;
743 :
744 0 : parameters.reset(vp8Parameters);
745 0 : } break;
746 : case RTP_RED: {
747 : SdpFmtpAttributeList::RedParameters* redParameters(
748 0 : new SdpFmtpAttributeList::RedParameters);
749 0 : for (int i = 0;
750 0 : i < SDP_FMTP_MAX_REDUNDANT_ENCODINGS && fmtp->redundant_encodings[i];
751 : ++i) {
752 0 : redParameters->encodings.push_back(fmtp->redundant_encodings[i]);
753 : }
754 :
755 0 : parameters.reset(redParameters);
756 0 : } break;
757 : case RTP_OPUS: {
758 : SdpFmtpAttributeList::OpusParameters* opusParameters(
759 0 : new SdpFmtpAttributeList::OpusParameters);
760 0 : opusParameters->maxplaybackrate = fmtp->maxplaybackrate;
761 0 : opusParameters->stereo = fmtp->stereo;
762 0 : opusParameters->useInBandFec = fmtp->useinbandfec;
763 0 : parameters.reset(opusParameters);
764 0 : } break;
765 : case RTP_TELEPHONE_EVENT: {
766 : SdpFmtpAttributeList::TelephoneEventParameters* teParameters(
767 0 : new SdpFmtpAttributeList::TelephoneEventParameters);
768 0 : if (strlen(fmtp->dtmf_tones) > 0) {
769 0 : teParameters->dtmfTones = fmtp->dtmf_tones;
770 : }
771 0 : parameters.reset(teParameters);
772 0 : } break;
773 : default: {
774 : }
775 : }
776 :
777 0 : fmtps->PushEntry(osPayloadType.str(), Move(parameters));
778 : }
779 :
780 0 : if (!fmtps->mFmtps.empty()) {
781 0 : SetAttribute(fmtps.release());
782 : }
783 0 : }
784 :
785 : void
786 0 : SipccSdpAttributeList::LoadMsids(sdp_t* sdp, uint16_t level,
787 : SdpErrorHolder& errorHolder)
788 : {
789 0 : uint16_t attrCount = 0;
790 0 : if (sdp_attr_num_instances(sdp, level, 0, SDP_ATTR_MSID, &attrCount) !=
791 : SDP_SUCCESS) {
792 0 : MOZ_ASSERT(false, "Unable to get count of msid attributes");
793 : errorHolder.AddParseError(0, "Unable to get count of msid attributes");
794 : return;
795 : }
796 0 : auto msids = MakeUnique<SdpMsidAttributeList>();
797 0 : for (uint16_t i = 1; i <= attrCount; ++i) {
798 0 : uint32_t lineNumber = sdp_attr_line_number(sdp, SDP_ATTR_MSID, level, 0, i);
799 :
800 0 : const char* identifier = sdp_attr_get_msid_identifier(sdp, level, 0, i);
801 0 : if (!identifier) {
802 0 : errorHolder.AddParseError(lineNumber, "msid attribute with bad identity");
803 0 : continue;
804 : }
805 :
806 0 : const char* appdata = sdp_attr_get_msid_appdata(sdp, level, 0, i);
807 0 : if (!appdata) {
808 0 : errorHolder.AddParseError(lineNumber, "msid attribute with bad appdata");
809 0 : continue;
810 : }
811 :
812 0 : msids->PushEntry(identifier, appdata);
813 : }
814 :
815 0 : if (!msids->mMsids.empty()) {
816 0 : SetAttribute(msids.release());
817 : }
818 : }
819 :
820 : bool
821 0 : SipccSdpAttributeList::LoadRid(sdp_t* sdp,
822 : uint16_t level,
823 : SdpErrorHolder& errorHolder)
824 : {
825 0 : UniquePtr<SdpRidAttributeList> rids(new SdpRidAttributeList);
826 :
827 0 : for (uint16_t i = 1; i < UINT16_MAX; ++i) {
828 0 : const char* ridRaw = sdp_attr_get_simple_string(sdp,
829 : SDP_ATTR_RID,
830 : level,
831 : 0,
832 0 : i);
833 0 : if (!ridRaw) {
834 0 : break;
835 : }
836 :
837 0 : std::string error;
838 : size_t errorPos;
839 0 : if (!rids->PushEntry(ridRaw, &error, &errorPos)) {
840 0 : std::ostringstream fullError;
841 0 : fullError << error << " at column " << errorPos;
842 0 : errorHolder.AddParseError(
843 0 : sdp_attr_line_number(sdp, SDP_ATTR_RID, level, 0, i),
844 0 : fullError.str());
845 0 : return false;
846 : }
847 : }
848 :
849 0 : if (!rids->mRids.empty()) {
850 0 : SetAttribute(rids.release());
851 : }
852 0 : return true;
853 : }
854 :
855 : void
856 0 : SipccSdpAttributeList::LoadExtmap(sdp_t* sdp, uint16_t level,
857 : SdpErrorHolder& errorHolder)
858 : {
859 0 : auto extmaps = MakeUnique<SdpExtmapAttributeList>();
860 :
861 0 : for (uint16_t i = 1; i < UINT16_MAX; ++i) {
862 0 : sdp_attr_t* attr = sdp_find_attr(sdp, level, 0, SDP_ATTR_EXTMAP, i);
863 :
864 0 : if (!attr) {
865 0 : break;
866 : }
867 :
868 0 : sdp_extmap_t* extmap = &(attr->attr.extmap);
869 :
870 0 : SdpDirectionAttribute::Direction dir = SdpDirectionAttribute::kSendrecv;
871 :
872 0 : if (extmap->media_direction_specified) {
873 0 : ConvertDirection(extmap->media_direction, &dir);
874 : }
875 :
876 0 : extmaps->PushEntry(extmap->id, dir, extmap->media_direction_specified,
877 0 : extmap->uri, extmap->extension_attributes);
878 : }
879 :
880 0 : if (!extmaps->mExtmaps.empty()) {
881 0 : if (!AtSessionLevel() &&
882 0 : mSessionLevel->HasAttribute(SdpAttribute::kExtmapAttribute)) {
883 : uint32_t lineNumber =
884 0 : sdp_attr_line_number(sdp, SDP_ATTR_EXTMAP, level, 0, 1);
885 0 : errorHolder.AddParseError(
886 0 : lineNumber, "extmap attributes in both session and media level");
887 : }
888 0 : SetAttribute(extmaps.release());
889 : }
890 0 : }
891 :
892 : void
893 0 : SipccSdpAttributeList::LoadRtcpFb(sdp_t* sdp, uint16_t level,
894 : SdpErrorHolder& errorHolder)
895 : {
896 0 : auto rtcpfbs = MakeUnique<SdpRtcpFbAttributeList>();
897 :
898 0 : for (uint16_t i = 1; i < UINT16_MAX; ++i) {
899 0 : sdp_attr_t* attr = sdp_find_attr(sdp, level, 0, SDP_ATTR_RTCP_FB, i);
900 :
901 0 : if (!attr) {
902 0 : break;
903 : }
904 :
905 0 : sdp_fmtp_fb_t* rtcpfb = &attr->attr.rtcp_fb;
906 :
907 : SdpRtcpFbAttributeList::Type type;
908 0 : std::string parameter;
909 :
910 : // Set type and parameter
911 0 : switch (rtcpfb->feedback_type) {
912 : case SDP_RTCP_FB_ACK:
913 0 : type = SdpRtcpFbAttributeList::kAck;
914 0 : switch (rtcpfb->param.ack) {
915 : // TODO: sipcc doesn't seem to support ack with no following token.
916 : // Issue 189.
917 : case SDP_RTCP_FB_ACK_RPSI:
918 0 : parameter = SdpRtcpFbAttributeList::rpsi;
919 0 : break;
920 : case SDP_RTCP_FB_ACK_APP:
921 0 : parameter = SdpRtcpFbAttributeList::app;
922 0 : break;
923 : default:
924 : // Type we don't care about, ignore.
925 0 : continue;
926 : }
927 0 : break;
928 : case SDP_RTCP_FB_CCM:
929 0 : type = SdpRtcpFbAttributeList::kCcm;
930 0 : switch (rtcpfb->param.ccm) {
931 : case SDP_RTCP_FB_CCM_FIR:
932 0 : parameter = SdpRtcpFbAttributeList::fir;
933 0 : break;
934 : case SDP_RTCP_FB_CCM_TMMBR:
935 0 : parameter = SdpRtcpFbAttributeList::tmmbr;
936 0 : break;
937 : case SDP_RTCP_FB_CCM_TSTR:
938 0 : parameter = SdpRtcpFbAttributeList::tstr;
939 0 : break;
940 : case SDP_RTCP_FB_CCM_VBCM:
941 0 : parameter = SdpRtcpFbAttributeList::vbcm;
942 0 : break;
943 : default:
944 : // Type we don't care about, ignore.
945 0 : continue;
946 : }
947 0 : break;
948 : case SDP_RTCP_FB_NACK:
949 0 : type = SdpRtcpFbAttributeList::kNack;
950 0 : switch (rtcpfb->param.nack) {
951 : case SDP_RTCP_FB_NACK_BASIC:
952 0 : break;
953 : case SDP_RTCP_FB_NACK_SLI:
954 0 : parameter = SdpRtcpFbAttributeList::sli;
955 0 : break;
956 : case SDP_RTCP_FB_NACK_PLI:
957 0 : parameter = SdpRtcpFbAttributeList::pli;
958 0 : break;
959 : case SDP_RTCP_FB_NACK_RPSI:
960 0 : parameter = SdpRtcpFbAttributeList::rpsi;
961 0 : break;
962 : case SDP_RTCP_FB_NACK_APP:
963 0 : parameter = SdpRtcpFbAttributeList::app;
964 0 : break;
965 : default:
966 : // Type we don't care about, ignore.
967 0 : continue;
968 : }
969 0 : break;
970 : case SDP_RTCP_FB_TRR_INT: {
971 0 : type = SdpRtcpFbAttributeList::kTrrInt;
972 0 : std::ostringstream os;
973 0 : os << rtcpfb->param.trr_int;
974 0 : parameter = os.str();
975 0 : } break;
976 : case SDP_RTCP_FB_REMB: {
977 0 : type = SdpRtcpFbAttributeList::kRemb;
978 0 : } break;
979 : default:
980 : // Type we don't care about, ignore.
981 0 : continue;
982 : }
983 :
984 0 : std::stringstream osPayloadType;
985 0 : if (rtcpfb->payload_num == UINT16_MAX) {
986 0 : osPayloadType << "*";
987 : } else {
988 0 : osPayloadType << rtcpfb->payload_num;
989 : }
990 :
991 0 : std::string pt(osPayloadType.str());
992 0 : std::string extra(rtcpfb->extra);
993 :
994 0 : rtcpfbs->PushEntry(pt, type, parameter, extra);
995 : }
996 :
997 0 : if (!rtcpfbs->mFeedbacks.empty()) {
998 0 : SetAttribute(rtcpfbs.release());
999 : }
1000 0 : }
1001 :
1002 : void
1003 0 : SipccSdpAttributeList::LoadRtcp(sdp_t* sdp, uint16_t level,
1004 : SdpErrorHolder& errorHolder)
1005 : {
1006 0 : sdp_attr_t* attr = sdp_find_attr(sdp, level, 0, SDP_ATTR_RTCP, 1);
1007 :
1008 0 : if (!attr) {
1009 0 : return;
1010 : }
1011 :
1012 0 : sdp_rtcp_t* rtcp = &attr->attr.rtcp;
1013 :
1014 0 : if (rtcp->nettype != SDP_NT_INTERNET) {
1015 0 : return;
1016 : }
1017 :
1018 0 : if (rtcp->addrtype != SDP_AT_IP4 && rtcp->addrtype != SDP_AT_IP6) {
1019 0 : return;
1020 : }
1021 :
1022 0 : if (!strlen(rtcp->addr)) {
1023 0 : SetAttribute(new SdpRtcpAttribute(rtcp->port));
1024 : } else {
1025 0 : SetAttribute(
1026 : new SdpRtcpAttribute(
1027 0 : rtcp->port,
1028 : sdp::kInternet,
1029 0 : rtcp->addrtype == SDP_AT_IP4 ? sdp::kIPv4 : sdp::kIPv6,
1030 0 : rtcp->addr));
1031 : }
1032 : }
1033 :
1034 : bool
1035 0 : SipccSdpAttributeList::Load(sdp_t* sdp, uint16_t level,
1036 : SdpErrorHolder& errorHolder)
1037 : {
1038 :
1039 0 : LoadSimpleStrings(sdp, level, errorHolder);
1040 0 : LoadSimpleNumbers(sdp, level, errorHolder);
1041 0 : LoadFlags(sdp, level);
1042 0 : LoadDirection(sdp, level, errorHolder);
1043 :
1044 0 : if (AtSessionLevel()) {
1045 0 : if (!LoadGroups(sdp, level, errorHolder)) {
1046 0 : return false;
1047 : }
1048 :
1049 0 : if (!LoadMsidSemantics(sdp, level, errorHolder)) {
1050 0 : return false;
1051 : }
1052 :
1053 0 : LoadIdentity(sdp, level);
1054 0 : LoadDtlsMessage(sdp, level);
1055 : } else {
1056 0 : sdp_media_e mtype = sdp_get_media_type(sdp, level);
1057 0 : if (mtype == SDP_MEDIA_APPLICATION) {
1058 0 : LoadSctpmap(sdp, level, errorHolder);
1059 : } else {
1060 0 : if (!LoadRtpmap(sdp, level, errorHolder)) {
1061 0 : return false;
1062 : }
1063 : }
1064 0 : LoadCandidate(sdp, level);
1065 0 : LoadFmtp(sdp, level);
1066 0 : LoadMsids(sdp, level, errorHolder);
1067 0 : LoadRtcpFb(sdp, level, errorHolder);
1068 0 : LoadRtcp(sdp, level, errorHolder);
1069 0 : LoadSsrc(sdp, level);
1070 0 : if (!LoadImageattr(sdp, level, errorHolder)) {
1071 0 : return false;
1072 : }
1073 0 : if (!LoadSimulcast(sdp, level, errorHolder)) {
1074 0 : return false;
1075 : }
1076 0 : if (!LoadRid(sdp, level, errorHolder)) {
1077 0 : return false;
1078 : }
1079 : }
1080 :
1081 0 : LoadIceAttributes(sdp, level);
1082 0 : if (!LoadFingerprint(sdp, level, errorHolder)) {
1083 0 : return false;
1084 : }
1085 0 : LoadSetup(sdp, level);
1086 0 : LoadExtmap(sdp, level, errorHolder);
1087 :
1088 0 : return true;
1089 : }
1090 :
1091 : bool
1092 0 : SipccSdpAttributeList::IsAllowedHere(SdpAttribute::AttributeType type) const
1093 : {
1094 0 : if (AtSessionLevel() && !SdpAttribute::IsAllowedAtSessionLevel(type)) {
1095 0 : return false;
1096 : }
1097 :
1098 0 : if (!AtSessionLevel() && !SdpAttribute::IsAllowedAtMediaLevel(type)) {
1099 0 : return false;
1100 : }
1101 :
1102 0 : return true;
1103 : }
1104 :
1105 : void
1106 0 : SipccSdpAttributeList::WarnAboutMisplacedAttribute(
1107 : SdpAttribute::AttributeType type, uint32_t lineNumber,
1108 : SdpErrorHolder& errorHolder)
1109 : {
1110 0 : std::string warning = SdpAttribute::GetAttributeTypeString(type) +
1111 0 : (AtSessionLevel() ? " at session level. Ignoring."
1112 0 : : " at media level. Ignoring.");
1113 0 : errorHolder.AddParseError(lineNumber, warning);
1114 0 : }
1115 :
1116 : const std::vector<std::string>&
1117 0 : SipccSdpAttributeList::GetCandidate() const
1118 : {
1119 0 : if (!HasAttribute(SdpAttribute::kCandidateAttribute)) {
1120 0 : MOZ_CRASH();
1121 : }
1122 :
1123 : return static_cast<const SdpMultiStringAttribute*>(
1124 0 : GetAttribute(SdpAttribute::kCandidateAttribute))->mValues;
1125 : }
1126 :
1127 : const SdpConnectionAttribute&
1128 0 : SipccSdpAttributeList::GetConnection() const
1129 : {
1130 0 : if (!HasAttribute(SdpAttribute::kConnectionAttribute)) {
1131 0 : MOZ_CRASH();
1132 : }
1133 :
1134 : return *static_cast<const SdpConnectionAttribute*>(
1135 0 : GetAttribute(SdpAttribute::kConnectionAttribute));
1136 : }
1137 :
1138 : SdpDirectionAttribute::Direction
1139 0 : SipccSdpAttributeList::GetDirection() const
1140 : {
1141 0 : if (!HasAttribute(SdpAttribute::kDirectionAttribute)) {
1142 0 : MOZ_CRASH();
1143 : }
1144 :
1145 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kDirectionAttribute);
1146 0 : return static_cast<const SdpDirectionAttribute*>(attr)->mValue;
1147 : }
1148 :
1149 : const SdpDtlsMessageAttribute&
1150 0 : SipccSdpAttributeList::GetDtlsMessage() const
1151 : {
1152 0 : if (!HasAttribute(SdpAttribute::kDtlsMessageAttribute)) {
1153 0 : MOZ_CRASH();
1154 : }
1155 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kDtlsMessageAttribute);
1156 0 : return *static_cast<const SdpDtlsMessageAttribute*>(attr);
1157 : }
1158 :
1159 : const SdpExtmapAttributeList&
1160 0 : SipccSdpAttributeList::GetExtmap() const
1161 : {
1162 0 : if (!HasAttribute(SdpAttribute::kExtmapAttribute)) {
1163 0 : MOZ_CRASH();
1164 : }
1165 :
1166 : return *static_cast<const SdpExtmapAttributeList*>(
1167 0 : GetAttribute(SdpAttribute::kExtmapAttribute));
1168 : }
1169 :
1170 : const SdpFingerprintAttributeList&
1171 0 : SipccSdpAttributeList::GetFingerprint() const
1172 : {
1173 0 : if (!HasAttribute(SdpAttribute::kFingerprintAttribute)) {
1174 0 : MOZ_CRASH();
1175 : }
1176 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kFingerprintAttribute);
1177 0 : return *static_cast<const SdpFingerprintAttributeList*>(attr);
1178 : }
1179 :
1180 : const SdpFmtpAttributeList&
1181 0 : SipccSdpAttributeList::GetFmtp() const
1182 : {
1183 0 : if (!HasAttribute(SdpAttribute::kFmtpAttribute)) {
1184 0 : MOZ_CRASH();
1185 : }
1186 :
1187 : return *static_cast<const SdpFmtpAttributeList*>(
1188 0 : GetAttribute(SdpAttribute::kFmtpAttribute));
1189 : }
1190 :
1191 : const SdpGroupAttributeList&
1192 0 : SipccSdpAttributeList::GetGroup() const
1193 : {
1194 0 : if (!HasAttribute(SdpAttribute::kGroupAttribute)) {
1195 0 : MOZ_CRASH();
1196 : }
1197 :
1198 : return *static_cast<const SdpGroupAttributeList*>(
1199 0 : GetAttribute(SdpAttribute::kGroupAttribute));
1200 : }
1201 :
1202 : const SdpOptionsAttribute&
1203 0 : SipccSdpAttributeList::GetIceOptions() const
1204 : {
1205 0 : if (!HasAttribute(SdpAttribute::kIceOptionsAttribute)) {
1206 0 : MOZ_CRASH();
1207 : }
1208 :
1209 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kIceOptionsAttribute);
1210 0 : return *static_cast<const SdpOptionsAttribute*>(attr);
1211 : }
1212 :
1213 : const std::string&
1214 0 : SipccSdpAttributeList::GetIcePwd() const
1215 : {
1216 0 : if (!HasAttribute(SdpAttribute::kIcePwdAttribute)) {
1217 0 : return kEmptyString;
1218 : }
1219 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kIcePwdAttribute);
1220 0 : return static_cast<const SdpStringAttribute*>(attr)->mValue;
1221 : }
1222 :
1223 : const std::string&
1224 0 : SipccSdpAttributeList::GetIceUfrag() const
1225 : {
1226 0 : if (!HasAttribute(SdpAttribute::kIceUfragAttribute)) {
1227 0 : return kEmptyString;
1228 : }
1229 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kIceUfragAttribute);
1230 0 : return static_cast<const SdpStringAttribute*>(attr)->mValue;
1231 : }
1232 :
1233 : const std::string&
1234 0 : SipccSdpAttributeList::GetIdentity() const
1235 : {
1236 0 : if (!HasAttribute(SdpAttribute::kIdentityAttribute)) {
1237 0 : return kEmptyString;
1238 : }
1239 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kIdentityAttribute);
1240 0 : return static_cast<const SdpStringAttribute*>(attr)->mValue;
1241 : }
1242 :
1243 : const SdpImageattrAttributeList&
1244 0 : SipccSdpAttributeList::GetImageattr() const
1245 : {
1246 0 : if (!HasAttribute(SdpAttribute::kImageattrAttribute)) {
1247 0 : MOZ_CRASH();
1248 : }
1249 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kImageattrAttribute);
1250 0 : return *static_cast<const SdpImageattrAttributeList*>(attr);
1251 : }
1252 :
1253 : const SdpSimulcastAttribute&
1254 0 : SipccSdpAttributeList::GetSimulcast() const
1255 : {
1256 0 : if (!HasAttribute(SdpAttribute::kSimulcastAttribute)) {
1257 0 : MOZ_CRASH();
1258 : }
1259 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kSimulcastAttribute);
1260 0 : return *static_cast<const SdpSimulcastAttribute*>(attr);
1261 : }
1262 :
1263 : const std::string&
1264 0 : SipccSdpAttributeList::GetLabel() const
1265 : {
1266 0 : if (!HasAttribute(SdpAttribute::kLabelAttribute)) {
1267 0 : return kEmptyString;
1268 : }
1269 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kLabelAttribute);
1270 0 : return static_cast<const SdpStringAttribute*>(attr)->mValue;
1271 : }
1272 :
1273 : uint32_t
1274 0 : SipccSdpAttributeList::GetMaxptime() const
1275 : {
1276 0 : if (!HasAttribute(SdpAttribute::kMaxptimeAttribute)) {
1277 0 : MOZ_CRASH();
1278 : }
1279 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kMaxptimeAttribute);
1280 0 : return static_cast<const SdpNumberAttribute*>(attr)->mValue;
1281 : }
1282 :
1283 : const std::string&
1284 0 : SipccSdpAttributeList::GetMid() const
1285 : {
1286 0 : if (!HasAttribute(SdpAttribute::kMidAttribute)) {
1287 0 : return kEmptyString;
1288 : }
1289 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kMidAttribute);
1290 0 : return static_cast<const SdpStringAttribute*>(attr)->mValue;
1291 : }
1292 :
1293 : const SdpMsidAttributeList&
1294 0 : SipccSdpAttributeList::GetMsid() const
1295 : {
1296 0 : if (!HasAttribute(SdpAttribute::kMsidAttribute)) {
1297 0 : MOZ_CRASH();
1298 : }
1299 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kMsidAttribute);
1300 0 : return *static_cast<const SdpMsidAttributeList*>(attr);
1301 : }
1302 :
1303 : const SdpMsidSemanticAttributeList&
1304 0 : SipccSdpAttributeList::GetMsidSemantic() const
1305 : {
1306 0 : if (!HasAttribute(SdpAttribute::kMsidSemanticAttribute)) {
1307 0 : MOZ_CRASH();
1308 : }
1309 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kMsidSemanticAttribute);
1310 0 : return *static_cast<const SdpMsidSemanticAttributeList*>(attr);
1311 : }
1312 :
1313 : const SdpRidAttributeList&
1314 0 : SipccSdpAttributeList::GetRid() const
1315 : {
1316 0 : if (!HasAttribute(SdpAttribute::kRidAttribute)) {
1317 0 : MOZ_CRASH();
1318 : }
1319 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kRidAttribute);
1320 0 : return *static_cast<const SdpRidAttributeList*>(attr);
1321 : }
1322 :
1323 : uint32_t
1324 0 : SipccSdpAttributeList::GetPtime() const
1325 : {
1326 0 : if (!HasAttribute(SdpAttribute::kPtimeAttribute)) {
1327 0 : MOZ_CRASH();
1328 : }
1329 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kPtimeAttribute);
1330 0 : return static_cast<const SdpNumberAttribute*>(attr)->mValue;
1331 : }
1332 :
1333 : const SdpRtcpAttribute&
1334 0 : SipccSdpAttributeList::GetRtcp() const
1335 : {
1336 0 : if (!HasAttribute(SdpAttribute::kRtcpAttribute)) {
1337 0 : MOZ_CRASH();
1338 : }
1339 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtcpAttribute);
1340 0 : return *static_cast<const SdpRtcpAttribute*>(attr);
1341 : }
1342 :
1343 : const SdpRtcpFbAttributeList&
1344 0 : SipccSdpAttributeList::GetRtcpFb() const
1345 : {
1346 0 : if (!HasAttribute(SdpAttribute::kRtcpFbAttribute)) {
1347 0 : MOZ_CRASH();
1348 : }
1349 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtcpFbAttribute);
1350 0 : return *static_cast<const SdpRtcpFbAttributeList*>(attr);
1351 : }
1352 :
1353 : const SdpRemoteCandidatesAttribute&
1354 0 : SipccSdpAttributeList::GetRemoteCandidates() const
1355 : {
1356 0 : MOZ_CRASH("Not yet implemented");
1357 : }
1358 :
1359 : const SdpRtpmapAttributeList&
1360 0 : SipccSdpAttributeList::GetRtpmap() const
1361 : {
1362 0 : if (!HasAttribute(SdpAttribute::kRtpmapAttribute)) {
1363 0 : MOZ_CRASH();
1364 : }
1365 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtpmapAttribute);
1366 0 : return *static_cast<const SdpRtpmapAttributeList*>(attr);
1367 : }
1368 :
1369 : const SdpSctpmapAttributeList&
1370 0 : SipccSdpAttributeList::GetSctpmap() const
1371 : {
1372 0 : if (!HasAttribute(SdpAttribute::kSctpmapAttribute)) {
1373 0 : MOZ_CRASH();
1374 : }
1375 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kSctpmapAttribute);
1376 0 : return *static_cast<const SdpSctpmapAttributeList*>(attr);
1377 : }
1378 :
1379 : uint32_t
1380 0 : SipccSdpAttributeList::GetSctpPort() const
1381 : {
1382 0 : if (!HasAttribute(SdpAttribute::kSctpPortAttribute)) {
1383 0 : MOZ_CRASH();
1384 : }
1385 :
1386 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kSctpPortAttribute);
1387 0 : return static_cast<const SdpNumberAttribute*>(attr)->mValue;
1388 : }
1389 :
1390 : uint32_t
1391 0 : SipccSdpAttributeList::GetMaxMessageSize() const
1392 : {
1393 0 : if (!HasAttribute(SdpAttribute::kMaxMessageSizeAttribute)) {
1394 0 : MOZ_CRASH();
1395 : }
1396 :
1397 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kMaxMessageSizeAttribute);
1398 0 : return static_cast<const SdpNumberAttribute*>(attr)->mValue;
1399 : }
1400 :
1401 : const SdpSetupAttribute&
1402 0 : SipccSdpAttributeList::GetSetup() const
1403 : {
1404 0 : if (!HasAttribute(SdpAttribute::kSetupAttribute)) {
1405 0 : MOZ_CRASH();
1406 : }
1407 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kSetupAttribute);
1408 0 : return *static_cast<const SdpSetupAttribute*>(attr);
1409 : }
1410 :
1411 : const SdpSsrcAttributeList&
1412 0 : SipccSdpAttributeList::GetSsrc() const
1413 : {
1414 0 : if (!HasAttribute(SdpAttribute::kSsrcAttribute)) {
1415 0 : MOZ_CRASH();
1416 : }
1417 0 : const SdpAttribute* attr = GetAttribute(SdpAttribute::kSsrcAttribute);
1418 0 : return *static_cast<const SdpSsrcAttributeList*>(attr);
1419 : }
1420 :
1421 : const SdpSsrcGroupAttributeList&
1422 0 : SipccSdpAttributeList::GetSsrcGroup() const
1423 : {
1424 0 : MOZ_CRASH("Not yet implemented");
1425 : }
1426 :
1427 : void
1428 0 : SipccSdpAttributeList::Serialize(std::ostream& os) const
1429 : {
1430 0 : for (size_t i = 0; i < kNumAttributeTypes; ++i) {
1431 0 : if (mAttributes[i]) {
1432 0 : os << *mAttributes[i];
1433 : }
1434 : }
1435 0 : }
1436 :
1437 : } // namespace mozilla
|