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