From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- dom/media/webrtc/sdp/RsdparsaSdpAttributeList.cpp | 1301 +++++++++++++++++++++ 1 file changed, 1301 insertions(+) create mode 100644 dom/media/webrtc/sdp/RsdparsaSdpAttributeList.cpp (limited to 'dom/media/webrtc/sdp/RsdparsaSdpAttributeList.cpp') diff --git a/dom/media/webrtc/sdp/RsdparsaSdpAttributeList.cpp b/dom/media/webrtc/sdp/RsdparsaSdpAttributeList.cpp new file mode 100644 index 0000000000..0b76757c44 --- /dev/null +++ b/dom/media/webrtc/sdp/RsdparsaSdpAttributeList.cpp @@ -0,0 +1,1301 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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 "nsCRT.h" + +#include "sdp/RsdparsaSdpAttributeList.h" +#include "sdp/RsdparsaSdpInc.h" +#include "sdp/RsdparsaSdpGlue.h" + +#include +#include "mozilla/Assertions.h" + +#include + +namespace mozilla { + +const std::string RsdparsaSdpAttributeList::kEmptyString = ""; + +RsdparsaSdpAttributeList::~RsdparsaSdpAttributeList() { + for (size_t i = 0; i < kNumAttributeTypes; ++i) { + delete mAttributes[i]; + } +} + +bool RsdparsaSdpAttributeList::HasAttribute(AttributeType type, + bool sessionFallback) const { + return !!GetAttribute(type, sessionFallback); +} + +const SdpAttribute* RsdparsaSdpAttributeList::GetAttribute( + AttributeType type, bool sessionFallback) const { + const SdpAttribute* value = mAttributes[static_cast(type)]; + // 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(AttributeType type) { + delete mAttributes[static_cast(type)]; + mAttributes[static_cast(type)] = nullptr; +} + +void RsdparsaSdpAttributeList::Clear() { + for (size_t i = 0; i < kNumAttributeTypes; ++i) { + RemoveAttribute(static_cast(i)); + } +} + +uint32_t RsdparsaSdpAttributeList::Count() const { + uint32_t count = 0; + for (size_t i = 0; i < kNumAttributeTypes; ++i) { + if (mAttributes[i]) { + count++; + } + } + return count; +} + +void RsdparsaSdpAttributeList::SetAttribute(SdpAttribute* attr) { + if (!IsAllowedHere(attr->GetType())) { + MOZ_ASSERT(false, "This type of attribute is not allowed here"); + delete attr; + return; + } + RemoveAttribute(attr->GetType()); + mAttributes[attr->GetType()] = attr; +} + +const std::vector& RsdparsaSdpAttributeList::GetCandidate() const { + if (!HasAttribute(SdpAttribute::kCandidateAttribute)) { + MOZ_CRASH(); + } + + return static_cast( + GetAttribute(SdpAttribute::kCandidateAttribute)) + ->mValues; +} + +const SdpConnectionAttribute& RsdparsaSdpAttributeList::GetConnection() const { + if (!HasAttribute(SdpAttribute::kConnectionAttribute)) { + MOZ_CRASH(); + } + + return *static_cast( + GetAttribute(SdpAttribute::kConnectionAttribute)); +} + +SdpDirectionAttribute::Direction RsdparsaSdpAttributeList::GetDirection() + const { + if (!HasAttribute(SdpAttribute::kDirectionAttribute)) { + MOZ_CRASH(); + } + + const SdpAttribute* attr = GetAttribute(SdpAttribute::kDirectionAttribute); + return static_cast(attr)->mValue; +} + +const SdpDtlsMessageAttribute& RsdparsaSdpAttributeList::GetDtlsMessage() + const { + if (!HasAttribute(SdpAttribute::kDtlsMessageAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kDtlsMessageAttribute); + return *static_cast(attr); +} + +const SdpExtmapAttributeList& RsdparsaSdpAttributeList::GetExtmap() const { + if (!HasAttribute(SdpAttribute::kExtmapAttribute)) { + MOZ_CRASH(); + } + + return *static_cast( + GetAttribute(SdpAttribute::kExtmapAttribute)); +} + +const SdpFingerprintAttributeList& RsdparsaSdpAttributeList::GetFingerprint() + const { + if (!HasAttribute(SdpAttribute::kFingerprintAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kFingerprintAttribute); + return *static_cast(attr); +} + +const SdpFmtpAttributeList& RsdparsaSdpAttributeList::GetFmtp() const { + if (!HasAttribute(SdpAttribute::kFmtpAttribute)) { + MOZ_CRASH(); + } + + return *static_cast( + GetAttribute(SdpAttribute::kFmtpAttribute)); +} + +const SdpGroupAttributeList& RsdparsaSdpAttributeList::GetGroup() const { + if (!HasAttribute(SdpAttribute::kGroupAttribute)) { + MOZ_CRASH(); + } + + return *static_cast( + GetAttribute(SdpAttribute::kGroupAttribute)); +} + +const SdpOptionsAttribute& RsdparsaSdpAttributeList::GetIceOptions() const { + if (!HasAttribute(SdpAttribute::kIceOptionsAttribute)) { + MOZ_CRASH(); + } + + const SdpAttribute* attr = GetAttribute(SdpAttribute::kIceOptionsAttribute); + return *static_cast(attr); +} + +const std::string& RsdparsaSdpAttributeList::GetIcePwd() const { + if (!HasAttribute(SdpAttribute::kIcePwdAttribute)) { + return kEmptyString; + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kIcePwdAttribute); + return static_cast(attr)->mValue; +} + +const std::string& RsdparsaSdpAttributeList::GetIceUfrag() const { + if (!HasAttribute(SdpAttribute::kIceUfragAttribute)) { + return kEmptyString; + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kIceUfragAttribute); + return static_cast(attr)->mValue; +} + +const std::string& RsdparsaSdpAttributeList::GetIdentity() const { + if (!HasAttribute(SdpAttribute::kIdentityAttribute)) { + return kEmptyString; + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kIdentityAttribute); + return static_cast(attr)->mValue; +} + +const SdpImageattrAttributeList& RsdparsaSdpAttributeList::GetImageattr() + const { + if (!HasAttribute(SdpAttribute::kImageattrAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kImageattrAttribute); + return *static_cast(attr); +} + +const SdpSimulcastAttribute& RsdparsaSdpAttributeList::GetSimulcast() const { + if (!HasAttribute(SdpAttribute::kSimulcastAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kSimulcastAttribute); + return *static_cast(attr); +} + +const std::string& RsdparsaSdpAttributeList::GetLabel() const { + if (!HasAttribute(SdpAttribute::kLabelAttribute)) { + return kEmptyString; + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kLabelAttribute); + return static_cast(attr)->mValue; +} + +uint32_t RsdparsaSdpAttributeList::GetMaxptime() const { + if (!HasAttribute(SdpAttribute::kMaxptimeAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kMaxptimeAttribute); + return static_cast(attr)->mValue; +} + +const std::string& RsdparsaSdpAttributeList::GetMid() const { + if (!HasAttribute(SdpAttribute::kMidAttribute)) { + return kEmptyString; + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kMidAttribute); + return static_cast(attr)->mValue; +} + +const SdpMsidAttributeList& RsdparsaSdpAttributeList::GetMsid() const { + if (!HasAttribute(SdpAttribute::kMsidAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kMsidAttribute); + return *static_cast(attr); +} + +const SdpMsidSemanticAttributeList& RsdparsaSdpAttributeList::GetMsidSemantic() + const { + if (!HasAttribute(SdpAttribute::kMsidSemanticAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kMsidSemanticAttribute); + return *static_cast(attr); +} + +const SdpRidAttributeList& RsdparsaSdpAttributeList::GetRid() const { + if (!HasAttribute(SdpAttribute::kRidAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kRidAttribute); + return *static_cast(attr); +} + +uint32_t RsdparsaSdpAttributeList::GetPtime() const { + if (!HasAttribute(SdpAttribute::kPtimeAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kPtimeAttribute); + return static_cast(attr)->mValue; +} + +const SdpRtcpAttribute& RsdparsaSdpAttributeList::GetRtcp() const { + if (!HasAttribute(SdpAttribute::kRtcpAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtcpAttribute); + return *static_cast(attr); +} + +const SdpRtcpFbAttributeList& RsdparsaSdpAttributeList::GetRtcpFb() const { + if (!HasAttribute(SdpAttribute::kRtcpFbAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtcpFbAttribute); + return *static_cast(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(attr); +} + +const SdpSctpmapAttributeList& RsdparsaSdpAttributeList::GetSctpmap() const { + if (!HasAttribute(SdpAttribute::kSctpmapAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kSctpmapAttribute); + return *static_cast(attr); +} + +uint32_t RsdparsaSdpAttributeList::GetSctpPort() const { + if (!HasAttribute(SdpAttribute::kSctpPortAttribute)) { + MOZ_CRASH(); + } + + const SdpAttribute* attr = GetAttribute(SdpAttribute::kSctpPortAttribute); + return static_cast(attr)->mValue; +} + +uint32_t RsdparsaSdpAttributeList::GetMaxMessageSize() const { + if (!HasAttribute(SdpAttribute::kMaxMessageSizeAttribute)) { + MOZ_CRASH(); + } + + const SdpAttribute* attr = + GetAttribute(SdpAttribute::kMaxMessageSizeAttribute); + return static_cast(attr)->mValue; +} + +const SdpSetupAttribute& RsdparsaSdpAttributeList::GetSetup() const { + if (!HasAttribute(SdpAttribute::kSetupAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kSetupAttribute); + return *static_cast(attr); +} + +const SdpSsrcAttributeList& RsdparsaSdpAttributeList::GetSsrc() const { + if (!HasAttribute(SdpAttribute::kSsrcAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kSsrcAttribute); + return *static_cast(attr); +} + +const SdpSsrcGroupAttributeList& RsdparsaSdpAttributeList::GetSsrcGroup() + const { + if (!HasAttribute(SdpAttribute::kSsrcGroupAttribute)) { + MOZ_CRASH(); + } + const SdpAttribute* attr = GetAttribute(SdpAttribute::kSsrcGroupAttribute); + return *static_cast(attr); +} + +void RsdparsaSdpAttributeList::LoadAttribute(RustAttributeList* attributeList, + 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: + 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(i)); + } +} + +void RsdparsaSdpAttributeList::LoadIceUfrag(RustAttributeList* attributeList) { + StringView ufragStr; + nsresult nr = sdp_get_iceufrag(attributeList, &ufragStr); + if (NS_SUCCEEDED(nr)) { + std::string iceufrag = convertStringView(ufragStr); + SetAttribute( + new SdpStringAttribute(SdpAttribute::kIceUfragAttribute, iceufrag)); + } +} + +void RsdparsaSdpAttributeList::LoadIcePwd(RustAttributeList* attributeList) { + StringView pwdStr; + nsresult nr = sdp_get_icepwd(attributeList, &pwdStr); + if (NS_SUCCEEDED(nr)) { + std::string icePwd = convertStringView(pwdStr); + SetAttribute( + new SdpStringAttribute(SdpAttribute::kIcePwdAttribute, icePwd)); + } +} + +void RsdparsaSdpAttributeList::LoadIdentity(RustAttributeList* attributeList) { + StringView identityStr; + nsresult nr = sdp_get_identity(attributeList, &identityStr); + if (NS_SUCCEEDED(nr)) { + std::string identity = convertStringView(identityStr); + SetAttribute( + new SdpStringAttribute(SdpAttribute::kIdentityAttribute, identity)); + } +} + +void RsdparsaSdpAttributeList::LoadIceOptions( + RustAttributeList* attributeList) { + StringVec* options; + nsresult nr = sdp_get_iceoptions(attributeList, &options); + if (NS_SUCCEEDED(nr)) { + std::vector optionsVec; + auto optionsAttr = + MakeUnique(SdpAttribute::kIceOptionsAttribute); + for (size_t i = 0; i < string_vec_len(options); i++) { + StringView optionStr; + string_vec_get_view(options, i, &optionStr); + optionsAttr->PushEntry(convertStringView(optionStr)); + } + SetAttribute(optionsAttr.release()); + } +} + +void RsdparsaSdpAttributeList::LoadFingerprint( + RustAttributeList* attributeList) { + size_t nFp = sdp_get_fingerprint_count(attributeList); + if (nFp == 0) { + return; + } + auto rustFingerprints = MakeUnique(nFp); + sdp_get_fingerprints(attributeList, nFp, rustFingerprints.get()); + auto fingerprints = MakeUnique(); + for (size_t i = 0; i < nFp; i++) { + const RustSdpAttributeFingerprint& fingerprint = rustFingerprints[i]; + std::string algorithm; + switch (fingerprint.hashAlgorithm) { + case RustSdpAttributeFingerprintHashAlgorithm::kSha1: + algorithm = "sha-1"; + break; + case RustSdpAttributeFingerprintHashAlgorithm::kSha224: + algorithm = "sha-224"; + break; + case RustSdpAttributeFingerprintHashAlgorithm::kSha256: + algorithm = "sha-256"; + break; + case RustSdpAttributeFingerprintHashAlgorithm::kSha384: + algorithm = "sha-384"; + break; + case RustSdpAttributeFingerprintHashAlgorithm::kSha512: + algorithm = "sha-512"; + break; + } + + std::vector fingerprintBytes = + convertU8Vec(fingerprint.fingerprint); + + fingerprints->PushEntry(algorithm, fingerprintBytes); + } + SetAttribute(fingerprints.release()); +} + +void RsdparsaSdpAttributeList::LoadDtlsMessage( + RustAttributeList* attributeList) { + RustSdpAttributeDtlsMessage rustDtlsMessage; + nsresult nr = sdp_get_dtls_message(attributeList, &rustDtlsMessage); + if (NS_SUCCEEDED(nr)) { + SdpDtlsMessageAttribute::Role role; + if (rustDtlsMessage.role == RustSdpAttributeDtlsMessageType::kClient) { + role = SdpDtlsMessageAttribute::kClient; + } else { + role = SdpDtlsMessageAttribute::kServer; + } + + std::string value = convertStringView(rustDtlsMessage.value); + + SetAttribute(new SdpDtlsMessageAttribute(role, value)); + } +} + +void RsdparsaSdpAttributeList::LoadSetup(RustAttributeList* attributeList) { + RustSdpSetup rustSetup; + nsresult nr = sdp_get_setup(attributeList, &rustSetup); + if (NS_SUCCEEDED(nr)) { + SdpSetupAttribute::Role setupEnum; + switch (rustSetup) { + case RustSdpSetup::kRustActive: + setupEnum = SdpSetupAttribute::kActive; + break; + case RustSdpSetup::kRustActpass: + setupEnum = SdpSetupAttribute::kActpass; + break; + case RustSdpSetup::kRustHoldconn: + setupEnum = SdpSetupAttribute::kHoldconn; + break; + case RustSdpSetup::kRustPassive: + setupEnum = SdpSetupAttribute::kPassive; + break; + } + SetAttribute(new SdpSetupAttribute(setupEnum)); + } +} + +void RsdparsaSdpAttributeList::LoadSsrc(RustAttributeList* attributeList) { + size_t numSsrc = sdp_get_ssrc_count(attributeList); + if (numSsrc == 0) { + return; + } + auto rustSsrcs = MakeUnique(numSsrc); + sdp_get_ssrcs(attributeList, numSsrc, rustSsrcs.get()); + auto ssrcs = MakeUnique(); + for (size_t i = 0; i < numSsrc; i++) { + RustSdpAttributeSsrc& ssrc = rustSsrcs[i]; + std::string attribute = convertStringView(ssrc.attribute); + std::string value = convertStringView(ssrc.value); + if (value.length() == 0) { + ssrcs->PushEntry(ssrc.id, attribute); + } else { + ssrcs->PushEntry(ssrc.id, attribute + ":" + value); + } + } + SetAttribute(ssrcs.release()); +} + +void RsdparsaSdpAttributeList::LoadSsrcGroup(RustAttributeList* attributeList) { + size_t numSsrcGroups = sdp_get_ssrc_group_count(attributeList); + if (numSsrcGroups == 0) { + return; + } + auto rustSsrcGroups = MakeUnique(numSsrcGroups); + sdp_get_ssrc_groups(attributeList, numSsrcGroups, rustSsrcGroups.get()); + auto ssrcGroups = MakeUnique(); + for (size_t i = 0; i < numSsrcGroups; i++) { + RustSdpAttributeSsrcGroup& ssrcGroup = rustSsrcGroups[i]; + SdpSsrcGroupAttributeList::Semantics semantic; + switch (ssrcGroup.semantic) { + case RustSdpAttributeSsrcGroupSemantic ::kRustDup: + semantic = SdpSsrcGroupAttributeList::kDup; + break; + case RustSdpAttributeSsrcGroupSemantic ::kRustFec: + semantic = SdpSsrcGroupAttributeList::kFec; + break; + case RustSdpAttributeSsrcGroupSemantic ::kRustFecFr: + semantic = SdpSsrcGroupAttributeList::kFecFr; + break; + case RustSdpAttributeSsrcGroupSemantic ::kRustFid: + semantic = SdpSsrcGroupAttributeList::kFid; + break; + case RustSdpAttributeSsrcGroupSemantic ::kRustSim: + semantic = SdpSsrcGroupAttributeList::kSim; + break; + } + std::vector ssrcs; + for (size_t i = 0; i < ssrc_vec_len(ssrcGroup.ssrcs); ++i) { + uint32_t ssrc; + ssrc_vec_get_id(ssrcGroup.ssrcs, i, &ssrc); + ssrcs.push_back(ssrc); + } + ssrcGroups->PushEntry(semantic, ssrcs); + } + SetAttribute(ssrcGroups.release()); +} + +struct FmtDefaults { + uint32_t minimumChannels = 0; +}; + +std::tuple 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) { + size_t numRtpmap = sdp_get_rtpmap_count(attributeList); + if (numRtpmap == 0) { + return; + } + auto rustRtpmaps = MakeUnique(numRtpmap); + sdp_get_rtpmaps(attributeList, numRtpmap, rustRtpmaps.get()); + auto rtpmapList = MakeUnique(); + for (size_t i = 0; i < numRtpmap; i++) { + RustSdpAttributeRtpmap& rtpmap = rustRtpmaps[i]; + std::string payloadType = std::to_string(rtpmap.payloadType); + std::string name = convertStringView(rtpmap.codecName); + 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(rtpmapList.release()); +} + +void RsdparsaSdpAttributeList::LoadFmtp(RustAttributeList* attributeList) { + size_t numFmtp = sdp_get_fmtp_count(attributeList); + if (numFmtp == 0) { + return; + } + auto rustFmtps = MakeUnique(numFmtp); + size_t numValidFmtp = sdp_get_fmtp(attributeList, numFmtp, rustFmtps.get()); + auto fmtpList = MakeUnique(); + for (size_t i = 0; i < numValidFmtp; i++) { + const RustSdpAttributeFmtp& fmtp = rustFmtps[i]; + uint8_t payloadType = fmtp.payloadType; + std::string codecName = convertStringView(fmtp.codecName); + const RustSdpAttributeFmtpParameters& rustFmtpParameters = fmtp.parameters; + + UniquePtr 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.reset( + new 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.reset( + new 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.reset( + new SdpFmtpAttributeList::VP8Parameters(std::move(vp8Parameters))); + } else if (codecName == "TELEPHONE-EVENT") { + SdpFmtpAttributeList::TelephoneEventParameters telephoneEventParameters; + + telephoneEventParameters.dtmfTones = + convertStringView(rustFmtpParameters.dtmf_tones); + + fmtpParameters.reset(new SdpFmtpAttributeList::TelephoneEventParameters( + std::move(telephoneEventParameters))); + } else if (codecName == "RED") { + SdpFmtpAttributeList::RedParameters redParameters; + + redParameters.encodings = convertU8Vec(rustFmtpParameters.encodings); + + fmtpParameters.reset( + new 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.reset( + new SdpFmtpAttributeList::RtxParameters(rtxParameters)); + } else { + // The parameter set is unknown so skip it + continue; + } + fmtpList->PushEntry(std::to_string(payloadType), *fmtpParameters); + } + SetAttribute(fmtpList.release()); +} + +void RsdparsaSdpAttributeList::LoadPtime(RustAttributeList* attributeList) { + int64_t ptime = sdp_get_ptime(attributeList); + if (ptime >= 0) { + SetAttribute(new SdpNumberAttribute(SdpAttribute::kPtimeAttribute, + static_cast(ptime))); + } +} + +void RsdparsaSdpAttributeList::LoadFlags(RustAttributeList* attributeList) { + RustSdpAttributeFlags flags = sdp_get_attribute_flags(attributeList); + if (flags.iceLite) { + SetAttribute(new SdpFlagAttribute(SdpAttribute::kIceLiteAttribute)); + } + if (flags.rtcpMux) { + SetAttribute(new SdpFlagAttribute(SdpAttribute::kRtcpMuxAttribute)); + } + if (flags.rtcpRsize) { + SetAttribute(new SdpFlagAttribute(SdpAttribute::kRtcpRsizeAttribute)); + } + if (flags.bundleOnly) { + SetAttribute(new SdpFlagAttribute(SdpAttribute::kBundleOnlyAttribute)); + } + if (flags.endOfCandidates) { + SetAttribute(new SdpFlagAttribute(SdpAttribute::kEndOfCandidatesAttribute)); + } +} + +void RsdparsaSdpAttributeList::LoadMaxMessageSize( + RustAttributeList* attributeList) { + int64_t max_msg_size = sdp_get_max_msg_size(attributeList); + if (max_msg_size >= 0) { + SetAttribute(new SdpNumberAttribute(SdpAttribute::kMaxMessageSizeAttribute, + static_cast(max_msg_size))); + } +} + +void RsdparsaSdpAttributeList::LoadMid(RustAttributeList* attributeList) { + StringView rustMid; + if (NS_SUCCEEDED(sdp_get_mid(attributeList, &rustMid))) { + std::string mid = convertStringView(rustMid); + SetAttribute(new SdpStringAttribute(SdpAttribute::kMidAttribute, mid)); + } +} + +void RsdparsaSdpAttributeList::LoadMsid(RustAttributeList* attributeList) { + size_t numMsid = sdp_get_msid_count(attributeList); + if (numMsid == 0) { + return; + } + auto rustMsid = MakeUnique(numMsid); + sdp_get_msids(attributeList, numMsid, rustMsid.get()); + auto msids = MakeUnique(); + for (size_t i = 0; i < numMsid; i++) { + RustSdpAttributeMsid& msid = rustMsid[i]; + std::string id = convertStringView(msid.id); + std::string appdata = convertStringView(msid.appdata); + msids->PushEntry(id, appdata); + } + SetAttribute(msids.release()); +} + +void RsdparsaSdpAttributeList::LoadMsidSemantics( + RustAttributeList* attributeList) { + size_t numMsidSemantic = sdp_get_msid_semantic_count(attributeList); + if (numMsidSemantic == 0) { + return; + } + auto rustMsidSemantics = + MakeUnique(numMsidSemantic); + sdp_get_msid_semantics(attributeList, numMsidSemantic, + rustMsidSemantics.get()); + auto msidSemantics = MakeUnique(); + for (size_t i = 0; i < numMsidSemantic; i++) { + RustSdpAttributeMsidSemantic& rustMsidSemantic = rustMsidSemantics[i]; + std::string semantic = convertStringView(rustMsidSemantic.semantic); + std::vector msids = convertStringVec(rustMsidSemantic.msids); + msidSemantics->PushEntry(semantic, msids); + } + SetAttribute(msidSemantics.release()); +} + +void RsdparsaSdpAttributeList::LoadGroup(RustAttributeList* attributeList) { + size_t numGroup = sdp_get_group_count(attributeList); + if (numGroup == 0) { + return; + } + auto rustGroups = MakeUnique(numGroup); + sdp_get_groups(attributeList, numGroup, rustGroups.get()); + auto groups = MakeUnique(); + for (size_t i = 0; i < numGroup; i++) { + RustSdpAttributeGroup& group = rustGroups[i]; + SdpGroupAttributeList::Semantics semantic; + switch (group.semantic) { + case RustSdpAttributeGroupSemantic ::kRustLipSynchronization: + semantic = SdpGroupAttributeList::kLs; + break; + case RustSdpAttributeGroupSemantic ::kRustFlowIdentification: + semantic = SdpGroupAttributeList::kFid; + break; + case RustSdpAttributeGroupSemantic ::kRustSingleReservationFlow: + semantic = SdpGroupAttributeList::kSrf; + break; + case RustSdpAttributeGroupSemantic ::kRustAlternateNetworkAddressType: + semantic = SdpGroupAttributeList::kAnat; + break; + case RustSdpAttributeGroupSemantic ::kRustForwardErrorCorrection: + semantic = SdpGroupAttributeList::kFec; + break; + case RustSdpAttributeGroupSemantic ::kRustDecodingDependency: + semantic = SdpGroupAttributeList::kDdp; + break; + case RustSdpAttributeGroupSemantic ::kRustBundle: + semantic = SdpGroupAttributeList::kBundle; + break; + } + std::vector tags = convertStringVec(group.tags); + groups->PushEntry(semantic, tags); + } + SetAttribute(groups.release()); +} + +void RsdparsaSdpAttributeList::LoadRtcp(RustAttributeList* attributeList) { + RustSdpAttributeRtcp rtcp; + if (NS_SUCCEEDED(sdp_get_rtcp(attributeList, &rtcp))) { + if (rtcp.has_address) { + auto address = convertExplicitlyTypedAddress(&rtcp.unicastAddr); + SetAttribute(new SdpRtcpAttribute(rtcp.port, sdp::kInternet, + address.first, address.second)); + } else { + SetAttribute(new SdpRtcpAttribute(rtcp.port)); + } + } +} + +void RsdparsaSdpAttributeList::LoadRtcpFb(RustAttributeList* attributeList) { + auto rtcpfbsCount = sdp_get_rtcpfb_count(attributeList); + if (!rtcpfbsCount) { + return; + } + + auto rustRtcpfbs = MakeUnique(rtcpfbsCount); + sdp_get_rtcpfbs(attributeList, rtcpfbsCount, rustRtcpfbs.get()); + + auto rtcpfbList = MakeUnique(); + for (size_t i = 0; i < rtcpfbsCount; i++) { + RustSdpAttributeRtcpFb& rtcpfb = rustRtcpfbs[i]; + uint32_t payloadTypeU32 = rtcpfb.payloadType; + + std::stringstream ss; + if (payloadTypeU32 == std::numeric_limits::max()) { + ss << "*"; + } else { + ss << payloadTypeU32; + } + + uint32_t feedbackType = rtcpfb.feedbackType; + std::string parameter = convertStringView(rtcpfb.parameter); + std::string extra = convertStringView(rtcpfb.extra); + + rtcpfbList->PushEntry( + ss.str(), static_cast(feedbackType), + parameter, extra); + } + + SetAttribute(rtcpfbList.release()); +} + +SdpSimulcastAttribute::Versions LoadSimulcastVersions( + const RustSdpAttributeSimulcastVersionVec* rustVersionList) { + size_t rustVersionCount = sdp_simulcast_get_version_count(rustVersionList); + auto rustVersionArray = + MakeUnique(rustVersionCount); + sdp_simulcast_get_versions(rustVersionList, rustVersionCount, + rustVersionArray.get()); + + SdpSimulcastAttribute::Versions versions; + + for (size_t i = 0; i < rustVersionCount; i++) { + const RustSdpAttributeSimulcastVersion& rustVersion = rustVersionArray[i]; + size_t rustIdCount = sdp_simulcast_get_ids_count(rustVersion.ids); + if (!rustIdCount) { + continue; + } + + SdpSimulcastAttribute::Version version; + auto rustIdArray = MakeUnique(rustIdCount); + sdp_simulcast_get_ids(rustVersion.ids, rustIdCount, rustIdArray.get()); + + for (size_t j = 0; j < rustIdCount; j++) { + const RustSdpAttributeSimulcastId& rustId = rustIdArray[j]; + std::string id = convertStringView(rustId.id); + // TODO: Bug 1225877. Added support for 'paused'-state + version.choices.push_back( + SdpSimulcastAttribute::Encoding(id, rustId.paused)); + } + + versions.push_back(version); + } + + return versions; +} + +void RsdparsaSdpAttributeList::LoadSimulcast(RustAttributeList* attributeList) { + RustSdpAttributeSimulcast rustSimulcast; + if (NS_SUCCEEDED(sdp_get_simulcast(attributeList, &rustSimulcast))) { + auto simulcast = MakeUnique(); + + simulcast->sendVersions = LoadSimulcastVersions(rustSimulcast.send); + simulcast->recvVersions = LoadSimulcastVersions(rustSimulcast.recv); + + SetAttribute(simulcast.release()); + } +} + +SdpImageattrAttributeList::XYRange LoadImageattrXYRange( + const RustSdpAttributeImageAttrXYRange& rustXYRange) { + SdpImageattrAttributeList::XYRange xyRange; + + if (!rustXYRange.discrete_values) { + xyRange.min = rustXYRange.min; + xyRange.max = rustXYRange.max; + xyRange.step = rustXYRange.step; + + } else { + xyRange.discreteValues = convertU32Vec(rustXYRange.discrete_values); + } + + return xyRange; +} + +std::vector LoadImageattrSets( + const RustSdpAttributeImageAttrSetVec* rustSets) { + std::vector sets; + + size_t rustSetCount = sdp_imageattr_get_set_count(rustSets); + if (!rustSetCount) { + return sets; + } + + auto rustSetArray = MakeUnique(rustSetCount); + sdp_imageattr_get_sets(rustSets, rustSetCount, rustSetArray.get()); + + for (size_t i = 0; i < rustSetCount; i++) { + const RustSdpAttributeImageAttrSet& rustSet = rustSetArray[i]; + SdpImageattrAttributeList::Set set; + + set.xRange = LoadImageattrXYRange(rustSet.x); + set.yRange = LoadImageattrXYRange(rustSet.y); + + if (rustSet.has_sar) { + if (!rustSet.sar.discrete_values) { + set.sRange.min = rustSet.sar.min; + set.sRange.max = rustSet.sar.max; + } else { + set.sRange.discreteValues = convertF32Vec(rustSet.sar.discrete_values); + } + } + + if (rustSet.has_par) { + set.pRange.min = rustSet.par.min; + set.pRange.max = rustSet.par.max; + } + + set.qValue = rustSet.q; + + sets.push_back(set); + } + + return sets; +} + +void RsdparsaSdpAttributeList::LoadImageattr(RustAttributeList* attributeList) { + size_t numImageattrs = sdp_get_imageattr_count(attributeList); + if (numImageattrs == 0) { + return; + } + auto rustImageattrs = MakeUnique(numImageattrs); + sdp_get_imageattrs(attributeList, numImageattrs, rustImageattrs.get()); + auto imageattrList = MakeUnique(); + for (size_t i = 0; i < numImageattrs; i++) { + const RustSdpAttributeImageAttr& rustImageAttr = rustImageattrs[i]; + + SdpImageattrAttributeList::Imageattr imageAttr; + + if (rustImageAttr.payloadType != std::numeric_limits::max()) { + imageAttr.pt = Some(rustImageAttr.payloadType); + } + + if (rustImageAttr.send.sets) { + imageAttr.sendSets = LoadImageattrSets(rustImageAttr.send.sets); + } else { + imageAttr.sendAll = true; + } + + if (rustImageAttr.recv.sets) { + imageAttr.recvSets = LoadImageattrSets(rustImageAttr.recv.sets); + } else { + imageAttr.recvAll = true; + } + + imageattrList->mImageattrs.push_back(imageAttr); + } + SetAttribute(imageattrList.release()); +} + +void RsdparsaSdpAttributeList::LoadSctpmaps(RustAttributeList* attributeList) { + size_t numSctpmaps = sdp_get_sctpmap_count(attributeList); + if (numSctpmaps == 0) { + return; + } + auto rustSctpmaps = MakeUnique(numSctpmaps); + sdp_get_sctpmaps(attributeList, numSctpmaps, rustSctpmaps.get()); + auto sctpmapList = MakeUnique(); + for (size_t i = 0; i < numSctpmaps; i++) { + RustSdpAttributeSctpmap& sctpmap = rustSctpmaps[i]; + sctpmapList->PushEntry(std::to_string(sctpmap.port), "webrtc-datachannel", + sctpmap.channels); + } + SetAttribute(sctpmapList.release()); +} + +void RsdparsaSdpAttributeList::LoadDirection(RustAttributeList* attributeList) { + SdpDirectionAttribute::Direction dir; + RustDirection rustDir = sdp_get_direction(attributeList); + switch (rustDir) { + case RustDirection::kRustRecvonly: + dir = SdpDirectionAttribute::kRecvonly; + break; + case RustDirection::kRustSendonly: + dir = SdpDirectionAttribute::kSendonly; + break; + case RustDirection::kRustSendrecv: + dir = SdpDirectionAttribute::kSendrecv; + break; + case RustDirection::kRustInactive: + dir = SdpDirectionAttribute::kInactive; + break; + } + SetAttribute(new SdpDirectionAttribute(dir)); +} + +void RsdparsaSdpAttributeList::LoadRemoteCandidates( + RustAttributeList* attributeList) { + size_t nC = sdp_get_remote_candidate_count(attributeList); + if (nC == 0) { + return; + } + auto rustCandidates = MakeUnique(nC); + sdp_get_remote_candidates(attributeList, nC, rustCandidates.get()); + std::vector candidates; + for (size_t i = 0; i < nC; i++) { + RustSdpAttributeRemoteCandidate& rustCandidate = rustCandidates[i]; + SdpRemoteCandidatesAttribute::Candidate candidate; + candidate.port = rustCandidate.port; + candidate.id = std::to_string(rustCandidate.component); + candidate.address = convertAddress(&rustCandidate.address); + candidates.push_back(candidate); + } + SdpRemoteCandidatesAttribute* candidatesList; + candidatesList = new SdpRemoteCandidatesAttribute(candidates); + SetAttribute(candidatesList); +} + +void RsdparsaSdpAttributeList::LoadRids(RustAttributeList* attributeList) { + size_t numRids = sdp_get_rid_count(attributeList); + if (numRids == 0) { + return; + } + + auto rustRids = MakeUnique(numRids); + sdp_get_rids(attributeList, numRids, rustRids.get()); + + auto ridList = MakeUnique(); + for (size_t i = 0; i < numRids; i++) { + const RustSdpAttributeRid& rid = rustRids[i]; + + std::string id = convertStringView(rid.id); + auto direction = static_cast(rid.direction); + std::vector formats = convertU16Vec(rid.formats); + + EncodingConstraints 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 depends = convertStringVec(rid.depends); + + ridList->PushEntry(id, direction, formats, parameters, depends); + } + + SetAttribute(ridList.release()); +} + +void RsdparsaSdpAttributeList::LoadSctpPort(RustAttributeList* attributeList) { + int64_t port = sdp_get_sctp_port(attributeList); + if (port >= 0) { + SetAttribute(new SdpNumberAttribute(SdpAttribute::kSctpPortAttribute, + static_cast(port))); + } +} + +void RsdparsaSdpAttributeList::LoadExtmap(RustAttributeList* attributeList) { + size_t numExtmap = sdp_get_extmap_count(attributeList); + if (numExtmap == 0) { + return; + } + auto rustExtmaps = MakeUnique(numExtmap); + sdp_get_extmaps(attributeList, numExtmap, rustExtmaps.get()); + auto extmaps = MakeUnique(); + for (size_t i = 0; i < numExtmap; i++) { + RustSdpAttributeExtmap& rustExtmap = rustExtmaps[i]; + std::string name = convertStringView(rustExtmap.url); + SdpDirectionAttribute::Direction direction; + bool directionSpecified = rustExtmap.direction_specified; + switch (rustExtmap.direction) { + case RustDirection::kRustRecvonly: + direction = SdpDirectionAttribute::kRecvonly; + break; + case RustDirection::kRustSendonly: + direction = SdpDirectionAttribute::kSendonly; + break; + case RustDirection::kRustSendrecv: + direction = SdpDirectionAttribute::kSendrecv; + break; + case RustDirection::kRustInactive: + direction = SdpDirectionAttribute::kInactive; + break; + } + std::string extensionAttributes; + extensionAttributes = convertStringView(rustExtmap.extensionAttributes); + extmaps->PushEntry((uint16_t)rustExtmap.id, direction, directionSpecified, + name, extensionAttributes); + } + SetAttribute(extmaps.release()); +} + +void RsdparsaSdpAttributeList::LoadMaxPtime(RustAttributeList* attributeList) { + uint64_t maxPtime = 0; + nsresult nr = sdp_get_maxptime(attributeList, &maxPtime); + if (NS_SUCCEEDED(nr)) { + SetAttribute( + new SdpNumberAttribute(SdpAttribute::kMaxptimeAttribute, maxPtime)); + } +} + +void RsdparsaSdpAttributeList::LoadCandidate(RustAttributeList* attributeList) { + size_t candidatesCount = sdp_get_candidate_count(attributeList); + if (!candidatesCount) { + return; + } + + StringVec* rustCandidatesStrings; + sdp_get_candidates(attributeList, candidatesCount, &rustCandidatesStrings); + + std::vector candidatesStrings = + convertStringVec(rustCandidatesStrings); + free_boxed_string_vec(rustCandidatesStrings); + + auto candidates = + MakeUnique(SdpAttribute::kCandidateAttribute); + candidates->mValues = candidatesStrings; + + SetAttribute(candidates.release()); +} + +bool RsdparsaSdpAttributeList::IsAllowedHere(SdpAttribute::AttributeType type) { + if (AtSessionLevel() && !SdpAttribute::IsAllowedAtSessionLevel(type)) { + return false; + } + + if (!AtSessionLevel() && !SdpAttribute::IsAllowedAtMediaLevel(type)) { + return false; + } + + return true; +} + +void RsdparsaSdpAttributeList::Serialize(std::ostream& os) const { + for (size_t i = 0; i < kNumAttributeTypes; ++i) { + if (mAttributes[i]) { + os << *mAttributes[i]; + } + } +} + +} // namespace mozilla -- cgit v1.2.3