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

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       3             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include "signaling/src/sdp/SdpHelper.h"
       6             : 
       7             : #include "signaling/src/sdp/Sdp.h"
       8             : #include "signaling/src/sdp/SdpMediaSection.h"
       9             : #include "logging.h"
      10             : 
      11             : #include "nsDebug.h"
      12             : #include "nsError.h"
      13             : #include "prprf.h"
      14             : 
      15             : #include <string.h>
      16             : #include <set>
      17             : 
      18             : namespace mozilla {
      19           0 : MOZ_MTLOG_MODULE("sdp")
      20             : 
      21             : #define SDP_SET_ERROR(error)                                                   \
      22             :   do {                                                                         \
      23             :     std::ostringstream os;                                                     \
      24             :     os << error;                                                               \
      25             :     mLastError = os.str();                                                     \
      26             :     MOZ_MTLOG(ML_ERROR, mLastError);                                           \
      27             :   } while (0);
      28             : 
      29             : nsresult
      30           0 : SdpHelper::CopyTransportParams(size_t numComponents,
      31             :                                const SdpMediaSection& oldLocal,
      32             :                                SdpMediaSection* newLocal)
      33             : {
      34             :   // Copy over m-section details
      35           0 :   newLocal->SetPort(oldLocal.GetPort());
      36           0 :   newLocal->GetConnection() = oldLocal.GetConnection();
      37             : 
      38           0 :   const SdpAttributeList& oldLocalAttrs = oldLocal.GetAttributeList();
      39           0 :   SdpAttributeList& newLocalAttrs = newLocal->GetAttributeList();
      40             : 
      41             :   // Now we copy over attributes that won't be added by the usual logic
      42           0 :   if (oldLocalAttrs.HasAttribute(SdpAttribute::kCandidateAttribute) &&
      43             :       numComponents) {
      44             :     UniquePtr<SdpMultiStringAttribute> candidateAttrs(
      45           0 :       new SdpMultiStringAttribute(SdpAttribute::kCandidateAttribute));
      46           0 :     for (const std::string& candidate : oldLocalAttrs.GetCandidate()) {
      47             :       size_t component;
      48           0 :       nsresult rv = GetComponent(candidate, &component);
      49           0 :       NS_ENSURE_SUCCESS(rv, rv);
      50           0 :       if (numComponents >= component) {
      51           0 :         candidateAttrs->mValues.push_back(candidate);
      52             :       }
      53             :     }
      54           0 :     if (candidateAttrs->mValues.size()) {
      55           0 :       newLocalAttrs.SetAttribute(candidateAttrs.release());
      56             :     }
      57             :   }
      58             : 
      59           0 :   if (numComponents == 2 &&
      60           0 :       oldLocalAttrs.HasAttribute(SdpAttribute::kRtcpAttribute)) {
      61             :     // copy rtcp attribute if we had one that we are using
      62           0 :     newLocalAttrs.SetAttribute(new SdpRtcpAttribute(oldLocalAttrs.GetRtcp()));
      63             :   }
      64             : 
      65           0 :   return NS_OK;
      66             : }
      67             : 
      68             : bool
      69           0 : SdpHelper::AreOldTransportParamsValid(const Sdp& oldAnswer,
      70             :                                       const Sdp& offerersPreviousSdp,
      71             :                                       const Sdp& newOffer,
      72             :                                       size_t level)
      73             : {
      74           0 :   if (MsectionIsDisabled(oldAnswer.GetMediaSection(level)) ||
      75           0 :       MsectionIsDisabled(newOffer.GetMediaSection(level))) {
      76             :     // Obvious
      77           0 :     return false;
      78             :   }
      79             : 
      80           0 :   if (IsBundleSlave(oldAnswer, level)) {
      81             :     // The transport attributes on this m-section were thrown away, because it
      82             :     // was bundled.
      83           0 :     return false;
      84             :   }
      85             : 
      86           0 :   if (newOffer.GetMediaSection(level).GetAttributeList().HasAttribute(
      87           0 :         SdpAttribute::kBundleOnlyAttribute) &&
      88           0 :       IsBundleSlave(newOffer, level)) {
      89             :     // It never makes sense to put transport attributes in a bundle-only
      90             :     // m-section
      91           0 :     return false;
      92             :   }
      93             : 
      94           0 :   if (IceCredentialsDiffer(newOffer.GetMediaSection(level),
      95           0 :                            offerersPreviousSdp.GetMediaSection(level))) {
      96           0 :     return false;
      97             :   }
      98             : 
      99           0 :   return true;
     100             : }
     101             : 
     102             : bool
     103           0 : SdpHelper::IceCredentialsDiffer(const SdpMediaSection& msection1,
     104             :                                 const SdpMediaSection& msection2)
     105             : {
     106           0 :   const SdpAttributeList& attrs1(msection1.GetAttributeList());
     107           0 :   const SdpAttributeList& attrs2(msection2.GetAttributeList());
     108             : 
     109           0 :   if ((attrs1.GetIceUfrag() != attrs2.GetIceUfrag()) ||
     110           0 :       (attrs1.GetIcePwd() != attrs2.GetIcePwd())) {
     111           0 :     return true;
     112             :   }
     113             : 
     114           0 :   return false;
     115             : }
     116             : 
     117             : nsresult
     118           0 : SdpHelper::GetComponent(const std::string& candidate, size_t* component)
     119             : {
     120             :   unsigned int temp;
     121           0 :   int32_t result = PR_sscanf(candidate.c_str(), "%*s %u", &temp);
     122           0 :   if (result == 1) {
     123           0 :     *component = temp;
     124           0 :     return NS_OK;
     125             :   }
     126           0 :   SDP_SET_ERROR("Malformed ICE candidate: " << candidate);
     127           0 :   return NS_ERROR_INVALID_ARG;
     128             : }
     129             : 
     130             : bool
     131           0 : SdpHelper::MsectionIsDisabled(const SdpMediaSection& msection) const
     132             : {
     133           0 :   return !msection.GetPort() &&
     134           0 :          !msection.GetAttributeList().HasAttribute(
     135           0 :              SdpAttribute::kBundleOnlyAttribute);
     136             : }
     137             : 
     138             : void
     139           0 : SdpHelper::DisableMsection(Sdp* sdp, SdpMediaSection* msection)
     140             : {
     141             :   // Make sure to remove the mid from any group attributes
     142           0 :   if (msection->GetAttributeList().HasAttribute(SdpAttribute::kMidAttribute)) {
     143           0 :     std::string mid = msection->GetAttributeList().GetMid();
     144           0 :     if (sdp->GetAttributeList().HasAttribute(SdpAttribute::kGroupAttribute)) {
     145             :       UniquePtr<SdpGroupAttributeList> newGroupAttr(new SdpGroupAttributeList(
     146           0 :             sdp->GetAttributeList().GetGroup()));
     147           0 :       newGroupAttr->RemoveMid(mid);
     148           0 :       sdp->GetAttributeList().SetAttribute(newGroupAttr.release());
     149             :     }
     150             :   }
     151             : 
     152             :   // Clear out attributes.
     153           0 :   msection->GetAttributeList().Clear();
     154             : 
     155             :   auto* direction =
     156           0 :     new SdpDirectionAttribute(SdpDirectionAttribute::kInactive);
     157           0 :   msection->GetAttributeList().SetAttribute(direction);
     158           0 :   msection->SetPort(0);
     159             : 
     160           0 :   msection->ClearCodecs();
     161             : 
     162           0 :   auto mediaType = msection->GetMediaType();
     163           0 :   switch (mediaType) {
     164             :     case SdpMediaSection::kAudio:
     165           0 :       msection->AddCodec("0", "PCMU", 8000, 1);
     166           0 :       break;
     167             :     case SdpMediaSection::kVideo:
     168           0 :       msection->AddCodec("120", "VP8", 90000, 1);
     169           0 :       break;
     170             :     case SdpMediaSection::kApplication:
     171           0 :       msection->AddDataChannel("rejected", 0, 0, 0);
     172           0 :       break;
     173             :     default:
     174             :       // We need to have something here to fit the grammar, this seems safe
     175             :       // and 19 is a reserved payload type which should not be used by anyone.
     176           0 :       msection->AddCodec("19", "reserved", 8000, 1);
     177             :   }
     178           0 : }
     179             : 
     180             : void
     181           0 : SdpHelper::GetBundleGroups(
     182             :     const Sdp& sdp,
     183             :     std::vector<SdpGroupAttributeList::Group>* bundleGroups) const
     184             : {
     185           0 :   if (sdp.GetAttributeList().HasAttribute(SdpAttribute::kGroupAttribute)) {
     186           0 :     for (auto& group : sdp.GetAttributeList().GetGroup().mGroups) {
     187           0 :       if (group.semantics == SdpGroupAttributeList::kBundle) {
     188           0 :         bundleGroups->push_back(group);
     189             :       }
     190             :     }
     191             :   }
     192           0 : }
     193             : 
     194             : nsresult
     195           0 : SdpHelper::GetBundledMids(const Sdp& sdp, BundledMids* bundledMids)
     196             : {
     197           0 :   std::vector<SdpGroupAttributeList::Group> bundleGroups;
     198           0 :   GetBundleGroups(sdp, &bundleGroups);
     199             : 
     200           0 :   for (SdpGroupAttributeList::Group& group : bundleGroups) {
     201           0 :     if (group.tags.empty()) {
     202           0 :       SDP_SET_ERROR("Empty BUNDLE group");
     203           0 :       return NS_ERROR_INVALID_ARG;
     204             :     }
     205             : 
     206             :     const SdpMediaSection* masterBundleMsection(
     207           0 :         FindMsectionByMid(sdp, group.tags[0]));
     208             : 
     209           0 :     if (!masterBundleMsection) {
     210           0 :       SDP_SET_ERROR("mid specified for bundle transport in group attribute"
     211             :           " does not exist in the SDP. (mid=" << group.tags[0] << ")");
     212           0 :       return NS_ERROR_INVALID_ARG;
     213             :     }
     214             : 
     215           0 :     if (MsectionIsDisabled(*masterBundleMsection)) {
     216           0 :       SDP_SET_ERROR("mid specified for bundle transport in group attribute"
     217             :           " points at a disabled m-section. (mid=" << group.tags[0] << ")");
     218           0 :       return NS_ERROR_INVALID_ARG;
     219             :     }
     220             : 
     221           0 :     for (const std::string& mid : group.tags) {
     222           0 :       if (bundledMids->count(mid)) {
     223           0 :         SDP_SET_ERROR("mid \'" << mid << "\' appears more than once in a "
     224             :                        "BUNDLE group");
     225           0 :         return NS_ERROR_INVALID_ARG;
     226             :       }
     227             : 
     228           0 :       (*bundledMids)[mid] = masterBundleMsection;
     229             :     }
     230             :   }
     231             : 
     232           0 :   return NS_OK;
     233             : }
     234             : 
     235             : bool
     236           0 : SdpHelper::IsBundleSlave(const Sdp& sdp, uint16_t level)
     237             : {
     238           0 :   auto& msection = sdp.GetMediaSection(level);
     239             : 
     240           0 :   if (!msection.GetAttributeList().HasAttribute(SdpAttribute::kMidAttribute)) {
     241             :     // No mid, definitely no bundle for this m-section
     242           0 :     return false;
     243             :   }
     244           0 :   std::string mid(msection.GetAttributeList().GetMid());
     245             : 
     246           0 :   BundledMids bundledMids;
     247           0 :   nsresult rv = GetBundledMids(sdp, &bundledMids);
     248           0 :   if (NS_FAILED(rv)) {
     249             :     // Should have been caught sooner.
     250           0 :     MOZ_ASSERT(false);
     251             :     return false;
     252             :   }
     253             : 
     254           0 :   if (bundledMids.count(mid) && level != bundledMids[mid]->GetLevel()) {
     255             :     // mid is bundled, and isn't the bundle m-section
     256           0 :     return true;
     257             :   }
     258             : 
     259           0 :   return false;
     260             : }
     261             : 
     262             : nsresult
     263           0 : SdpHelper::GetMidFromLevel(const Sdp& sdp,
     264             :                            uint16_t level,
     265             :                            std::string* mid)
     266             : {
     267           0 :   if (level >= sdp.GetMediaSectionCount()) {
     268           0 :     SDP_SET_ERROR("Index " << level << " out of range");
     269           0 :     return NS_ERROR_INVALID_ARG;
     270             :   }
     271             : 
     272           0 :   const SdpMediaSection& msection = sdp.GetMediaSection(level);
     273           0 :   const SdpAttributeList& attrList = msection.GetAttributeList();
     274             : 
     275             :   // grab the mid and set the outparam
     276           0 :   if (attrList.HasAttribute(SdpAttribute::kMidAttribute)) {
     277           0 :     *mid = attrList.GetMid();
     278             :   }
     279             : 
     280           0 :   return NS_OK;
     281             : }
     282             : 
     283             : nsresult
     284           0 : SdpHelper::AddCandidateToSdp(Sdp* sdp,
     285             :                              const std::string& candidateUntrimmed,
     286             :                              const std::string& mid,
     287             :                              uint16_t level)
     288             : {
     289             : 
     290           0 :   if (level >= sdp->GetMediaSectionCount()) {
     291           0 :     SDP_SET_ERROR("Index " << level << " out of range");
     292           0 :     return NS_ERROR_INVALID_ARG;
     293             :   }
     294             : 
     295             :   // Trim off '[a=]candidate:'
     296           0 :   size_t begin = candidateUntrimmed.find(':');
     297           0 :   if (begin == std::string::npos) {
     298           0 :     SDP_SET_ERROR("Invalid candidate, no ':' (" << candidateUntrimmed << ")");
     299           0 :     return NS_ERROR_INVALID_ARG;
     300             :   }
     301           0 :   ++begin;
     302             : 
     303           0 :   std::string candidate = candidateUntrimmed.substr(begin);
     304             : 
     305             :   // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-11#section-3.4.2.1
     306             :   // Implementations receiving an ICE Candidate object MUST use the MID if
     307             :   // present, or the m= line index, if not (as it could have come from a
     308             :   // non-JSEP endpoint). (bug 1095793)
     309           0 :   SdpMediaSection* msection = 0;
     310           0 :   if (!mid.empty()) {
     311             :     // FindMsectionByMid could return nullptr
     312           0 :     msection = FindMsectionByMid(*sdp, mid);
     313             : 
     314             :     // Check to make sure mid matches what we'd get by
     315             :     // looking up the m= line using the level. (mjf)
     316           0 :     std::string checkMid;
     317           0 :     nsresult rv = GetMidFromLevel(*sdp, level, &checkMid);
     318           0 :     if (NS_FAILED(rv)) {
     319           0 :       return rv;
     320             :     }
     321           0 :     if (mid != checkMid) {
     322           0 :       SDP_SET_ERROR("Mismatch between mid and level - \"" << mid
     323             :                      << "\" is not the mid for level " << level
     324             :                      << "; \"" << checkMid << "\" is");
     325           0 :       return NS_ERROR_INVALID_ARG;
     326             :     }
     327             :   }
     328           0 :   if (!msection) {
     329           0 :     msection = &(sdp->GetMediaSection(level));
     330             :   }
     331             : 
     332           0 :   SdpAttributeList& attrList = msection->GetAttributeList();
     333             : 
     334           0 :   UniquePtr<SdpMultiStringAttribute> candidates;
     335           0 :   if (!attrList.HasAttribute(SdpAttribute::kCandidateAttribute)) {
     336             :     // Create new
     337             :     candidates.reset(
     338           0 :         new SdpMultiStringAttribute(SdpAttribute::kCandidateAttribute));
     339             :   } else {
     340             :     // Copy existing
     341             :     candidates.reset(new SdpMultiStringAttribute(
     342           0 :         *static_cast<const SdpMultiStringAttribute*>(
     343           0 :             attrList.GetAttribute(SdpAttribute::kCandidateAttribute))));
     344             :   }
     345           0 :   candidates->PushEntry(candidate);
     346           0 :   attrList.SetAttribute(candidates.release());
     347             : 
     348           0 :   return NS_OK;
     349             : }
     350             : 
     351             : void
     352           0 : SdpHelper::SetIceGatheringComplete(Sdp* sdp,
     353             :                                    uint16_t level,
     354             :                                    BundledMids bundledMids)
     355             : {
     356           0 :   SdpMediaSection& msection = sdp->GetMediaSection(level);
     357             : 
     358           0 :   if (kSlaveBundle == GetMsectionBundleType(*sdp,
     359             :                                             level,
     360             :                                             bundledMids,
     361             :                                             nullptr)) {
     362           0 :     return; // Slave bundle m-section. Skip.
     363             :   }
     364             : 
     365           0 :   SdpAttributeList& attrs = msection.GetAttributeList();
     366             :   attrs.SetAttribute(
     367           0 :       new SdpFlagAttribute(SdpAttribute::kEndOfCandidatesAttribute));
     368             :   // Remove trickle-ice option
     369           0 :   attrs.RemoveAttribute(SdpAttribute::kIceOptionsAttribute);
     370             : }
     371             : 
     372             : void
     373           0 : SdpHelper::SetDefaultAddresses(const std::string& defaultCandidateAddr,
     374             :                                uint16_t defaultCandidatePort,
     375             :                                const std::string& defaultRtcpCandidateAddr,
     376             :                                uint16_t defaultRtcpCandidatePort,
     377             :                                Sdp* sdp,
     378             :                                uint16_t level,
     379             :                                BundledMids bundledMids)
     380             : {
     381           0 :   SdpMediaSection& msection = sdp->GetMediaSection(level);
     382           0 :   std::string masterMid;
     383             : 
     384           0 :   MsectionBundleType bundleType = GetMsectionBundleType(*sdp,
     385             :                                                         level,
     386             :                                                         bundledMids,
     387           0 :                                                         &masterMid);
     388           0 :   if (kSlaveBundle == bundleType) {
     389           0 :     return; // Slave bundle m-section. Skip.
     390             :   }
     391           0 :   if (kMasterBundle == bundleType) {
     392             :     // Master bundle m-section. Set defaultCandidateAddr and
     393             :     // defaultCandidatePort on all bundled m-sections.
     394           0 :     const SdpMediaSection* masterBundleMsection(bundledMids[masterMid]);
     395           0 :     for (auto i = bundledMids.begin(); i != bundledMids.end(); ++i) {
     396           0 :       if (i->second != masterBundleMsection) {
     397           0 :         continue;
     398             :       }
     399           0 :       SdpMediaSection* bundledMsection = FindMsectionByMid(*sdp, i->first);
     400           0 :       if (!bundledMsection) {
     401           0 :         MOZ_ASSERT(false);
     402             :         continue;
     403             :       }
     404           0 :       SetDefaultAddresses(defaultCandidateAddr,
     405             :                           defaultCandidatePort,
     406             :                           defaultRtcpCandidateAddr,
     407             :                           defaultRtcpCandidatePort,
     408           0 :                           bundledMsection);
     409             :     }
     410             :   }
     411             : 
     412           0 :   SetDefaultAddresses(defaultCandidateAddr,
     413             :                       defaultCandidatePort,
     414             :                       defaultRtcpCandidateAddr,
     415             :                       defaultRtcpCandidatePort,
     416           0 :                       &msection);
     417             : }
     418             : 
     419             : void
     420           0 : SdpHelper::SetDefaultAddresses(const std::string& defaultCandidateAddr,
     421             :                                uint16_t defaultCandidatePort,
     422             :                                const std::string& defaultRtcpCandidateAddr,
     423             :                                uint16_t defaultRtcpCandidatePort,
     424             :                                SdpMediaSection* msection)
     425             : {
     426           0 :   msection->GetConnection().SetAddress(defaultCandidateAddr);
     427           0 :   SdpAttributeList& attrList = msection->GetAttributeList();
     428             : 
     429             :   // only set the port if there is no bundle-only attribute
     430           0 :   if (!attrList.HasAttribute(SdpAttribute::kBundleOnlyAttribute)) {
     431           0 :     msection->SetPort(defaultCandidatePort);
     432             :   }
     433             : 
     434           0 :   if (!defaultRtcpCandidateAddr.empty()) {
     435           0 :     sdp::AddrType ipVersion = sdp::kIPv4;
     436           0 :     if (defaultRtcpCandidateAddr.find(':') != std::string::npos) {
     437           0 :       ipVersion = sdp::kIPv6;
     438             :     }
     439             :     attrList.SetAttribute(new SdpRtcpAttribute(
     440             :           defaultRtcpCandidatePort,
     441             :           sdp::kInternet,
     442             :           ipVersion,
     443           0 :           defaultRtcpCandidateAddr));
     444             :   }
     445           0 : }
     446             : 
     447             : nsresult
     448           0 : SdpHelper::GetIdsFromMsid(const Sdp& sdp,
     449             :                                 const SdpMediaSection& msection,
     450             :                                 std::string* streamId,
     451             :                                 std::string* trackId)
     452             : {
     453           0 :   if (!sdp.GetAttributeList().HasAttribute(
     454             :         SdpAttribute::kMsidSemanticAttribute)) {
     455           0 :     return NS_ERROR_NOT_AVAILABLE;
     456             :   }
     457             : 
     458           0 :   auto& msidSemantics = sdp.GetAttributeList().GetMsidSemantic().mMsidSemantics;
     459           0 :   std::vector<SdpMsidAttributeList::Msid> allMsids;
     460           0 :   nsresult rv = GetMsids(msection, &allMsids);
     461           0 :   NS_ENSURE_SUCCESS(rv, rv);
     462             : 
     463           0 :   bool allMsidsAreWebrtc = false;
     464           0 :   std::set<std::string> webrtcMsids;
     465             : 
     466           0 :   for (auto i = msidSemantics.begin(); i != msidSemantics.end(); ++i) {
     467           0 :     if (i->semantic == "WMS") {
     468           0 :       for (auto j = i->msids.begin(); j != i->msids.end(); ++j) {
     469           0 :         if (*j == "*") {
     470           0 :           allMsidsAreWebrtc = true;
     471             :         } else {
     472           0 :           webrtcMsids.insert(*j);
     473             :         }
     474             :       }
     475           0 :       break;
     476             :     }
     477             :   }
     478             : 
     479           0 :   bool found = false;
     480             : 
     481           0 :   for (auto i = allMsids.begin(); i != allMsids.end(); ++i) {
     482           0 :     if (allMsidsAreWebrtc || webrtcMsids.count(i->identifier)) {
     483           0 :       if (i->appdata.empty()) {
     484           0 :         SDP_SET_ERROR("Invalid webrtc msid at level " << msection.GetLevel()
     485             :                        << ": Missing track id.");
     486           0 :         return NS_ERROR_INVALID_ARG;
     487             :       }
     488           0 :       if (!found) {
     489           0 :         *streamId = i->identifier;
     490           0 :         *trackId = i->appdata;
     491           0 :         found = true;
     492           0 :       } else if ((*streamId != i->identifier) || (*trackId != i->appdata)) {
     493           0 :         MOZ_MTLOG(ML_WARNING, "Found multiple different webrtc msids in "
     494             :                        "m-section " << msection.GetLevel() << ". The "
     495             :                        "behavior w/o transceivers is undefined.");
     496             :       }
     497             :     }
     498             :   }
     499             : 
     500           0 :   if (!found) {
     501           0 :     return NS_ERROR_NOT_AVAILABLE;
     502             :   }
     503             : 
     504           0 :   return NS_OK;
     505             : }
     506             : 
     507             : nsresult
     508           0 : SdpHelper::GetMsids(const SdpMediaSection& msection,
     509             :                     std::vector<SdpMsidAttributeList::Msid>* msids)
     510             : {
     511           0 :   if (msection.GetAttributeList().HasAttribute(SdpAttribute::kMsidAttribute)) {
     512           0 :     *msids = msection.GetAttributeList().GetMsid().mMsids;
     513             :   }
     514             : 
     515             :   // Can we find some additional msids in ssrc attributes?
     516             :   // (Chrome does not put plain-old msid attributes in its SDP)
     517           0 :   if (msection.GetAttributeList().HasAttribute(SdpAttribute::kSsrcAttribute)) {
     518           0 :     auto& ssrcs = msection.GetAttributeList().GetSsrc().mSsrcs;
     519             : 
     520           0 :     for (auto i = ssrcs.begin(); i != ssrcs.end(); ++i) {
     521           0 :       if (i->attribute.find("msid:") == 0) {
     522           0 :         std::string streamId;
     523           0 :         std::string trackId;
     524           0 :         nsresult rv = ParseMsid(i->attribute, &streamId, &trackId);
     525           0 :         NS_ENSURE_SUCCESS(rv, rv);
     526           0 :         msids->push_back({streamId, trackId});
     527             :       }
     528             :     }
     529             :   }
     530             : 
     531           0 :   return NS_OK;
     532             : }
     533             : 
     534             : nsresult
     535           0 : SdpHelper::ParseMsid(const std::string& msidAttribute,
     536             :                      std::string* streamId,
     537             :                      std::string* trackId)
     538             : {
     539             :   // Would be nice if SdpSsrcAttributeList could parse out the contained
     540             :   // attribute, but at least the parse here is simple.
     541             :   // We are being very forgiving here wrt whitespace; tabs are not actually
     542             :   // allowed, nor is leading/trailing whitespace.
     543           0 :   size_t streamIdStart = msidAttribute.find_first_not_of(" \t", 5);
     544             :   // We do not assume the appdata token is here, since this is not
     545             :   // necessarily a webrtc msid
     546           0 :   if (streamIdStart == std::string::npos) {
     547           0 :     SDP_SET_ERROR("Malformed source-level msid attribute: "
     548             :         << msidAttribute);
     549           0 :     return NS_ERROR_INVALID_ARG;
     550             :   }
     551             : 
     552           0 :   size_t streamIdEnd = msidAttribute.find_first_of(" \t", streamIdStart);
     553           0 :   if (streamIdEnd == std::string::npos) {
     554           0 :     streamIdEnd = msidAttribute.size();
     555             :   }
     556             : 
     557             :   size_t trackIdStart =
     558           0 :     msidAttribute.find_first_not_of(" \t", streamIdEnd);
     559           0 :   if (trackIdStart == std::string::npos) {
     560           0 :     trackIdStart = msidAttribute.size();
     561             :   }
     562             : 
     563           0 :   size_t trackIdEnd = msidAttribute.find_first_of(" \t", trackIdStart);
     564           0 :   if (trackIdEnd == std::string::npos) {
     565           0 :     trackIdEnd = msidAttribute.size();
     566             :   }
     567             : 
     568           0 :   size_t streamIdSize = streamIdEnd - streamIdStart;
     569           0 :   size_t trackIdSize = trackIdEnd - trackIdStart;
     570             : 
     571           0 :   *streamId = msidAttribute.substr(streamIdStart, streamIdSize);
     572           0 :   *trackId = msidAttribute.substr(trackIdStart, trackIdSize);
     573           0 :   return NS_OK;
     574             : }
     575             : 
     576             : void
     577           0 : SdpHelper::SetupMsidSemantic(const std::vector<std::string>& msids,
     578             :                              Sdp* sdp) const
     579             : {
     580           0 :   if (!msids.empty()) {
     581             :     UniquePtr<SdpMsidSemanticAttributeList> msidSemantics(
     582           0 :         new SdpMsidSemanticAttributeList);
     583           0 :     msidSemantics->PushEntry("WMS", msids);
     584           0 :     sdp->GetAttributeList().SetAttribute(msidSemantics.release());
     585             :   }
     586           0 : }
     587             : 
     588             : std::string
     589           0 : SdpHelper::GetCNAME(const SdpMediaSection& msection) const
     590             : {
     591           0 :   if (msection.GetAttributeList().HasAttribute(SdpAttribute::kSsrcAttribute)) {
     592           0 :     auto& ssrcs = msection.GetAttributeList().GetSsrc().mSsrcs;
     593           0 :     for (auto i = ssrcs.begin(); i != ssrcs.end(); ++i) {
     594           0 :       if (i->attribute.find("cname:") == 0) {
     595           0 :         return i->attribute.substr(6);
     596             :       }
     597             :     }
     598             :   }
     599           0 :   return "";
     600             : }
     601             : 
     602             : const SdpMediaSection*
     603           0 : SdpHelper::FindMsectionByMid(const Sdp& sdp,
     604             :                              const std::string& mid) const
     605             : {
     606           0 :   for (size_t i = 0; i < sdp.GetMediaSectionCount(); ++i) {
     607           0 :     auto& attrs = sdp.GetMediaSection(i).GetAttributeList();
     608           0 :     if (attrs.HasAttribute(SdpAttribute::kMidAttribute) &&
     609           0 :         attrs.GetMid() == mid) {
     610           0 :       return &sdp.GetMediaSection(i);
     611             :     }
     612             :   }
     613           0 :   return nullptr;
     614             : }
     615             : 
     616             : SdpMediaSection*
     617           0 : SdpHelper::FindMsectionByMid(Sdp& sdp,
     618             :                              const std::string& mid) const
     619             : {
     620           0 :   for (size_t i = 0; i < sdp.GetMediaSectionCount(); ++i) {
     621           0 :     auto& attrs = sdp.GetMediaSection(i).GetAttributeList();
     622           0 :     if (attrs.HasAttribute(SdpAttribute::kMidAttribute) &&
     623           0 :         attrs.GetMid() == mid) {
     624           0 :       return &sdp.GetMediaSection(i);
     625             :     }
     626             :   }
     627           0 :   return nullptr;
     628             : }
     629             : 
     630             : nsresult
     631           0 : SdpHelper::CopyStickyParams(const SdpMediaSection& source,
     632             :                             SdpMediaSection* dest)
     633             : {
     634           0 :   auto& sourceAttrs = source.GetAttributeList();
     635           0 :   auto& destAttrs = dest->GetAttributeList();
     636             : 
     637             :   // There's no reason to renegotiate rtcp-mux
     638           0 :   if (sourceAttrs.HasAttribute(SdpAttribute::kRtcpMuxAttribute)) {
     639             :     destAttrs.SetAttribute(
     640           0 :         new SdpFlagAttribute(SdpAttribute::kRtcpMuxAttribute));
     641             :   }
     642             : 
     643             :   // mid should stay the same
     644           0 :   if (sourceAttrs.HasAttribute(SdpAttribute::kMidAttribute)) {
     645           0 :     destAttrs.SetAttribute(
     646             :         new SdpStringAttribute(SdpAttribute::kMidAttribute,
     647           0 :           sourceAttrs.GetMid()));
     648             :   }
     649             : 
     650           0 :   return NS_OK;
     651             : }
     652             : 
     653             : bool
     654           0 : SdpHelper::HasRtcp(SdpMediaSection::Protocol proto) const
     655             : {
     656           0 :   switch (proto) {
     657             :     case SdpMediaSection::kRtpAvpf:
     658             :     case SdpMediaSection::kDccpRtpAvpf:
     659             :     case SdpMediaSection::kDccpRtpSavpf:
     660             :     case SdpMediaSection::kRtpSavpf:
     661             :     case SdpMediaSection::kUdpTlsRtpSavpf:
     662             :     case SdpMediaSection::kTcpTlsRtpSavpf:
     663             :     case SdpMediaSection::kDccpTlsRtpSavpf:
     664           0 :       return true;
     665             :     case SdpMediaSection::kRtpAvp:
     666             :     case SdpMediaSection::kUdp:
     667             :     case SdpMediaSection::kVat:
     668             :     case SdpMediaSection::kRtp:
     669             :     case SdpMediaSection::kUdptl:
     670             :     case SdpMediaSection::kTcp:
     671             :     case SdpMediaSection::kTcpRtpAvp:
     672             :     case SdpMediaSection::kRtpSavp:
     673             :     case SdpMediaSection::kTcpBfcp:
     674             :     case SdpMediaSection::kTcpTlsBfcp:
     675             :     case SdpMediaSection::kTcpTls:
     676             :     case SdpMediaSection::kFluteUdp:
     677             :     case SdpMediaSection::kTcpMsrp:
     678             :     case SdpMediaSection::kTcpTlsMsrp:
     679             :     case SdpMediaSection::kDccp:
     680             :     case SdpMediaSection::kDccpRtpAvp:
     681             :     case SdpMediaSection::kDccpRtpSavp:
     682             :     case SdpMediaSection::kUdpTlsRtpSavp:
     683             :     case SdpMediaSection::kTcpTlsRtpSavp:
     684             :     case SdpMediaSection::kDccpTlsRtpSavp:
     685             :     case SdpMediaSection::kUdpMbmsFecRtpAvp:
     686             :     case SdpMediaSection::kUdpMbmsFecRtpSavp:
     687             :     case SdpMediaSection::kUdpMbmsRepair:
     688             :     case SdpMediaSection::kFecUdp:
     689             :     case SdpMediaSection::kUdpFec:
     690             :     case SdpMediaSection::kTcpMrcpv2:
     691             :     case SdpMediaSection::kTcpTlsMrcpv2:
     692             :     case SdpMediaSection::kPstn:
     693             :     case SdpMediaSection::kUdpTlsUdptl:
     694             :     case SdpMediaSection::kSctp:
     695             :     case SdpMediaSection::kDtlsSctp:
     696             :     case SdpMediaSection::kUdpDtlsSctp:
     697             :     case SdpMediaSection::kTcpDtlsSctp:
     698           0 :       return false;
     699             :   }
     700           0 :   MOZ_CRASH("Unknown protocol, probably corruption.");
     701             : }
     702             : 
     703             : SdpMediaSection::Protocol
     704           0 : SdpHelper::GetProtocolForMediaType(SdpMediaSection::MediaType type)
     705             : {
     706           0 :   if (type == SdpMediaSection::kApplication) {
     707           0 :     return SdpMediaSection::kDtlsSctp;
     708             :     // TODO switch to offer the new SCTP SDP (Bug 1335206)
     709             :     //return SdpMediaSection::kUdpDtlsSctp;
     710             :   }
     711             : 
     712           0 :   return SdpMediaSection::kUdpTlsRtpSavpf;
     713             : }
     714             : 
     715             : void
     716           0 : SdpHelper::appendSdpParseErrors(
     717             :     const std::vector<std::pair<size_t, std::string> >& aErrors,
     718             :     std::string* aErrorString)
     719             : {
     720           0 :   std::ostringstream os;
     721           0 :   for (auto i = aErrors.begin(); i != aErrors.end(); ++i) {
     722           0 :     os << "SDP Parse Error on line " << i->first << ": " + i->second
     723           0 :        << std::endl;
     724             :   }
     725           0 :   *aErrorString += os.str();
     726           0 : }
     727             : 
     728             : /* static */ bool
     729           0 : SdpHelper::GetPtAsInt(const std::string& ptString, uint16_t* ptOutparam)
     730             : {
     731             :   char* end;
     732           0 :   unsigned long pt = strtoul(ptString.c_str(), &end, 10);
     733           0 :   size_t length = static_cast<size_t>(end - ptString.c_str());
     734           0 :   if ((pt > UINT16_MAX) || (length != ptString.size())) {
     735           0 :     return false;
     736             :   }
     737           0 :   *ptOutparam = pt;
     738           0 :   return true;
     739             : }
     740             : 
     741             : void
     742           0 : SdpHelper::AddCommonExtmaps(
     743             :     const SdpMediaSection& remoteMsection,
     744             :     const std::vector<SdpExtmapAttributeList::Extmap>& localExtensions,
     745             :     SdpMediaSection* localMsection)
     746             : {
     747           0 :   if (!remoteMsection.GetAttributeList().HasAttribute(
     748             :         SdpAttribute::kExtmapAttribute)) {
     749           0 :     return;
     750             :   }
     751             : 
     752           0 :   UniquePtr<SdpExtmapAttributeList> localExtmap(new SdpExtmapAttributeList);
     753           0 :   auto& theirExtmap = remoteMsection.GetAttributeList().GetExtmap().mExtmaps;
     754           0 :   for (const auto& theirExt : theirExtmap) {
     755           0 :     for (const auto& ourExt : localExtensions) {
     756           0 :       if (theirExt.extensionname != ourExt.extensionname) {
     757           0 :         continue;
     758             :       }
     759             : 
     760           0 :       auto negotiatedExt = theirExt;
     761             : 
     762           0 :       negotiatedExt.direction =
     763           0 :         reverse(negotiatedExt.direction) & ourExt.direction;
     764           0 :       if (negotiatedExt.direction ==
     765             :             SdpDirectionAttribute::Direction::kInactive) {
     766           0 :         continue;
     767             :       }
     768             : 
     769             :       // RFC 5285 says that ids >= 4096 can be used by the offerer to
     770             :       // force the answerer to pick, otherwise the value in the offer is
     771             :       // used.
     772           0 :       if (negotiatedExt.entry >= 4096) {
     773           0 :         negotiatedExt.entry = ourExt.entry;
     774             :       }
     775             : 
     776           0 :       localExtmap->mExtmaps.push_back(negotiatedExt);
     777             :     }
     778             :   }
     779             : 
     780           0 :   if (!localExtmap->mExtmaps.empty()) {
     781           0 :     localMsection->GetAttributeList().SetAttribute(localExtmap.release());
     782             :   }
     783             : }
     784             : 
     785             : SdpHelper::MsectionBundleType
     786           0 : SdpHelper::GetMsectionBundleType(const Sdp& sdp,
     787             :                                  uint16_t level,
     788             :                                  BundledMids& bundledMids,
     789             :                                  std::string* masterMid) const
     790             : {
     791           0 :   const SdpMediaSection& msection = sdp.GetMediaSection(level);
     792           0 :   if (msection.GetAttributeList().HasAttribute(SdpAttribute::kMidAttribute)) {
     793           0 :     std::string mid(msection.GetAttributeList().GetMid());
     794           0 :     if (bundledMids.count(mid)) {
     795           0 :       const SdpMediaSection* masterBundleMsection(bundledMids[mid]);
     796           0 :       if (msection.GetLevel() != masterBundleMsection->GetLevel()) {
     797           0 :         return kSlaveBundle;
     798             :       }
     799             : 
     800             :       // allow the caller not to care about the masterMid
     801           0 :       if (masterMid) {
     802           0 :         *masterMid = mid;
     803             :       }
     804           0 :       return kMasterBundle;
     805             :     }
     806             :   }
     807           0 :   return kNoBundle;
     808             : }
     809             : 
     810             : } // namespace mozilla
     811             : 
     812             : 

Generated by: LCOV version 1.13