new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdp.cpp
@@ -0,0 +1,120 @@
+/* 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 "signaling/src/sdp/RsdparsaSdp.h"
+
+#include <cstdlib>
+#include "mozilla/UniquePtr.h"
+#include "mozilla/Assertions.h"
+#include "nsError.h"
+
+
+#include "signaling/src/sdp/SdpErrorHolder.h"
+#include "signaling/src/sdp/RsdparsaSdpInc.h"
+#include "signaling/src/sdp/RsdparsaSdpMediaSection.h"
+
+#ifdef CRLF
+#undef CRLF
+#endif
+#define CRLF "\r\n"
+
+namespace mozilla
+{
+
+RsdparsaSdp::RsdparsaSdp(RsdparsaSessionHandle session, const SdpOrigin& origin)
+ : mSession(Move(session))
+ , mOrigin(origin)
+{
+ RsdparsaSessionHandle attributeSession(sdp_new_reference(mSession.get()));
+ mAttributeList.reset(new RsdparsaSdpAttributeList(Move(attributeSession)));
+
+ size_t section_count = sdp_media_section_count(mSession.get());
+ for (size_t level = 0; level < section_count; level++) {
+ RustMediaSection* mediaSection = sdp_get_media_section(mSession.get(),
+ level);
+ if (!mediaSection) {
+ MOZ_ASSERT(false, "sdp_get_media_section failed because level was out of"
+ " bounds, but we did a bounds check!");
+ break;
+ }
+ RsdparsaSessionHandle newSession(sdp_new_reference(mSession.get()));
+ RsdparsaSdpMediaSection* sdpMediaSection;
+ sdpMediaSection = new RsdparsaSdpMediaSection(level,
+ Move(newSession),
+ mediaSection,
+ mAttributeList.get());
+ mMediaSections.values.push_back(sdpMediaSection);
+ }
+}
+
+const SdpOrigin&
+RsdparsaSdp::GetOrigin() const
+{
+ return mOrigin;
+}
+
+uint32_t
+RsdparsaSdp::GetBandwidth(const std::string& type) const
+{
+ return get_sdp_bandwidth(mSession.get(), type.c_str());
+}
+
+const SdpMediaSection&
+RsdparsaSdp::GetMediaSection(size_t level) const
+{
+ if (level > mMediaSections.values.size()) {
+ MOZ_CRASH();
+ }
+ return *mMediaSections.values[level];
+}
+
+SdpMediaSection&
+RsdparsaSdp::GetMediaSection(size_t level)
+{
+ if (level > mMediaSections.values.size()) {
+ MOZ_CRASH();
+ }
+ return *mMediaSections.values[level];
+}
+
+SdpMediaSection&
+RsdparsaSdp::AddMediaSection(SdpMediaSection::MediaType mediaType,
+ SdpDirectionAttribute::Direction dir,
+ uint16_t port,
+ SdpMediaSection::Protocol protocol,
+ sdp::AddrType addrType, const std::string& addr)
+{
+ //TODO: See Bug 1436080
+ MOZ_CRASH("Method not implemented");
+}
+
+void
+RsdparsaSdp::Serialize(std::ostream& os) const
+{
+ os << "v=0" << CRLF << mOrigin << "s=-" << CRLF;
+
+ // We don't support creating i=, u=, e=, p=
+ // We don't generate c= at the session level (only in media)
+
+ BandwidthVec* bwVec = sdp_get_session_bandwidth_vec(mSession.get());
+ char *bwString = sdp_serialize_bandwidth(bwVec);
+ if (bwString) {
+ os << bwString;
+ sdp_free_string(bwString);
+ }
+
+ os << "t=0 0" << CRLF;
+
+ // We don't support r= or z=
+
+ // attributes
+ os << *mAttributeList;
+
+ // media sections
+ for (const SdpMediaSection* msection : mMediaSections.values) {
+ os << *msection;
+ }
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdp.h
@@ -0,0 +1,82 @@
+/* -*- 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/. */
+
+#ifndef _RSDPARSA_SDP_H_
+#define _RSDPARSA_SDP_H_
+
+#include "mozilla/UniquePtr.h"
+#include "mozilla/Attributes.h"
+
+#include "signaling/src/common/PtrVector.h"
+
+#include "signaling/src/sdp/Sdp.h"
+
+#include "signaling/src/sdp/RsdparsaSdpMediaSection.h"
+#include "signaling/src/sdp/RsdparsaSdpAttributeList.h"
+#include "signaling/src/sdp/RsdparsaSdpInc.h"
+#include "signaling/src/sdp/RsdparsaSdpGlue.h"
+
+
+namespace mozilla
+{
+
+class RsdparsaSdpParser;
+class SdpErrorHolder;
+
+class RsdparsaSdp final : public Sdp
+{
+ friend class RsdparsaSdpParser;
+
+public:
+ explicit RsdparsaSdp(RsdparsaSessionHandle session, const SdpOrigin& origin);
+
+ const SdpOrigin& GetOrigin() const override;
+
+ // Note: connection information is always retrieved from media sections
+ uint32_t GetBandwidth(const std::string& type) const override;
+
+ size_t
+ GetMediaSectionCount() const override
+ {
+ return sdp_media_section_count(mSession.get());
+ }
+
+ const SdpAttributeList&
+ GetAttributeList() const override
+ {
+ return *mAttributeList;
+ }
+
+ SdpAttributeList&
+ GetAttributeList() override
+ {
+ return *mAttributeList;
+ }
+
+ const SdpMediaSection& GetMediaSection(size_t level) const
+ override;
+
+ SdpMediaSection& GetMediaSection(size_t level) override;
+
+ SdpMediaSection& AddMediaSection(
+ SdpMediaSection::MediaType media, SdpDirectionAttribute::Direction dir,
+ uint16_t port, SdpMediaSection::Protocol proto, sdp::AddrType addrType,
+ const std::string& addr) override;
+
+ void Serialize(std::ostream&) const override;
+
+private:
+ RsdparsaSdp() : mOrigin("", 0, 0, sdp::kIPv4, "") {}
+
+ RsdparsaSessionHandle mSession;
+ SdpOrigin mOrigin;
+ UniquePtr<RsdparsaSdpAttributeList> mAttributeList;
+ PtrVector<RsdparsaSdpMediaSection> mMediaSections;
+};
+
+} // namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.cpp
@@ -0,0 +1,1021 @@
+/* -*- 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 "signaling/src/sdp/RsdparsaSdpAttributeList.h"
+#include "signaling/src/sdp/RsdparsaSdpInc.h"
+#include "signaling/src/sdp/RsdparsaSdpGlue.h"
+
+#include <ostream>
+#include "mozilla/Assertions.h"
+
+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<size_t>(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<size_t>(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 (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<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
+{
+ // TODO: See Bug 1437166.
+ MOZ_CRASH("Not yet implemented");
+}
+
+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::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::kBundleOnlyAttribute:
+ case SdpAttribute::kEndOfCandidatesAttribute:
+ LoadFlags(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::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::kExtmapAttribute:
+ LoadExtmap(attributeList);
+ return;
+ case SdpAttribute::kDtlsMessageAttribute:
+ case SdpAttribute::kLabelAttribute:
+ case SdpAttribute::kMaxptimeAttribute:
+ case SdpAttribute::kSsrcGroupAttribute:
+ case SdpAttribute::kMaxMessageSizeAttribute:
+ case SdpAttribute::kRtcpFbAttribute:
+ case SdpAttribute::kRtcpRsizeAttribute:
+ case SdpAttribute::kSctpPortAttribute:
+ case SdpAttribute::kCandidateAttribute:
+ case SdpAttribute::kSimulcastAttribute:
+ case SdpAttribute::kConnectionAttribute:
+ case SdpAttribute::kIceMismatchAttribute:
+ // TODO: Not implemented, or not applicable.
+ // Sort this out in Bug 1437165.
+ 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)
+{
+ 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<std::string> optionsVec;
+ auto optionsAttr = MakeUnique<SdpOptionsAttribute>(
+ 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<RustSdpAttributeFingerprint[]>(nFp);
+ sdp_get_fingerprints(attributeList, nFp, rustFingerprints.get());
+ auto fingerprints = MakeUnique<SdpFingerprintAttributeList>();
+ for(size_t i = 0; i < nFp; i++) {
+ RustSdpAttributeFingerprint& fingerprint = rustFingerprints[i];
+ std::string algorithm = convertStringView(fingerprint.hashAlgorithm);
+ std::string fingerprintToken = convertStringView(fingerprint.fingerprint);
+ std::vector<uint8_t> fingerprintBytes =
+ SdpFingerprintAttributeList::ParseFingerprint(fingerprintToken);
+ if (fingerprintBytes.size() == 0) {
+ // TODO: Should we load fingerprint earlier to detect if it is malformed
+ // and throw a proper error?
+ // TODO: We should improve our error checking. See Bug 1437169.
+ continue;
+ }
+ fingerprints->PushEntry(algorithm, fingerprintBytes);
+ }
+ SetAttribute(fingerprints.release());
+}
+
+void
+RsdparsaSdpAttributeList::LoadSetup(RustAttributeList* attributeList)
+{
+ RustSdpSetup rustSetup;
+ nsresult nr = sdp_get_setup(attributeList, &rustSetup);
+ if (NS_SUCCEEDED(nr)) {
+ SdpSetupAttribute::Role setupEnum;
+ switch(rustSetup) {
+ case kRustActive:
+ setupEnum = SdpSetupAttribute::kActive;
+ break;
+ case kRustActpass:
+ setupEnum = SdpSetupAttribute::kActpass;
+ break;
+ case kRustHoldconn:
+ setupEnum = SdpSetupAttribute::kHoldconn;
+ break;
+ case 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<RustSdpAttributeSsrc[]>(numSsrc);
+ sdp_get_ssrcs(attributeList, numSsrc, rustSsrcs.get());
+ auto ssrcs = MakeUnique<SdpSsrcAttributeList>();
+ 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());
+}
+
+SdpRtpmapAttributeList::CodecType
+strToCodecType(const std::string &name)
+{
+ auto codec = SdpRtpmapAttributeList::kOtherCodec;
+ if (!strcasecmp(name.c_str(), "opus")) {
+ codec = SdpRtpmapAttributeList::kOpus;
+ } else if (!strcasecmp(name.c_str(), "G722")) {
+ codec = SdpRtpmapAttributeList::kG722;
+ } else if (!strcasecmp(name.c_str(), "PCMU")) {
+ codec = SdpRtpmapAttributeList::kPCMU;
+ } else if (!strcasecmp(name.c_str(), "PCMA")) {
+ codec = SdpRtpmapAttributeList::kPCMA;
+ } else if (!strcasecmp(name.c_str(), "VP8")) {
+ codec = SdpRtpmapAttributeList::kVP8;
+ } else if (!strcasecmp(name.c_str(), "VP9")) {
+ codec = SdpRtpmapAttributeList::kVP9;
+ } else if (!strcasecmp(name.c_str(), "iLBC")) {
+ codec = SdpRtpmapAttributeList::kiLBC;
+ } else if(!strcasecmp(name.c_str(), "iSAC")) {
+ codec = SdpRtpmapAttributeList::kiSAC;
+ } else if (!strcasecmp(name.c_str(), "H264")) {
+ codec = SdpRtpmapAttributeList::kH264;
+ } else if (!strcasecmp(name.c_str(), "red")) {
+ codec = SdpRtpmapAttributeList::kRed;
+ } else if (!strcasecmp(name.c_str(), "ulpfec")) {
+ codec = SdpRtpmapAttributeList::kUlpfec;
+ } else if (!strcasecmp(name.c_str(), "telephone-event")) {
+ codec = SdpRtpmapAttributeList::kTelephoneEvent;
+ }
+ return codec;
+}
+
+void
+RsdparsaSdpAttributeList::LoadRtpmap(RustAttributeList* attributeList)
+{
+ size_t numRtpmap = sdp_get_rtpmap_count(attributeList);
+ if (numRtpmap == 0) {
+ return;
+ }
+ auto rustRtpmaps = MakeUnique<RustSdpAttributeRtpmap[]>(numRtpmap);
+ sdp_get_rtpmaps(attributeList, numRtpmap, rustRtpmaps.get());
+ auto rtpmapList = MakeUnique<SdpRtpmapAttributeList>();
+ 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 = strToCodecType(name);
+ uint32_t channels = rtpmap.channels;
+ if (mIsVideo) {
+ // channels is expected to be 0 for video in higher level code,
+ // channels don't make sense, so the value is arbitrary. 1 is
+ // the arbitrary value for that code.
+ // TODO: handle this in Rust parser, see Bug 1436403
+ channels = 0;
+ }
+ rtpmapList->PushEntry(payloadType, codec, name,
+ rtpmap.frequency, channels);
+ }
+ SetAttribute(rtpmapList.release());
+}
+
+void
+RsdparsaSdpAttributeList::LoadFmtp(RustAttributeList* attributeList)
+{
+ // TODO: Not implemented, see Bug 1432918
+#if 0
+ size_t numFmtp = sdp_get_fmtp_count(attributeList);
+ if (numFmtp == 0) {
+ return;
+ }
+ auto rustFmtps = MakeUnique<RustSdpAttributeFmtp[]>(numFmtp);
+ size_t numValidFmtp = sdp_get_fmtp(attributeList, numFmtp,
+ rustFmtps.get());
+ for(size_t i = 0; i < numValidFmtp; i++) {
+ RustSdpAttributeFmtp& fmtp = rustFmtps[i];
+ }
+#endif
+}
+
+void
+RsdparsaSdpAttributeList::LoadPtime(RustAttributeList* attributeList)
+{
+ int64_t ptime = sdp_get_ptime(attributeList);
+ if (ptime >= 0) {
+ SetAttribute(new SdpNumberAttribute(SdpAttribute::kPtimeAttribute,
+ static_cast<uint32_t>(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.bundleOnly) {
+ SetAttribute(new SdpFlagAttribute(SdpAttribute::kBundleOnlyAttribute));
+ }
+ if (flags.endOfCandidates) {
+ SetAttribute(new SdpFlagAttribute(SdpAttribute::kEndOfCandidatesAttribute));
+ }
+}
+
+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<RustSdpAttributeMsid[]>(numMsid);
+ sdp_get_msids(attributeList, numMsid, rustMsid.get());
+ auto msids = MakeUnique<SdpMsidAttributeList>();
+ 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<RustSdpAttributeMsidSemantic[]>(numMsidSemantic);
+ sdp_get_msid_semantics(attributeList, numMsidSemantic,
+ rustMsidSemantics.get());
+ auto msidSemantics = MakeUnique<SdpMsidSemanticAttributeList>();
+ for(size_t i = 0; i < numMsidSemantic; i++) {
+ RustSdpAttributeMsidSemantic& rustMsidSemantic = rustMsidSemantics[i];
+ std::string semantic = convertStringView(rustMsidSemantic.semantic);
+ std::vector<std::string> 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<RustSdpAttributeGroup[]>(numGroup);
+ nsresult nr = sdp_get_groups(attributeList, numGroup, rustGroups.get());
+ if (NS_FAILED(nr)) {
+ return;
+ }
+ auto groups = MakeUnique<SdpGroupAttributeList>();
+ 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<std::string> 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))) {
+ sdp::AddrType addrType = convertAddressType(rtcp.unicastAddr.addrType);
+ if (sdp::kAddrTypeNone == addrType) {
+ SetAttribute(new SdpRtcpAttribute(rtcp.port));
+ } else {
+ std::string addr(rtcp.unicastAddr.unicastAddr);
+ SetAttribute(new SdpRtcpAttribute(rtcp.port, sdp::kInternet,
+ addrType, addr));
+ }
+ }
+}
+
+void
+RsdparsaSdpAttributeList::LoadImageattr(RustAttributeList* attributeList)
+{
+ size_t numImageattrs = sdp_get_imageattr_count(attributeList);
+ if (numImageattrs == 0) {
+ return;
+ }
+ auto rustImageattrs = MakeUnique<StringView[]>(numImageattrs);
+ sdp_get_imageattrs(attributeList, numImageattrs, rustImageattrs.get());
+ auto imageattrList = MakeUnique<SdpImageattrAttributeList>();
+ for(size_t i = 0; i < numImageattrs; i++) {
+ StringView& imageAttr = rustImageattrs[i];
+ std::string image = convertStringView(imageAttr);
+ std::string error;
+ size_t errorPos;
+ if (!imageattrList->PushEntry(image, &error, &errorPos)) {
+ // TODO: handle error, see Bug 1438237
+ }
+ }
+ SetAttribute(imageattrList.release());
+}
+
+void
+RsdparsaSdpAttributeList::LoadSctpmaps(RustAttributeList* attributeList)
+{
+ size_t numSctpmaps = sdp_get_sctpmap_count(attributeList);
+ if (numSctpmaps == 0) {
+ return;
+ }
+ auto rustSctpmaps = MakeUnique<RustSdpAttributeSctpmap[]>(numSctpmaps);
+ sdp_get_sctpmaps(attributeList, numSctpmaps, rustSctpmaps.get());
+ auto sctpmapList = MakeUnique<SdpSctpmapAttributeList>();
+ 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 kRustRecvonly:
+ dir = SdpDirectionAttribute::kRecvonly;
+ break;
+ case kRustSendonly:
+ dir = SdpDirectionAttribute::kSendonly;
+ break;
+ case kRustSendrecv:
+ dir = SdpDirectionAttribute::kSendrecv;
+ break;
+ case 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<RustSdpAttributeRemoteCandidate[]>(nC);
+ sdp_get_remote_candidates(attributeList, nC,
+ rustCandidates.get());
+ std::vector<SdpRemoteCandidatesAttribute::Candidate> 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 = std::string(rustCandidate.address.unicastAddr);
+ 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<StringView[]>(numRids);
+ sdp_get_rids(attributeList, numRids,
+ rustRids.get());
+ auto rids = MakeUnique<SdpRidAttributeList>();
+ for(size_t i = 0; i < numRids; i++) {
+ std::string rid = convertStringView(rustRids[i]);
+ std::string error;
+ size_t errorPos;
+ if (!rids->PushEntry(rid, &error, &errorPos)) {
+ // TODO: handle error, see Bug 1438237
+ }
+ }
+ SetAttribute(rids.release());
+}
+
+void
+RsdparsaSdpAttributeList::LoadExtmap(RustAttributeList* attributeList)
+{
+ size_t numExtmap = sdp_get_extmap_count(attributeList);
+ if (numExtmap == 0) {
+ return;
+ }
+ auto rustExtmaps = MakeUnique<RustSdpAttributeExtmap[]>(numExtmap);
+ sdp_get_extmaps(attributeList, numExtmap,
+ rustExtmaps.get());
+ auto extmaps = MakeUnique<SdpExtmapAttributeList>();
+ for(size_t i = 0; i < numExtmap; i++) {
+ RustSdpAttributeExtmap& rustExtmap = rustExtmaps[i];
+ std::string name = convertStringView(rustExtmap.url);
+ SdpDirectionAttribute::Direction direction;
+ bool directionSpecified = true;
+ switch(rustExtmap.direction) {
+ case kRustRecvonly:
+ direction = SdpDirectionAttribute::kRecvonly;
+ break;
+ case kRustSendonly:
+ direction = SdpDirectionAttribute::kSendonly;
+ break;
+ case kRustSendrecv:
+ direction = SdpDirectionAttribute::kSendrecv;
+ break;
+ case kRustInactive:
+ // TODO: Fix this, see Bug 1438544
+ direction = SdpDirectionAttribute::kSendrecv;
+ directionSpecified = false;
+ break;
+ }
+ std::string extensionAttributes;
+ extensionAttributes = convertStringView(rustExtmap.extensionAttributes);
+ extmaps->PushEntry((uint16_t) rustExtmap.id, direction,
+ directionSpecified, name, extensionAttributes);
+ }
+ SetAttribute(extmaps.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
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.h
@@ -0,0 +1,158 @@
+/* -*- 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/. */
+
+#ifndef _RSDPARSA_SDP_ATTRIBUTE_LIST_H_
+#define _RSDPARSA_SDP_ATTRIBUTE_LIST_H_
+
+#include "signaling/src/sdp/RsdparsaSdpGlue.h"
+#include "signaling/src/sdp/RsdparsaSdpInc.h"
+#include "signaling/src/sdp/SdpAttributeList.h"
+
+namespace mozilla
+{
+
+class RsdparsaSdp;
+class RsdparsaSdpMediaSection;
+class SdpErrorHolder;
+
+class RsdparsaSdpAttributeList : public SdpAttributeList
+{
+ friend class RsdparsaSdpMediaSection;
+ friend class RsdparsaSdp;
+
+public:
+ // Make sure we don't hide the default arg thunks
+ using SdpAttributeList::HasAttribute;
+ using SdpAttributeList::GetAttribute;
+
+ bool HasAttribute(AttributeType type,
+ bool sessionFallback) const override;
+ const SdpAttribute* GetAttribute(AttributeType type,
+ bool sessionFallback) const override;
+ void SetAttribute(SdpAttribute* attr) override;
+ void RemoveAttribute(AttributeType type) override;
+ void Clear() override;
+ uint32_t Count() const override;
+
+ const SdpConnectionAttribute& GetConnection() const override;
+ const SdpFingerprintAttributeList& GetFingerprint() const override;
+ const SdpGroupAttributeList& GetGroup() const override;
+ const SdpOptionsAttribute& GetIceOptions() const override;
+ const SdpRtcpAttribute& GetRtcp() const override;
+ const SdpRemoteCandidatesAttribute& GetRemoteCandidates() const override;
+ const SdpSetupAttribute& GetSetup() const override;
+ const SdpSsrcAttributeList& GetSsrc() const override;
+ const SdpSsrcGroupAttributeList& GetSsrcGroup() const override;
+ const SdpDtlsMessageAttribute& GetDtlsMessage() const override;
+
+ // These attributes can appear multiple times, so the returned
+ // classes actually represent a collection of values.
+ const std::vector<std::string>& GetCandidate() const override;
+ const SdpExtmapAttributeList& GetExtmap() const override;
+ const SdpFmtpAttributeList& GetFmtp() const override;
+ const SdpImageattrAttributeList& GetImageattr() const override;
+ const SdpSimulcastAttribute& GetSimulcast() const override;
+ const SdpMsidAttributeList& GetMsid() const override;
+ const SdpMsidSemanticAttributeList& GetMsidSemantic() const override;
+ const SdpRidAttributeList& GetRid() const override;
+ const SdpRtcpFbAttributeList& GetRtcpFb() const override;
+ const SdpRtpmapAttributeList& GetRtpmap() const override;
+ const SdpSctpmapAttributeList& GetSctpmap() const override;
+
+ // These attributes are effectively simple types, so we'll make life
+ // easy by just returning their value.
+ uint32_t GetSctpPort() const override;
+ uint32_t GetMaxMessageSize() const override;
+ const std::string& GetIcePwd() const override;
+ const std::string& GetIceUfrag() const override;
+ const std::string& GetIdentity() const override;
+ const std::string& GetLabel() const override;
+ unsigned int GetMaxptime() const override;
+ const std::string& GetMid() const override;
+ unsigned int GetPtime() const override;
+
+ SdpDirectionAttribute::Direction GetDirection() const override;
+
+ void Serialize(std::ostream&) const override;
+
+ virtual ~RsdparsaSdpAttributeList();
+
+private:
+ explicit RsdparsaSdpAttributeList(RsdparsaSessionHandle session)
+ : mSession(Move(session))
+ , mSessionAttributes(nullptr)
+ , mIsVideo(false)
+ , mAttributes()
+ {
+ RustAttributeList* attributes = get_sdp_session_attributes(mSession.get());
+ LoadAll(attributes);
+ }
+
+ RsdparsaSdpAttributeList(RsdparsaSessionHandle session,
+ const RustMediaSection* const msection,
+ const RsdparsaSdpAttributeList* sessionAttributes)
+ : mSession(Move(session))
+ , mSessionAttributes(sessionAttributes)
+ , mAttributes()
+ {
+ mIsVideo = sdp_rust_get_media_type(msection) == kRustVideo;
+ RustAttributeList* attributes = sdp_get_media_attribute_list(msection);
+ LoadAll(attributes);
+ }
+
+ static const std::string kEmptyString;
+ static const size_t kNumAttributeTypes = SdpAttribute::kLastAttribute + 1;
+
+ const RsdparsaSessionHandle mSession;
+ const RsdparsaSdpAttributeList* mSessionAttributes;
+ bool mIsVideo;
+
+ bool
+ AtSessionLevel() const
+ {
+ return !mSessionAttributes;
+ }
+
+ bool IsAllowedHere(SdpAttribute::AttributeType type);
+ void LoadAll(RustAttributeList* attributeList);
+ void LoadAttribute(RustAttributeList* attributeList, AttributeType type);
+ void LoadIceUfrag(RustAttributeList* attributeList);
+ void LoadIcePwd(RustAttributeList* attributeList);
+ void LoadIdentity(RustAttributeList* attributeList);
+ void LoadIceOptions(RustAttributeList* attributeList);
+ void LoadFingerprint(RustAttributeList* attributeList);
+ void LoadSetup(RustAttributeList* attributeList);
+ void LoadSsrc(RustAttributeList* attributeList);
+ void LoadRtpmap(RustAttributeList* attributeList);
+ void LoadFmtp(RustAttributeList* attributeList);
+ void LoadPtime(RustAttributeList* attributeList);
+ void LoadFlags(RustAttributeList* attributeList);
+ void LoadMid(RustAttributeList* attributeList);
+ void LoadMsid(RustAttributeList* attributeList);
+ void LoadMsidSemantics(RustAttributeList* attributeList);
+ void LoadGroup(RustAttributeList* attributeList);
+ void LoadRtcp(RustAttributeList* attributeList);
+ void LoadImageattr(RustAttributeList* attributeList);
+ void LoadSctpmaps(RustAttributeList* attributeList);
+ void LoadDirection(RustAttributeList* attributeList);
+ void LoadRemoteCandidates(RustAttributeList* attributeList);
+ void LoadRids(RustAttributeList* attributeList);
+ void LoadExtmap(RustAttributeList* attributeList);
+
+ void WarnAboutMisplacedAttribute(SdpAttribute::AttributeType type,
+ uint32_t lineNumber,
+ SdpErrorHolder& errorHolder);
+
+
+ SdpAttribute* mAttributes[kNumAttributeTypes];
+
+ RsdparsaSdpAttributeList(const RsdparsaSdpAttributeList& orig) = delete;
+ RsdparsaSdpAttributeList& operator=(const RsdparsaSdpAttributeList& rhs) = delete;
+};
+
+} // namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.cpp
@@ -0,0 +1,48 @@
+/* -*- 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 <string>
+
+#include "signaling/src/sdp/RsdparsaSdpInc.h"
+#include "signaling/src/sdp/RsdparsaSdpGlue.h"
+namespace mozilla
+{
+
+std::string convertStringView(StringView str)
+{
+ if (nullptr == str.buf) {
+ return std::string();
+ } else {
+ return std::string(str.buf, str.len);
+ }
+}
+
+std::vector<std::string> convertStringVec(StringVec* vec)
+{
+ std::vector<std::string> ret;
+ size_t len = string_vec_len(vec);
+ for (size_t i = 0; i < len; i++) {
+ StringView view;
+ string_vec_get_view(vec, i, &view);
+ ret.push_back(convertStringView(view));
+ }
+ return ret;
+}
+
+sdp::AddrType convertAddressType(RustSdpAddrType addrType)
+{
+ switch(addrType) {
+ case kRustAddrNone:
+ return sdp::kAddrTypeNone;
+ case kRustAddrIp4:
+ return sdp::kIPv4;
+ case kRustAddrIp6:
+ return sdp::kIPv6;
+ }
+
+ MOZ_CRASH("unknown address type");
+}
+
+}
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.h
@@ -0,0 +1,31 @@
+/* -*- 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/. */
+#ifndef _RUSTSDPGLUE_H_
+#define _RUSTSDPGLUE_H_
+
+#include <string>
+#include <vector>
+
+#include "signaling/src/sdp/Sdp.h"
+#include "signaling/src/sdp/RsdparsaSdpInc.h"
+
+namespace mozilla
+{
+
+struct FreeRustSdpSession {
+ void operator()(RustSdpSession* aSess) { sdp_free_session(aSess); }
+};
+
+typedef UniquePtr<RustSdpSession, FreeRustSdpSession> RsdparsaSessionHandle;
+
+std::string convertStringView(StringView str);
+std::vector<std::string> convertStringVec(StringVec* vec);
+sdp::AddrType convertAddressType(RustSdpAddrType addr);
+
+}
+
+
+#endif
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h
@@ -0,0 +1,292 @@
+/* -*- 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/. */
+#ifndef _RUSTSDPINC_H_
+#define _RUSTSDPINC_H_
+
+#include "nsError.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+ typedef struct BandwidthVec BandwidthVec;
+ typedef struct RustSdpSession RustSdpSession;
+ typedef struct RustSdpError RustSdpError;
+ typedef struct RustMediaSection RustMediaSection;
+ typedef struct RustAttributeList RustAttributeList;
+ typedef struct StringVec StringVec;
+ typedef struct U32Vec U32Vec;
+ typedef struct RustHeapString RustHeapString;
+
+
+ enum RustSdpAddrType {
+ kRustAddrNone,
+ kRustAddrIp4,
+ kRustAddrIp6
+ };
+
+ typedef struct RustIpAddr {
+ RustSdpAddrType addrType;
+ char unicastAddr[50];
+ } RustIpAddr;
+
+ typedef struct StringView {
+ char* buf;
+ size_t len;
+ } StringView;
+
+ typedef struct RustSdpConnection {
+ RustIpAddr addr;
+ uint8_t ttl;
+ uint64_t amount;
+ } RustSdpConnection;
+
+ typedef struct RustSdpOrigin {
+ StringView username;
+ uint64_t sessionId;
+ uint64_t sessionVersion;
+ RustIpAddr addr;
+ } RustSdpOrigin;
+
+ enum RustSdpMediaValue {
+ kRustAudio,
+ kRustVideo,
+ kRustApplication
+ };
+
+ enum RustSdpProtocolValue {
+ kRustRtpSavpf,
+ kRustUdpTlsRtpSavpf,
+ kRustTcpTlsRtpSavpf,
+ kRustDtlsSctp,
+ kRustUdpDtlsSctp,
+ kRustTcpDtlsSctp,
+ };
+
+ enum RustSdpFormatType {
+ kRustIntegers,
+ kRustStrings
+ };
+
+ size_t string_vec_len(const StringVec* vec);
+ nsresult string_vec_get_view(const StringVec* vec, size_t index,
+ StringView* str);
+
+ size_t u32_vec_len(const U32Vec* vec);
+ nsresult u32_vec_get(const U32Vec* vec, size_t index, uint32_t* ret);
+
+ void sdp_free_string(char* string);
+
+ nsresult parse_sdp(const char* sdp, uint32_t length, bool fail_on_warning,
+ RustSdpSession** ret, RustSdpError** err);
+ RustSdpSession* sdp_new_reference(RustSdpSession* aSess);
+ void sdp_free_session(RustSdpSession* ret);
+ size_t sdp_get_error_line_num(const RustSdpError* err);
+ StringView sdp_get_error_message(const RustSdpError* err);
+ void sdp_free_error(RustSdpError* err);
+
+ RustSdpOrigin sdp_get_origin(const RustSdpSession* aSess);
+
+ uint32_t get_sdp_bandwidth(const RustSdpSession* aSess,
+ const char* aBandwidthType);
+ BandwidthVec* sdp_get_session_bandwidth_vec(const RustSdpSession* aSess);
+ BandwidthVec* sdp_get_media_bandwidth_vec(const RustMediaSection* aMediaSec);
+ char* sdp_serialize_bandwidth(const BandwidthVec* bandwidths);
+ bool sdp_session_has_connection(const RustSdpSession* aSess);
+ nsresult sdp_get_session_connection(const RustSdpSession* aSess,
+ RustSdpConnection* ret);
+ RustAttributeList* get_sdp_session_attributes(const RustSdpSession* aSess);
+
+ size_t sdp_media_section_count(const RustSdpSession* aSess);
+ RustMediaSection* sdp_get_media_section(const RustSdpSession* aSess,
+ size_t aLevel);
+ RustSdpMediaValue sdp_rust_get_media_type(const RustMediaSection* aMediaSec);
+ RustSdpProtocolValue
+ sdp_get_media_protocol(const RustMediaSection* aMediaSec);
+ RustSdpFormatType sdp_get_format_type(const RustMediaSection* aMediaSec);
+ StringVec* sdp_get_format_string_vec(const RustMediaSection* aMediaSec);
+ U32Vec* sdp_get_format_u32_vec(const RustMediaSection* aMediaSec);
+ uint32_t sdp_get_media_port(const RustMediaSection* aMediaSec);
+ uint32_t sdp_get_media_port_count(const RustMediaSection* aMediaSec);
+ uint32_t sdp_get_media_bandwidth(const RustMediaSection* aMediaSec,
+ const char* aBandwidthType);
+ bool sdp_media_has_connection(const RustMediaSection* aMediaSec);
+ nsresult sdp_get_media_connection(const RustMediaSection* aMediaSec,
+ RustSdpConnection* ret);
+
+ RustAttributeList*
+ sdp_get_media_attribute_list(const RustMediaSection* aMediaSec);
+
+ nsresult sdp_get_iceufrag(const RustAttributeList* aList, StringView* ret);
+ nsresult sdp_get_icepwd(const RustAttributeList* aList, StringView* ret);
+ nsresult sdp_get_identity(const RustAttributeList* aList, StringView* ret);
+ nsresult sdp_get_iceoptions(const RustAttributeList* aList, StringVec** ret);
+
+ typedef struct RustSdpAttributeFingerprint {
+ StringView hashAlgorithm;
+ StringView fingerprint;
+ } RustSdpAttributeFingerprint;
+
+ size_t sdp_get_fingerprint_count(const RustAttributeList* aList);
+ void sdp_get_fingerprints(const RustAttributeList* aList, size_t listSize,
+ RustSdpAttributeFingerprint* ret);
+
+ enum RustSdpSetup {
+ kRustActive,
+ kRustActpass,
+ kRustHoldconn,
+ kRustPassive
+ };
+
+ nsresult sdp_get_setup(const RustAttributeList* aList, RustSdpSetup* ret);
+
+ typedef struct RustSdpAttributeSsrc {
+ uint32_t id;
+ StringView attribute;
+ StringView value;
+ } RustSdpAttributeSsrc;
+
+ size_t sdp_get_ssrc_count(const RustAttributeList* aList);
+ void sdp_get_ssrcs(const RustAttributeList* aList,
+ size_t listSize, RustSdpAttributeSsrc* ret);
+
+ typedef struct RustSdpAttributeRtpmap {
+ uint8_t payloadType;
+ StringView codecName;
+ uint32_t frequency;
+ uint32_t channels;
+ } RustSdpAttributeRtpmap;
+
+ size_t sdp_get_rtpmap_count(const RustAttributeList* aList);
+ void sdp_get_rtpmaps(const RustAttributeList* aList, size_t listSize,
+ RustSdpAttributeRtpmap* ret);
+
+ typedef struct RustSdpAttributeFmtp {
+ uint8_t payloadType;
+ StringView codecName;
+ StringVec* tokens;
+ } RustSdpAttributeFmtp;
+
+ size_t sdp_get_fmtp_count(const RustAttributeList* aList);
+ size_t sdp_get_fmtp(const RustAttributeList* aList, size_t listSize,
+ RustSdpAttributeFmtp* ret);
+
+ int64_t sdp_get_ptime(const RustAttributeList* aList);
+
+ typedef struct RustSdpAttributeFlags {
+ bool iceLite;
+ bool rtcpMux;
+ bool bundleOnly;
+ bool endOfCandidates;
+ } RustSdpAttributeFlags;
+
+ RustSdpAttributeFlags sdp_get_attribute_flags(const RustAttributeList* aList);
+
+ nsresult sdp_get_mid(const RustAttributeList* aList, StringView* ret);
+
+ typedef struct RustSdpAttributeMsid {
+ StringView id;
+ StringView appdata;
+ } RustSdpAttributeMsid;
+
+ size_t sdp_get_msid_count(const RustAttributeList* aList);
+ void sdp_get_msids(const RustAttributeList* aList, size_t listSize,
+ RustSdpAttributeMsid* ret);
+
+ typedef struct RustSdpAttributeMsidSemantic {
+ StringView semantic;
+ StringVec* msids;
+ } RustSdpAttributeMsidSemantic;
+
+ size_t sdp_get_msid_semantic_count(RustAttributeList* aList);
+ void sdp_get_msid_semantics(const RustAttributeList* aList, size_t listSize,
+ RustSdpAttributeMsidSemantic* ret);
+
+ enum RustSdpAttributeGroupSemantic {
+ kRustLipSynchronization,
+ kRustFlowIdentification,
+ kRustSingleReservationFlow,
+ kRustAlternateNetworkAddressType,
+ kRustForwardErrorCorrection,
+ kRustDecodingDependency,
+ kRustBundle,
+ };
+
+ typedef struct RustSdpAttributeGroup {
+ RustSdpAttributeGroupSemantic semantic;
+ StringVec* tags;
+ } RustSdpAttributeGroup;
+
+ size_t sdp_get_group_count(const RustAttributeList* aList);
+ nsresult sdp_get_groups(const RustAttributeList* aList, size_t listSize,
+ RustSdpAttributeGroup* ret);
+
+ typedef struct RustSdpAttributeRtcp {
+ uint16_t port;
+ RustIpAddr unicastAddr;
+ } RustSdpAttributeRtcp;
+
+ nsresult sdp_get_rtcp(const RustAttributeList* aList,
+ RustSdpAttributeRtcp* ret);
+
+ size_t sdp_get_imageattr_count(const RustAttributeList* aList);
+ void sdp_get_imageattrs(const RustAttributeList* aList, size_t listSize,
+ StringView* ret);
+
+ typedef struct RustSdpAttributeSctpmap {
+ uint16_t port;
+ uint32_t channels;
+ } RustSdpAttributeSctpmap;
+
+ size_t sdp_get_sctpmap_count(const RustAttributeList* aList);
+ void sdp_get_sctpmaps(const RustAttributeList* aList, size_t listSize,
+ RustSdpAttributeSctpmap* ret);
+
+ enum RustDirection {
+ kRustRecvonly,
+ kRustSendonly,
+ kRustSendrecv,
+ kRustInactive
+ };
+
+ RustDirection sdp_get_direction(const RustAttributeList* aList);
+
+ typedef struct RustSdpAttributeRemoteCandidate {
+ uint32_t component;
+ RustIpAddr address;
+ uint32_t port;
+ } RustSdpAttributeRemoteCandidate;
+
+ size_t sdp_get_remote_candidate_count(const RustAttributeList* aList);
+ void sdp_get_remote_candidates(const RustAttributeList* aList,
+ size_t listSize,
+ RustSdpAttributeRemoteCandidate* ret);
+
+ size_t sdp_get_rid_count(const RustAttributeList* aList);
+ void sdp_get_rids(const RustAttributeList* aList, size_t listSize,
+ StringView* ret);
+
+ // TODO: Add field indicating whether direction was specified
+ // See Bug 1438536.
+ typedef struct RustSdpAttributeExtmap {
+ uint16_t id;
+ RustDirection direction;
+ StringView url;
+ StringView extensionAttributes;
+ } RustSdpAttributeExtmap;
+
+ size_t sdp_get_extmap_count(const RustAttributeList* aList);
+ void sdp_get_extmaps(const RustAttributeList* aList, size_t listSize,
+ RustSdpAttributeExtmap* ret);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpMediaSection.cpp
@@ -0,0 +1,235 @@
+/* -*- 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/. */
+
+// Bug 1433534 tracks cleaning up the TODOs in the file
+
+#include "signaling/src/sdp/SdpMediaSection.h"
+#include "signaling/src/sdp/RsdparsaSdpMediaSection.h"
+
+#include "signaling/src/sdp/RsdparsaSdpGlue.h"
+#include "signaling/src/sdp/RsdparsaSdpInc.h"
+
+#include <ostream>
+#include "signaling/src/sdp/SdpErrorHolder.h"
+
+#ifdef CRLF
+#undef CRLF
+#endif
+#define CRLF "\r\n"
+
+namespace mozilla
+{
+
+RsdparsaSdpMediaSection::RsdparsaSdpMediaSection(size_t level,
+ RsdparsaSessionHandle session, const RustMediaSection* const section,
+ const RsdparsaSdpAttributeList* sessionLevel)
+ : SdpMediaSection(level), mSession(Move(session)),
+ mSection(section)
+{
+ switch(sdp_rust_get_media_type(section)) {
+ case kRustAudio:
+ mMediaType = kAudio;
+ break;
+ case kRustVideo:
+ mMediaType = kVideo;
+ break;
+ case kRustApplication:
+ mMediaType = kApplication;
+ break;
+ }
+
+ RsdparsaSessionHandle attributeSession(sdp_new_reference(mSession.get()));
+ mAttributeList.reset(new RsdparsaSdpAttributeList(Move(attributeSession),
+ section,
+ sessionLevel));
+
+ LoadFormats();
+ LoadConnection();
+}
+
+unsigned int
+RsdparsaSdpMediaSection::GetPort() const
+{
+ return sdp_get_media_port(mSection);
+}
+
+void
+RsdparsaSdpMediaSection::SetPort(unsigned int port)
+{
+ // TODO, see Bug 1433093
+}
+
+unsigned int
+RsdparsaSdpMediaSection::GetPortCount() const
+{
+ return sdp_get_media_port_count(mSection);
+}
+
+SdpMediaSection::Protocol
+RsdparsaSdpMediaSection::GetProtocol() const
+{
+ switch(sdp_get_media_protocol(mSection)) {
+ case kRustRtpSavpf:
+ return kRtpSavpf;
+ case kRustUdpTlsRtpSavpf:
+ return kUdpTlsRtpSavpf;
+ case kRustTcpTlsRtpSavpf:
+ return kTcpTlsRtpSavpf;
+ case kRustDtlsSctp:
+ return kDtlsSctp;
+ case kRustUdpDtlsSctp:
+ return kUdpDtlsSctp;
+ case kRustTcpDtlsSctp:
+ return kTcpDtlsSctp;
+ }
+
+ MOZ_CRASH("invalid media protocol");
+}
+
+const SdpConnection&
+RsdparsaSdpMediaSection::GetConnection() const
+{
+ MOZ_ASSERT(mConnection);
+ return *mConnection;
+}
+
+SdpConnection&
+RsdparsaSdpMediaSection::GetConnection()
+{
+ MOZ_ASSERT(mConnection);
+ return *mConnection;
+}
+
+uint32_t
+RsdparsaSdpMediaSection::GetBandwidth(const std::string& type) const
+{
+ return sdp_get_media_bandwidth(mSection, type.c_str());
+}
+
+const std::vector<std::string>&
+RsdparsaSdpMediaSection::GetFormats() const
+{
+ return mFormats;
+}
+
+const SdpAttributeList&
+RsdparsaSdpMediaSection::GetAttributeList() const
+{
+ return *mAttributeList;
+}
+
+SdpAttributeList&
+RsdparsaSdpMediaSection::GetAttributeList()
+{
+ return *mAttributeList;
+}
+
+SdpDirectionAttribute
+RsdparsaSdpMediaSection::GetDirectionAttribute() const
+{
+ return SdpDirectionAttribute(mAttributeList->GetDirection());
+}
+
+void
+RsdparsaSdpMediaSection::AddCodec(const std::string& pt,
+ const std::string& name,
+ uint32_t clockrate, uint16_t channels)
+{
+ //TODO: see Bug 1438289
+}
+
+void
+RsdparsaSdpMediaSection::ClearCodecs()
+{
+
+ //TODO: see Bug 1438289
+}
+
+void
+RsdparsaSdpMediaSection::AddDataChannel(const std::string& name, uint16_t port,
+ uint16_t streams, uint32_t message_size)
+{
+ //TODO: See 1438290
+}
+
+void
+RsdparsaSdpMediaSection::Serialize(std::ostream& os) const
+{
+ os << "m=" << mMediaType << " " << GetPort();
+ if (GetPortCount()) {
+ os << "/" << GetPortCount();
+ }
+ os << " " << GetProtocol();
+ for (auto i = mFormats.begin(); i != mFormats.end(); ++i) {
+ os << " " << (*i);
+ }
+ os << CRLF;
+
+ // We dont do i=
+
+ if (mConnection) {
+ os << *mConnection;
+ }
+
+ BandwidthVec* bwVec = sdp_get_media_bandwidth_vec(mSection);
+ char* bwString = sdp_serialize_bandwidth(bwVec);
+ if (bwString) {
+ os << bwString;
+ sdp_free_string(bwString);
+ }
+
+ // We dont do k= because they're evil
+
+ os << *mAttributeList;
+}
+
+void
+RsdparsaSdpMediaSection::LoadFormats()
+{
+ RustSdpFormatType formatType = sdp_get_format_type(mSection);
+ if (formatType == kRustIntegers) {
+ U32Vec* vec = sdp_get_format_u32_vec(mSection);
+ size_t len = u32_vec_len(vec);
+ for (size_t i = 0; i < len; i++) {
+ uint32_t val;
+ u32_vec_get(vec, i, &val);
+ mFormats.push_back(std::to_string(val));
+ }
+ } else {
+ StringVec* vec = sdp_get_format_string_vec(mSection);
+ mFormats = convertStringVec(vec);
+ }
+}
+
+UniquePtr<SdpConnection> convertRustConnection(RustSdpConnection conn)
+{
+ std::string addr(conn.addr.unicastAddr);
+ sdp::AddrType type = convertAddressType(conn.addr.addrType);
+ return MakeUnique<SdpConnection>(type, addr, conn.ttl, conn.amount);
+}
+
+void
+RsdparsaSdpMediaSection::LoadConnection()
+{
+ RustSdpConnection conn;
+ nsresult nr;
+ if (sdp_media_has_connection(mSection)) {
+ nr = sdp_get_media_connection(mSection, &conn);
+ if (NS_SUCCEEDED(nr)) {
+ mConnection = convertRustConnection(conn);
+ }
+ } else if (sdp_session_has_connection(mSession.get())){
+ // TODO: rsdparsa needs to ensure there is a connection at the session level
+ // if it is missing at a media level. See Bug 1438539.
+ nr = sdp_get_session_connection(mSession.get(), &conn);
+ if (NS_SUCCEEDED(nr)) {
+ mConnection = convertRustConnection(conn);
+ }
+ }
+}
+
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpMediaSection.h
@@ -0,0 +1,81 @@
+/* -*- 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/. */
+
+#ifndef _RUSTSDPMEDIASECTION_H_
+#define _RUSTSDPMEDIASECTION_H_
+
+#include "mozilla/Attributes.h"
+#include "mozilla/UniquePtr.h"
+#include "signaling/src/sdp/RsdparsaSdpInc.h"
+#include "signaling/src/sdp/RsdparsaSdpGlue.h"
+#include "signaling/src/sdp/SdpMediaSection.h"
+#include "signaling/src/sdp/RsdparsaSdpAttributeList.h"
+
+#include <map>
+
+namespace mozilla
+{
+
+class RsdparsaSdp;
+class SdpErrorHolder;
+
+class RsdparsaSdpMediaSection final : public SdpMediaSection
+{
+ friend class RsdparsaSdp;
+
+public:
+ ~RsdparsaSdpMediaSection() {}
+
+ MediaType
+ GetMediaType() const override
+ {
+ return mMediaType;
+ }
+
+ unsigned int GetPort() const override;
+ void SetPort(unsigned int port) override;
+ unsigned int GetPortCount() const override;
+ Protocol GetProtocol() const override;
+ const SdpConnection& GetConnection() const override;
+ SdpConnection& GetConnection() override;
+ uint32_t GetBandwidth(const std::string& type) const override;
+ const std::vector<std::string>& GetFormats() const override;
+
+ const SdpAttributeList& GetAttributeList() const override;
+ SdpAttributeList& GetAttributeList() override;
+ SdpDirectionAttribute GetDirectionAttribute() const override;
+
+ void AddCodec(const std::string& pt, const std::string& name,
+ uint32_t clockrate, uint16_t channels) override;
+ void ClearCodecs() override;
+
+ void AddDataChannel(const std::string& name, uint16_t port,
+ uint16_t streams, uint32_t message_size) override;
+
+ void Serialize(std::ostream&) const override;
+
+private:
+ RsdparsaSdpMediaSection(size_t level,
+ RsdparsaSessionHandle session,
+ const RustMediaSection* const section,
+ const RsdparsaSdpAttributeList* sessionLevel);
+
+ void LoadFormats();
+ void LoadConnection();
+
+ RsdparsaSessionHandle mSession;
+ const RustMediaSection* mSection;
+
+ MediaType mMediaType;
+ std::vector<std::string> mFormats;
+
+ UniquePtr<SdpConnection> mConnection;
+
+ UniquePtr<RsdparsaSdpAttributeList> mAttributeList;
+};
+}
+
+#endif
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpParser.cpp
@@ -0,0 +1,53 @@
+/* -*- 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 "nsError.h"
+
+#include "mozilla/UniquePtr.h"
+
+#include "signaling/src/sdp/Sdp.h"
+#include "signaling/src/sdp/SdpEnum.h"
+#include "signaling/src/sdp/RsdparsaSdp.h"
+#include "signaling/src/sdp/RsdparsaSdpParser.h"
+#include "signaling/src/sdp/RsdparsaSdpInc.h"
+#include "signaling/src/sdp/RsdparsaSdpGlue.h"
+
+namespace mozilla
+{
+
+UniquePtr<Sdp>
+RsdparsaSdpParser::Parse(const std::string &sdpText)
+{
+ ClearParseErrors();
+ const char* rawString = sdpText.c_str();
+ RustSdpSession* result;
+ RustSdpError* err;
+ nsresult rv = parse_sdp(rawString, sdpText.length() + 1, false,
+ &result, &err);
+ if (rv != NS_OK) {
+ // TODO: err should eventually never be null if rv != NS_OK
+ // see Bug 1433529
+ if (err != nullptr) {
+ size_t line = sdp_get_error_line_num(err);
+ std::string errMsg = convertStringView(sdp_get_error_message(err));
+ sdp_free_error(err);
+ AddParseError(line, errMsg);
+ } else {
+ AddParseError(0, "Unhandled Rsdparsa parsing error");
+ }
+ return nullptr;
+ }
+ RsdparsaSessionHandle uniqueResult;
+ uniqueResult.reset(result);
+ RustSdpOrigin rustOrigin = sdp_get_origin(uniqueResult.get());
+ sdp::AddrType addrType = convertAddressType(rustOrigin.addr.addrType);
+ SdpOrigin origin(convertStringView(rustOrigin.username),
+ rustOrigin.sessionId, rustOrigin.sessionVersion,
+ addrType, std::string(rustOrigin.addr.unicastAddr));
+ return MakeUnique<RsdparsaSdp>(Move(uniqueResult), origin);
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpParser.h
@@ -0,0 +1,35 @@
+/* -*- 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/. */
+
+#ifndef _RUSTSDPPARSER_H_
+#define _RUSTSDPPARSER_H_
+
+#include <string>
+
+#include "mozilla/UniquePtr.h"
+
+#include "signaling/src/sdp/Sdp.h"
+#include "signaling/src/sdp/SdpErrorHolder.h"
+
+namespace mozilla
+{
+
+class RsdparsaSdpParser final : public SdpErrorHolder
+{
+public:
+ RsdparsaSdpParser() {}
+ virtual ~RsdparsaSdpParser() {}
+
+ /**
+ * This parses the provided text into an SDP object.
+ * This returns a nullptr-valued pointer if things go poorly.
+ */
+ UniquePtr<Sdp> Parse(const std::string& sdpText);
+};
+
+} // namespace mozilla
+
+#endif
--- a/media/webrtc/signaling/src/sdp/moz.build
+++ b/media/webrtc/signaling/src/sdp/moz.build
@@ -32,18 +32,25 @@ UNIFIED_SOURCES += [
'SdpHelper.cpp',
'SdpMediaSection.cpp',
'SipccSdp.cpp',
'SipccSdpAttributeList.cpp',
'SipccSdpMediaSection.cpp',
'SipccSdpParser.cpp',
]
-# Multiple definitions of "logTag" mean we can't use unified build here.
SOURCES += [
+ # Building these as part of the unified build leads to multiply defined
+ # symbols on windows.
+ 'RsdparsaSdp.cpp',
+ 'RsdparsaSdpAttributeList.cpp',
+ 'RsdparsaSdpGlue.cpp',
+ 'RsdparsaSdpMediaSection.cpp',
+ 'RsdparsaSdpParser.cpp',
+ # Multiple definitions of "logTag" mean we can't use unified build here.
'sipcc/cpr_string.c',
'sipcc/sdp_access.c',
'sipcc/sdp_attr.c',
'sipcc/sdp_attr_access.c',
'sipcc/sdp_base64.c',
'sipcc/sdp_config.c',
'sipcc/sdp_main.c',
'sipcc/sdp_token.c',