Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  RsdparsaSdpAttributeList.cpp

  Sprache: C
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "sdp/RsdparsaSdpAttributeList.h"

#include <limits>
#include <ostream>

#include "SdpAttribute.h"
#include "mozilla/Assertions.h"
#include "nsCRT.h"
#include "nsTArray.h"
#include "sdp/RsdparsaSdpGlue.h"
#include "sdp/RsdparsaSdpInc.h"

namespace mozilla {

namespace ffi = mozilla::sdp::ffi;

MOZ_GLIBCXX_CONSTINIT const std::string RsdparsaSdpAttributeList::kEmptyString;

bool RsdparsaSdpAttributeList::HasAttribute(const AttributeType type,
                                            const bool sessionFallback) const {
  return !!GetAttribute(type, sessionFallback);
}

const SdpAttribute* RsdparsaSdpAttributeList::GetAttribute(
    const AttributeType type, const bool sessionFallback) const {
  const SdpAttribute* value = mAttributes[static_cast<size_t>(type)].get();
  // Only do fallback when the attribute can appear at both the media and
  // session level
  if (!value && !AtSessionLevel() && sessionFallback &&
      SdpAttribute::IsAllowedAtSessionLevel(type) &&
      SdpAttribute::IsAllowedAtMediaLevel(type)) {
    return mSessionAttributes->GetAttribute(type, false);
  }
  return value;
}

void RsdparsaSdpAttributeList::RemoveAttribute(const AttributeType type) {
  mAttributes[static_cast<size_t>(type)] = nullptr;
}

void RsdparsaSdpAttributeList::Clear() {
  for (size_t i = 0; i < kNumAttributeTypes; ++i) {
    RemoveAttribute(static_cast<AttributeType>(i));
  }
}

uint32_t RsdparsaSdpAttributeList::Count() const {
  uint32_t count = 0;
  for (auto& mAttribute : mAttributes) {
    if (mAttribute) {
      count++;
    }
  }
  return count;
}

void RsdparsaSdpAttributeList::SetAttribute(UniquePtr<SdpAttribute>&& attr) {
  if (!IsAllowedHere(attr->GetType())) {
    MOZ_ASSERT(false"This type of attribute is not allowed here");
    return;
  }
  mAttributes[attr->GetType()] = std::move(attr);
}

const std::vector<std::string>& RsdparsaSdpAttributeList::GetCandidate() const {
  if (!HasAttribute(SdpAttribute::kCandidateAttribute)) {
    MOZ_CRASH();
  }

  return static_cast<const SdpMultiStringAttribute*>(
             GetAttribute(SdpAttribute::kCandidateAttribute))
      ->mValues;
}

const SdpConnectionAttribute& RsdparsaSdpAttributeList::GetConnection() const {
  if (!HasAttribute(SdpAttribute::kConnectionAttribute)) {
    MOZ_CRASH();
  }

  return *static_cast<const SdpConnectionAttribute*>(
      GetAttribute(SdpAttribute::kConnectionAttribute));
}

SdpDirectionAttribute::Direction RsdparsaSdpAttributeList::GetDirection()
    const {
  if (!HasAttribute(SdpAttribute::kDirectionAttribute)) {
    MOZ_CRASH();
  }

  const SdpAttribute* attr = GetAttribute(SdpAttribute::kDirectionAttribute);
  return static_cast<const SdpDirectionAttribute*>(attr)->mValue;
}

const SdpDtlsMessageAttribute& RsdparsaSdpAttributeList::GetDtlsMessage()
    const {
  if (!HasAttribute(SdpAttribute::kDtlsMessageAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kDtlsMessageAttribute);
  return *static_cast<const SdpDtlsMessageAttribute*>(attr);
}

const SdpExtmapAttributeList& RsdparsaSdpAttributeList::GetExtmap() const {
  if (!HasAttribute(SdpAttribute::kExtmapAttribute)) {
    MOZ_CRASH();
  }

  return *static_cast<const SdpExtmapAttributeList*>(
      GetAttribute(SdpAttribute::kExtmapAttribute));
}

const SdpFingerprintAttributeList& RsdparsaSdpAttributeList::GetFingerprint()
    const {
  if (!HasAttribute(SdpAttribute::kFingerprintAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kFingerprintAttribute);
  return *static_cast<const SdpFingerprintAttributeList*>(attr);
}

const SdpFmtpAttributeList& RsdparsaSdpAttributeList::GetFmtp() const {
  if (!HasAttribute(SdpAttribute::kFmtpAttribute)) {
    MOZ_CRASH();
  }

  return *static_cast<const SdpFmtpAttributeList*>(
      GetAttribute(SdpAttribute::kFmtpAttribute));
}

const SdpGroupAttributeList& RsdparsaSdpAttributeList::GetGroup() const {
  if (!HasAttribute(SdpAttribute::kGroupAttribute)) {
    MOZ_CRASH();
  }

  return *static_cast<const SdpGroupAttributeList*>(
      GetAttribute(SdpAttribute::kGroupAttribute));
}

const SdpOptionsAttribute& RsdparsaSdpAttributeList::GetIceOptions() const {
  if (!HasAttribute(SdpAttribute::kIceOptionsAttribute)) {
    MOZ_CRASH();
  }

  const SdpAttribute* attr = GetAttribute(SdpAttribute::kIceOptionsAttribute);
  return *static_cast<const SdpOptionsAttribute*>(attr);
}

const std::string& RsdparsaSdpAttributeList::GetIcePwd() const {
  if (!HasAttribute(SdpAttribute::kIcePwdAttribute)) {
    return kEmptyString;
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kIcePwdAttribute);
  return static_cast<const SdpStringAttribute*>(attr)->mValue;
}

const std::string& RsdparsaSdpAttributeList::GetIceUfrag() const {
  if (!HasAttribute(SdpAttribute::kIceUfragAttribute)) {
    return kEmptyString;
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kIceUfragAttribute);
  return static_cast<const SdpStringAttribute*>(attr)->mValue;
}

const std::string& RsdparsaSdpAttributeList::GetIdentity() const {
  if (!HasAttribute(SdpAttribute::kIdentityAttribute)) {
    return kEmptyString;
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kIdentityAttribute);
  return static_cast<const SdpStringAttribute*>(attr)->mValue;
}

const SdpImageattrAttributeList& RsdparsaSdpAttributeList::GetImageattr()
    const {
  if (!HasAttribute(SdpAttribute::kImageattrAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kImageattrAttribute);
  return *static_cast<const SdpImageattrAttributeList*>(attr);
}

const SdpSimulcastAttribute& RsdparsaSdpAttributeList::GetSimulcast() const {
  if (!HasAttribute(SdpAttribute::kSimulcastAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSimulcastAttribute);
  return *static_cast<const SdpSimulcastAttribute*>(attr);
}

const std::string& RsdparsaSdpAttributeList::GetLabel() const {
  if (!HasAttribute(SdpAttribute::kLabelAttribute)) {
    return kEmptyString;
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kLabelAttribute);
  return static_cast<const SdpStringAttribute*>(attr)->mValue;
}

uint32_t RsdparsaSdpAttributeList::GetMaxptime() const {
  if (!HasAttribute(SdpAttribute::kMaxptimeAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kMaxptimeAttribute);
  return static_cast<const SdpNumberAttribute*>(attr)->mValue;
}

const std::string& RsdparsaSdpAttributeList::GetMid() const {
  if (!HasAttribute(SdpAttribute::kMidAttribute)) {
    return kEmptyString;
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kMidAttribute);
  return static_cast<const SdpStringAttribute*>(attr)->mValue;
}

const SdpMsidAttributeList& RsdparsaSdpAttributeList::GetMsid() const {
  if (!HasAttribute(SdpAttribute::kMsidAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kMsidAttribute);
  return *static_cast<const SdpMsidAttributeList*>(attr);
}

const SdpMsidSemanticAttributeList& RsdparsaSdpAttributeList::GetMsidSemantic()
    const {
  if (!HasAttribute(SdpAttribute::kMsidSemanticAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kMsidSemanticAttribute);
  return *static_cast<const SdpMsidSemanticAttributeList*>(attr);
}

const SdpRidAttributeList& RsdparsaSdpAttributeList::GetRid() const {
  if (!HasAttribute(SdpAttribute::kRidAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kRidAttribute);
  return *static_cast<const SdpRidAttributeList*>(attr);
}

uint32_t RsdparsaSdpAttributeList::GetPtime() const {
  if (!HasAttribute(SdpAttribute::kPtimeAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kPtimeAttribute);
  return static_cast<const SdpNumberAttribute*>(attr)->mValue;
}

const SdpRtcpAttribute& RsdparsaSdpAttributeList::GetRtcp() const {
  if (!HasAttribute(SdpAttribute::kRtcpAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtcpAttribute);
  return *static_cast<const SdpRtcpAttribute*>(attr);
}

const SdpRtcpFbAttributeList& RsdparsaSdpAttributeList::GetRtcpFb() const {
  if (!HasAttribute(SdpAttribute::kRtcpFbAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtcpFbAttribute);
  return *static_cast<const SdpRtcpFbAttributeList*>(attr);
}

const SdpRemoteCandidatesAttribute&
RsdparsaSdpAttributeList::GetRemoteCandidates() const {
  MOZ_CRASH("Not yet implemented");
}

const SdpRtpmapAttributeList& RsdparsaSdpAttributeList::GetRtpmap() const {
  if (!HasAttribute(SdpAttribute::kRtpmapAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtpmapAttribute);
  return *static_cast<const SdpRtpmapAttributeList*>(attr);
}

const SdpSctpmapAttributeList& RsdparsaSdpAttributeList::GetSctpmap() const {
  if (!HasAttribute(SdpAttribute::kSctpmapAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSctpmapAttribute);
  return *static_cast<const SdpSctpmapAttributeList*>(attr);
}

uint32_t RsdparsaSdpAttributeList::GetSctpPort() const {
  if (!HasAttribute(SdpAttribute::kSctpPortAttribute)) {
    MOZ_CRASH();
  }

  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSctpPortAttribute);
  return static_cast<const SdpNumberAttribute*>(attr)->mValue;
}

uint32_t RsdparsaSdpAttributeList::GetMaxMessageSize() const {
  if (!HasAttribute(SdpAttribute::kMaxMessageSizeAttribute)) {
    MOZ_CRASH();
  }

  const SdpAttribute* attr =
      GetAttribute(SdpAttribute::kMaxMessageSizeAttribute);
  return static_cast<const SdpNumberAttribute*>(attr)->mValue;
}

const SdpSetupAttribute& RsdparsaSdpAttributeList::GetSetup() const {
  if (!HasAttribute(SdpAttribute::kSetupAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSetupAttribute);
  return *static_cast<const SdpSetupAttribute*>(attr);
}

const SdpSsrcAttributeList& RsdparsaSdpAttributeList::GetSsrc() const {
  if (!HasAttribute(SdpAttribute::kSsrcAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSsrcAttribute);
  return *static_cast<const SdpSsrcAttributeList*>(attr);
}

const SdpSsrcGroupAttributeList& RsdparsaSdpAttributeList::GetSsrcGroup()
    const {
  if (!HasAttribute(SdpAttribute::kSsrcGroupAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSsrcGroupAttribute);
  return *static_cast<const SdpSsrcGroupAttributeList*>(attr);
}

void RsdparsaSdpAttributeList::LoadAttribute(RustAttributeList* attributeList,
                                             const AttributeType type) {
  if (!mAttributes[type]) {
    switch (type) {
      case SdpAttribute::kIceUfragAttribute:
        LoadIceUfrag(attributeList);
        return;
      case SdpAttribute::kIcePwdAttribute:
        LoadIcePwd(attributeList);
        return;
      case SdpAttribute::kIceOptionsAttribute:
        LoadIceOptions(attributeList);
        return;
      case SdpAttribute::kDtlsMessageAttribute:
        LoadDtlsMessage(attributeList);
        return;
      case SdpAttribute::kFingerprintAttribute:
        LoadFingerprint(attributeList);
        return;
      case SdpAttribute::kIdentityAttribute:
        LoadIdentity(attributeList);
        return;
      case SdpAttribute::kSetupAttribute:
        LoadSetup(attributeList);
        return;
      case SdpAttribute::kSsrcAttribute:
        LoadSsrc(attributeList);
        return;
      case SdpAttribute::kRtpmapAttribute:
        LoadRtpmap(attributeList);
        return;
      case SdpAttribute::kFmtpAttribute:
        LoadFmtp(attributeList);
        return;
      case SdpAttribute::kPtimeAttribute:
        LoadPtime(attributeList);
        return;
      case SdpAttribute::kIceLiteAttribute:
      case SdpAttribute::kRtcpMuxAttribute:
      case SdpAttribute::kRtcpRsizeAttribute:
      case SdpAttribute::kBundleOnlyAttribute:
      case SdpAttribute::kEndOfCandidatesAttribute:
      case SdpAttribute::kExtmapAllowMixedAttribute:
        LoadFlags(attributeList);
        return;
      case SdpAttribute::kMaxMessageSizeAttribute:
        LoadMaxMessageSize(attributeList);
        return;
      case SdpAttribute::kMidAttribute:
        LoadMid(attributeList);
        return;
      case SdpAttribute::kMsidAttribute:
        LoadMsid(attributeList);
        return;
      case SdpAttribute::kMsidSemanticAttribute:
        LoadMsidSemantics(attributeList);
        return;
      case SdpAttribute::kGroupAttribute:
        LoadGroup(attributeList);
        return;
      case SdpAttribute::kRtcpAttribute:
        LoadRtcp(attributeList);
        return;
      case SdpAttribute::kRtcpFbAttribute:
        LoadRtcpFb(attributeList);
        return;
      case SdpAttribute::kImageattrAttribute:
        LoadImageattr(attributeList);
        return;
      case SdpAttribute::kSctpmapAttribute:
        LoadSctpmaps(attributeList);
        return;
      case SdpAttribute::kDirectionAttribute:
        LoadDirection(attributeList);
        return;
      case SdpAttribute::kRemoteCandidatesAttribute:
        LoadRemoteCandidates(attributeList);
        return;
      case SdpAttribute::kRidAttribute:
        LoadRids(attributeList);
        return;
      case SdpAttribute::kSctpPortAttribute:
        LoadSctpPort(attributeList);
        return;
      case SdpAttribute::kExtmapAttribute:
        LoadExtmap(attributeList);
        return;
      case SdpAttribute::kSimulcastAttribute:
        LoadSimulcast(attributeList);
        return;
      case SdpAttribute::kMaxptimeAttribute:
        LoadMaxPtime(attributeList);
        return;
      case SdpAttribute::kCandidateAttribute:
        LoadCandidate(attributeList);
        return;
      case SdpAttribute::kSsrcGroupAttribute:
        LoadSsrcGroup(attributeList);
        return;
      case SdpAttribute::kConnectionAttribute:
      case SdpAttribute::kIceMismatchAttribute:
      case SdpAttribute::kLabelAttribute:
        // These attributes are unused
        return;
    }
  }
}

void RsdparsaSdpAttributeList::LoadAll(RustAttributeList* attributeList) {
  for (int i = SdpAttribute::kFirstAttribute; i <= SdpAttribute::kLastAttribute;
       i++) {
    LoadAttribute(attributeList, static_cast<SdpAttribute::AttributeType>(i));
  }
}

void RsdparsaSdpAttributeList::LoadIceUfrag(RustAttributeList* attributeList) {
  ffi::StringView ufragStr;
  nsresult nr = sdp_get_iceufrag(attributeList, &ufragStr);
  if (NS_SUCCEEDED(nr)) {
    SetAttribute(MakeUnique<SdpStringAttribute>(
        SdpAttribute::kIceUfragAttribute,
        std::string(convertStringView(ufragStr))));
  }
}

void RsdparsaSdpAttributeList::LoadIcePwd(RustAttributeList* attributeList) {
  ffi::StringView pwdStr;
  nsresult nr = sdp_get_icepwd(attributeList, &pwdStr);
  if (NS_SUCCEEDED(nr)) {
    SetAttribute(
        MakeUnique<SdpStringAttribute>(SdpAttribute::kIcePwdAttribute,
                                       std::string(convertStringView(pwdStr))));
  }
}

void RsdparsaSdpAttributeList::LoadIdentity(RustAttributeList* attributeList) {
  ffi::StringView identityStr;
  nsresult nr = sdp_get_identity(attributeList, &identityStr);
  if (NS_SUCCEEDED(nr)) {
    SetAttribute(MakeUnique<SdpStringAttribute>(
        SdpAttribute::kIdentityAttribute,
        std::string(convertStringView(identityStr))));
  }
}

void RsdparsaSdpAttributeList::LoadIceOptions(
    RustAttributeList* attributeList) {
  AutoTArray<ffi::StringView, 8> optionsArray;
  nsresult nr = sdp_get_iceoptions(attributeList, &optionsArray);
  if (NS_SUCCEEDED(nr)) {
    auto optionsAttr =
        MakeUnique<SdpOptionsAttribute>(SdpAttribute::kIceOptionsAttribute);
    for (const auto& view : optionsArray) {
      optionsAttr->PushEntry(std::string(convertStringView(view)));
    }
    SetAttribute(std::move(optionsAttr));
  }
}

void RsdparsaSdpAttributeList::LoadFingerprint(
    RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpAttributeFingerprint, 8> fingerprintsArray;
  sdp_get_fingerprints(attributeList, &fingerprintsArray);
  if (fingerprintsArray.IsEmpty()) {
    return;
  }
  auto fingerprints = MakeUnique<SdpFingerprintAttributeList>();
  for (const auto& rustFingerprint : fingerprintsArray) {
    std::string algorithm;
    switch (rustFingerprint.hash_algorithm) {
      case ffi::RustSdpAttributeFingerprintHashAlgorithm::Sha1:
        algorithm = "sha-1";
        break;
      case ffi::RustSdpAttributeFingerprintHashAlgorithm::Sha224:
        algorithm = "sha-224";
        break;
      case ffi::RustSdpAttributeFingerprintHashAlgorithm::Sha256:
        algorithm = "sha-256";
        break;
      case ffi::RustSdpAttributeFingerprintHashAlgorithm::Sha384:
        algorithm = "sha-384";
        break;
      case ffi::RustSdpAttributeFingerprintHashAlgorithm::Sha512:
        algorithm = "sha-512";
        break;
    }
    auto span = convertRustSpan(rustFingerprint.fingerprint);
    std::vector<uint8_t> fingerprint(span.begin(), span.end());
    fingerprints->PushEntry(std::move(algorithm), fingerprint);
  }
  SetAttribute(std::move(fingerprints));
}

void RsdparsaSdpAttributeList::LoadDtlsMessage(
    RustAttributeList* attributeList) {
  ffi::RustSdpAttributeDtlsMessage rustDtlsMessage;
  nsresult nr = sdp_get_dtls_message(attributeList, &rustDtlsMessage);
  if (NS_SUCCEEDED(nr)) {
    SdpDtlsMessageAttribute::Role role;
    if (rustDtlsMessage.role == ffi::RustSdpAttributeDtlsMessageRole::Client) {
      role = SdpDtlsMessageAttribute::kClient;
    } else {
      role = SdpDtlsMessageAttribute::kServer;
    }
    SetAttribute(MakeUnique<SdpDtlsMessageAttribute>(
        role, std::string(convertStringView(rustDtlsMessage.value))));
  }
}

void RsdparsaSdpAttributeList::LoadSetup(RustAttributeList* attributeList) {
  ffi::RustSdpAttributeSetup rustSetup;
  nsresult nr = sdp_get_setup(attributeList, &rustSetup);
  if (NS_SUCCEEDED(nr)) {
    SdpSetupAttribute::Role setupEnum;
    switch (rustSetup) {
      case ffi::RustSdpAttributeSetup::Active:
        setupEnum = SdpSetupAttribute::kActive;
        break;
      case ffi::RustSdpAttributeSetup::Actpass:
        setupEnum = SdpSetupAttribute::kActpass;
        break;
      case ffi::RustSdpAttributeSetup::Holdconn:
        setupEnum = SdpSetupAttribute::kHoldconn;
        break;
      case ffi::RustSdpAttributeSetup::Passive:
        setupEnum = SdpSetupAttribute::kPassive;
        break;
    }
    SetAttribute(MakeUnique<SdpSetupAttribute>(setupEnum));
  }
}

void RsdparsaSdpAttributeList::LoadSsrc(RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpAttributeSsrc, 8> rustSsrcs;
  sdp_get_ssrcs(attributeList, &rustSsrcs);
  if (rustSsrcs.IsEmpty()) {
    return;
  }
  auto ssrcs = MakeUnique<SdpSsrcAttributeList>();
  for (const auto& ssrc : rustSsrcs) {
    std::string attribute(convertStringView(ssrc.attribute));
    std::string value(convertStringView(ssrc.value));
    if (value.empty()) {
      ssrcs->PushEntry(ssrc.id, attribute);
    } else {
      std::string entry{std::move(attribute)};
      entry.push_back(':');
      entry.append(value);
      ssrcs->PushEntry(ssrc.id, entry);
    }
  }
  SetAttribute(std::move(ssrcs));
}

void RsdparsaSdpAttributeList::LoadSsrcGroup(RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpSsrcGroup, 8> rustSsrcGroups;
  sdp_get_ssrc_groups(attributeList, &rustSsrcGroups);
  if (rustSsrcGroups.IsEmpty()) {
    return;
  }
  auto ssrcGroups = MakeUnique<SdpSsrcGroupAttributeList>();
  for (const auto& ssrcGroup : rustSsrcGroups) {
    SdpSsrcGroupAttributeList::Semantics semantic;
    switch (ssrcGroup.semantic) {
      case ffi::RustSdpSsrcGroupSemantic::Duplication:
        semantic = SdpSsrcGroupAttributeList::kDup;
        break;
      case ffi::RustSdpSsrcGroupSemantic::ForwardErrorCorrection:
        semantic = SdpSsrcGroupAttributeList::kFec;
        break;
      case ffi::RustSdpSsrcGroupSemantic::ForwardErrorCorrectionFr:
        semantic = SdpSsrcGroupAttributeList::kFecFr;
        break;
      case ffi::RustSdpSsrcGroupSemantic::FlowIdentification:
        semantic = SdpSsrcGroupAttributeList::kFid;
        break;
      case ffi::RustSdpSsrcGroupSemantic::SIM:
        semantic = SdpSsrcGroupAttributeList::kSim;
        break;
    }
    std::vector<uint32_t> ssrcs(ssrcGroup.ssrcs.begin(), ssrcGroup.ssrcs.end());
    ssrcGroups->PushEntry(semantic, ssrcs);
  }
  SetAttribute(std::move(ssrcGroups));
}

struct FmtDefaults {
  uint32_t minimumChannels = 0;
};

std::tuple<SdpRtpmapAttributeList::CodecType, FmtDefaults> strToCodecType(
    const std::string& name) {
  auto codec = SdpRtpmapAttributeList::kOtherCodec;
  FmtDefaults defaults = {0};  // This is tracked to match SIPCC behavior only
  if (!nsCRT::strcasecmp(name.c_str(), "opus")) {
    codec = SdpRtpmapAttributeList::kOpus;
    defaults = {0};
  } else if (!nsCRT::strcasecmp(name.c_str(), "G722")) {
    codec = SdpRtpmapAttributeList::kG722;
    defaults = {1};
  } else if (!nsCRT::strcasecmp(name.c_str(), "PCMU")) {
    codec = SdpRtpmapAttributeList::kPCMU;
    defaults = {1};
  } else if (!nsCRT::strcasecmp(name.c_str(), "PCMA")) {
    codec = SdpRtpmapAttributeList::kPCMA;
    defaults = {1};
  } else if (!nsCRT::strcasecmp(name.c_str(), "VP8")) {
    codec = SdpRtpmapAttributeList::kVP8;
    defaults = {0};
  } else if (!nsCRT::strcasecmp(name.c_str(), "VP9")) {
    codec = SdpRtpmapAttributeList::kVP9;
    defaults = {0};
  } else if (!nsCRT::strcasecmp(name.c_str(), "iLBC")) {
    codec = SdpRtpmapAttributeList::kiLBC;
    defaults = {1};
  } else if (!nsCRT::strcasecmp(name.c_str(), "iSAC")) {
    codec = SdpRtpmapAttributeList::kiSAC;
    defaults = {1};
  } else if (!nsCRT::strcasecmp(name.c_str(), "H264")) {
    codec = SdpRtpmapAttributeList::kH264;
    defaults = {0};
  } else if (!nsCRT::strcasecmp(name.c_str(), "red")) {
    codec = SdpRtpmapAttributeList::kRed;
    defaults = {0};
  } else if (!nsCRT::strcasecmp(name.c_str(), "ulpfec")) {
    codec = SdpRtpmapAttributeList::kUlpfec;
    defaults = {0};
  } else if (!nsCRT::strcasecmp(name.c_str(), "telephone-event")) {
    codec = SdpRtpmapAttributeList::kTelephoneEvent;
    defaults = {1};
  } else if (!nsCRT::strcasecmp(name.c_str(), "rtx")) {
    codec = SdpRtpmapAttributeList::kRtx;
    defaults = {0};
  }
  return std::make_tuple(codec, defaults);
}

void RsdparsaSdpAttributeList::LoadRtpmap(RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpAttributeRtpmap, 8> rustRtpmaps;
  sdp_get_rtpmaps(attributeList, &rustRtpmaps);
  if (rustRtpmaps.IsEmpty()) {
    return;
  }
  auto rtpmapList = MakeUnique<SdpRtpmapAttributeList>();
  for (const auto& rtpmap : rustRtpmaps) {
    std::string payloadType = std::to_string(rtpmap.payload_type);
    std::string name(convertStringView(rtpmap.codec_name));
    auto [codec, defaults] = strToCodecType(name);
    uint32_t channels = rtpmap.channels;
    if (channels == 0) {
      channels = defaults.minimumChannels;
    }
    rtpmapList->PushEntry(payloadType, codec, name, rtpmap.frequency, channels);
  }
  SetAttribute(std::move(rtpmapList));
}

void RsdparsaSdpAttributeList::LoadFmtp(RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpAttributeFmtp, 8> rustFmtps;
  sdp_get_fmtp(attributeList, &rustFmtps);
  if (rustFmtps.IsEmpty()) {
    return;
  }
  auto fmtpList = MakeUnique<SdpFmtpAttributeList>();
  for (const auto& fmtp : rustFmtps) {
    uint8_t payloadType = fmtp.payload_type;
    std::string codecName(convertStringView(fmtp.codec_name));
    const ffi::RustSdpAttributeFmtpParameters& rustFmtpParameters =
        fmtp.parameters;

    UniquePtr<SdpFmtpAttributeList::Parameters> fmtpParameters;

    // use the upper case version of the codec name
    std::transform(codecName.begin(), codecName.end(), codecName.begin(),
                   ::toupper);

    if (codecName == "H264") {
      SdpFmtpAttributeList::H264Parameters h264Parameters;

      h264Parameters.packetization_mode = rustFmtpParameters.packetization_mode;
      h264Parameters.level_asymmetry_allowed =
          rustFmtpParameters.level_asymmetry_allowed;
      h264Parameters.profile_level_id = rustFmtpParameters.profile_level_id;
      h264Parameters.max_mbps = rustFmtpParameters.max_mbps;
      h264Parameters.max_fs = rustFmtpParameters.max_fs;
      h264Parameters.max_cpb = rustFmtpParameters.max_cpb;
      h264Parameters.max_dpb = rustFmtpParameters.max_dpb;
      h264Parameters.max_br = rustFmtpParameters.max_br;

      // TODO(bug 1466859): Support sprop-parameter-sets

      fmtpParameters = MakeUnique<SdpFmtpAttributeList::H264Parameters>(
          std::move(h264Parameters));
    } else if (codecName == "OPUS") {
      SdpFmtpAttributeList::OpusParameters opusParameters;

      opusParameters.maxplaybackrate = rustFmtpParameters.maxplaybackrate;
      opusParameters.maxAverageBitrate = rustFmtpParameters.maxaveragebitrate;
      opusParameters.useDTX = rustFmtpParameters.usedtx;
      opusParameters.stereo = rustFmtpParameters.stereo;
      opusParameters.useInBandFec = rustFmtpParameters.useinbandfec;
      opusParameters.frameSizeMs = rustFmtpParameters.ptime;
      opusParameters.minFrameSizeMs = rustFmtpParameters.minptime;
      opusParameters.maxFrameSizeMs = rustFmtpParameters.maxptime;
      opusParameters.useCbr = rustFmtpParameters.cbr;

      fmtpParameters = MakeUnique<SdpFmtpAttributeList::OpusParameters>(
          std::move(opusParameters));
    } else if ((codecName == "VP8") || (codecName == "VP9")) {
      SdpFmtpAttributeList::VP8Parameters vp8Parameters(
          codecName == "VP8" ? SdpRtpmapAttributeList::kVP8
                             : SdpRtpmapAttributeList::kVP9);

      vp8Parameters.max_fs = rustFmtpParameters.max_fs;
      vp8Parameters.max_fr = rustFmtpParameters.max_fr;

      fmtpParameters = MakeUnique<SdpFmtpAttributeList::VP8Parameters>(
          std::move(vp8Parameters));
    } else if (codecName == "TELEPHONE-EVENT") {
      SdpFmtpAttributeList::TelephoneEventParameters telephoneEventParameters;

      telephoneEventParameters.dtmfTones =
          std::string(convertStringView(rustFmtpParameters.dtmf_tones));

      fmtpParameters =
          MakeUnique<SdpFmtpAttributeList::TelephoneEventParameters>(
              std::move(telephoneEventParameters));
    } else if (codecName == "RED") {
      SdpFmtpAttributeList::RedParameters redParameters;

      auto encodings = convertRustSpan(rustFmtpParameters.encodings);
      redParameters.encodings.assign(encodings.begin(), encodings.end());

      fmtpParameters = MakeUnique<SdpFmtpAttributeList::RedParameters>(
          std::move(redParameters));
    } else if (codecName == "RTX") {
      SdpFmtpAttributeList::RtxParameters rtxParameters;

      rtxParameters.apt = rustFmtpParameters.rtx.apt;
      if (rustFmtpParameters.rtx.has_rtx_time) {
        rtxParameters.rtx_time = Some(rustFmtpParameters.rtx.rtx_time);
      }

      fmtpParameters =
          MakeUnique<SdpFmtpAttributeList::RtxParameters>(rtxParameters);
    } else if (codecName == "AV1") {
      SdpFmtpAttributeList::Av1Parameters av1Parameters;

      av1Parameters.profile = rustFmtpParameters.av1.has_profile
                                  ? Some(rustFmtpParameters.av1.profile)
                                  : Nothing();
      av1Parameters.levelIdx = rustFmtpParameters.av1.has_level_idx
                                   ? Some(rustFmtpParameters.av1.level_idx)
                                   : Nothing();
      av1Parameters.tier = rustFmtpParameters.av1.has_tier
                               ? Some(rustFmtpParameters.av1.tier)
                               : Nothing();
      fmtpParameters =
          MakeUnique<SdpFmtpAttributeList::Av1Parameters>(av1Parameters);

    } else {
      // The parameter set is unknown so skip it
      continue;
    }
    fmtpList->PushEntry(std::to_string(payloadType), *fmtpParameters);
  }
  SetAttribute(std::move(fmtpList));
}

void RsdparsaSdpAttributeList::LoadPtime(RustAttributeList* attributeList) {
  int64_t ptime = sdp_get_ptime(attributeList);
  if (ptime >= 0) {
    SetAttribute(MakeUnique<SdpNumberAttribute>(SdpAttribute::kPtimeAttribute,
                                                static_cast<uint32_t>(ptime)));
  }
}

void RsdparsaSdpAttributeList::LoadFlags(RustAttributeList* attributeList) {
  ffi::RustSdpAttributeFlags flags = sdp_get_attribute_flags(attributeList);
  if (flags.ice_lite) {
    SetAttribute(MakeUnique<SdpFlagAttribute>(SdpAttribute::kIceLiteAttribute));
  }
  if (flags.rtcp_mux) {
    SetAttribute(MakeUnique<SdpFlagAttribute>(SdpAttribute::kRtcpMuxAttribute));
  }
  if (flags.rtcp_rsize) {
    SetAttribute(
        MakeUnique<SdpFlagAttribute>(SdpAttribute::kRtcpRsizeAttribute));
  }
  if (flags.bundle_only) {
    SetAttribute(
        MakeUnique<SdpFlagAttribute>(SdpAttribute::kBundleOnlyAttribute));
  }
  if (flags.end_of_candidates) {
    SetAttribute(
        MakeUnique<SdpFlagAttribute>(SdpAttribute::kEndOfCandidatesAttribute));
  }
  if (flags.extmap_allow_mixed) {
    SetAttribute(
        MakeUnique<SdpFlagAttribute>(SdpAttribute::kExtmapAllowMixedAttribute));
  }
}

void RsdparsaSdpAttributeList::LoadMaxMessageSize(
    RustAttributeList* attributeList) {
  int64_t max_msg_size = sdp_get_max_msg_size(attributeList);
  if (max_msg_size >= 0) {
    SetAttribute(
        MakeUnique<SdpNumberAttribute>(SdpAttribute::kMaxMessageSizeAttribute,
                                       static_cast<uint32_t>(max_msg_size)));
  }
}

void RsdparsaSdpAttributeList::LoadMid(RustAttributeList* attributeList) {
  ffi::StringView rustMid;
  if (NS_SUCCEEDED(sdp_get_mid(attributeList, &rustMid))) {
    SetAttribute(MakeUnique<SdpStringAttribute>(
        SdpAttribute::kMidAttribute, std::string(convertStringView(rustMid))));
  }
}

void RsdparsaSdpAttributeList::LoadMsid(RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpAttributeMsid, 8> rustMsids;
  sdp_get_msids(attributeList, &rustMsids);
  if (rustMsids.IsEmpty()) {
    return;
  }
  auto msids = MakeUnique<SdpMsidAttributeList>();
  for (const auto& msid : rustMsids) {
    msids->PushEntry(std::string(convertStringView(msid.id)),
                     std::string(convertStringView(msid.appdata)));
  }
  SetAttribute(std::move(msids));
}

void RsdparsaSdpAttributeList::LoadMsidSemantics(
    RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpAttributeMsidSemantic, 8> rustMsidSemantics;
  sdp_get_msid_semantics(attributeList, &rustMsidSemantics);
  if (rustMsidSemantics.IsEmpty()) {
    return;
  }
  auto msidSemantics = MakeUnique<SdpMsidSemanticAttributeList>();
  for (const auto& rustMsidSemantic : rustMsidSemantics) {
    std::string semantic(convertStringView(rustMsidSemantic.semantic));
    std::vector<std::string> msids;
    msids.reserve(rustMsidSemantic.msids.Length());
    for (const auto& msid : rustMsidSemantic.msids) {
      msids.emplace_back(convertStringView(msid));
    }
    msidSemantics->PushEntry(semantic, msids);
  }
  SetAttribute(std::move(msidSemantics));
}

void RsdparsaSdpAttributeList::LoadGroup(RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpAttributeGroup, 8> rustGroups;
  sdp_get_groups(attributeList, &rustGroups);
  if (rustGroups.IsEmpty()) {
    return;
  }
  auto groups = MakeUnique<SdpGroupAttributeList>();
  for (const auto& group : rustGroups) {
    SdpGroupAttributeList::Semantics semantic;
    switch (group.semantic) {
      case ffi::RustSdpAttributeGroupSemantic::LipSynchronization:
        semantic = SdpGroupAttributeList::kLs;
        break;
      case ffi::RustSdpAttributeGroupSemantic::FlowIdentification:
        semantic = SdpGroupAttributeList::kFid;
        break;
      case ffi::RustSdpAttributeGroupSemantic::SingleReservationFlow:
        semantic = SdpGroupAttributeList::kSrf;
        break;
      case ffi::RustSdpAttributeGroupSemantic::AlternateNetworkAddressType:
        semantic = SdpGroupAttributeList::kAnat;
        break;
      case ffi::RustSdpAttributeGroupSemantic::ForwardErrorCorrection:
        semantic = SdpGroupAttributeList::kFec;
        break;
      case ffi::RustSdpAttributeGroupSemantic::DecodingDependency:
        semantic = SdpGroupAttributeList::kDdp;
        break;
      case ffi::RustSdpAttributeGroupSemantic::Bundle:
        semantic = SdpGroupAttributeList::kBundle;
        break;
    }
    std::vector<std::string> tags;
    tags.reserve(group.tags.Length());
    for (const auto& tag : group.tags) {
      tags.emplace_back(convertStringView(tag));
    }
    groups->PushEntry(semantic, tags);
  }
  SetAttribute(std::move(groups));
}

void RsdparsaSdpAttributeList::LoadRtcp(RustAttributeList* attributeList) {
  ffi::RustSdpAttributeRtcp rtcp;
  if (NS_SUCCEEDED(sdp_get_rtcp(attributeList, &rtcp))) {
    if (rtcp.has_address) {
      auto address = convertExplicitlyTypedAddress(rtcp.unicast_addr);
      SetAttribute(MakeUnique<SdpRtcpAttribute>(rtcp.port, sdp::kInternet,
                                                address.first, address.second));
    } else {
      SetAttribute(MakeUnique<SdpRtcpAttribute>(rtcp.port));
    }
  }
}

void RsdparsaSdpAttributeList::LoadRtcpFb(RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpAttributeRtcpFb, 8> rustRtcpfbs;
  sdp_get_rtcpfbs(attributeList, &rustRtcpfbs);
  if (rustRtcpfbs.IsEmpty()) {
    return;
  }

  auto rtcpfbList = MakeUnique<SdpRtcpFbAttributeList>();
  for (const auto& rtcpfb : rustRtcpfbs) {
    uint32_t payloadTypeU32 = rtcpfb.payload_type;

    std::stringstream ss;
    if (payloadTypeU32 == std::numeric_limits<uint32_t>::max()) {
      ss << "*";
    } else {
      ss << payloadTypeU32;
    }

    uint32_t feedbackType = rtcpfb.feedback_type;
    std::string parameter(convertStringView(rtcpfb.parameter));
    std::string extra(convertStringView(rtcpfb.extra));

    rtcpfbList->PushEntry(
        ss.str(), static_cast<SdpRtcpFbAttributeList::Type>(feedbackType),
        parameter, extra);
  }

  SetAttribute(std::move(rtcpfbList));
}

SdpImageattrAttributeList::XYRange LoadImageattrXYRange(
    const ffi::RustSdpAttributeImageAttrXyRange& rustXYRange) {
  SdpImageattrAttributeList::XYRange xyRange;

  auto discreteValues = convertRustSpan(rustXYRange.discrete_values);
  if (discreteValues.empty()) {
    xyRange.min = rustXYRange.min;
    xyRange.max = rustXYRange.max;
    xyRange.step = rustXYRange.step;
  } else {
    xyRange.discreteValues.assign(discreteValues.begin(), discreteValues.end());
  }

  return xyRange;
}

std::vector<SdpImageattrAttributeList::Set> LoadImageattrSets(
    const nsTArray<ffi::RustSdpAttributeImageAttrSet>& rustSets) {
  std::vector<SdpImageattrAttributeList::Set> sets;
  sets.reserve(rustSets.Length());
  for (const auto& rustSet : rustSets) {
    SdpImageattrAttributeList::Set set;

    set.xRange = LoadImageattrXYRange(rustSet.x);
    set.yRange = LoadImageattrXYRange(rustSet.y);

    if (rustSet.has_sar) {
      auto discreteValues = convertRustSpan(rustSet.sar.discrete_values);
      if (discreteValues.empty()) {
        set.sRange.min = rustSet.sar.min;
        set.sRange.max = rustSet.sar.max;
      } else {
        set.sRange.discreteValues.assign(discreteValues.begin(),
                                         discreteValues.end());
      }
    }

    if (rustSet.has_par) {
      set.pRange.min = rustSet.par.min;
      set.pRange.max = rustSet.par.max;
    }

    set.qValue = rustSet.q;

    sets.push_back(std::move(set));
  }

  return sets;
}

void RsdparsaSdpAttributeList::LoadImageattr(RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpAttributeImageAttr, 8> rustImageattrs;
  sdp_get_imageattrs(attributeList, &rustImageattrs);
  if (rustImageattrs.IsEmpty()) {
    return;
  }
  auto imageattrList = MakeUnique<SdpImageattrAttributeList>();
  for (const auto& rustImageAttr : rustImageattrs) {
    SdpImageattrAttributeList::Imageattr imageAttr;

    if (rustImageAttr.pt != std::numeric_limits<uint32_t>::max()) {
      imageAttr.pt = Some(rustImageAttr.pt);
    }

    if (rustImageAttr.send.is_wildcard) {
      imageAttr.sendAll = true;
    } else {
      imageAttr.sendSets = LoadImageattrSets(rustImageAttr.send.sets);
    }

    if (rustImageAttr.recv.is_wildcard) {
      imageAttr.recvAll = true;
    } else {
      imageAttr.recvSets = LoadImageattrSets(rustImageAttr.recv.sets);
    }

    imageattrList->mImageattrs.push_back(std::move(imageAttr));
  }
  SetAttribute(std::move(imageattrList));
}

void RsdparsaSdpAttributeList::LoadSctpmaps(RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpAttributeSctpmap, 8> rustSctpmaps;
  sdp_get_sctpmaps(attributeList, &rustSctpmaps);
  if (rustSctpmaps.IsEmpty()) {
    return;
  }
  auto sctpmapList = MakeUnique<SdpSctpmapAttributeList>();
  for (const auto& sctpmap : rustSctpmaps) {
    sctpmapList->PushEntry(std::to_string(sctpmap.port), "webrtc-datachannel",
                           sctpmap.channels);
  }
  SetAttribute(std::move(sctpmapList));
}

static SdpSimulcastAttribute::Versions LoadSimulcastVersions(
    const nsTArray<ffi::RustSdpAttributeSimulcastVersion>& rustVersions) {
  SdpSimulcastAttribute::Versions versions;
  for (const auto& rustVersion : rustVersions) {
    if (rustVersion.ids.IsEmpty()) {
      continue;
    }
    SdpSimulcastAttribute::Version version;
    for (const auto& rustId : rustVersion.ids) {
      std::string id(convertStringView(rustId.id));
      version.choices.push_back(
          SdpSimulcastAttribute::Encoding(std::move(id), rustId.paused));
    }
    versions.push_back(std::move(version));
  }
  return versions;
}

void RsdparsaSdpAttributeList::LoadSimulcast(RustAttributeList* attributeList) {
  ffi::RustSdpAttributeSimulcast rustSimulcast;
  if (NS_SUCCEEDED(sdp_get_simulcast(attributeList, &rustSimulcast))) {
    auto simulcast = MakeUnique<SdpSimulcastAttribute>();

    simulcast->sendVersions = LoadSimulcastVersions(rustSimulcast.send);
    simulcast->recvVersions = LoadSimulcastVersions(rustSimulcast.receive);

    SetAttribute(std::move(simulcast));
  }
}

void RsdparsaSdpAttributeList::LoadDirection(RustAttributeList* attributeList) {
  SdpDirectionAttribute::Direction dir;
  ffi::RustDirection rustDir = sdp_get_direction(attributeList);
  switch (rustDir) {
    case ffi::RustDirection::Recvonly:
      dir = SdpDirectionAttribute::kRecvonly;
      break;
    case ffi::RustDirection::Sendonly:
      dir = SdpDirectionAttribute::kSendonly;
      break;
    case ffi::RustDirection::Sendrecv:
      dir = SdpDirectionAttribute::kSendrecv;
      break;
    case ffi::RustDirection::Inactive:
      dir = SdpDirectionAttribute::kInactive;
      break;
  }
  SetAttribute(MakeUnique<SdpDirectionAttribute>(dir));
}

void RsdparsaSdpAttributeList::LoadRemoteCandidates(
    RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpAttributeRemoteCandidate, 8> rustCandidates;
  sdp_get_remote_candidates(attributeList, &rustCandidates);
  if (rustCandidates.IsEmpty()) {
    return;
  }
  std::vector<SdpRemoteCandidatesAttribute::Candidate> candidates;
  candidates.reserve(rustCandidates.Length());
  for (const auto& rustCandidate : rustCandidates) {
    SdpRemoteCandidatesAttribute::Candidate candidate;
    candidate.port = rustCandidate.port;
    candidate.id = std::to_string(rustCandidate.component);
    candidate.address = convertAddress(rustCandidate.address);
    candidates.push_back(std::move(candidate));
  }
  SetAttribute(MakeUnique<SdpRemoteCandidatesAttribute>(candidates));
}

void RsdparsaSdpAttributeList::LoadRids(RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpAttributeRid, 8> rustRids;
  sdp_get_rids(attributeList, &rustRids);
  if (rustRids.IsEmpty()) {
    return;
  }

  auto ridList = MakeUnique<SdpRidAttributeList>();
  for (const auto& rid : rustRids) {
    std::string id(convertStringView(rid.id));
    auto direction = static_cast<sdp::Direction>(rid.direction);

    auto formatsSpan = convertRustSpan(rid.formats);
    std::vector<uint16_t> formats(formatsSpan.begin(), formatsSpan.end());

    VideoEncodingConstraints parameters;
    parameters.maxWidth = rid.params.max_width;
    parameters.maxHeight = rid.params.max_height;
    // Right now, we treat max-fps=0 and the absence of max-fps as no limit.
    // We will eventually want to treat max-fps=0 as 0 frames per second, and
    // the absence of max-fps as no limit (bug 1762632).
    if (rid.params.max_fps) {
      parameters.maxFps = Some(rid.params.max_fps);
    }
    parameters.maxFs = rid.params.max_fs;
    parameters.maxBr = rid.params.max_br;
    parameters.maxPps = rid.params.max_pps;

    std::vector<std::string> depends;
    depends.reserve(rid.depends.Length());
    for (const auto& dep : rid.depends) {
      depends.emplace_back(convertStringView(dep));
    }

    ridList->PushEntry(id, direction, formats, parameters, depends);
  }

  SetAttribute(std::move(ridList));
}

void RsdparsaSdpAttributeList::LoadSctpPort(RustAttributeList* attributeList) {
  int64_t port = sdp_get_sctp_port(attributeList);
  if (port >= 0) {
    SetAttribute(MakeUnique<SdpNumberAttribute>(
        SdpAttribute::kSctpPortAttribute, static_cast<uint32_t>(port)));
  }
}

void RsdparsaSdpAttributeList::LoadExtmap(RustAttributeList* attributeList) {
  AutoTArray<ffi::RustSdpAttributeExtmap, 8> rustExtmaps;
  sdp_get_extmaps(attributeList, &rustExtmaps);
  if (rustExtmaps.IsEmpty()) {
    return;
  }
  auto extmaps = MakeUnique<SdpExtmapAttributeList>();
  for (const auto& rustExtmap : rustExtmaps) {
    std::string name(convertStringView(rustExtmap.url));
    SdpDirectionAttribute::Direction direction;
    bool directionSpecified = rustExtmap.direction_specified;
    switch (rustExtmap.direction) {
      case ffi::RustDirection::Recvonly:
        direction = SdpDirectionAttribute::kRecvonly;
        break;
      case ffi::RustDirection::Sendonly:
        direction = SdpDirectionAttribute::kSendonly;
        break;
      case ffi::RustDirection::Sendrecv:
        direction = SdpDirectionAttribute::kSendrecv;
        break;
      case ffi::RustDirection::Inactive:
        direction = SdpDirectionAttribute::kInactive;
        break;
    }
    std::string extensionAttributes(
        convertStringView(rustExtmap.extension_attributes));
    extmaps->PushEntry(rustExtmap.id, direction, directionSpecified, name,
                       extensionAttributes);
  }
  SetAttribute(std::move(extmaps));
}

void RsdparsaSdpAttributeList::LoadMaxPtime(RustAttributeList* attributeList) {
  uint64_t maxPtime = 0;
  nsresult nr = sdp_get_maxptime(attributeList, &maxPtime);
  if (NS_SUCCEEDED(nr)) {
    SetAttribute(MakeUnique<SdpNumberAttribute>(
        SdpAttribute::kMaxptimeAttribute, maxPtime));
  }
}

void RsdparsaSdpAttributeList::LoadCandidate(RustAttributeList* attributeList) {
  AutoTArray<nsCString, 8> rustCandidates;
  sdp_get_candidates(attributeList, &rustCandidates);
  if (rustCandidates.IsEmpty()) {
    return;
  }

  std::vector<std::string> candidatesStrings;
  candidatesStrings.reserve(rustCandidates.Length());
  for (const auto& candidate : rustCandidates) {
    candidatesStrings.emplace_back(candidate.get(), candidate.Length());
  }

  auto candidates =
      MakeUnique<SdpMultiStringAttribute>(SdpAttribute::kCandidateAttribute);
  candidates->mValues = std::move(candidatesStrings);

  SetAttribute(std::move(candidates));
}

bool RsdparsaSdpAttributeList::IsAllowedHere(
    const SdpAttribute::AttributeType type) const {
  if (AtSessionLevel() && !SdpAttribute::IsAllowedAtSessionLevel(type)) {
    return false;
  }

  if (!AtSessionLevel() && !SdpAttribute::IsAllowedAtMediaLevel(type)) {
    return false;
  }

  return true;
}

void RsdparsaSdpAttributeList::Serialize(std::ostream& os) const {
  for (auto& mAttribute : mAttributes) {
    if (mAttribute) {
      os << *mAttribute;
    }
  }
}

}  // namespace mozilla

Messung V0.5 in Prozent
C=96 H=90 G=93

¤ Dauer der Verarbeitung: 0.22 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002