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