LCOV - code coverage report
Current view: top level - media/webrtc/signaling/src/sdp - SipccSdpMediaSection.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 236 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 21 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/SipccSdpMediaSection.h"
       8             : 
       9             : #include <ostream>
      10             : #include "signaling/src/sdp/SdpErrorHolder.h"
      11             : 
      12             : #ifdef CRLF
      13             : #undef CRLF
      14             : #endif
      15             : #define CRLF "\r\n"
      16             : 
      17             : namespace mozilla
      18             : {
      19             : 
      20             : unsigned int
      21           0 : SipccSdpMediaSection::GetPort() const
      22             : {
      23           0 :   return mPort;
      24             : }
      25             : 
      26             : void
      27           0 : SipccSdpMediaSection::SetPort(unsigned int port)
      28             : {
      29           0 :   mPort = port;
      30           0 : }
      31             : 
      32             : unsigned int
      33           0 : SipccSdpMediaSection::GetPortCount() const
      34             : {
      35           0 :   return mPortCount;
      36             : }
      37             : 
      38             : SdpMediaSection::Protocol
      39           0 : SipccSdpMediaSection::GetProtocol() const
      40             : {
      41           0 :   return mProtocol;
      42             : }
      43             : 
      44             : const SdpConnection&
      45           0 : SipccSdpMediaSection::GetConnection() const
      46             : {
      47           0 :   return *mConnection;
      48             : }
      49             : 
      50             : SdpConnection&
      51           0 : SipccSdpMediaSection::GetConnection()
      52             : {
      53           0 :   return *mConnection;
      54             : }
      55             : 
      56             : uint32_t
      57           0 : SipccSdpMediaSection::GetBandwidth(const std::string& type) const
      58             : {
      59           0 :   auto found = mBandwidths.find(type);
      60           0 :   if (found == mBandwidths.end()) {
      61           0 :     return 0;
      62             :   }
      63           0 :   return found->second;
      64             : }
      65             : 
      66             : const std::vector<std::string>&
      67           0 : SipccSdpMediaSection::GetFormats() const
      68             : {
      69           0 :   return mFormats;
      70             : }
      71             : 
      72             : const SdpAttributeList&
      73           0 : SipccSdpMediaSection::GetAttributeList() const
      74             : {
      75           0 :   return mAttributeList;
      76             : }
      77             : 
      78             : SdpAttributeList&
      79           0 : SipccSdpMediaSection::GetAttributeList()
      80             : {
      81           0 :   return mAttributeList;
      82             : }
      83             : 
      84             : SdpDirectionAttribute
      85           0 : SipccSdpMediaSection::GetDirectionAttribute() const
      86             : {
      87           0 :   return SdpDirectionAttribute(mAttributeList.GetDirection());
      88             : }
      89             : 
      90             : bool
      91           0 : SipccSdpMediaSection::Load(sdp_t* sdp, uint16_t level,
      92             :                            SdpErrorHolder& errorHolder)
      93             : {
      94           0 :   switch (sdp_get_media_type(sdp, level)) {
      95             :     case SDP_MEDIA_AUDIO:
      96           0 :       mMediaType = kAudio;
      97           0 :       break;
      98             :     case SDP_MEDIA_VIDEO:
      99           0 :       mMediaType = kVideo;
     100           0 :       break;
     101             :     case SDP_MEDIA_APPLICATION:
     102           0 :       mMediaType = kApplication;
     103           0 :       break;
     104             :     case SDP_MEDIA_TEXT:
     105           0 :       mMediaType = kText;
     106           0 :       break;
     107             : 
     108             :     default:
     109           0 :       errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
     110           0 :                                 "Unsupported media section type");
     111           0 :       return false;
     112             :   }
     113             : 
     114           0 :   mPort = sdp_get_media_portnum(sdp, level);
     115           0 :   int32_t pc = sdp_get_media_portcount(sdp, level);
     116           0 :   if (pc == SDP_INVALID_VALUE) {
     117             :     // SDP_INVALID_VALUE (ie; -2) is used when there is no port count. :(
     118           0 :     mPortCount = 0;
     119           0 :   } else if (pc > static_cast<int32_t>(UINT16_MAX) || pc < 0) {
     120           0 :     errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
     121           0 :                               "Invalid port count");
     122           0 :     return false;
     123             :   } else {
     124           0 :     mPortCount = pc;
     125             :   }
     126             : 
     127           0 :   if (!LoadProtocol(sdp, level, errorHolder)) {
     128           0 :     return false;
     129             :   }
     130             : 
     131           0 :   if (!LoadFormats(sdp, level, errorHolder)) {
     132           0 :     return false;
     133             :   }
     134             : 
     135           0 :   if (!mAttributeList.Load(sdp, level, errorHolder)) {
     136           0 :     return false;
     137             :   }
     138             : 
     139           0 :   if (!ValidateSimulcast(sdp, level, errorHolder)) {
     140           0 :     return false;
     141             :   }
     142             : 
     143           0 :   if (!mBandwidths.Load(sdp, level, errorHolder)) {
     144           0 :     return false;
     145             :   }
     146             : 
     147           0 :   return LoadConnection(sdp, level, errorHolder);
     148             : }
     149             : 
     150             : bool
     151           0 : SipccSdpMediaSection::LoadProtocol(sdp_t* sdp, uint16_t level,
     152             :                                    SdpErrorHolder& errorHolder)
     153             : {
     154           0 :   switch (sdp_get_media_transport(sdp, level)) {
     155             :     case SDP_TRANSPORT_RTPAVP:
     156           0 :       mProtocol = kRtpAvp;
     157           0 :       break;
     158             :     case SDP_TRANSPORT_RTPSAVP:
     159           0 :       mProtocol = kRtpSavp;
     160           0 :       break;
     161             :     case SDP_TRANSPORT_RTPAVPF:
     162           0 :       mProtocol = kRtpAvpf;
     163           0 :       break;
     164             :     case SDP_TRANSPORT_RTPSAVPF:
     165           0 :       mProtocol = kRtpSavpf;
     166           0 :       break;
     167             :     case SDP_TRANSPORT_UDPTLSRTPSAVP:
     168           0 :       mProtocol = kUdpTlsRtpSavp;
     169           0 :       break;
     170             :     case SDP_TRANSPORT_UDPTLSRTPSAVPF:
     171           0 :       mProtocol = kUdpTlsRtpSavpf;
     172           0 :       break;
     173             :     case SDP_TRANSPORT_TCPTLSRTPSAVP:
     174           0 :       mProtocol = kTcpTlsRtpSavp;
     175           0 :       break;
     176             :     case SDP_TRANSPORT_TCPTLSRTPSAVPF:
     177           0 :       mProtocol = kTcpTlsRtpSavpf;
     178           0 :       break;
     179             :     case SDP_TRANSPORT_DTLSSCTP:
     180           0 :       mProtocol = kDtlsSctp;
     181           0 :       break;
     182             :     case SDP_TRANSPORT_UDPDTLSSCTP:
     183           0 :       mProtocol = kUdpDtlsSctp;
     184           0 :       break;
     185             :     case SDP_TRANSPORT_TCPDTLSSCTP:
     186           0 :       mProtocol = kTcpDtlsSctp;
     187           0 :       break;
     188             : 
     189             :     default:
     190           0 :       errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
     191           0 :                                 "Unsupported media transport type");
     192           0 :       return false;
     193             :   }
     194           0 :   return true;
     195             : }
     196             : 
     197             : bool
     198           0 : SipccSdpMediaSection::LoadFormats(sdp_t* sdp,
     199             :                                   uint16_t level,
     200             :                                   SdpErrorHolder& errorHolder)
     201             : {
     202           0 :   sdp_media_e mtype = sdp_get_media_type(sdp, level);
     203             : 
     204           0 :   if (mtype == SDP_MEDIA_APPLICATION) {
     205           0 :     sdp_transport_e ttype = sdp_get_media_transport(sdp, level);
     206           0 :     if ((ttype == SDP_TRANSPORT_UDPDTLSSCTP) ||
     207             :         (ttype == SDP_TRANSPORT_TCPDTLSSCTP)) {
     208           0 :       if (sdp_get_media_sctp_fmt(sdp, level) ==
     209             :             SDP_SCTP_MEDIA_FMT_WEBRTC_DATACHANNEL) {
     210           0 :         mFormats.push_back("webrtc-datachannel");
     211             :       }
     212             :     } else {
     213           0 :       uint32_t ptype = sdp_get_media_sctp_port(sdp, level);
     214           0 :       std::ostringstream osPayloadType;
     215           0 :       osPayloadType << ptype;
     216           0 :       mFormats.push_back(osPayloadType.str());
     217             :     }
     218           0 :   } else if (mtype == SDP_MEDIA_AUDIO || mtype == SDP_MEDIA_VIDEO) {
     219           0 :     uint16_t count = sdp_get_media_num_payload_types(sdp, level);
     220           0 :     for (uint16_t i = 0; i < count; ++i) {
     221             :       sdp_payload_ind_e indicator; // we ignore this, which is fine
     222             :       uint32_t ptype =
     223           0 :           sdp_get_media_payload_type(sdp, level, i + 1, &indicator);
     224             : 
     225           0 :       if (GET_DYN_PAYLOAD_TYPE_VALUE(ptype) > UINT8_MAX) {
     226           0 :         errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
     227           0 :                                   "Format is too large");
     228           0 :         return false;
     229             :       }
     230             : 
     231           0 :       std::ostringstream osPayloadType;
     232             :       // sipcc stores payload types in a funny way. When sipcc and the SDP it
     233             :       // parsed differ on what payload type number should be used for a given
     234             :       // codec, sipcc's value goes in the lower byte, and the SDP's value in
     235             :       // the upper byte. When they do not differ, only the lower byte is used.
     236             :       // We want what was in the SDP, verbatim.
     237           0 :       osPayloadType << GET_DYN_PAYLOAD_TYPE_VALUE(ptype);
     238           0 :       mFormats.push_back(osPayloadType.str());
     239             :     }
     240             :   }
     241             : 
     242           0 :   return true;
     243             : }
     244             : 
     245             : bool
     246           0 : SipccSdpMediaSection::ValidateSimulcast(sdp_t* sdp, uint16_t level,
     247             :                                         SdpErrorHolder& errorHolder) const
     248             : {
     249           0 :   if (!GetAttributeList().HasAttribute(SdpAttribute::kSimulcastAttribute)) {
     250           0 :     return true;
     251             :   }
     252             : 
     253           0 :   const SdpSimulcastAttribute& simulcast(GetAttributeList().GetSimulcast());
     254           0 :   if (!ValidateSimulcastVersions(
     255             :         sdp, level, simulcast.sendVersions, sdp::kSend, errorHolder)) {
     256           0 :     return false;
     257             :   }
     258           0 :   if (!ValidateSimulcastVersions(
     259             :         sdp, level, simulcast.recvVersions, sdp::kRecv, errorHolder)) {
     260           0 :     return false;
     261             :   }
     262           0 :   return true;
     263             : }
     264             : 
     265             : bool
     266           0 : SipccSdpMediaSection::ValidateSimulcastVersions(
     267             :     sdp_t* sdp,
     268             :     uint16_t level,
     269             :     const SdpSimulcastAttribute::Versions& versions,
     270             :     sdp::Direction direction,
     271             :     SdpErrorHolder& errorHolder) const
     272             : {
     273           0 :   if (versions.IsSet() && !(direction & GetDirectionAttribute().mValue)) {
     274           0 :     errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
     275             :                               "simulcast attribute has a direction that is "
     276             :                               "inconsistent with the direction of this media "
     277           0 :                               "section.");
     278           0 :     return false;
     279             :   }
     280             : 
     281           0 :   for (const SdpSimulcastAttribute::Version& version : versions) {
     282           0 :     for (const std::string& id : version.choices) {
     283           0 :       if (versions.type == SdpSimulcastAttribute::Versions::kRid) {
     284           0 :         const SdpRidAttributeList::Rid* ridAttr = FindRid(id);
     285           0 :         if (!ridAttr || (ridAttr->direction != direction)) {
     286           0 :           std::ostringstream os;
     287           0 :           os << "No rid attribute for \'" << id << "\'";
     288           0 :           errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
     289           0 :                                     os.str());
     290           0 :           return false;
     291             :         }
     292           0 :       } else if (versions.type == SdpSimulcastAttribute::Versions::kPt) {
     293           0 :         if (std::find(mFormats.begin(), mFormats.end(), id)
     294           0 :             == mFormats.end()) {
     295           0 :           std::ostringstream os;
     296           0 :           os << "No pt for \'" << id << "\'";
     297           0 :           errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
     298           0 :                                     os.str());
     299           0 :           return false;
     300             :         }
     301             :       }
     302             :     }
     303             :   }
     304           0 :   return true;
     305             : }
     306             : 
     307             : bool
     308           0 : SipccSdpMediaSection::LoadConnection(sdp_t* sdp, uint16_t level,
     309             :                                      SdpErrorHolder& errorHolder)
     310             : {
     311           0 :   if (!sdp_connection_valid(sdp, level)) {
     312           0 :     level = SDP_SESSION_LEVEL;
     313           0 :     if (!sdp_connection_valid(sdp, level)) {
     314           0 :       errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
     315           0 :                                 "Missing c= line");
     316           0 :       return false;
     317             :     }
     318             :   }
     319             : 
     320           0 :   sdp_nettype_e type = sdp_get_conn_nettype(sdp, level);
     321           0 :   if (type != SDP_NT_INTERNET) {
     322           0 :     errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
     323           0 :                               "Unsupported network type");
     324           0 :     return false;
     325             :   }
     326             : 
     327             :   sdp::AddrType addrType;
     328           0 :   switch (sdp_get_conn_addrtype(sdp, level)) {
     329             :     case SDP_AT_IP4:
     330           0 :       addrType = sdp::kIPv4;
     331           0 :       break;
     332             :     case SDP_AT_IP6:
     333           0 :       addrType = sdp::kIPv6;
     334           0 :       break;
     335             :     default:
     336           0 :       errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
     337           0 :                                 "Unsupported address type");
     338           0 :       return false;
     339             :   }
     340             : 
     341           0 :   std::string address = sdp_get_conn_address(sdp, level);
     342           0 :   int16_t ttl = static_cast<uint16_t>(sdp_get_mcast_ttl(sdp, level));
     343           0 :   if (ttl < 0) {
     344           0 :     ttl = 0;
     345             :   }
     346             :   int32_t numAddr =
     347           0 :       static_cast<uint32_t>(sdp_get_mcast_num_of_addresses(sdp, level));
     348           0 :   if (numAddr < 0) {
     349           0 :     numAddr = 0;
     350             :   }
     351           0 :   mConnection = MakeUnique<SdpConnection>(addrType, address, ttl, numAddr);
     352           0 :   return true;
     353             : }
     354             : 
     355             : void
     356           0 : SipccSdpMediaSection::AddCodec(const std::string& pt, const std::string& name,
     357             :                                uint32_t clockrate, uint16_t channels)
     358             : {
     359           0 :   mFormats.push_back(pt);
     360             : 
     361           0 :   SdpRtpmapAttributeList* rtpmap = new SdpRtpmapAttributeList();
     362           0 :   if (mAttributeList.HasAttribute(SdpAttribute::kRtpmapAttribute)) {
     363           0 :     const SdpRtpmapAttributeList& old = mAttributeList.GetRtpmap();
     364           0 :     for (auto it = old.mRtpmaps.begin(); it != old.mRtpmaps.end(); ++it) {
     365           0 :       rtpmap->mRtpmaps.push_back(*it);
     366             :     }
     367             :   }
     368           0 :   SdpRtpmapAttributeList::CodecType codec = SdpRtpmapAttributeList::kOtherCodec;
     369           0 :   if (name == "opus") {
     370           0 :     codec = SdpRtpmapAttributeList::kOpus;
     371           0 :   } else if (name == "G722") {
     372           0 :     codec = SdpRtpmapAttributeList::kG722;
     373           0 :   } else if (name == "PCMU") {
     374           0 :     codec = SdpRtpmapAttributeList::kPCMU;
     375           0 :   } else if (name == "PCMA") {
     376           0 :     codec = SdpRtpmapAttributeList::kPCMA;
     377           0 :   } else if (name == "VP8") {
     378           0 :     codec = SdpRtpmapAttributeList::kVP8;
     379           0 :   } else if (name == "VP9") {
     380           0 :     codec = SdpRtpmapAttributeList::kVP9;
     381           0 :   } else if (name == "H264") {
     382           0 :     codec = SdpRtpmapAttributeList::kH264;
     383             :   }
     384             : 
     385           0 :   rtpmap->PushEntry(pt, codec, name, clockrate, channels);
     386           0 :   mAttributeList.SetAttribute(rtpmap);
     387           0 : }
     388             : 
     389             : void
     390           0 : SipccSdpMediaSection::ClearCodecs()
     391             : {
     392           0 :   mFormats.clear();
     393           0 :   mAttributeList.RemoveAttribute(SdpAttribute::kRtpmapAttribute);
     394           0 :   mAttributeList.RemoveAttribute(SdpAttribute::kFmtpAttribute);
     395           0 :   mAttributeList.RemoveAttribute(SdpAttribute::kSctpmapAttribute);
     396           0 :   mAttributeList.RemoveAttribute(SdpAttribute::kRtcpFbAttribute);
     397           0 : }
     398             : 
     399             : void
     400           0 : SipccSdpMediaSection::AddDataChannel(const std::string& name, uint16_t port,
     401             :                                      uint16_t streams, uint32_t message_size)
     402             : {
     403             :   // Only one allowed, for now. This may change as the specs (and deployments)
     404             :   // evolve.
     405           0 :   mFormats.clear();
     406           0 :   if ((mProtocol == kUdpDtlsSctp) ||
     407           0 :       (mProtocol == kTcpDtlsSctp)) {
     408             :     // new data channel format according to draft 21
     409           0 :     mFormats.push_back(name);
     410           0 :     mAttributeList.SetAttribute(new SdpNumberAttribute(
     411           0 :           SdpAttribute::kSctpPortAttribute, port));
     412           0 :     if (message_size) {
     413           0 :       mAttributeList.SetAttribute(new SdpNumberAttribute(
     414           0 :             SdpAttribute::kMaxMessageSizeAttribute, message_size));
     415             :     }
     416             :   } else {
     417             :     // old data channels format according to draft 05
     418           0 :     std::string port_str = std::to_string(port);
     419           0 :     mFormats.push_back(port_str);
     420           0 :     SdpSctpmapAttributeList* sctpmap = new SdpSctpmapAttributeList();
     421           0 :     sctpmap->PushEntry(port_str, name, streams);
     422           0 :     mAttributeList.SetAttribute(sctpmap);
     423           0 :     if (message_size) {
     424             :       // This is a workaround to allow detecting Firefox's w/o EOR support
     425           0 :       mAttributeList.SetAttribute(new SdpNumberAttribute(
     426           0 :             SdpAttribute::kMaxMessageSizeAttribute, message_size));
     427             :     }
     428             :   }
     429           0 : }
     430             : 
     431             : void
     432           0 : SipccSdpMediaSection::Serialize(std::ostream& os) const
     433             : {
     434           0 :   os << "m=" << mMediaType << " " << mPort;
     435           0 :   if (mPortCount) {
     436           0 :     os << "/" << mPortCount;
     437             :   }
     438           0 :   os << " " << mProtocol;
     439           0 :   for (auto i = mFormats.begin(); i != mFormats.end(); ++i) {
     440           0 :     os << " " << (*i);
     441             :   }
     442           0 :   os << CRLF;
     443             : 
     444             :   // We dont do i=
     445             : 
     446           0 :   if (mConnection) {
     447           0 :     os << *mConnection;
     448             :   }
     449             : 
     450           0 :   mBandwidths.Serialize(os);
     451             : 
     452             :   // We dont do k= because they're evil
     453             : 
     454           0 :   os << mAttributeList;
     455           0 : }
     456             : 
     457             : } // namespace mozilla

Generated by: LCOV version 1.13