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