LCOV - code coverage report
Current view: top level - media/webrtc/signaling/src/sdp - SdpAttribute.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 860 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 82 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13