tor-browser

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

RsdparsaSdpAttributeList.cpp (46574B)


      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/RsdparsaSdpAttributeList.h"
      8 
      9 #include <limits>
     10 #include <ostream>
     11 #include <string>
     12 
     13 #include "SdpAttribute.h"
     14 #include "mozilla/Assertions.h"
     15 #include "nsCRT.h"
     16 #include "sdp/RsdparsaSdpGlue.h"
     17 #include "sdp/RsdparsaSdpInc.h"
     18 
     19 namespace mozilla {
     20 
     21 MOZ_RUNINIT const std::string RsdparsaSdpAttributeList::kEmptyString = "";
     22 
     23 RsdparsaSdpAttributeList::~RsdparsaSdpAttributeList() {
     24  for (size_t i = 0; i < kNumAttributeTypes; ++i) {
     25    delete mAttributes[i];
     26  }
     27 }
     28 
     29 bool RsdparsaSdpAttributeList::HasAttribute(AttributeType type,
     30                                            bool sessionFallback) const {
     31  return !!GetAttribute(type, sessionFallback);
     32 }
     33 
     34 const SdpAttribute* RsdparsaSdpAttributeList::GetAttribute(
     35    AttributeType type, bool sessionFallback) const {
     36  const SdpAttribute* value = mAttributes[static_cast<size_t>(type)];
     37  // Only do fallback when the attribute can appear at both the media and
     38  // session level
     39  if (!value && !AtSessionLevel() && sessionFallback &&
     40      SdpAttribute::IsAllowedAtSessionLevel(type) &&
     41      SdpAttribute::IsAllowedAtMediaLevel(type)) {
     42    return mSessionAttributes->GetAttribute(type, false);
     43  }
     44  return value;
     45 }
     46 
     47 void RsdparsaSdpAttributeList::RemoveAttribute(AttributeType type) {
     48  delete mAttributes[static_cast<size_t>(type)];
     49  mAttributes[static_cast<size_t>(type)] = nullptr;
     50 }
     51 
     52 void RsdparsaSdpAttributeList::Clear() {
     53  for (size_t i = 0; i < kNumAttributeTypes; ++i) {
     54    RemoveAttribute(static_cast<AttributeType>(i));
     55  }
     56 }
     57 
     58 uint32_t RsdparsaSdpAttributeList::Count() const {
     59  uint32_t count = 0;
     60  for (size_t i = 0; i < kNumAttributeTypes; ++i) {
     61    if (mAttributes[i]) {
     62      count++;
     63    }
     64  }
     65  return count;
     66 }
     67 
     68 void RsdparsaSdpAttributeList::SetAttribute(SdpAttribute* attr) {
     69  if (!IsAllowedHere(attr->GetType())) {
     70    MOZ_ASSERT(false, "This type of attribute is not allowed here");
     71    delete attr;
     72    return;
     73  }
     74  RemoveAttribute(attr->GetType());
     75  mAttributes[attr->GetType()] = attr;
     76 }
     77 
     78 const std::vector<std::string>& RsdparsaSdpAttributeList::GetCandidate() const {
     79  if (!HasAttribute(SdpAttribute::kCandidateAttribute)) {
     80    MOZ_CRASH();
     81  }
     82 
     83  return static_cast<const SdpMultiStringAttribute*>(
     84             GetAttribute(SdpAttribute::kCandidateAttribute))
     85      ->mValues;
     86 }
     87 
     88 const SdpConnectionAttribute& RsdparsaSdpAttributeList::GetConnection() const {
     89  if (!HasAttribute(SdpAttribute::kConnectionAttribute)) {
     90    MOZ_CRASH();
     91  }
     92 
     93  return *static_cast<const SdpConnectionAttribute*>(
     94      GetAttribute(SdpAttribute::kConnectionAttribute));
     95 }
     96 
     97 SdpDirectionAttribute::Direction RsdparsaSdpAttributeList::GetDirection()
     98    const {
     99  if (!HasAttribute(SdpAttribute::kDirectionAttribute)) {
    100    MOZ_CRASH();
    101  }
    102 
    103  const SdpAttribute* attr = GetAttribute(SdpAttribute::kDirectionAttribute);
    104  return static_cast<const SdpDirectionAttribute*>(attr)->mValue;
    105 }
    106 
    107 const SdpDtlsMessageAttribute& RsdparsaSdpAttributeList::GetDtlsMessage()
    108    const {
    109  if (!HasAttribute(SdpAttribute::kDtlsMessageAttribute)) {
    110    MOZ_CRASH();
    111  }
    112  const SdpAttribute* attr = GetAttribute(SdpAttribute::kDtlsMessageAttribute);
    113  return *static_cast<const SdpDtlsMessageAttribute*>(attr);
    114 }
    115 
    116 const SdpExtmapAttributeList& RsdparsaSdpAttributeList::GetExtmap() const {
    117  if (!HasAttribute(SdpAttribute::kExtmapAttribute)) {
    118    MOZ_CRASH();
    119  }
    120 
    121  return *static_cast<const SdpExtmapAttributeList*>(
    122      GetAttribute(SdpAttribute::kExtmapAttribute));
    123 }
    124 
    125 const SdpFingerprintAttributeList& RsdparsaSdpAttributeList::GetFingerprint()
    126    const {
    127  if (!HasAttribute(SdpAttribute::kFingerprintAttribute)) {
    128    MOZ_CRASH();
    129  }
    130  const SdpAttribute* attr = GetAttribute(SdpAttribute::kFingerprintAttribute);
    131  return *static_cast<const SdpFingerprintAttributeList*>(attr);
    132 }
    133 
    134 const SdpFmtpAttributeList& RsdparsaSdpAttributeList::GetFmtp() const {
    135  if (!HasAttribute(SdpAttribute::kFmtpAttribute)) {
    136    MOZ_CRASH();
    137  }
    138 
    139  return *static_cast<const SdpFmtpAttributeList*>(
    140      GetAttribute(SdpAttribute::kFmtpAttribute));
    141 }
    142 
    143 const SdpGroupAttributeList& RsdparsaSdpAttributeList::GetGroup() const {
    144  if (!HasAttribute(SdpAttribute::kGroupAttribute)) {
    145    MOZ_CRASH();
    146  }
    147 
    148  return *static_cast<const SdpGroupAttributeList*>(
    149      GetAttribute(SdpAttribute::kGroupAttribute));
    150 }
    151 
    152 const SdpOptionsAttribute& RsdparsaSdpAttributeList::GetIceOptions() const {
    153  if (!HasAttribute(SdpAttribute::kIceOptionsAttribute)) {
    154    MOZ_CRASH();
    155  }
    156 
    157  const SdpAttribute* attr = GetAttribute(SdpAttribute::kIceOptionsAttribute);
    158  return *static_cast<const SdpOptionsAttribute*>(attr);
    159 }
    160 
    161 const std::string& RsdparsaSdpAttributeList::GetIcePwd() const {
    162  if (!HasAttribute(SdpAttribute::kIcePwdAttribute)) {
    163    return kEmptyString;
    164  }
    165  const SdpAttribute* attr = GetAttribute(SdpAttribute::kIcePwdAttribute);
    166  return static_cast<const SdpStringAttribute*>(attr)->mValue;
    167 }
    168 
    169 const std::string& RsdparsaSdpAttributeList::GetIceUfrag() const {
    170  if (!HasAttribute(SdpAttribute::kIceUfragAttribute)) {
    171    return kEmptyString;
    172  }
    173  const SdpAttribute* attr = GetAttribute(SdpAttribute::kIceUfragAttribute);
    174  return static_cast<const SdpStringAttribute*>(attr)->mValue;
    175 }
    176 
    177 const std::string& RsdparsaSdpAttributeList::GetIdentity() const {
    178  if (!HasAttribute(SdpAttribute::kIdentityAttribute)) {
    179    return kEmptyString;
    180  }
    181  const SdpAttribute* attr = GetAttribute(SdpAttribute::kIdentityAttribute);
    182  return static_cast<const SdpStringAttribute*>(attr)->mValue;
    183 }
    184 
    185 const SdpImageattrAttributeList& RsdparsaSdpAttributeList::GetImageattr()
    186    const {
    187  if (!HasAttribute(SdpAttribute::kImageattrAttribute)) {
    188    MOZ_CRASH();
    189  }
    190  const SdpAttribute* attr = GetAttribute(SdpAttribute::kImageattrAttribute);
    191  return *static_cast<const SdpImageattrAttributeList*>(attr);
    192 }
    193 
    194 const SdpSimulcastAttribute& RsdparsaSdpAttributeList::GetSimulcast() const {
    195  if (!HasAttribute(SdpAttribute::kSimulcastAttribute)) {
    196    MOZ_CRASH();
    197  }
    198  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSimulcastAttribute);
    199  return *static_cast<const SdpSimulcastAttribute*>(attr);
    200 }
    201 
    202 const std::string& RsdparsaSdpAttributeList::GetLabel() const {
    203  if (!HasAttribute(SdpAttribute::kLabelAttribute)) {
    204    return kEmptyString;
    205  }
    206  const SdpAttribute* attr = GetAttribute(SdpAttribute::kLabelAttribute);
    207  return static_cast<const SdpStringAttribute*>(attr)->mValue;
    208 }
    209 
    210 uint32_t RsdparsaSdpAttributeList::GetMaxptime() const {
    211  if (!HasAttribute(SdpAttribute::kMaxptimeAttribute)) {
    212    MOZ_CRASH();
    213  }
    214  const SdpAttribute* attr = GetAttribute(SdpAttribute::kMaxptimeAttribute);
    215  return static_cast<const SdpNumberAttribute*>(attr)->mValue;
    216 }
    217 
    218 const std::string& RsdparsaSdpAttributeList::GetMid() const {
    219  if (!HasAttribute(SdpAttribute::kMidAttribute)) {
    220    return kEmptyString;
    221  }
    222  const SdpAttribute* attr = GetAttribute(SdpAttribute::kMidAttribute);
    223  return static_cast<const SdpStringAttribute*>(attr)->mValue;
    224 }
    225 
    226 const SdpMsidAttributeList& RsdparsaSdpAttributeList::GetMsid() const {
    227  if (!HasAttribute(SdpAttribute::kMsidAttribute)) {
    228    MOZ_CRASH();
    229  }
    230  const SdpAttribute* attr = GetAttribute(SdpAttribute::kMsidAttribute);
    231  return *static_cast<const SdpMsidAttributeList*>(attr);
    232 }
    233 
    234 const SdpMsidSemanticAttributeList& RsdparsaSdpAttributeList::GetMsidSemantic()
    235    const {
    236  if (!HasAttribute(SdpAttribute::kMsidSemanticAttribute)) {
    237    MOZ_CRASH();
    238  }
    239  const SdpAttribute* attr = GetAttribute(SdpAttribute::kMsidSemanticAttribute);
    240  return *static_cast<const SdpMsidSemanticAttributeList*>(attr);
    241 }
    242 
    243 const SdpRidAttributeList& RsdparsaSdpAttributeList::GetRid() const {
    244  if (!HasAttribute(SdpAttribute::kRidAttribute)) {
    245    MOZ_CRASH();
    246  }
    247  const SdpAttribute* attr = GetAttribute(SdpAttribute::kRidAttribute);
    248  return *static_cast<const SdpRidAttributeList*>(attr);
    249 }
    250 
    251 uint32_t RsdparsaSdpAttributeList::GetPtime() const {
    252  if (!HasAttribute(SdpAttribute::kPtimeAttribute)) {
    253    MOZ_CRASH();
    254  }
    255  const SdpAttribute* attr = GetAttribute(SdpAttribute::kPtimeAttribute);
    256  return static_cast<const SdpNumberAttribute*>(attr)->mValue;
    257 }
    258 
    259 const SdpRtcpAttribute& RsdparsaSdpAttributeList::GetRtcp() const {
    260  if (!HasAttribute(SdpAttribute::kRtcpAttribute)) {
    261    MOZ_CRASH();
    262  }
    263  const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtcpAttribute);
    264  return *static_cast<const SdpRtcpAttribute*>(attr);
    265 }
    266 
    267 const SdpRtcpFbAttributeList& RsdparsaSdpAttributeList::GetRtcpFb() const {
    268  if (!HasAttribute(SdpAttribute::kRtcpFbAttribute)) {
    269    MOZ_CRASH();
    270  }
    271  const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtcpFbAttribute);
    272  return *static_cast<const SdpRtcpFbAttributeList*>(attr);
    273 }
    274 
    275 const SdpRemoteCandidatesAttribute&
    276 RsdparsaSdpAttributeList::GetRemoteCandidates() const {
    277  MOZ_CRASH("Not yet implemented");
    278 }
    279 
    280 const SdpRtpmapAttributeList& RsdparsaSdpAttributeList::GetRtpmap() const {
    281  if (!HasAttribute(SdpAttribute::kRtpmapAttribute)) {
    282    MOZ_CRASH();
    283  }
    284  const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtpmapAttribute);
    285  return *static_cast<const SdpRtpmapAttributeList*>(attr);
    286 }
    287 
    288 const SdpSctpmapAttributeList& RsdparsaSdpAttributeList::GetSctpmap() const {
    289  if (!HasAttribute(SdpAttribute::kSctpmapAttribute)) {
    290    MOZ_CRASH();
    291  }
    292  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSctpmapAttribute);
    293  return *static_cast<const SdpSctpmapAttributeList*>(attr);
    294 }
    295 
    296 uint32_t RsdparsaSdpAttributeList::GetSctpPort() const {
    297  if (!HasAttribute(SdpAttribute::kSctpPortAttribute)) {
    298    MOZ_CRASH();
    299  }
    300 
    301  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSctpPortAttribute);
    302  return static_cast<const SdpNumberAttribute*>(attr)->mValue;
    303 }
    304 
    305 uint32_t RsdparsaSdpAttributeList::GetMaxMessageSize() const {
    306  if (!HasAttribute(SdpAttribute::kMaxMessageSizeAttribute)) {
    307    MOZ_CRASH();
    308  }
    309 
    310  const SdpAttribute* attr =
    311      GetAttribute(SdpAttribute::kMaxMessageSizeAttribute);
    312  return static_cast<const SdpNumberAttribute*>(attr)->mValue;
    313 }
    314 
    315 const SdpSetupAttribute& RsdparsaSdpAttributeList::GetSetup() const {
    316  if (!HasAttribute(SdpAttribute::kSetupAttribute)) {
    317    MOZ_CRASH();
    318  }
    319  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSetupAttribute);
    320  return *static_cast<const SdpSetupAttribute*>(attr);
    321 }
    322 
    323 const SdpSsrcAttributeList& RsdparsaSdpAttributeList::GetSsrc() const {
    324  if (!HasAttribute(SdpAttribute::kSsrcAttribute)) {
    325    MOZ_CRASH();
    326  }
    327  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSsrcAttribute);
    328  return *static_cast<const SdpSsrcAttributeList*>(attr);
    329 }
    330 
    331 const SdpSsrcGroupAttributeList& RsdparsaSdpAttributeList::GetSsrcGroup()
    332    const {
    333  if (!HasAttribute(SdpAttribute::kSsrcGroupAttribute)) {
    334    MOZ_CRASH();
    335  }
    336  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSsrcGroupAttribute);
    337  return *static_cast<const SdpSsrcGroupAttributeList*>(attr);
    338 }
    339 
    340 void RsdparsaSdpAttributeList::LoadAttribute(RustAttributeList* attributeList,
    341                                             AttributeType type) {
    342  if (!mAttributes[type]) {
    343    switch (type) {
    344      case SdpAttribute::kIceUfragAttribute:
    345        LoadIceUfrag(attributeList);
    346        return;
    347      case SdpAttribute::kIcePwdAttribute:
    348        LoadIcePwd(attributeList);
    349        return;
    350      case SdpAttribute::kIceOptionsAttribute:
    351        LoadIceOptions(attributeList);
    352        return;
    353      case SdpAttribute::kDtlsMessageAttribute:
    354        LoadDtlsMessage(attributeList);
    355        return;
    356      case SdpAttribute::kFingerprintAttribute:
    357        LoadFingerprint(attributeList);
    358        return;
    359      case SdpAttribute::kIdentityAttribute:
    360        LoadIdentity(attributeList);
    361        return;
    362      case SdpAttribute::kSetupAttribute:
    363        LoadSetup(attributeList);
    364        return;
    365      case SdpAttribute::kSsrcAttribute:
    366        LoadSsrc(attributeList);
    367        return;
    368      case SdpAttribute::kRtpmapAttribute:
    369        LoadRtpmap(attributeList);
    370        return;
    371      case SdpAttribute::kFmtpAttribute:
    372        LoadFmtp(attributeList);
    373        return;
    374      case SdpAttribute::kPtimeAttribute:
    375        LoadPtime(attributeList);
    376        return;
    377      case SdpAttribute::kIceLiteAttribute:
    378      case SdpAttribute::kRtcpMuxAttribute:
    379      case SdpAttribute::kRtcpRsizeAttribute:
    380      case SdpAttribute::kBundleOnlyAttribute:
    381      case SdpAttribute::kEndOfCandidatesAttribute:
    382      case SdpAttribute::kExtmapAllowMixedAttribute:
    383        LoadFlags(attributeList);
    384        return;
    385      case SdpAttribute::kMaxMessageSizeAttribute:
    386        LoadMaxMessageSize(attributeList);
    387        return;
    388      case SdpAttribute::kMidAttribute:
    389        LoadMid(attributeList);
    390        return;
    391      case SdpAttribute::kMsidAttribute:
    392        LoadMsid(attributeList);
    393        return;
    394      case SdpAttribute::kMsidSemanticAttribute:
    395        LoadMsidSemantics(attributeList);
    396        return;
    397      case SdpAttribute::kGroupAttribute:
    398        LoadGroup(attributeList);
    399        return;
    400      case SdpAttribute::kRtcpAttribute:
    401        LoadRtcp(attributeList);
    402        return;
    403      case SdpAttribute::kRtcpFbAttribute:
    404        LoadRtcpFb(attributeList);
    405        return;
    406      case SdpAttribute::kImageattrAttribute:
    407        LoadImageattr(attributeList);
    408        return;
    409      case SdpAttribute::kSctpmapAttribute:
    410        LoadSctpmaps(attributeList);
    411        return;
    412      case SdpAttribute::kDirectionAttribute:
    413        LoadDirection(attributeList);
    414        return;
    415      case SdpAttribute::kRemoteCandidatesAttribute:
    416        LoadRemoteCandidates(attributeList);
    417        return;
    418      case SdpAttribute::kRidAttribute:
    419        LoadRids(attributeList);
    420        return;
    421      case SdpAttribute::kSctpPortAttribute:
    422        LoadSctpPort(attributeList);
    423        return;
    424      case SdpAttribute::kExtmapAttribute:
    425        LoadExtmap(attributeList);
    426        return;
    427      case SdpAttribute::kSimulcastAttribute:
    428        LoadSimulcast(attributeList);
    429        return;
    430      case SdpAttribute::kMaxptimeAttribute:
    431        LoadMaxPtime(attributeList);
    432        return;
    433      case SdpAttribute::kCandidateAttribute:
    434        LoadCandidate(attributeList);
    435        return;
    436      case SdpAttribute::kSsrcGroupAttribute:
    437        LoadSsrcGroup(attributeList);
    438        return;
    439      case SdpAttribute::kConnectionAttribute:
    440      case SdpAttribute::kIceMismatchAttribute:
    441      case SdpAttribute::kLabelAttribute:
    442        // These attributes are unused
    443        return;
    444    }
    445  }
    446 }
    447 
    448 void RsdparsaSdpAttributeList::LoadAll(RustAttributeList* attributeList) {
    449  for (int i = SdpAttribute::kFirstAttribute; i <= SdpAttribute::kLastAttribute;
    450       i++) {
    451    LoadAttribute(attributeList, static_cast<SdpAttribute::AttributeType>(i));
    452  }
    453 }
    454 
    455 void RsdparsaSdpAttributeList::LoadIceUfrag(RustAttributeList* attributeList) {
    456  StringView ufragStr;
    457  nsresult nr = sdp_get_iceufrag(attributeList, &ufragStr);
    458  if (NS_SUCCEEDED(nr)) {
    459    std::string iceufrag = convertStringView(ufragStr);
    460    SetAttribute(
    461        new SdpStringAttribute(SdpAttribute::kIceUfragAttribute, iceufrag));
    462  }
    463 }
    464 
    465 void RsdparsaSdpAttributeList::LoadIcePwd(RustAttributeList* attributeList) {
    466  StringView pwdStr;
    467  nsresult nr = sdp_get_icepwd(attributeList, &pwdStr);
    468  if (NS_SUCCEEDED(nr)) {
    469    std::string icePwd = convertStringView(pwdStr);
    470    SetAttribute(
    471        new SdpStringAttribute(SdpAttribute::kIcePwdAttribute, icePwd));
    472  }
    473 }
    474 
    475 void RsdparsaSdpAttributeList::LoadIdentity(RustAttributeList* attributeList) {
    476  StringView identityStr;
    477  nsresult nr = sdp_get_identity(attributeList, &identityStr);
    478  if (NS_SUCCEEDED(nr)) {
    479    std::string identity = convertStringView(identityStr);
    480    SetAttribute(
    481        new SdpStringAttribute(SdpAttribute::kIdentityAttribute, identity));
    482  }
    483 }
    484 
    485 void RsdparsaSdpAttributeList::LoadIceOptions(
    486    RustAttributeList* attributeList) {
    487  StringVec* options;
    488  nsresult nr = sdp_get_iceoptions(attributeList, &options);
    489  if (NS_SUCCEEDED(nr)) {
    490    std::vector<std::string> optionsVec;
    491    auto optionsAttr =
    492        MakeUnique<SdpOptionsAttribute>(SdpAttribute::kIceOptionsAttribute);
    493    for (size_t i = 0; i < string_vec_len(options); i++) {
    494      StringView optionStr;
    495      string_vec_get_view(options, i, &optionStr);
    496      optionsAttr->PushEntry(convertStringView(optionStr));
    497    }
    498    SetAttribute(optionsAttr.release());
    499  }
    500 }
    501 
    502 void RsdparsaSdpAttributeList::LoadFingerprint(
    503    RustAttributeList* attributeList) {
    504  size_t nFp = sdp_get_fingerprint_count(attributeList);
    505  if (nFp == 0) {
    506    return;
    507  }
    508  auto rustFingerprints = MakeUnique<RustSdpAttributeFingerprint[]>(nFp);
    509  sdp_get_fingerprints(attributeList, nFp, rustFingerprints.get());
    510  auto fingerprints = MakeUnique<SdpFingerprintAttributeList>();
    511  for (size_t i = 0; i < nFp; i++) {
    512    const RustSdpAttributeFingerprint& fingerprint = rustFingerprints[i];
    513    std::string algorithm;
    514    switch (fingerprint.hashAlgorithm) {
    515      case RustSdpAttributeFingerprintHashAlgorithm::kSha1:
    516        algorithm = "sha-1";
    517        break;
    518      case RustSdpAttributeFingerprintHashAlgorithm::kSha224:
    519        algorithm = "sha-224";
    520        break;
    521      case RustSdpAttributeFingerprintHashAlgorithm::kSha256:
    522        algorithm = "sha-256";
    523        break;
    524      case RustSdpAttributeFingerprintHashAlgorithm::kSha384:
    525        algorithm = "sha-384";
    526        break;
    527      case RustSdpAttributeFingerprintHashAlgorithm::kSha512:
    528        algorithm = "sha-512";
    529        break;
    530    }
    531 
    532    std::vector<uint8_t> fingerprintBytes =
    533        convertU8Vec(fingerprint.fingerprint);
    534 
    535    fingerprints->PushEntry(algorithm, fingerprintBytes);
    536  }
    537  SetAttribute(fingerprints.release());
    538 }
    539 
    540 void RsdparsaSdpAttributeList::LoadDtlsMessage(
    541    RustAttributeList* attributeList) {
    542  RustSdpAttributeDtlsMessage rustDtlsMessage;
    543  nsresult nr = sdp_get_dtls_message(attributeList, &rustDtlsMessage);
    544  if (NS_SUCCEEDED(nr)) {
    545    SdpDtlsMessageAttribute::Role role;
    546    if (rustDtlsMessage.role == RustSdpAttributeDtlsMessageType::kClient) {
    547      role = SdpDtlsMessageAttribute::kClient;
    548    } else {
    549      role = SdpDtlsMessageAttribute::kServer;
    550    }
    551 
    552    std::string value = convertStringView(rustDtlsMessage.value);
    553 
    554    SetAttribute(new SdpDtlsMessageAttribute(role, value));
    555  }
    556 }
    557 
    558 void RsdparsaSdpAttributeList::LoadSetup(RustAttributeList* attributeList) {
    559  RustSdpSetup rustSetup;
    560  nsresult nr = sdp_get_setup(attributeList, &rustSetup);
    561  if (NS_SUCCEEDED(nr)) {
    562    SdpSetupAttribute::Role setupEnum;
    563    switch (rustSetup) {
    564      case RustSdpSetup::kRustActive:
    565        setupEnum = SdpSetupAttribute::kActive;
    566        break;
    567      case RustSdpSetup::kRustActpass:
    568        setupEnum = SdpSetupAttribute::kActpass;
    569        break;
    570      case RustSdpSetup::kRustHoldconn:
    571        setupEnum = SdpSetupAttribute::kHoldconn;
    572        break;
    573      case RustSdpSetup::kRustPassive:
    574        setupEnum = SdpSetupAttribute::kPassive;
    575        break;
    576    }
    577    SetAttribute(new SdpSetupAttribute(setupEnum));
    578  }
    579 }
    580 
    581 void RsdparsaSdpAttributeList::LoadSsrc(RustAttributeList* attributeList) {
    582  size_t numSsrc = sdp_get_ssrc_count(attributeList);
    583  if (numSsrc == 0) {
    584    return;
    585  }
    586  auto rustSsrcs = MakeUnique<RustSdpAttributeSsrc[]>(numSsrc);
    587  sdp_get_ssrcs(attributeList, numSsrc, rustSsrcs.get());
    588  auto ssrcs = MakeUnique<SdpSsrcAttributeList>();
    589  for (size_t i = 0; i < numSsrc; i++) {
    590    RustSdpAttributeSsrc& ssrc = rustSsrcs[i];
    591    std::string attribute = convertStringView(ssrc.attribute);
    592    std::string value = convertStringView(ssrc.value);
    593    if (value.length() == 0) {
    594      ssrcs->PushEntry(ssrc.id, attribute);
    595    } else {
    596      ssrcs->PushEntry(ssrc.id, attribute + ":" + value);
    597    }
    598  }
    599  SetAttribute(ssrcs.release());
    600 }
    601 
    602 void RsdparsaSdpAttributeList::LoadSsrcGroup(RustAttributeList* attributeList) {
    603  size_t numSsrcGroups = sdp_get_ssrc_group_count(attributeList);
    604  if (numSsrcGroups == 0) {
    605    return;
    606  }
    607  auto rustSsrcGroups = MakeUnique<RustSdpAttributeSsrcGroup[]>(numSsrcGroups);
    608  sdp_get_ssrc_groups(attributeList, numSsrcGroups, rustSsrcGroups.get());
    609  auto ssrcGroups = MakeUnique<SdpSsrcGroupAttributeList>();
    610  for (size_t i = 0; i < numSsrcGroups; i++) {
    611    RustSdpAttributeSsrcGroup& ssrcGroup = rustSsrcGroups[i];
    612    SdpSsrcGroupAttributeList::Semantics semantic;
    613    switch (ssrcGroup.semantic) {
    614      case RustSdpAttributeSsrcGroupSemantic ::kRustDup:
    615        semantic = SdpSsrcGroupAttributeList::kDup;
    616        break;
    617      case RustSdpAttributeSsrcGroupSemantic ::kRustFec:
    618        semantic = SdpSsrcGroupAttributeList::kFec;
    619        break;
    620      case RustSdpAttributeSsrcGroupSemantic ::kRustFecFr:
    621        semantic = SdpSsrcGroupAttributeList::kFecFr;
    622        break;
    623      case RustSdpAttributeSsrcGroupSemantic ::kRustFid:
    624        semantic = SdpSsrcGroupAttributeList::kFid;
    625        break;
    626      case RustSdpAttributeSsrcGroupSemantic ::kRustSim:
    627        semantic = SdpSsrcGroupAttributeList::kSim;
    628        break;
    629    }
    630    std::vector<uint32_t> ssrcs;
    631    for (size_t i = 0; i < ssrc_vec_len(ssrcGroup.ssrcs); ++i) {
    632      uint32_t ssrc;
    633      ssrc_vec_get_id(ssrcGroup.ssrcs, i, &ssrc);
    634      ssrcs.push_back(ssrc);
    635    }
    636    ssrcGroups->PushEntry(semantic, ssrcs);
    637  }
    638  SetAttribute(ssrcGroups.release());
    639 }
    640 
    641 struct FmtDefaults {
    642  uint32_t minimumChannels = 0;
    643 };
    644 
    645 std::tuple<SdpRtpmapAttributeList::CodecType, FmtDefaults> strToCodecType(
    646    const std::string& name) {
    647  auto codec = SdpRtpmapAttributeList::kOtherCodec;
    648  FmtDefaults defaults = {0};  // This is tracked to match SIPCC behavior only
    649  if (!nsCRT::strcasecmp(name.c_str(), "opus")) {
    650    codec = SdpRtpmapAttributeList::kOpus;
    651    defaults = {0};
    652  } else if (!nsCRT::strcasecmp(name.c_str(), "G722")) {
    653    codec = SdpRtpmapAttributeList::kG722;
    654    defaults = {1};
    655  } else if (!nsCRT::strcasecmp(name.c_str(), "PCMU")) {
    656    codec = SdpRtpmapAttributeList::kPCMU;
    657    defaults = {1};
    658  } else if (!nsCRT::strcasecmp(name.c_str(), "PCMA")) {
    659    codec = SdpRtpmapAttributeList::kPCMA;
    660    defaults = {1};
    661  } else if (!nsCRT::strcasecmp(name.c_str(), "VP8")) {
    662    codec = SdpRtpmapAttributeList::kVP8;
    663    defaults = {0};
    664  } else if (!nsCRT::strcasecmp(name.c_str(), "VP9")) {
    665    codec = SdpRtpmapAttributeList::kVP9;
    666    defaults = {0};
    667  } else if (!nsCRT::strcasecmp(name.c_str(), "iLBC")) {
    668    codec = SdpRtpmapAttributeList::kiLBC;
    669    defaults = {1};
    670  } else if (!nsCRT::strcasecmp(name.c_str(), "iSAC")) {
    671    codec = SdpRtpmapAttributeList::kiSAC;
    672    defaults = {1};
    673  } else if (!nsCRT::strcasecmp(name.c_str(), "H264")) {
    674    codec = SdpRtpmapAttributeList::kH264;
    675    defaults = {0};
    676  } else if (!nsCRT::strcasecmp(name.c_str(), "red")) {
    677    codec = SdpRtpmapAttributeList::kRed;
    678    defaults = {0};
    679  } else if (!nsCRT::strcasecmp(name.c_str(), "ulpfec")) {
    680    codec = SdpRtpmapAttributeList::kUlpfec;
    681    defaults = {0};
    682  } else if (!nsCRT::strcasecmp(name.c_str(), "telephone-event")) {
    683    codec = SdpRtpmapAttributeList::kTelephoneEvent;
    684    defaults = {1};
    685  } else if (!nsCRT::strcasecmp(name.c_str(), "rtx")) {
    686    codec = SdpRtpmapAttributeList::kRtx;
    687    defaults = {0};
    688  }
    689  return std::make_tuple(codec, defaults);
    690 }
    691 
    692 void RsdparsaSdpAttributeList::LoadRtpmap(RustAttributeList* attributeList) {
    693  size_t numRtpmap = sdp_get_rtpmap_count(attributeList);
    694  if (numRtpmap == 0) {
    695    return;
    696  }
    697  auto rustRtpmaps = MakeUnique<RustSdpAttributeRtpmap[]>(numRtpmap);
    698  sdp_get_rtpmaps(attributeList, numRtpmap, rustRtpmaps.get());
    699  auto rtpmapList = MakeUnique<SdpRtpmapAttributeList>();
    700  for (size_t i = 0; i < numRtpmap; i++) {
    701    RustSdpAttributeRtpmap& rtpmap = rustRtpmaps[i];
    702    std::string payloadType = std::to_string(rtpmap.payloadType);
    703    std::string name = convertStringView(rtpmap.codecName);
    704    auto [codec, defaults] = strToCodecType(name);
    705    uint32_t channels = rtpmap.channels;
    706    if (channels == 0) {
    707      channels = defaults.minimumChannels;
    708    }
    709    rtpmapList->PushEntry(payloadType, codec, name, rtpmap.frequency, channels);
    710  }
    711  SetAttribute(rtpmapList.release());
    712 }
    713 
    714 void RsdparsaSdpAttributeList::LoadFmtp(RustAttributeList* attributeList) {
    715  size_t numFmtp = sdp_get_fmtp_count(attributeList);
    716  if (numFmtp == 0) {
    717    return;
    718  }
    719  auto rustFmtps = MakeUnique<RustSdpAttributeFmtp[]>(numFmtp);
    720  size_t numValidFmtp = sdp_get_fmtp(attributeList, numFmtp, rustFmtps.get());
    721  auto fmtpList = MakeUnique<SdpFmtpAttributeList>();
    722  for (size_t i = 0; i < numValidFmtp; i++) {
    723    const RustSdpAttributeFmtp& fmtp = rustFmtps[i];
    724    uint8_t payloadType = fmtp.payloadType;
    725    std::string codecName = convertStringView(fmtp.codecName);
    726    const RustSdpAttributeFmtpParameters& rustFmtpParameters = fmtp.parameters;
    727 
    728    UniquePtr<SdpFmtpAttributeList::Parameters> fmtpParameters;
    729 
    730    // use the upper case version of the codec name
    731    std::transform(codecName.begin(), codecName.end(), codecName.begin(),
    732                   ::toupper);
    733 
    734    if (codecName == "H264") {
    735      SdpFmtpAttributeList::H264Parameters h264Parameters;
    736 
    737      h264Parameters.packetization_mode = rustFmtpParameters.packetization_mode;
    738      h264Parameters.level_asymmetry_allowed =
    739          rustFmtpParameters.level_asymmetry_allowed;
    740      h264Parameters.profile_level_id = rustFmtpParameters.profile_level_id;
    741      h264Parameters.max_mbps = rustFmtpParameters.max_mbps;
    742      h264Parameters.max_fs = rustFmtpParameters.max_fs;
    743      h264Parameters.max_cpb = rustFmtpParameters.max_cpb;
    744      h264Parameters.max_dpb = rustFmtpParameters.max_dpb;
    745      h264Parameters.max_br = rustFmtpParameters.max_br;
    746 
    747      // TODO(bug 1466859): Support sprop-parameter-sets
    748 
    749      fmtpParameters.reset(
    750          new SdpFmtpAttributeList::H264Parameters(std::move(h264Parameters)));
    751    } else if (codecName == "OPUS") {
    752      SdpFmtpAttributeList::OpusParameters opusParameters;
    753 
    754      opusParameters.maxplaybackrate = rustFmtpParameters.maxplaybackrate;
    755      opusParameters.maxAverageBitrate = rustFmtpParameters.maxaveragebitrate;
    756      opusParameters.useDTX = rustFmtpParameters.usedtx;
    757      opusParameters.stereo = rustFmtpParameters.stereo;
    758      opusParameters.useInBandFec = rustFmtpParameters.useinbandfec;
    759      opusParameters.frameSizeMs = rustFmtpParameters.ptime;
    760      opusParameters.minFrameSizeMs = rustFmtpParameters.minptime;
    761      opusParameters.maxFrameSizeMs = rustFmtpParameters.maxptime;
    762      opusParameters.useCbr = rustFmtpParameters.cbr;
    763 
    764      fmtpParameters.reset(
    765          new SdpFmtpAttributeList::OpusParameters(std::move(opusParameters)));
    766    } else if ((codecName == "VP8") || (codecName == "VP9")) {
    767      SdpFmtpAttributeList::VP8Parameters vp8Parameters(
    768          codecName == "VP8" ? SdpRtpmapAttributeList::kVP8
    769                             : SdpRtpmapAttributeList::kVP9);
    770 
    771      vp8Parameters.max_fs = rustFmtpParameters.max_fs;
    772      vp8Parameters.max_fr = rustFmtpParameters.max_fr;
    773 
    774      fmtpParameters.reset(
    775          new SdpFmtpAttributeList::VP8Parameters(std::move(vp8Parameters)));
    776    } else if (codecName == "TELEPHONE-EVENT") {
    777      SdpFmtpAttributeList::TelephoneEventParameters telephoneEventParameters;
    778 
    779      telephoneEventParameters.dtmfTones =
    780          convertStringView(rustFmtpParameters.dtmf_tones);
    781 
    782      fmtpParameters.reset(new SdpFmtpAttributeList::TelephoneEventParameters(
    783          std::move(telephoneEventParameters)));
    784    } else if (codecName == "RED") {
    785      SdpFmtpAttributeList::RedParameters redParameters;
    786 
    787      redParameters.encodings = convertU8Vec(rustFmtpParameters.encodings);
    788 
    789      fmtpParameters.reset(
    790          new SdpFmtpAttributeList::RedParameters(std::move(redParameters)));
    791    } else if (codecName == "RTX") {
    792      SdpFmtpAttributeList::RtxParameters rtxParameters;
    793 
    794      rtxParameters.apt = rustFmtpParameters.rtx.apt;
    795      if (rustFmtpParameters.rtx.has_rtx_time) {
    796        rtxParameters.rtx_time = Some(rustFmtpParameters.rtx.rtx_time);
    797      }
    798 
    799      fmtpParameters.reset(
    800          new SdpFmtpAttributeList::RtxParameters(rtxParameters));
    801    } else if (codecName == "AV1") {
    802      SdpFmtpAttributeList::Av1Parameters av1Parameters;
    803 
    804      av1Parameters.profile = rustFmtpParameters.av1.has_profile
    805                                  ? Some(rustFmtpParameters.av1.profile)
    806                                  : Nothing();
    807      av1Parameters.levelIdx = rustFmtpParameters.av1.has_level_idx
    808                                   ? Some(rustFmtpParameters.av1.level_idx)
    809                                   : Nothing();
    810      av1Parameters.tier = rustFmtpParameters.av1.has_tier
    811                               ? Some(rustFmtpParameters.av1.tier)
    812                               : Nothing();
    813      fmtpParameters.reset(
    814          new SdpFmtpAttributeList::Av1Parameters(av1Parameters));
    815 
    816    } else {
    817      // The parameter set is unknown so skip it
    818      continue;
    819    }
    820    fmtpList->PushEntry(std::to_string(payloadType), *fmtpParameters);
    821  }
    822  SetAttribute(fmtpList.release());
    823 }
    824 
    825 void RsdparsaSdpAttributeList::LoadPtime(RustAttributeList* attributeList) {
    826  int64_t ptime = sdp_get_ptime(attributeList);
    827  if (ptime >= 0) {
    828    SetAttribute(new SdpNumberAttribute(SdpAttribute::kPtimeAttribute,
    829                                        static_cast<uint32_t>(ptime)));
    830  }
    831 }
    832 
    833 void RsdparsaSdpAttributeList::LoadFlags(RustAttributeList* attributeList) {
    834  RustSdpAttributeFlags flags = sdp_get_attribute_flags(attributeList);
    835  if (flags.iceLite) {
    836    SetAttribute(new SdpFlagAttribute(SdpAttribute::kIceLiteAttribute));
    837  }
    838  if (flags.rtcpMux) {
    839    SetAttribute(new SdpFlagAttribute(SdpAttribute::kRtcpMuxAttribute));
    840  }
    841  if (flags.rtcpRsize) {
    842    SetAttribute(new SdpFlagAttribute(SdpAttribute::kRtcpRsizeAttribute));
    843  }
    844  if (flags.bundleOnly) {
    845    SetAttribute(new SdpFlagAttribute(SdpAttribute::kBundleOnlyAttribute));
    846  }
    847  if (flags.endOfCandidates) {
    848    SetAttribute(new SdpFlagAttribute(SdpAttribute::kEndOfCandidatesAttribute));
    849  }
    850  if (flags.extmapAllowMixed) {
    851    SetAttribute(
    852        new SdpFlagAttribute(SdpAttribute::kExtmapAllowMixedAttribute));
    853  }
    854 }
    855 
    856 void RsdparsaSdpAttributeList::LoadMaxMessageSize(
    857    RustAttributeList* attributeList) {
    858  int64_t max_msg_size = sdp_get_max_msg_size(attributeList);
    859  if (max_msg_size >= 0) {
    860    SetAttribute(new SdpNumberAttribute(SdpAttribute::kMaxMessageSizeAttribute,
    861                                        static_cast<uint32_t>(max_msg_size)));
    862  }
    863 }
    864 
    865 void RsdparsaSdpAttributeList::LoadMid(RustAttributeList* attributeList) {
    866  StringView rustMid;
    867  if (NS_SUCCEEDED(sdp_get_mid(attributeList, &rustMid))) {
    868    std::string mid = convertStringView(rustMid);
    869    SetAttribute(new SdpStringAttribute(SdpAttribute::kMidAttribute, mid));
    870  }
    871 }
    872 
    873 void RsdparsaSdpAttributeList::LoadMsid(RustAttributeList* attributeList) {
    874  size_t numMsid = sdp_get_msid_count(attributeList);
    875  if (numMsid == 0) {
    876    return;
    877  }
    878  auto rustMsid = MakeUnique<RustSdpAttributeMsid[]>(numMsid);
    879  sdp_get_msids(attributeList, numMsid, rustMsid.get());
    880  auto msids = MakeUnique<SdpMsidAttributeList>();
    881  for (size_t i = 0; i < numMsid; i++) {
    882    RustSdpAttributeMsid& msid = rustMsid[i];
    883    std::string id = convertStringView(msid.id);
    884    std::string appdata = convertStringView(msid.appdata);
    885    msids->PushEntry(id, appdata);
    886  }
    887  SetAttribute(msids.release());
    888 }
    889 
    890 void RsdparsaSdpAttributeList::LoadMsidSemantics(
    891    RustAttributeList* attributeList) {
    892  size_t numMsidSemantic = sdp_get_msid_semantic_count(attributeList);
    893  if (numMsidSemantic == 0) {
    894    return;
    895  }
    896  auto rustMsidSemantics =
    897      MakeUnique<RustSdpAttributeMsidSemantic[]>(numMsidSemantic);
    898  sdp_get_msid_semantics(attributeList, numMsidSemantic,
    899                         rustMsidSemantics.get());
    900  auto msidSemantics = MakeUnique<SdpMsidSemanticAttributeList>();
    901  for (size_t i = 0; i < numMsidSemantic; i++) {
    902    RustSdpAttributeMsidSemantic& rustMsidSemantic = rustMsidSemantics[i];
    903    std::string semantic = convertStringView(rustMsidSemantic.semantic);
    904    std::vector<std::string> msids = convertStringVec(rustMsidSemantic.msids);
    905    msidSemantics->PushEntry(semantic, msids);
    906  }
    907  SetAttribute(msidSemantics.release());
    908 }
    909 
    910 void RsdparsaSdpAttributeList::LoadGroup(RustAttributeList* attributeList) {
    911  size_t numGroup = sdp_get_group_count(attributeList);
    912  if (numGroup == 0) {
    913    return;
    914  }
    915  auto rustGroups = MakeUnique<RustSdpAttributeGroup[]>(numGroup);
    916  sdp_get_groups(attributeList, numGroup, rustGroups.get());
    917  auto groups = MakeUnique<SdpGroupAttributeList>();
    918  for (size_t i = 0; i < numGroup; i++) {
    919    RustSdpAttributeGroup& group = rustGroups[i];
    920    SdpGroupAttributeList::Semantics semantic;
    921    switch (group.semantic) {
    922      case RustSdpAttributeGroupSemantic ::kRustLipSynchronization:
    923        semantic = SdpGroupAttributeList::kLs;
    924        break;
    925      case RustSdpAttributeGroupSemantic ::kRustFlowIdentification:
    926        semantic = SdpGroupAttributeList::kFid;
    927        break;
    928      case RustSdpAttributeGroupSemantic ::kRustSingleReservationFlow:
    929        semantic = SdpGroupAttributeList::kSrf;
    930        break;
    931      case RustSdpAttributeGroupSemantic ::kRustAlternateNetworkAddressType:
    932        semantic = SdpGroupAttributeList::kAnat;
    933        break;
    934      case RustSdpAttributeGroupSemantic ::kRustForwardErrorCorrection:
    935        semantic = SdpGroupAttributeList::kFec;
    936        break;
    937      case RustSdpAttributeGroupSemantic ::kRustDecodingDependency:
    938        semantic = SdpGroupAttributeList::kDdp;
    939        break;
    940      case RustSdpAttributeGroupSemantic ::kRustBundle:
    941        semantic = SdpGroupAttributeList::kBundle;
    942        break;
    943    }
    944    std::vector<std::string> tags = convertStringVec(group.tags);
    945    groups->PushEntry(semantic, tags);
    946  }
    947  SetAttribute(groups.release());
    948 }
    949 
    950 void RsdparsaSdpAttributeList::LoadRtcp(RustAttributeList* attributeList) {
    951  RustSdpAttributeRtcp rtcp;
    952  if (NS_SUCCEEDED(sdp_get_rtcp(attributeList, &rtcp))) {
    953    if (rtcp.has_address) {
    954      auto address = convertExplicitlyTypedAddress(&rtcp.unicastAddr);
    955      SetAttribute(new SdpRtcpAttribute(rtcp.port, sdp::kInternet,
    956                                        address.first, address.second));
    957    } else {
    958      SetAttribute(new SdpRtcpAttribute(rtcp.port));
    959    }
    960  }
    961 }
    962 
    963 void RsdparsaSdpAttributeList::LoadRtcpFb(RustAttributeList* attributeList) {
    964  auto rtcpfbsCount = sdp_get_rtcpfb_count(attributeList);
    965  if (!rtcpfbsCount) {
    966    return;
    967  }
    968 
    969  auto rustRtcpfbs = MakeUnique<RustSdpAttributeRtcpFb[]>(rtcpfbsCount);
    970  sdp_get_rtcpfbs(attributeList, rtcpfbsCount, rustRtcpfbs.get());
    971 
    972  auto rtcpfbList = MakeUnique<SdpRtcpFbAttributeList>();
    973  for (size_t i = 0; i < rtcpfbsCount; i++) {
    974    RustSdpAttributeRtcpFb& rtcpfb = rustRtcpfbs[i];
    975    uint32_t payloadTypeU32 = rtcpfb.payloadType;
    976 
    977    std::stringstream ss;
    978    if (payloadTypeU32 == std::numeric_limits<uint32_t>::max()) {
    979      ss << "*";
    980    } else {
    981      ss << payloadTypeU32;
    982    }
    983 
    984    uint32_t feedbackType = rtcpfb.feedbackType;
    985    std::string parameter = convertStringView(rtcpfb.parameter);
    986    std::string extra = convertStringView(rtcpfb.extra);
    987 
    988    rtcpfbList->PushEntry(
    989        ss.str(), static_cast<SdpRtcpFbAttributeList::Type>(feedbackType),
    990        parameter, extra);
    991  }
    992 
    993  SetAttribute(rtcpfbList.release());
    994 }
    995 
    996 SdpSimulcastAttribute::Versions LoadSimulcastVersions(
    997    const RustSdpAttributeSimulcastVersionVec* rustVersionList) {
    998  size_t rustVersionCount = sdp_simulcast_get_version_count(rustVersionList);
    999  auto rustVersionArray =
   1000      MakeUnique<RustSdpAttributeSimulcastVersion[]>(rustVersionCount);
   1001  sdp_simulcast_get_versions(rustVersionList, rustVersionCount,
   1002                             rustVersionArray.get());
   1003 
   1004  SdpSimulcastAttribute::Versions versions;
   1005 
   1006  for (size_t i = 0; i < rustVersionCount; i++) {
   1007    const RustSdpAttributeSimulcastVersion& rustVersion = rustVersionArray[i];
   1008    size_t rustIdCount = sdp_simulcast_get_ids_count(rustVersion.ids);
   1009    if (!rustIdCount) {
   1010      continue;
   1011    }
   1012 
   1013    SdpSimulcastAttribute::Version version;
   1014    auto rustIdArray = MakeUnique<RustSdpAttributeSimulcastId[]>(rustIdCount);
   1015    sdp_simulcast_get_ids(rustVersion.ids, rustIdCount, rustIdArray.get());
   1016 
   1017    for (size_t j = 0; j < rustIdCount; j++) {
   1018      const RustSdpAttributeSimulcastId& rustId = rustIdArray[j];
   1019      std::string id = convertStringView(rustId.id);
   1020      // TODO: Bug 1225877. Added support for 'paused'-state
   1021      version.choices.push_back(
   1022          SdpSimulcastAttribute::Encoding(id, rustId.paused));
   1023    }
   1024 
   1025    versions.push_back(version);
   1026  }
   1027 
   1028  return versions;
   1029 }
   1030 
   1031 void RsdparsaSdpAttributeList::LoadSimulcast(RustAttributeList* attributeList) {
   1032  RustSdpAttributeSimulcast rustSimulcast;
   1033  if (NS_SUCCEEDED(sdp_get_simulcast(attributeList, &rustSimulcast))) {
   1034    auto simulcast = MakeUnique<SdpSimulcastAttribute>();
   1035 
   1036    simulcast->sendVersions = LoadSimulcastVersions(rustSimulcast.send);
   1037    simulcast->recvVersions = LoadSimulcastVersions(rustSimulcast.recv);
   1038 
   1039    SetAttribute(simulcast.release());
   1040  }
   1041 }
   1042 
   1043 SdpImageattrAttributeList::XYRange LoadImageattrXYRange(
   1044    const RustSdpAttributeImageAttrXYRange& rustXYRange) {
   1045  SdpImageattrAttributeList::XYRange xyRange;
   1046 
   1047  if (!rustXYRange.discrete_values) {
   1048    xyRange.min = rustXYRange.min;
   1049    xyRange.max = rustXYRange.max;
   1050    xyRange.step = rustXYRange.step;
   1051 
   1052  } else {
   1053    xyRange.discreteValues = convertU32Vec(rustXYRange.discrete_values);
   1054  }
   1055 
   1056  return xyRange;
   1057 }
   1058 
   1059 std::vector<SdpImageattrAttributeList::Set> LoadImageattrSets(
   1060    const RustSdpAttributeImageAttrSetVec* rustSets) {
   1061  std::vector<SdpImageattrAttributeList::Set> sets;
   1062 
   1063  size_t rustSetCount = sdp_imageattr_get_set_count(rustSets);
   1064  if (!rustSetCount) {
   1065    return sets;
   1066  }
   1067 
   1068  auto rustSetArray = MakeUnique<RustSdpAttributeImageAttrSet[]>(rustSetCount);
   1069  sdp_imageattr_get_sets(rustSets, rustSetCount, rustSetArray.get());
   1070 
   1071  for (size_t i = 0; i < rustSetCount; i++) {
   1072    const RustSdpAttributeImageAttrSet& rustSet = rustSetArray[i];
   1073    SdpImageattrAttributeList::Set set;
   1074 
   1075    set.xRange = LoadImageattrXYRange(rustSet.x);
   1076    set.yRange = LoadImageattrXYRange(rustSet.y);
   1077 
   1078    if (rustSet.has_sar) {
   1079      if (!rustSet.sar.discrete_values) {
   1080        set.sRange.min = rustSet.sar.min;
   1081        set.sRange.max = rustSet.sar.max;
   1082      } else {
   1083        set.sRange.discreteValues = convertF32Vec(rustSet.sar.discrete_values);
   1084      }
   1085    }
   1086 
   1087    if (rustSet.has_par) {
   1088      set.pRange.min = rustSet.par.min;
   1089      set.pRange.max = rustSet.par.max;
   1090    }
   1091 
   1092    set.qValue = rustSet.q;
   1093 
   1094    sets.push_back(set);
   1095  }
   1096 
   1097  return sets;
   1098 }
   1099 
   1100 void RsdparsaSdpAttributeList::LoadImageattr(RustAttributeList* attributeList) {
   1101  size_t numImageattrs = sdp_get_imageattr_count(attributeList);
   1102  if (numImageattrs == 0) {
   1103    return;
   1104  }
   1105  auto rustImageattrs = MakeUnique<RustSdpAttributeImageAttr[]>(numImageattrs);
   1106  sdp_get_imageattrs(attributeList, numImageattrs, rustImageattrs.get());
   1107  auto imageattrList = MakeUnique<SdpImageattrAttributeList>();
   1108  for (size_t i = 0; i < numImageattrs; i++) {
   1109    const RustSdpAttributeImageAttr& rustImageAttr = rustImageattrs[i];
   1110 
   1111    SdpImageattrAttributeList::Imageattr imageAttr;
   1112 
   1113    if (rustImageAttr.payloadType != std::numeric_limits<uint32_t>::max()) {
   1114      imageAttr.pt = Some(rustImageAttr.payloadType);
   1115    }
   1116 
   1117    if (rustImageAttr.send.sets) {
   1118      imageAttr.sendSets = LoadImageattrSets(rustImageAttr.send.sets);
   1119    } else {
   1120      imageAttr.sendAll = true;
   1121    }
   1122 
   1123    if (rustImageAttr.recv.sets) {
   1124      imageAttr.recvSets = LoadImageattrSets(rustImageAttr.recv.sets);
   1125    } else {
   1126      imageAttr.recvAll = true;
   1127    }
   1128 
   1129    imageattrList->mImageattrs.push_back(imageAttr);
   1130  }
   1131  SetAttribute(imageattrList.release());
   1132 }
   1133 
   1134 void RsdparsaSdpAttributeList::LoadSctpmaps(RustAttributeList* attributeList) {
   1135  size_t numSctpmaps = sdp_get_sctpmap_count(attributeList);
   1136  if (numSctpmaps == 0) {
   1137    return;
   1138  }
   1139  auto rustSctpmaps = MakeUnique<RustSdpAttributeSctpmap[]>(numSctpmaps);
   1140  sdp_get_sctpmaps(attributeList, numSctpmaps, rustSctpmaps.get());
   1141  auto sctpmapList = MakeUnique<SdpSctpmapAttributeList>();
   1142  for (size_t i = 0; i < numSctpmaps; i++) {
   1143    RustSdpAttributeSctpmap& sctpmap = rustSctpmaps[i];
   1144    sctpmapList->PushEntry(std::to_string(sctpmap.port), "webrtc-datachannel",
   1145                           sctpmap.channels);
   1146  }
   1147  SetAttribute(sctpmapList.release());
   1148 }
   1149 
   1150 void RsdparsaSdpAttributeList::LoadDirection(RustAttributeList* attributeList) {
   1151  SdpDirectionAttribute::Direction dir;
   1152  RustDirection rustDir = sdp_get_direction(attributeList);
   1153  switch (rustDir) {
   1154    case RustDirection::kRustRecvonly:
   1155      dir = SdpDirectionAttribute::kRecvonly;
   1156      break;
   1157    case RustDirection::kRustSendonly:
   1158      dir = SdpDirectionAttribute::kSendonly;
   1159      break;
   1160    case RustDirection::kRustSendrecv:
   1161      dir = SdpDirectionAttribute::kSendrecv;
   1162      break;
   1163    case RustDirection::kRustInactive:
   1164      dir = SdpDirectionAttribute::kInactive;
   1165      break;
   1166  }
   1167  SetAttribute(new SdpDirectionAttribute(dir));
   1168 }
   1169 
   1170 void RsdparsaSdpAttributeList::LoadRemoteCandidates(
   1171    RustAttributeList* attributeList) {
   1172  size_t nC = sdp_get_remote_candidate_count(attributeList);
   1173  if (nC == 0) {
   1174    return;
   1175  }
   1176  auto rustCandidates = MakeUnique<RustSdpAttributeRemoteCandidate[]>(nC);
   1177  sdp_get_remote_candidates(attributeList, nC, rustCandidates.get());
   1178  std::vector<SdpRemoteCandidatesAttribute::Candidate> candidates;
   1179  for (size_t i = 0; i < nC; i++) {
   1180    RustSdpAttributeRemoteCandidate& rustCandidate = rustCandidates[i];
   1181    SdpRemoteCandidatesAttribute::Candidate candidate;
   1182    candidate.port = rustCandidate.port;
   1183    candidate.id = std::to_string(rustCandidate.component);
   1184    candidate.address = convertAddress(&rustCandidate.address);
   1185    candidates.push_back(candidate);
   1186  }
   1187  SdpRemoteCandidatesAttribute* candidatesList;
   1188  candidatesList = new SdpRemoteCandidatesAttribute(candidates);
   1189  SetAttribute(candidatesList);
   1190 }
   1191 
   1192 void RsdparsaSdpAttributeList::LoadRids(RustAttributeList* attributeList) {
   1193  size_t numRids = sdp_get_rid_count(attributeList);
   1194  if (numRids == 0) {
   1195    return;
   1196  }
   1197 
   1198  auto rustRids = MakeUnique<RustSdpAttributeRid[]>(numRids);
   1199  sdp_get_rids(attributeList, numRids, rustRids.get());
   1200 
   1201  auto ridList = MakeUnique<SdpRidAttributeList>();
   1202  for (size_t i = 0; i < numRids; i++) {
   1203    const RustSdpAttributeRid& rid = rustRids[i];
   1204 
   1205    std::string id = convertStringView(rid.id);
   1206    auto direction = static_cast<sdp::Direction>(rid.direction);
   1207    std::vector<uint16_t> formats = convertU16Vec(rid.formats);
   1208 
   1209    VideoEncodingConstraints parameters;
   1210    parameters.maxWidth = rid.params.max_width;
   1211    parameters.maxHeight = rid.params.max_height;
   1212    // Right now, we treat max-fps=0 and the absence of max-fps as no limit.
   1213    // We will eventually want to treat max-fps=0 as 0 frames per second, and
   1214    // the absence of max-fps as no limit (bug 1762632).
   1215    if (rid.params.max_fps) {
   1216      parameters.maxFps = Some(rid.params.max_fps);
   1217    }
   1218    parameters.maxFs = rid.params.max_fs;
   1219    parameters.maxBr = rid.params.max_br;
   1220    parameters.maxPps = rid.params.max_pps;
   1221 
   1222    std::vector<std::string> depends = convertStringVec(rid.depends);
   1223 
   1224    ridList->PushEntry(id, direction, formats, parameters, depends);
   1225  }
   1226 
   1227  SetAttribute(ridList.release());
   1228 }
   1229 
   1230 void RsdparsaSdpAttributeList::LoadSctpPort(RustAttributeList* attributeList) {
   1231  int64_t port = sdp_get_sctp_port(attributeList);
   1232  if (port >= 0) {
   1233    SetAttribute(new SdpNumberAttribute(SdpAttribute::kSctpPortAttribute,
   1234                                        static_cast<uint32_t>(port)));
   1235  }
   1236 }
   1237 
   1238 void RsdparsaSdpAttributeList::LoadExtmap(RustAttributeList* attributeList) {
   1239  size_t numExtmap = sdp_get_extmap_count(attributeList);
   1240  if (numExtmap == 0) {
   1241    return;
   1242  }
   1243  auto rustExtmaps = MakeUnique<RustSdpAttributeExtmap[]>(numExtmap);
   1244  sdp_get_extmaps(attributeList, numExtmap, rustExtmaps.get());
   1245  auto extmaps = MakeUnique<SdpExtmapAttributeList>();
   1246  for (size_t i = 0; i < numExtmap; i++) {
   1247    RustSdpAttributeExtmap& rustExtmap = rustExtmaps[i];
   1248    std::string name = convertStringView(rustExtmap.url);
   1249    SdpDirectionAttribute::Direction direction;
   1250    bool directionSpecified = rustExtmap.direction_specified;
   1251    switch (rustExtmap.direction) {
   1252      case RustDirection::kRustRecvonly:
   1253        direction = SdpDirectionAttribute::kRecvonly;
   1254        break;
   1255      case RustDirection::kRustSendonly:
   1256        direction = SdpDirectionAttribute::kSendonly;
   1257        break;
   1258      case RustDirection::kRustSendrecv:
   1259        direction = SdpDirectionAttribute::kSendrecv;
   1260        break;
   1261      case RustDirection::kRustInactive:
   1262        direction = SdpDirectionAttribute::kInactive;
   1263        break;
   1264    }
   1265    std::string extensionAttributes;
   1266    extensionAttributes = convertStringView(rustExtmap.extensionAttributes);
   1267    extmaps->PushEntry((uint16_t)rustExtmap.id, direction, directionSpecified,
   1268                       name, extensionAttributes);
   1269  }
   1270  SetAttribute(extmaps.release());
   1271 }
   1272 
   1273 void RsdparsaSdpAttributeList::LoadMaxPtime(RustAttributeList* attributeList) {
   1274  uint64_t maxPtime = 0;
   1275  nsresult nr = sdp_get_maxptime(attributeList, &maxPtime);
   1276  if (NS_SUCCEEDED(nr)) {
   1277    SetAttribute(
   1278        new SdpNumberAttribute(SdpAttribute::kMaxptimeAttribute, maxPtime));
   1279  }
   1280 }
   1281 
   1282 void RsdparsaSdpAttributeList::LoadCandidate(RustAttributeList* attributeList) {
   1283  size_t candidatesCount = sdp_get_candidate_count(attributeList);
   1284  if (!candidatesCount) {
   1285    return;
   1286  }
   1287 
   1288  StringVec* rustCandidatesStrings;
   1289  sdp_get_candidates(attributeList, candidatesCount, &rustCandidatesStrings);
   1290 
   1291  std::vector<std::string> candidatesStrings =
   1292      convertStringVec(rustCandidatesStrings);
   1293  free_boxed_string_vec(rustCandidatesStrings);
   1294 
   1295  auto candidates =
   1296      MakeUnique<SdpMultiStringAttribute>(SdpAttribute::kCandidateAttribute);
   1297  candidates->mValues = candidatesStrings;
   1298 
   1299  SetAttribute(candidates.release());
   1300 }
   1301 
   1302 bool RsdparsaSdpAttributeList::IsAllowedHere(SdpAttribute::AttributeType type) {
   1303  if (AtSessionLevel() && !SdpAttribute::IsAllowedAtSessionLevel(type)) {
   1304    return false;
   1305  }
   1306 
   1307  if (!AtSessionLevel() && !SdpAttribute::IsAllowedAtMediaLevel(type)) {
   1308    return false;
   1309  }
   1310 
   1311  return true;
   1312 }
   1313 
   1314 void RsdparsaSdpAttributeList::Serialize(std::ostream& os) const {
   1315  for (size_t i = 0; i < kNumAttributeTypes; ++i) {
   1316    if (mAttributes[i]) {
   1317      os << *mAttributes[i];
   1318    }
   1319  }
   1320 }
   1321 
   1322 }  // namespace mozilla