tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RsdparsaSdpMediaSection.cpp (8039B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "sdp/RsdparsaSdpMediaSection.h"
      8 
      9 #include <ostream>
     10 
     11 #include "sdp/RsdparsaSdpGlue.h"
     12 #include "sdp/RsdparsaSdpInc.h"
     13 #include "sdp/SdpMediaSection.h"
     14 
     15 #ifdef CRLF
     16 #  undef CRLF
     17 #endif
     18 #define CRLF "\r\n"
     19 
     20 namespace mozilla {
     21 
     22 RsdparsaSdpMediaSection::RsdparsaSdpMediaSection(
     23    size_t level, RsdparsaSessionHandle session,
     24    const RustMediaSection* const section,
     25    const RsdparsaSdpAttributeList* sessionLevel)
     26    : SdpMediaSection(level), mSession(std::move(session)), mSection(section) {
     27  switch (sdp_rust_get_media_type(section)) {
     28    case RustSdpMediaValue::kRustAudio:
     29      mMediaType = kAudio;
     30      break;
     31    case RustSdpMediaValue::kRustVideo:
     32      mMediaType = kVideo;
     33      break;
     34    case RustSdpMediaValue::kRustApplication:
     35      mMediaType = kApplication;
     36      break;
     37  }
     38 
     39  RsdparsaSessionHandle attributeSession(sdp_new_reference(mSession.get()));
     40  mAttributeList.reset(new RsdparsaSdpAttributeList(std::move(attributeSession),
     41                                                    section, sessionLevel));
     42 
     43  LoadFormats();
     44  LoadConnection();
     45 }
     46 
     47 unsigned int RsdparsaSdpMediaSection::GetPort() const {
     48  return sdp_get_media_port(mSection);
     49 }
     50 
     51 void RsdparsaSdpMediaSection::SetPort(unsigned int port) {
     52  sdp_set_media_port(mSection, port);
     53 }
     54 
     55 unsigned int RsdparsaSdpMediaSection::GetPortCount() const {
     56  return sdp_get_media_port_count(mSection);
     57 }
     58 
     59 SdpMediaSection::Protocol RsdparsaSdpMediaSection::GetProtocol() const {
     60  switch (sdp_get_media_protocol(mSection)) {
     61    case RustSdpProtocolValue::kRustRtpSavpf:
     62      return kRtpSavpf;
     63    case RustSdpProtocolValue::kRustUdpTlsRtpSavp:
     64      return kUdpTlsRtpSavp;
     65    case RustSdpProtocolValue::kRustTcpDtlsRtpSavp:
     66      return kTcpDtlsRtpSavp;
     67    case RustSdpProtocolValue::kRustUdpTlsRtpSavpf:
     68      return kUdpTlsRtpSavpf;
     69    case RustSdpProtocolValue::kRustTcpDtlsRtpSavpf:
     70      return kTcpDtlsRtpSavpf;
     71    case RustSdpProtocolValue::kRustDtlsSctp:
     72      return kDtlsSctp;
     73    case RustSdpProtocolValue::kRustUdpDtlsSctp:
     74      return kUdpDtlsSctp;
     75    case RustSdpProtocolValue::kRustTcpDtlsSctp:
     76      return kTcpDtlsSctp;
     77    case RustSdpProtocolValue::kRustRtpAvp:
     78      return kRtpAvp;
     79    case RustSdpProtocolValue::kRustRtpAvpf:
     80      return kRtpAvpf;
     81    case RustSdpProtocolValue::kRustRtpSavp:
     82      return kRtpSavp;
     83  }
     84  MOZ_CRASH("invalid media protocol");
     85 }
     86 
     87 const SdpConnection& RsdparsaSdpMediaSection::GetConnection() const {
     88  MOZ_ASSERT(mConnection);
     89  return *mConnection;
     90 }
     91 
     92 SdpConnection& RsdparsaSdpMediaSection::GetConnection() {
     93  MOZ_ASSERT(mConnection);
     94  return *mConnection;
     95 }
     96 
     97 uint32_t RsdparsaSdpMediaSection::GetBandwidth(const std::string& type) const {
     98  return sdp_get_media_bandwidth(mSection, type.c_str());
     99 }
    100 
    101 const std::vector<std::string>& RsdparsaSdpMediaSection::GetFormats() const {
    102  return mFormats;
    103 }
    104 
    105 const SdpAttributeList& RsdparsaSdpMediaSection::GetAttributeList() const {
    106  return *mAttributeList;
    107 }
    108 
    109 SdpAttributeList& RsdparsaSdpMediaSection::GetAttributeList() {
    110  return *mAttributeList;
    111 }
    112 
    113 SdpDirectionAttribute RsdparsaSdpMediaSection::GetDirectionAttribute() const {
    114  return SdpDirectionAttribute(mAttributeList->GetDirection());
    115 }
    116 
    117 void RsdparsaSdpMediaSection::AddCodec(const std::string& pt,
    118                                       const std::string& name,
    119                                       uint32_t clockrate, uint16_t channels) {
    120  StringView rustName{name.c_str(), name.size()};
    121 
    122  // call the rust interface
    123  auto nr = sdp_media_add_codec(mSection, std::stoul(pt), rustName, clockrate,
    124                                channels);
    125 
    126  if (NS_SUCCEEDED(nr)) {
    127    // If the rust call was successful, adjust the shadow C++ structures
    128    mFormats.push_back(pt);
    129 
    130    // Add a rtpmap in mAttributeList
    131    SdpRtpmapAttributeList* rtpmap = new SdpRtpmapAttributeList();
    132    if (mAttributeList->HasAttribute(SdpAttribute::kRtpmapAttribute)) {
    133      const SdpRtpmapAttributeList& old = mAttributeList->GetRtpmap();
    134      for (auto it = old.mRtpmaps.begin(); it != old.mRtpmaps.end(); ++it) {
    135        rtpmap->mRtpmaps.push_back(*it);
    136      }
    137    }
    138 
    139    SdpRtpmapAttributeList::CodecType codec =
    140        SdpRtpmapAttributeList::kOtherCodec;
    141    if (name == "opus") {
    142      codec = SdpRtpmapAttributeList::kOpus;
    143    } else if (name == "VP8") {
    144      codec = SdpRtpmapAttributeList::kVP8;
    145    } else if (name == "VP9") {
    146      codec = SdpRtpmapAttributeList::kVP9;
    147    } else if (name == "H264") {
    148      codec = SdpRtpmapAttributeList::kH264;
    149    }
    150 
    151    rtpmap->PushEntry(pt, codec, name, clockrate, channels);
    152    mAttributeList->SetAttribute(rtpmap);
    153  }
    154 }
    155 
    156 void RsdparsaSdpMediaSection::ClearCodecs() {
    157  // Clear the codecs in rust
    158  sdp_media_clear_codecs(mSection);
    159 
    160  mFormats.clear();
    161  mAttributeList->RemoveAttribute(SdpAttribute::kRtpmapAttribute);
    162  mAttributeList->RemoveAttribute(SdpAttribute::kFmtpAttribute);
    163  mAttributeList->RemoveAttribute(SdpAttribute::kSctpmapAttribute);
    164  mAttributeList->RemoveAttribute(SdpAttribute::kRtcpFbAttribute);
    165 }
    166 
    167 void RsdparsaSdpMediaSection::AddDataChannel(const std::string& name,
    168                                             uint16_t port, uint16_t streams,
    169                                             uint32_t message_size) {
    170  StringView rustName{name.c_str(), name.size()};
    171  auto nr = sdp_media_add_datachannel(mSection, rustName, port, streams,
    172                                      message_size);
    173  if (NS_SUCCEEDED(nr)) {
    174    // Update the formats
    175    mFormats.clear();
    176    LoadFormats();
    177 
    178    // Update the attribute list
    179    RsdparsaSessionHandle sessHandle(sdp_new_reference(mSession.get()));
    180    auto sessAttributes = mAttributeList->mSessionAttributes;
    181    mAttributeList.reset(new RsdparsaSdpAttributeList(
    182        std::move(sessHandle), mSection, sessAttributes));
    183  }
    184 }
    185 
    186 void RsdparsaSdpMediaSection::Serialize(std::ostream& os) const {
    187  os << "m=" << mMediaType << " " << GetPort();
    188  if (GetPortCount()) {
    189    os << "/" << GetPortCount();
    190  }
    191  os << " " << GetProtocol();
    192  for (auto i = mFormats.begin(); i != mFormats.end(); ++i) {
    193    os << " " << (*i);
    194  }
    195  os << CRLF;
    196 
    197  // We dont do i=
    198 
    199  if (mConnection) {
    200    os << *mConnection;
    201  }
    202 
    203  BandwidthVec* bwVec = sdp_get_media_bandwidth_vec(mSection);
    204  char* bwString = sdp_serialize_bandwidth(bwVec);
    205  if (bwString) {
    206    os << bwString;
    207    sdp_free_string(bwString);
    208  }
    209 
    210  // We dont do k= because they're evil
    211 
    212  os << *mAttributeList;
    213 }
    214 
    215 void RsdparsaSdpMediaSection::LoadFormats() {
    216  RustSdpFormatType formatType = sdp_get_format_type(mSection);
    217  if (formatType == RustSdpFormatType::kRustIntegers) {
    218    U32Vec* vec = sdp_get_format_u32_vec(mSection);
    219    size_t len = u32_vec_len(vec);
    220    for (size_t i = 0; i < len; i++) {
    221      uint32_t val;
    222      u32_vec_get(vec, i, &val);
    223      mFormats.push_back(std::to_string(val));
    224    }
    225  } else {
    226    StringVec* vec = sdp_get_format_string_vec(mSection);
    227    mFormats = convertStringVec(vec);
    228  }
    229 }
    230 
    231 UniquePtr<SdpConnection> convertRustConnection(RustSdpConnection conn) {
    232  auto address = convertExplicitlyTypedAddress(&conn.addr);
    233  return MakeUnique<SdpConnection>(address.first, address.second, conn.ttl,
    234                                   conn.amount);
    235 }
    236 
    237 void RsdparsaSdpMediaSection::LoadConnection() {
    238  RustSdpConnection conn;
    239  nsresult nr;
    240  if (sdp_media_has_connection(mSection)) {
    241    nr = sdp_get_media_connection(mSection, &conn);
    242    if (NS_SUCCEEDED(nr)) {
    243      mConnection = convertRustConnection(conn);
    244    }
    245  } else if (sdp_session_has_connection(mSession.get())) {
    246    nr = sdp_get_session_connection(mSession.get(), &conn);
    247    if (NS_SUCCEEDED(nr)) {
    248      mConnection = convertRustConnection(conn);
    249    }
    250  }
    251 }
    252 
    253 }  // namespace mozilla