SdpAttribute.cpp (38849B)
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/SdpAttribute.h" 8 9 #include <bitset> 10 #include <iomanip> 11 12 #include "sdp/SdpHelper.h" 13 14 #ifdef CRLF 15 # undef CRLF 16 #endif 17 #define CRLF "\r\n" 18 19 namespace mozilla { 20 21 static unsigned char PeekChar(std::istream& is, std::string* error) { 22 int next = is.peek(); 23 if (next == EOF) { 24 *error = "Truncated"; 25 return 0; 26 } 27 28 return next; 29 } 30 31 static std::string ParseToken(std::istream& is, const std::string& delims, 32 std::string* error) { 33 std::string token; 34 while (is) { 35 unsigned char c = PeekChar(is, error); 36 if (!c || (delims.find(c) != std::string::npos)) { 37 break; 38 } 39 token.push_back(std::tolower(is.get())); 40 } 41 return token; 42 } 43 44 static bool SkipChar(std::istream& is, unsigned char c, std::string* error) { 45 if (PeekChar(is, error) != c) { 46 *error = "Expected \'"; 47 error->push_back(c); 48 error->push_back('\''); 49 return false; 50 } 51 52 is.get(); 53 return true; 54 } 55 56 void SdpConnectionAttribute::Serialize(std::ostream& os) const { 57 os << "a=" << mType << ":" << mValue << CRLF; 58 } 59 60 void SdpDirectionAttribute::Serialize(std::ostream& os) const { 61 os << "a=" << mValue << CRLF; 62 } 63 64 void SdpDtlsMessageAttribute::Serialize(std::ostream& os) const { 65 os << "a=" << mType << ":" << mRole << " " << mValue << CRLF; 66 } 67 68 bool SdpDtlsMessageAttribute::Parse(std::istream& is, std::string* error) { 69 std::string roleToken = ParseToken(is, " ", error); 70 if (roleToken == "server") { 71 mRole = kServer; 72 } else if (roleToken == "client") { 73 mRole = kClient; 74 } else { 75 *error = "Invalid dtls-message role; must be either client or server"; 76 return false; 77 } 78 79 is >> std::ws; 80 81 std::string s(std::istreambuf_iterator<char>(is), {}); 82 mValue = s; 83 84 return true; 85 } 86 87 void SdpExtmapAttributeList::Serialize(std::ostream& os) const { 88 for (auto i = mExtmaps.begin(); i != mExtmaps.end(); ++i) { 89 os << "a=" << mType << ":" << i->entry; 90 if (i->direction_specified) { 91 os << "/" << i->direction; 92 } 93 os << " " << i->extensionname; 94 if (i->extensionattributes.length()) { 95 os << " " << i->extensionattributes; 96 } 97 os << CRLF; 98 } 99 } 100 101 void SdpFingerprintAttributeList::Serialize(std::ostream& os) const { 102 for (auto i = mFingerprints.begin(); i != mFingerprints.end(); ++i) { 103 os << "a=" << mType << ":" << i->hashFunc << " " 104 << FormatFingerprint(i->fingerprint) << CRLF; 105 } 106 } 107 108 // Format the fingerprint in RFC 4572 Section 5 attribute format 109 std::string SdpFingerprintAttributeList::FormatFingerprint( 110 const std::vector<uint8_t>& fp) { 111 if (fp.empty()) { 112 MOZ_ASSERT(false, "Cannot format an empty fingerprint."); 113 return ""; 114 } 115 116 std::ostringstream os; 117 for (auto i = fp.begin(); i != fp.end(); ++i) { 118 os << ":" << std::hex << std::uppercase << std::setw(2) << std::setfill('0') 119 << static_cast<uint32_t>(*i); 120 } 121 return os.str().substr(1); 122 } 123 124 static uint8_t FromUppercaseHex(char ch) { 125 if ((ch >= '0') && (ch <= '9')) { 126 return ch - '0'; 127 } 128 if ((ch >= 'A') && (ch <= 'F')) { 129 return ch - 'A' + 10; 130 } 131 return 16; // invalid 132 } 133 134 // Parse the fingerprint from RFC 4572 Section 5 attribute format 135 std::vector<uint8_t> SdpFingerprintAttributeList::ParseFingerprint( 136 const std::string& str) { 137 size_t targetSize = (str.length() + 1) / 3; 138 std::vector<uint8_t> fp(targetSize); 139 size_t fpIndex = 0; 140 141 if (str.length() % 3 != 2) { 142 fp.clear(); 143 return fp; 144 } 145 146 for (size_t i = 0; i < str.length(); i += 3) { 147 uint8_t high = FromUppercaseHex(str[i]); 148 uint8_t low = FromUppercaseHex(str[i + 1]); 149 if (high > 0xf || low > 0xf || 150 (i + 2 < str.length() && str[i + 2] != ':')) { 151 fp.clear(); // error 152 return fp; 153 } 154 fp[fpIndex++] = high << 4 | low; 155 } 156 return fp; 157 } 158 159 bool SdpFmtpAttributeList::operator==(const SdpFmtpAttributeList& other) const { 160 return mFmtps == other.mFmtps; 161 } 162 163 void SdpFmtpAttributeList::Serialize(std::ostream& os) const { 164 for (auto i = mFmtps.begin(); i != mFmtps.end(); ++i) { 165 if (i->parameters && i->parameters->ShouldSerialize()) { 166 os << "a=" << mType << ":" << i->format << " "; 167 i->parameters->Serialize(os); 168 os << CRLF; 169 } 170 } 171 } 172 173 void SdpGroupAttributeList::Serialize(std::ostream& os) const { 174 for (auto i = mGroups.begin(); i != mGroups.end(); ++i) { 175 os << "a=" << mType << ":" << i->semantics; 176 for (auto j = i->tags.begin(); j != i->tags.end(); ++j) { 177 os << " " << (*j); 178 } 179 os << CRLF; 180 } 181 } 182 183 // We're just using an SdpStringAttribute for this right now 184 #if 0 185 void SdpIdentityAttribute::Serialize(std::ostream& os) const 186 { 187 os << "a=" << mType << ":" << mAssertion; 188 for (auto i = mExtensions.begin(); i != mExtensions.end(); i++) { 189 os << (i == mExtensions.begin() ? " " : ";") << (*i); 190 } 191 os << CRLF; 192 } 193 #endif 194 195 // Class to help with omitting a leading delimiter for the first item in a list 196 class SkipFirstDelimiter { 197 public: 198 explicit SkipFirstDelimiter(const std::string& delim) 199 : mDelim(delim), mFirst(true) {} 200 201 std::ostream& print(std::ostream& os) { 202 if (!mFirst) { 203 os << mDelim; 204 } 205 mFirst = false; 206 return os; 207 } 208 209 private: 210 std::string mDelim; 211 bool mFirst; 212 }; 213 214 static std::ostream& operator<<(std::ostream& os, SkipFirstDelimiter& delim) { 215 return delim.print(os); 216 } 217 218 void SdpImageattrAttributeList::XYRange::Serialize(std::ostream& os) const { 219 if (discreteValues.empty()) { 220 os << "[" << min << ":"; 221 if (step != 1) { 222 os << step << ":"; 223 } 224 os << max << "]"; 225 } else if (discreteValues.size() == 1) { 226 os << discreteValues.front(); 227 } else { 228 os << "["; 229 SkipFirstDelimiter comma(","); 230 for (auto value : discreteValues) { 231 os << comma << value; 232 } 233 os << "]"; 234 } 235 } 236 237 template <typename T> 238 bool GetUnsigned(std::istream& is, T min, T max, T* value, std::string* error) { 239 if (PeekChar(is, error) == '-') { 240 *error = "Value is less than 0"; 241 return false; 242 } 243 244 is >> std::noskipws >> *value; 245 246 if (is.fail()) { 247 *error = "Malformed"; 248 return false; 249 } 250 251 if (*value < min) { 252 *error = "Value too small"; 253 return false; 254 } 255 256 if (*value > max) { 257 *error = "Value too large"; 258 return false; 259 } 260 261 return true; 262 } 263 264 static bool GetXYValue(std::istream& is, uint32_t* value, std::string* error) { 265 return GetUnsigned<uint32_t>(is, 1, 999999, value, error); 266 } 267 268 bool SdpImageattrAttributeList::XYRange::ParseDiscreteValues( 269 std::istream& is, std::string* error) { 270 do { 271 uint32_t value; 272 if (!GetXYValue(is, &value, error)) { 273 return false; 274 } 275 discreteValues.push_back(value); 276 } while (SkipChar(is, ',', error)); 277 278 return SkipChar(is, ']', error); 279 } 280 281 bool SdpImageattrAttributeList::XYRange::ParseAfterMin(std::istream& is, 282 std::string* error) { 283 // We have already parsed "[320:", and now expect another uint 284 uint32_t value; 285 if (!GetXYValue(is, &value, error)) { 286 return false; 287 } 288 289 if (SkipChar(is, ':', error)) { 290 // Range with step eg [320:16:640] 291 step = value; 292 // Now |value| should be the max 293 if (!GetXYValue(is, &value, error)) { 294 return false; 295 } 296 } 297 298 max = value; 299 if (min >= max) { 300 *error = "Min is not smaller than max"; 301 return false; 302 } 303 304 return SkipChar(is, ']', error); 305 } 306 307 bool SdpImageattrAttributeList::XYRange::ParseAfterBracket(std::istream& is, 308 std::string* error) { 309 // Either a range, or a list of discrete values 310 // [320:640], [320:16:640], or [320,640] 311 uint32_t value; 312 if (!GetXYValue(is, &value, error)) { 313 return false; 314 } 315 316 if (SkipChar(is, ':', error)) { 317 // Range - [640:480] or [640:16:480] 318 min = value; 319 return ParseAfterMin(is, error); 320 } 321 322 if (SkipChar(is, ',', error)) { 323 discreteValues.push_back(value); 324 return ParseDiscreteValues(is, error); 325 } 326 327 *error = "Expected \':\' or \',\'"; 328 return false; 329 } 330 331 bool SdpImageattrAttributeList::XYRange::Parse(std::istream& is, 332 std::string* error) { 333 if (SkipChar(is, '[', error)) { 334 return ParseAfterBracket(is, error); 335 } 336 337 // Single discrete value 338 uint32_t value; 339 if (!GetXYValue(is, &value, error)) { 340 return false; 341 } 342 discreteValues.push_back(value); 343 344 return true; 345 } 346 347 static bool GetSPValue(std::istream& is, float* value, std::string* error) { 348 return GetUnsigned<float>(is, 0.1f, 9.9999f, value, error); 349 } 350 351 static bool GetQValue(std::istream& is, float* value, std::string* error) { 352 return GetUnsigned<float>(is, 0.0f, 1.0f, value, error); 353 } 354 355 bool SdpImageattrAttributeList::SRange::ParseDiscreteValues( 356 std::istream& is, std::string* error) { 357 do { 358 float value; 359 if (!GetSPValue(is, &value, error)) { 360 return false; 361 } 362 discreteValues.push_back(value); 363 } while (SkipChar(is, ',', error)); 364 365 return SkipChar(is, ']', error); 366 } 367 368 bool SdpImageattrAttributeList::SRange::ParseAfterMin(std::istream& is, 369 std::string* error) { 370 if (!GetSPValue(is, &max, error)) { 371 return false; 372 } 373 374 if (min >= max) { 375 *error = "Min is not smaller than max"; 376 return false; 377 } 378 379 return SkipChar(is, ']', error); 380 } 381 382 bool SdpImageattrAttributeList::SRange::ParseAfterBracket(std::istream& is, 383 std::string* error) { 384 // Either a range, or a list of discrete values 385 float value; 386 if (!GetSPValue(is, &value, error)) { 387 return false; 388 } 389 390 if (SkipChar(is, '-', error)) { 391 min = value; 392 return ParseAfterMin(is, error); 393 } 394 395 if (SkipChar(is, ',', error)) { 396 discreteValues.push_back(value); 397 return ParseDiscreteValues(is, error); 398 } 399 400 *error = "Expected either \'-\' or \',\'"; 401 return false; 402 } 403 404 bool SdpImageattrAttributeList::SRange::Parse(std::istream& is, 405 std::string* error) { 406 if (SkipChar(is, '[', error)) { 407 return ParseAfterBracket(is, error); 408 } 409 410 // Single discrete value 411 float value; 412 if (!GetSPValue(is, &value, error)) { 413 return false; 414 } 415 discreteValues.push_back(value); 416 return true; 417 } 418 419 bool SdpImageattrAttributeList::PRange::Parse(std::istream& is, 420 std::string* error) { 421 if (!SkipChar(is, '[', error)) { 422 return false; 423 } 424 425 if (!GetSPValue(is, &min, error)) { 426 return false; 427 } 428 429 if (!SkipChar(is, '-', error)) { 430 return false; 431 } 432 433 if (!GetSPValue(is, &max, error)) { 434 return false; 435 } 436 437 if (min >= max) { 438 *error = "min must be smaller than max"; 439 return false; 440 } 441 442 if (!SkipChar(is, ']', error)) { 443 return false; 444 } 445 return true; 446 } 447 448 void SdpImageattrAttributeList::SRange::Serialize(std::ostream& os) const { 449 os << std::setprecision(4) << std::fixed; 450 if (discreteValues.empty()) { 451 os << "[" << min << "-" << max << "]"; 452 } else if (discreteValues.size() == 1) { 453 os << discreteValues.front(); 454 } else { 455 os << "["; 456 SkipFirstDelimiter comma(","); 457 for (auto value : discreteValues) { 458 os << comma << value; 459 } 460 os << "]"; 461 } 462 } 463 464 void SdpImageattrAttributeList::PRange::Serialize(std::ostream& os) const { 465 os << std::setprecision(4) << std::fixed; 466 os << "[" << min << "-" << max << "]"; 467 } 468 469 static std::string ParseKey(std::istream& is, std::string* error) { 470 std::string token = ParseToken(is, "=", error); 471 if (!SkipChar(is, '=', error)) { 472 return ""; 473 } 474 return token; 475 } 476 477 static bool SkipBraces(std::istream& is, std::string* error) { 478 if (PeekChar(is, error) != '[') { 479 *error = "Expected \'[\'"; 480 return false; 481 } 482 483 size_t braceCount = 0; 484 do { 485 switch (PeekChar(is, error)) { 486 case '[': 487 ++braceCount; 488 break; 489 case ']': 490 --braceCount; 491 break; 492 default: 493 break; 494 } 495 is.get(); 496 } while (braceCount && is); 497 498 if (!is) { 499 *error = "Expected closing brace"; 500 return false; 501 } 502 503 return true; 504 } 505 506 // Assumptions: 507 // 1. If the value contains '[' or ']', they are balanced. 508 // 2. The value contains no ',' outside of brackets. 509 static bool SkipValue(std::istream& is, std::string* error) { 510 while (is) { 511 switch (PeekChar(is, error)) { 512 case ',': 513 case ']': 514 return true; 515 case '[': 516 if (!SkipBraces(is, error)) { 517 return false; 518 } 519 break; 520 default: 521 is.get(); 522 } 523 } 524 525 *error = "No closing \']\' on set"; 526 return false; 527 } 528 529 bool SdpImageattrAttributeList::Set::Parse(std::istream& is, 530 std::string* error) { 531 if (!SkipChar(is, '[', error)) { 532 return false; 533 } 534 535 if (ParseKey(is, error) != "x") { 536 *error = "Expected x="; 537 return false; 538 } 539 540 if (!xRange.Parse(is, error)) { 541 return false; 542 } 543 544 if (!SkipChar(is, ',', error)) { 545 return false; 546 } 547 548 if (ParseKey(is, error) != "y") { 549 *error = "Expected y="; 550 return false; 551 } 552 553 if (!yRange.Parse(is, error)) { 554 return false; 555 } 556 557 qValue = 0.5f; // default 558 559 bool gotSar = false; 560 bool gotPar = false; 561 bool gotQ = false; 562 563 while (SkipChar(is, ',', error)) { 564 std::string key = ParseKey(is, error); 565 if (key.empty()) { 566 *error = "Expected key-value"; 567 return false; 568 } 569 570 if (key == "sar") { 571 if (gotSar) { 572 *error = "Extra sar parameter"; 573 return false; 574 } 575 gotSar = true; 576 if (!sRange.Parse(is, error)) { 577 return false; 578 } 579 } else if (key == "par") { 580 if (gotPar) { 581 *error = "Extra par parameter"; 582 return false; 583 } 584 gotPar = true; 585 if (!pRange.Parse(is, error)) { 586 return false; 587 } 588 } else if (key == "q") { 589 if (gotQ) { 590 *error = "Extra q parameter"; 591 return false; 592 } 593 gotQ = true; 594 if (!GetQValue(is, &qValue, error)) { 595 return false; 596 } 597 } else { 598 if (!SkipValue(is, error)) { 599 return false; 600 } 601 } 602 } 603 604 return SkipChar(is, ']', error); 605 } 606 607 void SdpImageattrAttributeList::Set::Serialize(std::ostream& os) const { 608 os << "[x="; 609 xRange.Serialize(os); 610 os << ",y="; 611 yRange.Serialize(os); 612 if (sRange.IsSet()) { 613 os << ",sar="; 614 sRange.Serialize(os); 615 } 616 if (pRange.IsSet()) { 617 os << ",par="; 618 pRange.Serialize(os); 619 } 620 if (qValue >= 0) { 621 os << std::setprecision(2) << std::fixed << ",q=" << qValue; 622 } 623 os << "]"; 624 } 625 626 bool SdpImageattrAttributeList::Imageattr::ParseSets(std::istream& is, 627 std::string* error) { 628 std::string type = ParseToken(is, " \t", error); 629 630 bool* isAll = nullptr; 631 std::vector<Set>* sets = nullptr; 632 633 if (type == "send") { 634 isAll = &sendAll; 635 sets = &sendSets; 636 } else if (type == "recv") { 637 isAll = &recvAll; 638 sets = &recvSets; 639 } else { 640 *error = "Unknown type, must be either send or recv"; 641 return false; 642 } 643 644 if (*isAll || !sets->empty()) { 645 *error = "Multiple send or recv set lists"; 646 return false; 647 } 648 649 is >> std::ws; 650 if (SkipChar(is, '*', error)) { 651 *isAll = true; 652 return true; 653 } 654 655 do { 656 Set set; 657 if (!set.Parse(is, error)) { 658 return false; 659 } 660 661 sets->push_back(set); 662 is >> std::ws; 663 } while (PeekChar(is, error) == '['); 664 665 return true; 666 } 667 668 bool SdpImageattrAttributeList::Imageattr::Parse(std::istream& is, 669 std::string* error) { 670 if (!SkipChar(is, '*', error)) { 671 uint16_t value; 672 if (!GetUnsigned<uint16_t>(is, 0, UINT16_MAX, &value, error)) { 673 return false; 674 } 675 pt = Some(value); 676 } 677 678 is >> std::ws; 679 if (!ParseSets(is, error)) { 680 return false; 681 } 682 683 // There might be a second one 684 is >> std::ws; 685 if (is.eof()) { 686 return true; 687 } 688 689 if (!ParseSets(is, error)) { 690 return false; 691 } 692 693 is >> std::ws; 694 if (!is.eof()) { 695 *error = "Trailing characters"; 696 return false; 697 } 698 699 return true; 700 } 701 702 void SdpImageattrAttributeList::Imageattr::Serialize(std::ostream& os) const { 703 if (pt.isSome()) { 704 os << *pt; 705 } else { 706 os << "*"; 707 } 708 709 if (sendAll) { 710 os << " send *"; 711 } else if (!sendSets.empty()) { 712 os << " send"; 713 for (auto& set : sendSets) { 714 os << " "; 715 set.Serialize(os); 716 } 717 } 718 719 if (recvAll) { 720 os << " recv *"; 721 } else if (!recvSets.empty()) { 722 os << " recv"; 723 for (auto& set : recvSets) { 724 os << " "; 725 set.Serialize(os); 726 } 727 } 728 } 729 730 void SdpImageattrAttributeList::Serialize(std::ostream& os) const { 731 for (auto& imageattr : mImageattrs) { 732 os << "a=" << mType << ":"; 733 imageattr.Serialize(os); 734 os << CRLF; 735 } 736 } 737 738 bool SdpImageattrAttributeList::PushEntry(const std::string& raw, 739 std::string* error, 740 size_t* errorPos) { 741 std::istringstream is(raw); 742 743 Imageattr imageattr; 744 if (!imageattr.Parse(is, error)) { 745 is.clear(); 746 *errorPos = is.tellg(); 747 return false; 748 } 749 750 mImageattrs.push_back(imageattr); 751 return true; 752 } 753 754 void SdpMsidAttributeList::Serialize(std::ostream& os) const { 755 for (auto i = mMsids.begin(); i != mMsids.end(); ++i) { 756 os << "a=" << mType << ":" << i->identifier; 757 if (i->appdata.length()) { 758 os << " " << i->appdata; 759 } 760 os << CRLF; 761 } 762 } 763 764 void SdpMsidSemanticAttributeList::Serialize(std::ostream& os) const { 765 for (auto i = mMsidSemantics.begin(); i != mMsidSemantics.end(); ++i) { 766 os << "a=" << mType << ":" << i->semantic; 767 for (auto j = i->msids.begin(); j != i->msids.end(); ++j) { 768 os << " " << *j; 769 } 770 os << CRLF; 771 } 772 } 773 774 void SdpRemoteCandidatesAttribute::Serialize(std::ostream& os) const { 775 if (mCandidates.empty()) { 776 return; 777 } 778 779 os << "a=" << mType; 780 for (auto i = mCandidates.begin(); i != mCandidates.end(); i++) { 781 os << (i == mCandidates.begin() ? ":" : " ") << i->id << " " << i->address 782 << " " << i->port; 783 } 784 os << CRLF; 785 } 786 787 // Remove this function. See Bug 1469702 788 bool SdpRidAttributeList::Rid::ParseParameters(std::istream& is, 789 std::string* error) { 790 if (!PeekChar(is, error)) { 791 // No parameters 792 return true; 793 } 794 795 do { 796 is >> std::ws; 797 std::string key = ParseKey(is, error); 798 if (key.empty()) { 799 return false; // Illegal trailing cruft 800 } 801 802 // This allows pt= to appear anywhere, instead of only at the beginning, but 803 // this ends up being significantly less code. 804 if (key == "pt") { 805 if (!ParseFormats(is, error)) { 806 return false; 807 } 808 } else if (key == "max-width") { 809 if (!GetUnsigned<uint32_t>(is, 0, UINT32_MAX, &constraints.maxWidth, 810 error)) { 811 return false; 812 } 813 } else if (key == "max-height") { 814 if (!GetUnsigned<uint32_t>(is, 0, UINT32_MAX, &constraints.maxHeight, 815 error)) { 816 return false; 817 } 818 } else if (key == "max-fps") { 819 uint32_t maxFps; 820 if (!GetUnsigned<uint32_t>(is, 0, UINT32_MAX, &maxFps, error)) { 821 return false; 822 } 823 constraints.maxFps = Some(maxFps); 824 } else if (key == "max-fs") { 825 if (!GetUnsigned<uint32_t>(is, 0, UINT32_MAX, &constraints.maxFs, 826 error)) { 827 return false; 828 } 829 } else if (key == "max-br") { 830 if (!GetUnsigned<uint32_t>(is, 0, UINT32_MAX, &constraints.maxBr, 831 error)) { 832 return false; 833 } 834 } else if (key == "max-pps") { 835 if (!GetUnsigned<uint32_t>(is, 0, UINT32_MAX, &constraints.maxPps, 836 error)) { 837 return false; 838 } 839 } else if (key == "depend") { 840 if (!ParseDepend(is, error)) { 841 return false; 842 } 843 } else { 844 (void)ParseToken(is, ";", error); 845 } 846 } while (SkipChar(is, ';', error)); 847 return true; 848 } 849 850 // Remove this function. See Bug 1469702 851 bool SdpRidAttributeList::Rid::ParseDepend(std::istream& is, 852 std::string* error) { 853 do { 854 std::string id = ParseToken(is, ",;", error); 855 if (id.empty()) { 856 return false; 857 } 858 dependIds.push_back(id); 859 } while (SkipChar(is, ',', error)); 860 861 return true; 862 } 863 864 // Remove this function. See Bug 1469702 865 bool SdpRidAttributeList::Rid::ParseFormats(std::istream& is, 866 std::string* error) { 867 do { 868 uint16_t fmt; 869 if (!GetUnsigned<uint16_t>(is, 0, 127, &fmt, error)) { 870 return false; 871 } 872 formats.push_back(fmt); 873 } while (SkipChar(is, ',', error)); 874 875 return true; 876 } 877 878 void SdpRidAttributeList::Rid::SerializeParameters(std::ostream& os) const { 879 if (!HasParameters()) { 880 return; 881 } 882 883 os << " "; 884 885 SkipFirstDelimiter semic(";"); 886 887 if (!formats.empty()) { 888 os << semic << "pt="; 889 SkipFirstDelimiter comma(","); 890 for (uint16_t fmt : formats) { 891 os << comma << fmt; 892 } 893 } 894 895 if (constraints.maxWidth) { 896 os << semic << "max-width=" << constraints.maxWidth; 897 } 898 899 if (constraints.maxHeight) { 900 os << semic << "max-height=" << constraints.maxHeight; 901 } 902 903 if (constraints.maxFps) { 904 os << semic << "max-fps=" << constraints.maxFps; 905 } 906 907 if (constraints.maxFs) { 908 os << semic << "max-fs=" << constraints.maxFs; 909 } 910 911 if (constraints.maxBr) { 912 os << semic << "max-br=" << constraints.maxBr; 913 } 914 915 if (constraints.maxPps) { 916 os << semic << "max-pps=" << constraints.maxPps; 917 } 918 919 if (!dependIds.empty()) { 920 os << semic << "depend="; 921 SkipFirstDelimiter comma(","); 922 for (const std::string& id : dependIds) { 923 os << comma << id; 924 } 925 } 926 } 927 928 // Remove this function. See Bug 1469702 929 bool SdpRidAttributeList::Rid::Parse(std::istream& is, std::string* error) { 930 id = ParseToken(is, " ", error); 931 if (!CheckRidValidity(id, error)) { 932 return false; 933 } 934 935 is >> std::ws; 936 std::string directionToken = ParseToken(is, " ", error); 937 if (directionToken == "send") { 938 direction = sdp::kSend; 939 } else if (directionToken == "recv") { 940 direction = sdp::kRecv; 941 } else { 942 *error = "Invalid direction, must be either send or recv"; 943 return false; 944 } 945 946 return ParseParameters(is, error); 947 } 948 949 static std::bitset<256> GetAllowedRidCharacters() { 950 // From RFC 8851: 951 // rid-id = 1*(alpha-numeric / "-" / "_") 952 std::bitset<256> result; 953 for (unsigned char c = 'a'; c <= 'z'; ++c) { 954 result.set(c); 955 } 956 for (unsigned char c = 'A'; c <= 'Z'; ++c) { 957 result.set(c); 958 } 959 for (unsigned char c = '0'; c <= '9'; ++c) { 960 result.set(c); 961 } 962 // NOTE: RFC 8851 says these are allowed, but RFC 8852 says they are not 963 // https://www.rfc-editor.org/errata/eid7132 964 // result.set('-'); 965 // result.set('_'); 966 return result; 967 } 968 969 /* static */ 970 bool SdpRidAttributeList::CheckRidValidity(const std::string& aRid, 971 std::string* aError) { 972 if (aRid.empty()) { 973 *aError = "Rid must be non-empty (according to RFC 8851)"; 974 return false; 975 } 976 977 // We need to check against a maximum length, but that is nowhere 978 // specified in webrtc-pc right now. 979 if (aRid.size() > 255) { 980 *aError = "Rid can be at most 255 characters long (according to RFC 8852)"; 981 return false; 982 } 983 984 // TODO: Right now, if the rid is longer than kMaxRidLength, we don't treat it 985 // as a parse error, since the grammar does not have this restriction. 986 // Instead, our JSEP code ignores rids that exceed this limit. However, there 987 // is a possibility that the IETF grammar (in RFC 8852) will change the limit 988 // from 255 to 16, in which case we will need to revise this code. 989 990 static const std::bitset<256> allowed = GetAllowedRidCharacters(); 991 for (unsigned char c : aRid) { 992 if (!allowed[c]) { 993 *aError = 994 "Rid can contain only alphanumeric characters (according to RFC " 995 "8852)"; 996 return false; 997 } 998 } 999 1000 return true; 1001 } 1002 1003 // This can be overridden if necessary 1004 size_t SdpRidAttributeList::kMaxRidLength = 255; 1005 1006 void SdpRidAttributeList::Rid::Serialize(std::ostream& os) const { 1007 os << id << " " << direction; 1008 SerializeParameters(os); 1009 } 1010 1011 bool SdpRidAttributeList::Rid::HasFormat(const std::string& format) const { 1012 if (formats.empty()) { 1013 return true; 1014 } 1015 1016 uint16_t formatAsInt; 1017 if (!SdpHelper::GetPtAsInt(format, &formatAsInt)) { 1018 return false; 1019 } 1020 1021 return (std::find(formats.begin(), formats.end(), formatAsInt) != 1022 formats.end()); 1023 } 1024 1025 void SdpRidAttributeList::Serialize(std::ostream& os) const { 1026 for (const Rid& rid : mRids) { 1027 os << "a=" << mType << ":"; 1028 rid.Serialize(os); 1029 os << CRLF; 1030 } 1031 } 1032 1033 // Remove this function. See Bug 1469702 1034 bool SdpRidAttributeList::PushEntry(const std::string& raw, std::string* error, 1035 size_t* errorPos) { 1036 std::istringstream is(raw); 1037 1038 Rid rid; 1039 if (!rid.Parse(is, error)) { 1040 is.clear(); 1041 *errorPos = is.tellg(); 1042 return false; 1043 } 1044 1045 mRids.push_back(rid); 1046 return true; 1047 } 1048 1049 void SdpRidAttributeList::PushEntry(const std::string& id, sdp::Direction dir, 1050 const std::vector<uint16_t>& formats, 1051 const VideoEncodingConstraints& constraints, 1052 const std::vector<std::string>& dependIds) { 1053 SdpRidAttributeList::Rid rid; 1054 1055 rid.id = id; 1056 rid.direction = dir; 1057 rid.formats = formats; 1058 rid.constraints = constraints; 1059 rid.dependIds = dependIds; 1060 1061 mRids.push_back(std::move(rid)); 1062 } 1063 1064 void SdpRtcpAttribute::Serialize(std::ostream& os) const { 1065 os << "a=" << mType << ":" << mPort; 1066 if (!mAddress.empty()) { 1067 os << " " << mNetType << " " << mAddrType << " " << mAddress; 1068 } 1069 os << CRLF; 1070 } 1071 1072 const char* SdpRtcpFbAttributeList::pli = "pli"; 1073 const char* SdpRtcpFbAttributeList::sli = "sli"; 1074 const char* SdpRtcpFbAttributeList::rpsi = "rpsi"; 1075 const char* SdpRtcpFbAttributeList::app = "app"; 1076 1077 const char* SdpRtcpFbAttributeList::fir = "fir"; 1078 const char* SdpRtcpFbAttributeList::tmmbr = "tmmbr"; 1079 const char* SdpRtcpFbAttributeList::tstr = "tstr"; 1080 const char* SdpRtcpFbAttributeList::vbcm = "vbcm"; 1081 1082 void SdpRtcpFbAttributeList::Serialize(std::ostream& os) const { 1083 for (auto i = mFeedbacks.begin(); i != mFeedbacks.end(); ++i) { 1084 os << "a=" << mType << ":" << i->pt << " " << i->type; 1085 if (i->parameter.length()) { 1086 os << " " << i->parameter; 1087 if (i->extra.length()) { 1088 os << " " << i->extra; 1089 } 1090 } 1091 os << CRLF; 1092 } 1093 } 1094 1095 static bool ShouldSerializeChannels(SdpRtpmapAttributeList::CodecType type) { 1096 switch (type) { 1097 case SdpRtpmapAttributeList::kOpus: 1098 case SdpRtpmapAttributeList::kG722: 1099 return true; 1100 case SdpRtpmapAttributeList::kPCMU: 1101 case SdpRtpmapAttributeList::kPCMA: 1102 case SdpRtpmapAttributeList::kVP8: 1103 case SdpRtpmapAttributeList::kVP9: 1104 case SdpRtpmapAttributeList::kiLBC: 1105 case SdpRtpmapAttributeList::kiSAC: 1106 case SdpRtpmapAttributeList::kH264: 1107 case SdpRtpmapAttributeList::kAV1: 1108 case SdpRtpmapAttributeList::kRed: 1109 case SdpRtpmapAttributeList::kUlpfec: 1110 case SdpRtpmapAttributeList::kTelephoneEvent: 1111 case SdpRtpmapAttributeList::kRtx: 1112 return false; 1113 case SdpRtpmapAttributeList::kOtherCodec: 1114 return true; 1115 } 1116 MOZ_CRASH(); 1117 } 1118 1119 void SdpRtpmapAttributeList::Serialize(std::ostream& os) const { 1120 for (auto i = mRtpmaps.begin(); i != mRtpmaps.end(); ++i) { 1121 os << "a=" << mType << ":" << i->pt << " " << i->name << "/" << i->clock; 1122 if (i->channels && ShouldSerializeChannels(i->codec)) { 1123 os << "/" << i->channels; 1124 } 1125 os << CRLF; 1126 } 1127 } 1128 1129 void SdpSctpmapAttributeList::Serialize(std::ostream& os) const { 1130 for (auto i = mSctpmaps.begin(); i != mSctpmaps.end(); ++i) { 1131 os << "a=" << mType << ":" << i->pt << " " << i->name << " " << i->streams 1132 << CRLF; 1133 } 1134 } 1135 1136 void SdpSetupAttribute::Serialize(std::ostream& os) const { 1137 os << "a=" << mType << ":" << mRole << CRLF; 1138 } 1139 1140 void SdpSimulcastAttribute::Version::Serialize(std::ostream& os) const { 1141 SkipFirstDelimiter comma(","); 1142 for (const Encoding& choice : choices) { 1143 os << comma; 1144 if (choice.paused) { 1145 os << '~'; 1146 } 1147 os << choice.rid; 1148 } 1149 } 1150 1151 bool SdpSimulcastAttribute::Version::Parse(std::istream& is, 1152 std::string* error) { 1153 do { 1154 bool paused = SkipChar(is, '~', error); 1155 std::string value = ParseToken(is, ",; ", error); 1156 if (value.empty()) { 1157 *error = "Missing rid"; 1158 return false; 1159 } 1160 if (!SdpRidAttributeList::CheckRidValidity(value, error)) { 1161 return false; 1162 } 1163 choices.push_back(Encoding(value, paused)); 1164 } while (SkipChar(is, ',', error)); 1165 1166 return true; 1167 } 1168 1169 void SdpSimulcastAttribute::Versions::Serialize(std::ostream& os) const { 1170 SkipFirstDelimiter semic(";"); 1171 for (const Version& version : *this) { 1172 if (!version.IsSet()) { 1173 continue; 1174 } 1175 os << semic; 1176 version.Serialize(os); 1177 } 1178 } 1179 1180 bool SdpSimulcastAttribute::Versions::Parse(std::istream& is, 1181 std::string* error) { 1182 do { 1183 Version version; 1184 if (!version.Parse(is, error)) { 1185 return false; 1186 } 1187 push_back(version); 1188 } while (SkipChar(is, ';', error)); 1189 1190 return true; 1191 } 1192 1193 void SdpSimulcastAttribute::Serialize(std::ostream& os) const { 1194 MOZ_ASSERT(sendVersions.IsSet() || recvVersions.IsSet()); 1195 1196 os << "a=" << mType << ":"; 1197 1198 if (sendVersions.IsSet()) { 1199 os << "send "; 1200 sendVersions.Serialize(os); 1201 } 1202 1203 if (recvVersions.IsSet()) { 1204 if (sendVersions.IsSet()) { 1205 os << " "; 1206 } 1207 os << "recv "; 1208 recvVersions.Serialize(os); 1209 } 1210 1211 os << CRLF; 1212 } 1213 1214 bool SdpSimulcastAttribute::Parse(std::istream& is, std::string* error) { 1215 bool gotRecv = false; 1216 bool gotSend = false; 1217 1218 while (true) { 1219 is >> std::ws; 1220 std::string token = ParseToken(is, " \t", error); 1221 if (token.empty()) { 1222 break; 1223 } 1224 1225 if (token == "send") { 1226 if (gotSend) { 1227 *error = "Already got a send list"; 1228 return false; 1229 } 1230 gotSend = true; 1231 1232 is >> std::ws; 1233 if (!sendVersions.Parse(is, error)) { 1234 return false; 1235 } 1236 } else if (token == "recv") { 1237 if (gotRecv) { 1238 *error = "Already got a recv list"; 1239 return false; 1240 } 1241 gotRecv = true; 1242 1243 is >> std::ws; 1244 if (!recvVersions.Parse(is, error)) { 1245 return false; 1246 } 1247 } else { 1248 *error = "Type must be either 'send' or 'recv'"; 1249 return false; 1250 } 1251 } 1252 1253 if (!gotSend && !gotRecv) { 1254 *error = "Empty simulcast attribute"; 1255 return false; 1256 } 1257 1258 return true; 1259 } 1260 1261 void SdpSsrcAttributeList::Serialize(std::ostream& os) const { 1262 for (auto i = mSsrcs.begin(); i != mSsrcs.end(); ++i) { 1263 os << "a=" << mType << ":" << i->ssrc << " " << i->attribute << CRLF; 1264 } 1265 } 1266 1267 void SdpSsrcGroupAttributeList::Serialize(std::ostream& os) const { 1268 for (auto i = mSsrcGroups.begin(); i != mSsrcGroups.end(); ++i) { 1269 os << "a=" << mType << ":" << i->semantics; 1270 for (auto j = i->ssrcs.begin(); j != i->ssrcs.end(); ++j) { 1271 os << " " << (*j); 1272 } 1273 os << CRLF; 1274 } 1275 } 1276 1277 void SdpMultiStringAttribute::Serialize(std::ostream& os) const { 1278 for (auto i = mValues.begin(); i != mValues.end(); ++i) { 1279 os << "a=" << mType << ":" << *i << CRLF; 1280 } 1281 } 1282 1283 void SdpOptionsAttribute::Serialize(std::ostream& os) const { 1284 if (mValues.empty()) { 1285 return; 1286 } 1287 1288 os << "a=" << mType << ":"; 1289 1290 for (auto i = mValues.begin(); i != mValues.end(); ++i) { 1291 if (i != mValues.begin()) { 1292 os << " "; 1293 } 1294 os << *i; 1295 } 1296 os << CRLF; 1297 } 1298 1299 void SdpOptionsAttribute::Load(const std::string& value) { 1300 size_t start = 0; 1301 size_t end = value.find(' '); 1302 while (end != std::string::npos) { 1303 PushEntry(value.substr(start, end)); 1304 start = end + 1; 1305 end = value.find(' ', start); 1306 } 1307 PushEntry(value.substr(start)); 1308 } 1309 1310 void SdpFlagAttribute::Serialize(std::ostream& os) const { 1311 os << "a=" << mType << CRLF; 1312 } 1313 1314 void SdpStringAttribute::Serialize(std::ostream& os) const { 1315 os << "a=" << mType << ":" << mValue << CRLF; 1316 } 1317 1318 void SdpNumberAttribute::Serialize(std::ostream& os) const { 1319 os << "a=" << mType << ":" << mValue << CRLF; 1320 } 1321 1322 bool SdpAttribute::IsAllowedAtMediaLevel(AttributeType type) { 1323 switch (type) { 1324 case kBundleOnlyAttribute: 1325 return true; 1326 case kCandidateAttribute: 1327 return true; 1328 case kConnectionAttribute: 1329 return true; 1330 case kDirectionAttribute: 1331 return true; 1332 case kDtlsMessageAttribute: 1333 return false; 1334 case kEndOfCandidatesAttribute: 1335 return true; 1336 case kExtmapAttribute: 1337 return true; 1338 case kExtmapAllowMixedAttribute: 1339 return true; 1340 case kFingerprintAttribute: 1341 return true; 1342 case kFmtpAttribute: 1343 return true; 1344 case kGroupAttribute: 1345 return false; 1346 case kIceLiteAttribute: 1347 return false; 1348 case kIceMismatchAttribute: 1349 return true; 1350 // RFC 5245 says this is session-level only, but 1351 // draft-ietf-mmusic-ice-sip-sdp-03 updates this to allow at the media 1352 // level. 1353 case kIceOptionsAttribute: 1354 return true; 1355 case kIcePwdAttribute: 1356 return true; 1357 case kIceUfragAttribute: 1358 return true; 1359 case kIdentityAttribute: 1360 return false; 1361 case kImageattrAttribute: 1362 return true; 1363 case kLabelAttribute: 1364 return true; 1365 case kMaxptimeAttribute: 1366 return true; 1367 case kMidAttribute: 1368 return true; 1369 case kMsidAttribute: 1370 return true; 1371 case kMsidSemanticAttribute: 1372 return false; 1373 case kPtimeAttribute: 1374 return true; 1375 case kRemoteCandidatesAttribute: 1376 return true; 1377 case kRidAttribute: 1378 return true; 1379 case kRtcpAttribute: 1380 return true; 1381 case kRtcpFbAttribute: 1382 return true; 1383 case kRtcpMuxAttribute: 1384 return true; 1385 case kRtcpRsizeAttribute: 1386 return true; 1387 case kRtpmapAttribute: 1388 return true; 1389 case kSctpmapAttribute: 1390 return true; 1391 case kSetupAttribute: 1392 return true; 1393 case kSimulcastAttribute: 1394 return true; 1395 case kSsrcAttribute: 1396 return true; 1397 case kSsrcGroupAttribute: 1398 return true; 1399 case kSctpPortAttribute: 1400 return true; 1401 case kMaxMessageSizeAttribute: 1402 return true; 1403 } 1404 MOZ_CRASH("Unknown attribute type"); 1405 } 1406 1407 bool SdpAttribute::IsAllowedAtSessionLevel(AttributeType type) { 1408 switch (type) { 1409 case kBundleOnlyAttribute: 1410 return false; 1411 case kCandidateAttribute: 1412 return false; 1413 case kConnectionAttribute: 1414 return true; 1415 case kDirectionAttribute: 1416 return true; 1417 case kDtlsMessageAttribute: 1418 return true; 1419 case kEndOfCandidatesAttribute: 1420 return true; 1421 case kExtmapAttribute: 1422 return true; 1423 case kExtmapAllowMixedAttribute: 1424 return true; 1425 case kFingerprintAttribute: 1426 return true; 1427 case kFmtpAttribute: 1428 return false; 1429 case kGroupAttribute: 1430 return true; 1431 case kIceLiteAttribute: 1432 return true; 1433 case kIceMismatchAttribute: 1434 return false; 1435 case kIceOptionsAttribute: 1436 return true; 1437 case kIcePwdAttribute: 1438 return true; 1439 case kIceUfragAttribute: 1440 return true; 1441 case kIdentityAttribute: 1442 return true; 1443 case kImageattrAttribute: 1444 return false; 1445 case kLabelAttribute: 1446 return false; 1447 case kMaxptimeAttribute: 1448 return false; 1449 case kMidAttribute: 1450 return false; 1451 case kMsidSemanticAttribute: 1452 return true; 1453 case kMsidAttribute: 1454 return false; 1455 case kPtimeAttribute: 1456 return false; 1457 case kRemoteCandidatesAttribute: 1458 return false; 1459 case kRidAttribute: 1460 return false; 1461 case kRtcpAttribute: 1462 return false; 1463 case kRtcpFbAttribute: 1464 return false; 1465 case kRtcpMuxAttribute: 1466 return false; 1467 case kRtcpRsizeAttribute: 1468 return false; 1469 case kRtpmapAttribute: 1470 return false; 1471 case kSctpmapAttribute: 1472 return false; 1473 case kSetupAttribute: 1474 return true; 1475 case kSimulcastAttribute: 1476 return false; 1477 case kSsrcAttribute: 1478 return false; 1479 case kSsrcGroupAttribute: 1480 return false; 1481 case kSctpPortAttribute: 1482 return false; 1483 case kMaxMessageSizeAttribute: 1484 return false; 1485 } 1486 MOZ_CRASH("Unknown attribute type"); 1487 } 1488 1489 const std::string SdpAttribute::GetAttributeTypeString(AttributeType type) { 1490 switch (type) { 1491 case kBundleOnlyAttribute: 1492 return "bundle-only"; 1493 case kCandidateAttribute: 1494 return "candidate"; 1495 case kConnectionAttribute: 1496 return "connection"; 1497 case kDtlsMessageAttribute: 1498 return "dtls-message"; 1499 case kEndOfCandidatesAttribute: 1500 return "end-of-candidates"; 1501 case kExtmapAttribute: 1502 return "extmap"; 1503 case kExtmapAllowMixedAttribute: 1504 return "extmap-allow-mixed"; 1505 case kFingerprintAttribute: 1506 return "fingerprint"; 1507 case kFmtpAttribute: 1508 return "fmtp"; 1509 case kGroupAttribute: 1510 return "group"; 1511 case kIceLiteAttribute: 1512 return "ice-lite"; 1513 case kIceMismatchAttribute: 1514 return "ice-mismatch"; 1515 case kIceOptionsAttribute: 1516 return "ice-options"; 1517 case kIcePwdAttribute: 1518 return "ice-pwd"; 1519 case kIceUfragAttribute: 1520 return "ice-ufrag"; 1521 case kIdentityAttribute: 1522 return "identity"; 1523 case kImageattrAttribute: 1524 return "imageattr"; 1525 case kLabelAttribute: 1526 return "label"; 1527 case kMaxptimeAttribute: 1528 return "maxptime"; 1529 case kMidAttribute: 1530 return "mid"; 1531 case kMsidAttribute: 1532 return "msid"; 1533 case kMsidSemanticAttribute: 1534 return "msid-semantic"; 1535 case kPtimeAttribute: 1536 return "ptime"; 1537 case kRemoteCandidatesAttribute: 1538 return "remote-candidates"; 1539 case kRidAttribute: 1540 return "rid"; 1541 case kRtcpAttribute: 1542 return "rtcp"; 1543 case kRtcpFbAttribute: 1544 return "rtcp-fb"; 1545 case kRtcpMuxAttribute: 1546 return "rtcp-mux"; 1547 case kRtcpRsizeAttribute: 1548 return "rtcp-rsize"; 1549 case kRtpmapAttribute: 1550 return "rtpmap"; 1551 case kSctpmapAttribute: 1552 return "sctpmap"; 1553 case kSetupAttribute: 1554 return "setup"; 1555 case kSimulcastAttribute: 1556 return "simulcast"; 1557 case kSsrcAttribute: 1558 return "ssrc"; 1559 case kSsrcGroupAttribute: 1560 return "ssrc-group"; 1561 case kSctpPortAttribute: 1562 return "sctp-port"; 1563 case kMaxMessageSizeAttribute: 1564 return "max-message-size"; 1565 case kDirectionAttribute: 1566 MOZ_CRASH("kDirectionAttribute not valid here"); 1567 } 1568 MOZ_CRASH("Unknown attribute type"); 1569 } 1570 1571 } // namespace mozilla