Bug 1091242 - Part 1: SDP wrapper code around sipcc sdp impl. See https://github.com/unicorn-wg/gecko-dev/tree/multistream_rebase for more history. r=jesup

This commit is contained in:
Byron Campen [:bwc] 2014-11-19 16:11:06 -08:00
parent 5f2852c277
commit 2967aafd0c
16 changed files with 6299 additions and 58 deletions

View File

@ -0,0 +1,195 @@
/* -*- 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/. */
/*
,-----. ,--. ,--.
' .--./ ,--,--.,--.,--.,-' '-.`--' ,---. ,--,--,
| | ' ,-. || || |'-. .-',--.| .-. || `
' '--'\\ '-' |' '' ' | | | |' '-' '| || |
`-----' `--`--' `----' `--' `--' `---' `--''--'
:+o+-
-dNNNNNd.
yNNNNNNNs
:mNNNNNm-
`/sso/``-://-
.:+sydNNNNNNms: `://`
`-/+shmNNNNNNNNNNNNNNNms- :mNNNm/
`-/oydmNNNNNNNNNNNNNNNNNNNNNNNNdo- +NNNNNN+
.shmNNNNNNNNNNNmdyo/:dNNNNNNNNNNNNNNNNdo. `sNNNNNm+
hNNNNNNNNmhs+:-` .dNNNNNNNNNNNNNNNNNNNNh+-` `hNNNNNm:
-yddyo/:. -dNNNNm::ymNNNNNNNNNNNNNNNmdy+/dNNNNNd.
:mNNNNd. `/ymNNNNNNNNNNNNNNNNNNNNNNh`
+NNNNNh` `+hNNNNNNNNNNNNNNNNNNNs
sNNNNNy` .yNNNNNm`-/oymNNNm+
`yNNNNNo oNNNNNm` `-.
.dNNNNm/ oNNNNNm`
oNNNNm: +NNNNNm`
`+yho. +NNNNNm`
+NNNNNNs.
`yNNNNNNmy-
-smNNNNNNh:
.smNNNNNNh/
`omNNNNNNd:
`+dNNNNNd
````......```` /hmdy-
`.:/+osyhddmNNMMMMMMMMMMMMMMMMMMMMNNmddhyso+/:.`
`-+shmNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNmhs+-`
-smMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMds-
hMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMh
yMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMs
.ohNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNh+.
./oydmMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMmhyo:.
`.:/+osyyhddmmNNMMMMMMMMMMMMMMNNmmddhyyso+/:.`
,--------.,--. ,--. ,--.
'--. .--'| ,---. `--' ,---. | | ,---.
| | | .-. |,--.( .-' | |( .-'
| | | | | || |.-' `) | |.-' `)
`--' `--' `--'`--'`----' `--'`----'
,--.
,---. ,------. ,------. ,--. | |
' .-' | .-. \ | .--. ' ,--,--.,--.--.,-' '-. ,--,--.| |
`. `-. | | \ :| '--' |' ,-. || .--''-. .-'' ,-. || |
.-' || '--' /| | --' \ '-' || | | | \ '-' |`--'
`-----' `-------' `--' `--`--'`--' `--' `--`--'.--.
'__'
*/
#ifndef _SDP_H_
#define _SDP_H_
#include <ostream>
#include <vector>
#include <sstream>
#include "mozilla/UniquePtr.h"
#include "mozilla/Maybe.h"
#include "signaling/src/sdp/SdpMediaSection.h"
#include "signaling/src/sdp/SdpAttributeList.h"
#include "signaling/src/sdp/SdpEnum.h"
namespace mozilla
{
class SdpOrigin;
class SdpEncryptionKey;
class SdpMediaSection;
/**
* Base class for an SDP
*/
class Sdp
{
public:
Sdp(){};
virtual ~Sdp(){};
virtual const SdpOrigin& GetOrigin() const = 0;
// Note: connection information is always retrieved from media sections
virtual uint32_t GetBandwidth(const std::string& type) const = 0;
virtual const SdpAttributeList& GetAttributeList() const = 0;
virtual SdpAttributeList& GetAttributeList() = 0;
virtual size_t GetMediaSectionCount() const = 0;
virtual const SdpMediaSection& GetMediaSection(size_t level) const = 0;
virtual SdpMediaSection& GetMediaSection(size_t level) = 0;
virtual SdpMediaSection& AddMediaSection(SdpMediaSection::MediaType media,
SdpDirectionAttribute::Direction dir,
uint16_t port,
SdpMediaSection::Protocol proto,
sdp::AddrType addrType,
const std::string& addr) = 0;
virtual void Serialize(std::ostream&) const = 0;
std::string ToString() const;
};
inline std::ostream& operator<<(std::ostream& os, const Sdp& sdp)
{
sdp.Serialize(os);
return os;
}
inline std::string
Sdp::ToString() const
{
std::stringstream s;
s << *this;
return s.str();
}
class SdpOrigin
{
public:
SdpOrigin(const std::string& username, uint64_t sessId, uint64_t sessVer,
sdp::AddrType addrType, const std::string& addr)
: mUsername(username),
mSessionId(sessId),
mSessionVersion(sessVer),
mAddrType(addrType),
mAddress(addr)
{
}
const std::string&
GetUsername() const
{
return mUsername;
}
uint64_t
GetSessionId() const
{
return mSessionId;
}
uint64_t
GetSessionVersion() const
{
return mSessionVersion;
}
const sdp::AddrType
GetAddrType() const
{
return mAddrType;
}
const std::string&
GetAddress() const
{
return mAddress;
}
void
Serialize(std::ostream& os) const
{
sdp::NetType netType = sdp::kInternet;
os << "o=" << mUsername << " " << mSessionId << " " << mSessionVersion
<< " " << netType << " " << mAddrType << " " << mAddress << "\r\n";
}
private:
std::string mUsername;
uint64_t mSessionId;
uint64_t mSessionVersion;
sdp::AddrType mAddrType;
std::string mAddress;
};
inline std::ostream& operator<<(std::ostream& os, const SdpOrigin& origin)
{
origin.Serialize(os);
return os;
}
} // namespace mozilla
#endif

View File

@ -0,0 +1,588 @@
/* -*- 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/SdpAttribute.h"
#include <iomanip>
#ifdef CRLF
#undef CRLF
#endif
#define CRLF "\r\n"
namespace mozilla
{
void
SdpConnectionAttribute::Serialize(std::ostream& os) const
{
os << "a=" << mType << ":" << mValue << CRLF;
}
void
SdpDirectionAttribute::Serialize(std::ostream& os) const
{
os << "a=" << mValue << CRLF;
}
void
SdpExtmapAttributeList::Serialize(std::ostream& os) const
{
for (auto i = mExtmaps.begin(); i != mExtmaps.end(); ++i) {
os << "a=" << mType << ":" << i->entry;
if (i->direction_specified) {
os << "/" << i->direction;
}
os << " " << i->extensionname;
if (i->extensionattributes.length()) {
os << " " << i->extensionattributes;
}
os << CRLF;
}
}
void
SdpFingerprintAttributeList::Serialize(std::ostream& os) const
{
for (auto i = mFingerprints.begin(); i != mFingerprints.end(); ++i) {
os << "a=" << mType << ":" << i->hashFunc << " "
<< FormatFingerprint(i->fingerprint) << CRLF;
}
}
// Format the fingerprint in RFC 4572 Section 5 attribute format
std::string
SdpFingerprintAttributeList::FormatFingerprint(const std::vector<uint8_t>& fp)
{
if (fp.empty()) {
MOZ_ASSERT(false, "Cannot format an empty fingerprint.");
return "";
}
std::ostringstream os;
for (auto i = fp.begin(); i != fp.end(); ++i) {
os << ":" << std::hex << std::uppercase << std::setw(2) << std::setfill('0')
<< static_cast<uint32_t>(*i);
}
return os.str().substr(1);
}
static uint8_t
FromUppercaseHex(char ch)
{
if ((ch >= '0') && (ch <= '9')) {
return ch - '0';
}
if ((ch >= 'A') && (ch <= 'F')) {
return ch - 'A' + 10;
}
return 16; // invalid
}
// Parse the fingerprint from RFC 4572 Section 5 attribute format
std::vector<uint8_t>
SdpFingerprintAttributeList::ParseFingerprint(const std::string& str)
{
size_t targetSize = (str.length() + 1) / 3;
std::vector<uint8_t> fp(targetSize);
size_t fpIndex = 0;
if (str.length() % 3 != 2) {
fp.clear();
return fp;
}
for (size_t i = 0; i < str.length(); i += 3) {
uint8_t high = FromUppercaseHex(str[i]);
uint8_t low = FromUppercaseHex(str[i + 1]);
if (high > 0xf || low > 0xf ||
(i + 2 < str.length() && str[i + 2] != ':')) {
fp.clear(); // error
return fp;
}
fp[fpIndex++] = high << 4 | low;
}
return fp;
}
void
SdpFmtpAttributeList::Serialize(std::ostream& os) const
{
for (auto i = mFmtps.begin(); i != mFmtps.end(); ++i) {
os << "a=" << mType << ":" << i->format << " ";
if (i->parameters) {
i->parameters->Serialize(os);
} else {
os << i->parameters_string;
}
os << CRLF;
}
}
void
SdpGroupAttributeList::Serialize(std::ostream& os) const
{
for (auto i = mGroups.begin(); i != mGroups.end(); ++i) {
os << "a=" << mType << ":" << i->semantics;
for (auto j = i->tags.begin(); j != i->tags.end(); ++j) {
os << " " << (*j);
}
os << CRLF;
}
}
// We're just using an SdpStringAttribute for this right now
#if 0
void SdpIdentityAttribute::Serialize(std::ostream& os) const
{
os << "a=" << mType << ":" << mAssertion;
for (auto i = mExtensions.begin(); i != mExtensions.end(); i++) {
os << (i == mExtensions.begin() ? " " : ";") << (*i);
}
os << CRLF;
}
#endif
void
SdpImageattrAttributeList::Serialize(std::ostream& os) const
{
MOZ_ASSERT(false, "Serializer not yet implemented");
}
void
SdpMsidAttributeList::Serialize(std::ostream& os) const
{
for (auto i = mMsids.begin(); i != mMsids.end(); ++i) {
os << "a=" << mType << ":" << i->identifier;
if (i->appdata.length()) {
os << " " << i->appdata;
}
os << CRLF;
}
}
void
SdpRemoteCandidatesAttribute::Serialize(std::ostream& os) const
{
if (mCandidates.empty()) {
return;
}
os << "a=" << mType;
for (auto i = mCandidates.begin(); i != mCandidates.end(); i++) {
os << (i == mCandidates.begin() ? ":" : " ") << i->id << " " << i->address
<< " " << i->port;
}
os << CRLF;
}
void
SdpRtcpAttribute::Serialize(std::ostream& os) const
{
os << "a=" << mType << ":" << mPort;
if (mNetType != sdp::kNetTypeNone && mAddrType != sdp::kAddrTypeNone) {
os << " " << mNetType << " " << mAddrType << " " << mAddress;
}
os << CRLF;
}
const char* SdpRtcpFbAttributeList::pli = "pli";
const char* SdpRtcpFbAttributeList::sli = "sli";
const char* SdpRtcpFbAttributeList::rpsi = "rpsi";
const char* SdpRtcpFbAttributeList::app = "app";
const char* SdpRtcpFbAttributeList::fir = "fir";
const char* SdpRtcpFbAttributeList::tmmbr = "tmmbr";
const char* SdpRtcpFbAttributeList::tstr = "tstr";
const char* SdpRtcpFbAttributeList::vbcm = "vbcm";
void
SdpRtcpFbAttributeList::Serialize(std::ostream& os) const
{
for (auto i = mFeedbacks.begin(); i != mFeedbacks.end(); ++i) {
os << "a=" << mType << ":" << i->pt << " " << i->type;
if (i->parameter.length()) {
os << " " << i->parameter;
if (i->extra.length()) {
os << " " << i->extra;
}
}
os << CRLF;
}
}
static bool
ShouldSerializeChannels(SdpRtpmapAttributeList::CodecType type)
{
switch (type) {
case SdpRtpmapAttributeList::kOpus:
case SdpRtpmapAttributeList::kG722:
return true;
case SdpRtpmapAttributeList::kPCMU:
case SdpRtpmapAttributeList::kPCMA:
case SdpRtpmapAttributeList::kVP8:
case SdpRtpmapAttributeList::kVP9:
case SdpRtpmapAttributeList::kiLBC:
case SdpRtpmapAttributeList::kiSAC:
case SdpRtpmapAttributeList::kH264:
return false;
case SdpRtpmapAttributeList::kOtherCodec:
return true;
}
MOZ_CRASH();
}
void
SdpRtpmapAttributeList::Serialize(std::ostream& os) const
{
for (auto i = mRtpmaps.begin(); i != mRtpmaps.end(); ++i) {
os << "a=" << mType << ":" << i->pt << " " << i->name << "/" << i->clock;
if (i->channels && ShouldSerializeChannels(i->codec)) {
os << "/" << i->channels;
}
os << CRLF;
}
}
void
SdpSctpmapAttributeList::Serialize(std::ostream& os) const
{
for (auto i = mSctpmaps.begin(); i != mSctpmaps.end(); ++i) {
os << "a=" << mType << ":" << i->pt << " " << i->name;
if (i->streams) {
os << " " << i->streams;
}
os << CRLF;
}
}
void
SdpSetupAttribute::Serialize(std::ostream& os) const
{
os << "a=" << mType << ":" << mRole << CRLF;
}
void
SdpSsrcAttributeList::Serialize(std::ostream& os) const
{
for (auto i = mSsrcs.begin(); i != mSsrcs.end(); ++i) {
os << "a=" << mType << ":" << i->ssrc << " " << i->attribute << CRLF;
}
}
void
SdpSsrcGroupAttributeList::Serialize(std::ostream& os) const
{
for (auto i = mSsrcGroups.begin(); i != mSsrcGroups.end(); ++i) {
os << "a=" << mType << ":" << i->semantics;
for (auto j = i->ssrcs.begin(); j != i->ssrcs.end(); ++j) {
os << " " << (*j);
}
os << CRLF;
}
}
void
SdpMultiStringAttribute::Serialize(std::ostream& os) const
{
for (auto i = mValues.begin(); i != mValues.end(); ++i) {
os << "a=" << mType << ":" << *i << CRLF;
}
}
void
SdpOptionsAttribute::Serialize(std::ostream& os) const
{
if (mValues.empty()) {
return;
}
os << "a=" << mType << ":";
for (auto i = mValues.begin(); i != mValues.end(); ++i) {
if (i != mValues.begin()) {
os << " ";
}
os << *i;
}
os << CRLF;
}
void
SdpOptionsAttribute::Load(const std::string& value)
{
size_t start = 0;
size_t end = value.find(' ');
while (end != std::string::npos) {
PushEntry(value.substr(start, end));
start = end + 1;
end = value.find(' ', start);
}
PushEntry(value.substr(start));
}
void
SdpFlagAttribute::Serialize(std::ostream& os) const
{
os << "a=" << mType << CRLF;
}
void
SdpStringAttribute::Serialize(std::ostream& os) const
{
os << "a=" << mType << ":" << mValue << CRLF;
}
void
SdpNumberAttribute::Serialize(std::ostream& os) const
{
os << "a=" << mType << ":" << mValue << CRLF;
}
bool
SdpAttribute::IsAllowedAtMediaLevel(AttributeType type)
{
switch (type) {
case kBundleOnlyAttribute:
return true;
case kCandidateAttribute:
return true;
case kConnectionAttribute:
return true;
case kDirectionAttribute:
return true;
case kEndOfCandidatesAttribute:
return true;
case kExtmapAttribute:
return true;
case kFingerprintAttribute:
return true;
case kFmtpAttribute:
return true;
case kGroupAttribute:
return false;
case kIceLiteAttribute:
return false;
case kIceMismatchAttribute:
return true;
// RFC 5245 says this is session-level only, but
// draft-ietf-mmusic-ice-sip-sdp-03 updates this to allow at the media
// level.
case kIceOptionsAttribute:
return true;
case kIcePwdAttribute:
return true;
case kIceUfragAttribute:
return true;
case kIdentityAttribute:
return false;
case kImageattrAttribute:
return true;
case kInactiveAttribute:
return true;
case kLabelAttribute:
return true;
case kMaxptimeAttribute:
return true;
case kMidAttribute:
return true;
case kMsidAttribute:
return true;
case kMsidSemanticAttribute:
return false;
case kPtimeAttribute:
return true;
case kRecvonlyAttribute:
return true;
case kRemoteCandidatesAttribute:
return true;
case kRtcpAttribute:
return true;
case kRtcpFbAttribute:
return true;
case kRtcpMuxAttribute:
return true;
case kRtcpRsizeAttribute:
return true;
case kRtpmapAttribute:
return true;
case kSctpmapAttribute:
return true;
case kSendonlyAttribute:
return true;
case kSendrecvAttribute:
return true;
case kSetupAttribute:
return true;
case kSsrcAttribute:
return true;
case kSsrcGroupAttribute:
return true;
}
MOZ_CRASH("Unknown attribute type");
}
bool
SdpAttribute::IsAllowedAtSessionLevel(AttributeType type)
{
switch (type) {
case kBundleOnlyAttribute:
return false;
case kCandidateAttribute:
return false;
case kConnectionAttribute:
return true;
case kDirectionAttribute:
return true;
case kEndOfCandidatesAttribute:
return true;
case kExtmapAttribute:
return true;
case kFingerprintAttribute:
return true;
case kFmtpAttribute:
return false;
case kGroupAttribute:
return true;
case kIceLiteAttribute:
return true;
case kIceMismatchAttribute:
return false;
case kIceOptionsAttribute:
return true;
case kIcePwdAttribute:
return true;
case kIceUfragAttribute:
return true;
case kIdentityAttribute:
return true;
case kImageattrAttribute:
return false;
case kInactiveAttribute:
return true;
case kLabelAttribute:
return false;
case kMaxptimeAttribute:
return false;
case kMidAttribute:
return false;
case kMsidSemanticAttribute:
return true;
case kMsidAttribute:
return false;
case kPtimeAttribute:
return false;
case kRecvonlyAttribute:
return true;
case kRemoteCandidatesAttribute:
return false;
case kRtcpAttribute:
return false;
case kRtcpFbAttribute:
return false;
case kRtcpMuxAttribute:
return false;
case kRtcpRsizeAttribute:
return false;
case kRtpmapAttribute:
return false;
case kSctpmapAttribute:
return false;
case kSendonlyAttribute:
return true;
case kSendrecvAttribute:
return true;
case kSetupAttribute:
return true;
case kSsrcAttribute:
return false;
case kSsrcGroupAttribute:
return false;
}
MOZ_CRASH("Unknown attribute type");
}
const std::string
SdpAttribute::GetAttributeTypeString(AttributeType type)
{
switch (type) {
case kBundleOnlyAttribute:
return "bundle-only";
case kCandidateAttribute:
return "candidate";
case kConnectionAttribute:
return "connection";
case kEndOfCandidatesAttribute:
return "end-of-candidates";
case kExtmapAttribute:
return "extmap";
case kFingerprintAttribute:
return "fingerprint";
case kFmtpAttribute:
return "fmtp";
case kGroupAttribute:
return "group";
case kIceLiteAttribute:
return "ice-lite";
case kIceMismatchAttribute:
return "ice-mismatch";
case kIceOptionsAttribute:
return "ice-options";
case kIcePwdAttribute:
return "ice-pwd";
case kIceUfragAttribute:
return "ice-ufrag";
case kIdentityAttribute:
return "identity";
case kImageattrAttribute:
return "imageattr";
case kInactiveAttribute:
return "inactive";
case kLabelAttribute:
return "label";
case kMaxptimeAttribute:
return "maxptime";
case kMidAttribute:
return "mid";
case kMsidAttribute:
return "msid";
case kMsidSemanticAttribute:
return "msid-semantic";
case kPtimeAttribute:
return "ptime";
case kRecvonlyAttribute:
return "recvonly";
case kRemoteCandidatesAttribute:
return "remote-candidates";
case kRtcpAttribute:
return "rtcp";
case kRtcpFbAttribute:
return "rtcp-fb";
case kRtcpMuxAttribute:
return "rtcp-mux";
case kRtcpRsizeAttribute:
return "rtcp-rsize";
case kRtpmapAttribute:
return "rtpmap";
case kSctpmapAttribute:
return "sctpmap";
case kSendonlyAttribute:
return "sendonly";
case kSendrecvAttribute:
return "sendrecv";
case kSetupAttribute:
return "setup";
case kSsrcAttribute:
return "ssrc";
case kSsrcGroupAttribute:
return "ssrc-group";
case kDirectionAttribute:
MOZ_CRASH("kDirectionAttribute not valid here");
}
MOZ_CRASH("Unknown attribute type");
}
} // namespace mozilla

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,90 @@
/* -*- 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 _SDPATTRIBUTELIST_H_
#define _SDPATTRIBUTELIST_H_
#include "mozilla/UniquePtr.h"
#include "mozilla/Attributes.h"
#include "signaling/src/sdp/SdpAttribute.h"
namespace mozilla
{
class SdpAttributeList
{
public:
typedef SdpAttribute::AttributeType AttributeType;
// Avoid default params on virtual functions
bool
HasAttribute(AttributeType type) const
{
return HasAttribute(type, true);
}
const SdpAttribute*
GetAttribute(AttributeType type) const
{
return GetAttribute(type, true);
}
virtual bool HasAttribute(AttributeType type, bool sessionFallback) const = 0;
virtual const SdpAttribute* GetAttribute(AttributeType type,
bool sessionFallback) const = 0;
// The setter takes an attribute of any type, and takes ownership
virtual void SetAttribute(SdpAttribute* attr) = 0;
virtual void RemoveAttribute(AttributeType type) = 0;
virtual void Clear() = 0;
virtual const SdpConnectionAttribute& GetConnection() const = 0;
virtual const SdpOptionsAttribute& GetIceOptions() const = 0;
virtual const SdpRtcpAttribute& GetRtcp() const = 0;
virtual const SdpRemoteCandidatesAttribute& GetRemoteCandidates() const = 0;
virtual const SdpSetupAttribute& GetSetup() const = 0;
// These attributes can appear multiple times, so the returned
// classes actually represent a collection of values.
virtual const std::vector<std::string>& GetCandidate() const = 0;
virtual const SdpExtmapAttributeList& GetExtmap() const = 0;
virtual const SdpFingerprintAttributeList& GetFingerprint() const = 0;
virtual const SdpFmtpAttributeList& GetFmtp() const = 0;
virtual const SdpGroupAttributeList& GetGroup() const = 0;
virtual const SdpImageattrAttributeList& GetImageattr() const = 0;
virtual const SdpMsidAttributeList& GetMsid() const = 0;
virtual const SdpRtcpFbAttributeList& GetRtcpFb() const = 0;
virtual const SdpRtpmapAttributeList& GetRtpmap() const = 0;
virtual const SdpSctpmapAttributeList& GetSctpmap() const = 0;
virtual const SdpSsrcAttributeList& GetSsrc() const = 0;
virtual const SdpSsrcGroupAttributeList& GetSsrcGroup() const = 0;
// These attributes are effectively simple types, so we'll make life
// easy by just returning their value.
virtual const std::string& GetIcePwd() const = 0;
virtual const std::string& GetIceUfrag() const = 0;
virtual const std::string& GetIdentity() const = 0;
virtual const std::string& GetLabel() const = 0;
virtual unsigned int GetMaxptime() const = 0;
virtual const std::string& GetMid() const = 0;
virtual const std::string& GetMsidSemantic() const = 0;
virtual unsigned int GetPtime() const = 0;
// This is "special", because it's multiple things
virtual SdpDirectionAttribute::Direction GetDirection() const = 0;
virtual void Serialize(std::ostream&) const = 0;
};
inline std::ostream& operator<<(std::ostream& os, const SdpAttributeList& al)
{
al.Serialize(os);
return os;
}
} // namespace mozilla
#endif

View File

@ -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/. */
#ifndef _SDPENUM_H_
#define _SDPENUM_H_
#include <ostream>
#include "mozilla/Assertions.h"
namespace mozilla
{
namespace sdp
{
enum NetType { kNetTypeNone, kInternet };
inline std::ostream& operator<<(std::ostream& os, sdp::NetType t)
{
switch (t) {
case sdp::kNetTypeNone:
MOZ_ASSERT(false);
return os << "NONE";
case sdp::kInternet:
return os << "IN";
}
MOZ_CRASH("Unknown NetType");
}
enum AddrType { kAddrTypeNone, kIPv4, kIPv6 };
inline std::ostream& operator<<(std::ostream& os, sdp::AddrType t)
{
switch (t) {
case sdp::kAddrTypeNone:
MOZ_ASSERT(false);
return os << "NONE";
case sdp::kIPv4:
return os << "IP4";
case sdp::kIPv6:
return os << "IP6";
}
MOZ_CRASH("Unknown AddrType");
}
} // namespace sdp
} // namespace mozilla
#endif

View File

@ -0,0 +1,50 @@
/* -*- 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 _SDPERRORHOLDER_H_
#define _SDPERRORHOLDER_H_
#include <vector>
#include <string>
namespace mozilla
{
class SdpErrorHolder
{
public:
SdpErrorHolder() {}
virtual ~SdpErrorHolder() {}
void
AddParseError(size_t line, const std::string& message)
{
mErrors.push_back(std::make_pair(line, message));
}
void
ClearParseErrors()
{
mErrors.clear();
}
/**
* Returns a reference to the list of parse errors.
* This gets cleared out when you call Parse.
*/
const std::vector<std::pair<size_t, std::string> >&
GetParseErrors() const
{
return mErrors;
}
private:
std::vector<std::pair<size_t, std::string> > mErrors;
};
} // namespace mozilla
#endif

View File

@ -0,0 +1,284 @@
/* -*- 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 _SDPMEDIASECTION_H_
#define _SDPMEDIASECTION_H_
#include "mozilla/Maybe.h"
#include "signaling/src/sdp/SdpEnum.h"
#include "signaling/src/sdp/SdpAttributeList.h"
#include <string>
#include <vector>
#include "signaling/src/sdp/SdpEnum.h"
namespace mozilla
{
class SdpAttributeList;
class SdpConnection;
class SdpMediaSection
{
public:
enum MediaType { kAudio, kVideo, kText, kApplication, kMessage };
enum Protocol {
kRtpAvp, // RTP/AVP [RFC4566]
kUdp, // udp [RFC4566]
kVat, // vat [historic]
kRtp, // rtp [historic]
kUdptl, // udptl [ITU-T]
kTcp, // TCP [RFC4145]
kRtpAvpf, // RTP/AVPF [RFC4585]
kTcpRtpAvp, // TCP/RTP/AVP [RFC4571]
kRtpSavp, // RTP/SAVP [RFC3711]
kTcpBfcp, // TCP/BFCP [RFC4583]
kTcpTlsBfcp, // TCP/TLS/BFCP [RFC4583]
kTcpTls, // TCP/TLS [RFC4572]
kFluteUdp, // FLUTE/UDP [RFC-mehta-rmt-flute-sdp-05]
kTcpMsrp, // TCP/MSRP [RFC4975]
kTcpTlsMsrp, // TCP/TLS/MSRP [RFC4975]
kDccp, // DCCP [RFC5762]
kDccpRtpAvp, // DCCP/RTP/AVP [RFC5762]
kDccpRtpSavp, // DCCP/RTP/SAVP [RFC5762]
kDccpRtpAvpf, // DCCP/RTP/AVPF [RFC5762]
kDccpRtpSavpf, // DCCP/RTP/SAVPF [RFC5762]
kRtpSavpf, // RTP/SAVPF [RFC5124]
kUdpTlsRtpSavp, // UDP/TLS/RTP/SAVP [RFC5764]
kTcpTlsRtpSavp, // TCP/TLS/RTP/SAVP [JSEP-TBD]
kDccpTlsRtpSavp, // DCCP/TLS/RTP/SAVP [RFC5764]
kUdpTlsRtpSavpf, // UDP/TLS/RTP/SAVPF [RFC5764]
kTcpTlsRtpSavpf, // TCP/TLS/RTP/SAVPF [JSEP-TBD]
kDccpTlsRtpSavpf, // DCCP/TLS/RTP/SAVPF [RFC5764]
kUdpMbmsFecRtpAvp, // UDP/MBMS-FEC/RTP/AVP [RFC6064]
kUdpMbmsFecRtpSavp, // UDP/MBMS-FEC/RTP/SAVP [RFC6064]
kUdpMbmsRepair, // UDP/MBMS-REPAIR [RFC6064]
kFecUdp, // FEC/UDP [RFC6364]
kUdpFec, // UDP/FEC [RFC6364]
kTcpMrcpv2, // TCP/MRCPv2 [RFC6787]
kTcpTlsMrcpv2, // TCP/TLS/MRCPv2 [RFC6787]
kPstn, // PSTN [RFC7195]
kUdpTlsUdptl, // UDP/TLS/UDPTL [RFC7345]
kSctp, // SCTP [draft-ietf-mmusic-sctp-sdp-07]
kSctpDtls, // SCTP/DTLS [draft-ietf-mmusic-sctp-sdp-07]
kDtlsSctp // DTLS/SCTP [draft-ietf-mmusic-sctp-sdp-07]
};
explicit SdpMediaSection(size_t level) : mLevel(level) {}
virtual MediaType GetMediaType() const = 0;
virtual unsigned int GetPort() const = 0;
virtual void SetPort(unsigned int port) = 0;
virtual unsigned int GetPortCount() const = 0;
virtual Protocol GetProtocol() const = 0;
virtual const SdpConnection& GetConnection() const = 0;
virtual SdpConnection& GetConnection() = 0;
virtual uint32_t GetBandwidth(const std::string& type) const = 0;
virtual const std::vector<std::string>& GetFormats() const = 0;
virtual const SdpAttributeList& GetAttributeList() const = 0;
virtual SdpAttributeList& GetAttributeList() = 0;
virtual SdpDirectionAttribute GetDirectionAttribute() const = 0;
virtual void Serialize(std::ostream&) const = 0;
virtual void AddCodec(const std::string& pt, const std::string& name,
uint32_t clockrate, uint16_t channels) = 0;
virtual void AddDataChannel(const std::string& pt, const std::string& name,
uint16_t streams) = 0;
size_t
GetLevel() const
{
return mLevel;
}
private:
size_t mLevel;
};
inline std::ostream& operator<<(std::ostream& os, const SdpMediaSection& ms)
{
ms.Serialize(os);
return os;
}
inline std::ostream& operator<<(std::ostream& os, SdpMediaSection::MediaType t)
{
switch (t) {
case SdpMediaSection::kAudio:
return os << "audio";
case SdpMediaSection::kVideo:
return os << "video";
case SdpMediaSection::kText:
return os << "text";
case SdpMediaSection::kApplication:
return os << "application";
case SdpMediaSection::kMessage:
return os << "message";
}
MOZ_ASSERT(false, "Unknown MediaType");
return os << "?";
}
inline std::ostream& operator<<(std::ostream& os, SdpMediaSection::Protocol p)
{
switch (p) {
case SdpMediaSection::kRtpAvp:
return os << "RTP/AVP";
case SdpMediaSection::kUdp:
return os << "udp";
case SdpMediaSection::kVat:
return os << "vat";
case SdpMediaSection::kRtp:
return os << "rtp";
case SdpMediaSection::kUdptl:
return os << "udptl";
case SdpMediaSection::kTcp:
return os << "TCP";
case SdpMediaSection::kRtpAvpf:
return os << "RTP/AVPF";
case SdpMediaSection::kTcpRtpAvp:
return os << "TCP/RTP/AVP";
case SdpMediaSection::kRtpSavp:
return os << "RTP/SAVP";
case SdpMediaSection::kTcpBfcp:
return os << "TCP/BFCP";
case SdpMediaSection::kTcpTlsBfcp:
return os << "TCP/TLS/BFCP";
case SdpMediaSection::kTcpTls:
return os << "TCP/TLS";
case SdpMediaSection::kFluteUdp:
return os << "FLUTE/UDP";
case SdpMediaSection::kTcpMsrp:
return os << "TCP/MSRP";
case SdpMediaSection::kTcpTlsMsrp:
return os << "TCP/TLS/MSRP";
case SdpMediaSection::kDccp:
return os << "DCCP";
case SdpMediaSection::kDccpRtpAvp:
return os << "DCCP/RTP/AVP";
case SdpMediaSection::kDccpRtpSavp:
return os << "DCCP/RTP/SAVP";
case SdpMediaSection::kDccpRtpAvpf:
return os << "DCCP/RTP/AVPF";
case SdpMediaSection::kDccpRtpSavpf:
return os << "DCCP/RTP/SAVPF";
case SdpMediaSection::kRtpSavpf:
return os << "RTP/SAVPF";
case SdpMediaSection::kUdpTlsRtpSavp:
return os << "UDP/TLS/RTP/SAVP";
case SdpMediaSection::kTcpTlsRtpSavp:
return os << "TCP/TLS/RTP/SAVP";
case SdpMediaSection::kDccpTlsRtpSavp:
return os << "DCCP/TLS/RTP/SAVP";
case SdpMediaSection::kUdpTlsRtpSavpf:
return os << "UDP/TLS/RTP/SAVPF";
case SdpMediaSection::kTcpTlsRtpSavpf:
return os << "TCP/TLS/RTP/SAVPF";
case SdpMediaSection::kDccpTlsRtpSavpf:
return os << "DCCP/TLS/RTP/SAVPF";
case SdpMediaSection::kUdpMbmsFecRtpAvp:
return os << "UDP/MBMS-FEC/RTP/AVP";
case SdpMediaSection::kUdpMbmsFecRtpSavp:
return os << "UDP/MBMS-FEC/RTP/SAVP";
case SdpMediaSection::kUdpMbmsRepair:
return os << "UDP/MBMS-REPAIR";
case SdpMediaSection::kFecUdp:
return os << "FEC/UDP";
case SdpMediaSection::kUdpFec:
return os << "UDP/FEC";
case SdpMediaSection::kTcpMrcpv2:
return os << "TCP/MRCPv2";
case SdpMediaSection::kTcpTlsMrcpv2:
return os << "TCP/TLS/MRCPv2";
case SdpMediaSection::kPstn:
return os << "PSTN";
case SdpMediaSection::kUdpTlsUdptl:
return os << "UDP/TLS/UDPTL";
case SdpMediaSection::kSctp:
return os << "SCTP";
case SdpMediaSection::kSctpDtls:
return os << "SCTP/DTLS";
case SdpMediaSection::kDtlsSctp:
return os << "DTLS/SCTP";
}
MOZ_ASSERT(false, "Unknown Protocol");
return os << "?";
}
class SdpConnection
{
public:
SdpConnection(sdp::AddrType addrType, std::string addr, uint8_t ttl = 0,
uint32_t count = 0)
: mAddrType(addrType), mAddr(addr), mTtl(ttl), mCount(count)
{
}
~SdpConnection() {}
sdp::AddrType
GetAddrType() const
{
return mAddrType;
}
const std::string&
GetAddress() const
{
return mAddr;
}
void
SetAddress(const std::string& address)
{
mAddr = address;
}
uint8_t
GetTtl() const
{
return mTtl;
}
uint32_t
GetCount() const
{
return mCount;
}
void
Serialize(std::ostream& os) const
{
sdp::NetType netType = sdp::kInternet;
os << "c=" << netType << " " << mAddrType << " " << mAddr;
if (mTtl) {
os << "/" << static_cast<uint32_t>(mTtl);
if (mCount) {
os << "/" << mCount;
}
}
os << "\r\n";
}
private:
sdp::AddrType mAddrType;
std::string mAddr;
uint8_t mTtl; // 0-255; 0 when unset
uint32_t mCount; // 0 when unset
};
inline std::ostream& operator<<(std::ostream& os, const SdpConnection& c)
{
c.Serialize(os);
return os;
}
} // namespace mozilla
#endif

View File

@ -0,0 +1,186 @@
/* 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/SipccSdp.h"
#include <cstdlib>
#include "mozilla/Assertions.h"
#include "signaling/src/sdp/SdpErrorHolder.h"
#ifdef CRLF
#undef CRLF
#endif
#define CRLF "\r\n"
namespace mozilla
{
SipccSdp::~SipccSdp()
{
for (auto i = mMediaSections.begin(); i != mMediaSections.end(); ++i) {
delete *i;
}
}
const SdpOrigin&
SipccSdp::GetOrigin() const
{
return mOrigin;
}
uint32_t
SipccSdp::GetBandwidth(const std::string& type) const
{
auto found = mBandwidths.find(type);
if (found == mBandwidths.end()) {
return 0;
}
return found->second;
}
const SdpMediaSection&
SipccSdp::GetMediaSection(size_t level) const
{
if (level > mMediaSections.size()) {
MOZ_CRASH();
}
return *mMediaSections[level];
}
SdpMediaSection&
SipccSdp::GetMediaSection(size_t level)
{
if (level > mMediaSections.size()) {
MOZ_CRASH();
}
return *mMediaSections[level];
}
SdpMediaSection&
SipccSdp::AddMediaSection(SdpMediaSection::MediaType mediaType,
SdpDirectionAttribute::Direction dir, uint16_t port,
SdpMediaSection::Protocol protocol,
sdp::AddrType addrType, const std::string& addr)
{
size_t level = mMediaSections.size();
SipccSdpMediaSection* media =
new SipccSdpMediaSection(level, &mAttributeList);
media->mMediaType = mediaType;
media->mPort = port;
media->mPortCount = 0;
media->mProtocol = protocol;
media->mConnection = MakeUnique<SdpConnection>(addrType, addr);
media->GetAttributeList().SetAttribute(new SdpDirectionAttribute(dir));
mMediaSections.push_back(media);
return *media;
}
bool
SipccSdp::LoadOrigin(sdp_t* sdp, SdpErrorHolder& errorHolder)
{
std::string username = sdp_get_owner_username(sdp);
uint64_t sessId = strtoul(sdp_get_owner_sessionid(sdp), nullptr, 10);
uint64_t sessVer = strtoul(sdp_get_owner_version(sdp), nullptr, 10);
sdp_nettype_e type = sdp_get_owner_network_type(sdp);
if (type != SDP_NT_INTERNET) {
errorHolder.AddParseError(2, "Unsupported network type");
return false;
}
sdp::AddrType addrType;
switch (sdp_get_owner_address_type(sdp)) {
case SDP_AT_IP4:
addrType = sdp::kIPv4;
break;
case SDP_AT_IP6:
addrType = sdp::kIPv6;
break;
default:
errorHolder.AddParseError(2, "Unsupported address type");
return false;
}
std::string address = sdp_get_owner_address(sdp);
mOrigin = SdpOrigin(username, sessId, sessVer, addrType, address);
return true;
}
bool
SipccSdp::Load(sdp_t* sdp, SdpErrorHolder& errorHolder)
{
// Believe it or not, SDP_SESSION_LEVEL is 0xFFFF
if (!mAttributeList.Load(sdp, SDP_SESSION_LEVEL, errorHolder)) {
return false;
}
if (!LoadOrigin(sdp, errorHolder)) {
return false;
}
if (!mBandwidths.Load(sdp, SDP_SESSION_LEVEL, errorHolder)) {
return false;
}
for (int i = 0; i < sdp_get_num_media_lines(sdp); ++i) {
// note that we pass a "level" here that is one higher
// sipcc counts media sections from 1, using 0xFFFF as the "session"
UniquePtr<SipccSdpMediaSection> section(
new SipccSdpMediaSection(i, &mAttributeList));
if (!section->Load(sdp, i + 1, errorHolder)) {
return false;
}
mMediaSections.push_back(section.release());
}
return true;
}
void
SipccSdp::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)
mBandwidths.Serialize(os);
os << "t=0 0" << CRLF;
// We don't support r= or z=
// attributes
os << mAttributeList;
// media sections
for (auto i = mMediaSections.begin(); i != mMediaSections.end(); ++i) {
os << (**i);
}
}
bool
SipccSdpBandwidths::Load(sdp_t* sdp, uint16_t level,
SdpErrorHolder& errorHolder)
{
size_t count = sdp_get_num_bw_lines(sdp, level);
for (size_t i = 1; i <= count; ++i) {
sdp_bw_modifier_e bwtype = sdp_get_bw_modifier(sdp, level, i);
uint32_t bandwidth = sdp_get_bw_value(sdp, level, i);
if (bwtype != SDP_BW_MODIFIER_UNSUPPORTED) {
const char* typeName = sdp_get_bw_modifier_name(bwtype);
(*this)[typeName] = bandwidth;
}
}
return true;
}
void
SipccSdpBandwidths::Serialize(std::ostream& os) const
{
for (auto i = begin(); i != end(); ++i) {
os << "b=" << i->first << ":" << i->second << CRLF;
}
}
} // namespace mozilla

View File

@ -0,0 +1,88 @@
/* -*- 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 _SIPCCSDP_H_
#define _SIPCCSDP_H_
#include <map>
#include <vector>
#include "mozilla/Attributes.h"
#include "mozilla/UniquePtr.h"
#include "signaling/src/sdp/Sdp.h"
#include "signaling/src/sdp/SipccSdpMediaSection.h"
#include "signaling/src/sdp/SipccSdpAttributeList.h"
extern "C" {
#include "signaling/src/sdp/sipcc/sdp.h"
}
namespace mozilla
{
class SipccSdpParser;
class SdpErrorHolder;
class SipccSdp MOZ_FINAL : public Sdp
{
friend class SipccSdpParser;
public:
explicit SipccSdp(const SdpOrigin& origin)
: mOrigin(origin), mAttributeList(nullptr)
{
}
~SipccSdp();
virtual const SdpOrigin& GetOrigin() const MOZ_OVERRIDE;
// Note: connection information is always retrieved from media sections
virtual uint32_t GetBandwidth(const std::string& type) const MOZ_OVERRIDE;
virtual size_t
GetMediaSectionCount() const MOZ_OVERRIDE
{
return mMediaSections.size();
}
virtual const SdpAttributeList&
GetAttributeList() const MOZ_OVERRIDE
{
return mAttributeList;
}
virtual SdpAttributeList&
GetAttributeList() MOZ_OVERRIDE
{
return mAttributeList;
}
virtual const SdpMediaSection& GetMediaSection(size_t level) const
MOZ_OVERRIDE;
virtual SdpMediaSection& GetMediaSection(size_t level) MOZ_OVERRIDE;
virtual SdpMediaSection& AddMediaSection(
SdpMediaSection::MediaType media, SdpDirectionAttribute::Direction dir,
uint16_t port, SdpMediaSection::Protocol proto, sdp::AddrType addrType,
const std::string& addr) MOZ_OVERRIDE;
virtual void Serialize(std::ostream&) const MOZ_OVERRIDE;
private:
SipccSdp() : mOrigin("", 0, 0, sdp::kIPv4, ""), mAttributeList(nullptr) {}
bool Load(sdp_t* sdp, SdpErrorHolder& errorHolder);
bool LoadOrigin(sdp_t* sdp, SdpErrorHolder& errorHolder);
SdpOrigin mOrigin;
SipccSdpBandwidths mBandwidths;
SipccSdpAttributeList mAttributeList;
std::vector<SipccSdpMediaSection*> mMediaSections;
};
} // namespace mozilla
#endif // _sdp_h_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,133 @@
/* -*- 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 _SIPCCSDPATTRIBUTELIST_H_
#define _SIPCCSDPATTRIBUTELIST_H_
#include "signaling/src/sdp/SdpAttributeList.h"
extern "C" {
#include "signaling/src/sdp/sipcc/sdp.h"
}
namespace mozilla
{
class SipccSdp;
class SipccSdpMediaSection;
class SdpErrorHolder;
class SipccSdpAttributeList : public SdpAttributeList
{
friend class SipccSdpMediaSection;
friend class SipccSdp;
public:
// Make sure we don't hide the default arg thunks
using SdpAttributeList::HasAttribute;
using SdpAttributeList::GetAttribute;
virtual bool HasAttribute(AttributeType type,
bool sessionFallback) const MOZ_OVERRIDE;
virtual const SdpAttribute* GetAttribute(
AttributeType type, bool sessionFallback) const MOZ_OVERRIDE;
virtual void SetAttribute(SdpAttribute* attr) MOZ_OVERRIDE;
virtual void RemoveAttribute(AttributeType type) MOZ_OVERRIDE;
virtual void Clear() MOZ_OVERRIDE;
virtual const SdpConnectionAttribute& GetConnection() const MOZ_OVERRIDE;
virtual const SdpFingerprintAttributeList& GetFingerprint() const
MOZ_OVERRIDE;
virtual const SdpGroupAttributeList& GetGroup() const MOZ_OVERRIDE;
virtual const SdpOptionsAttribute& GetIceOptions() const MOZ_OVERRIDE;
virtual const SdpRtcpAttribute& GetRtcp() const MOZ_OVERRIDE;
virtual const SdpRemoteCandidatesAttribute& GetRemoteCandidates() const
MOZ_OVERRIDE;
virtual const SdpSetupAttribute& GetSetup() const MOZ_OVERRIDE;
virtual const SdpSsrcAttributeList& GetSsrc() const MOZ_OVERRIDE;
virtual const SdpSsrcGroupAttributeList& GetSsrcGroup() const MOZ_OVERRIDE;
// These attributes can appear multiple times, so the returned
// classes actually represent a collection of values.
virtual const std::vector<std::string>& GetCandidate() const MOZ_OVERRIDE;
virtual const SdpExtmapAttributeList& GetExtmap() const MOZ_OVERRIDE;
virtual const SdpFmtpAttributeList& GetFmtp() const MOZ_OVERRIDE;
virtual const SdpImageattrAttributeList& GetImageattr() const MOZ_OVERRIDE;
virtual const SdpMsidAttributeList& GetMsid() const MOZ_OVERRIDE;
virtual const SdpRtcpFbAttributeList& GetRtcpFb() const MOZ_OVERRIDE;
virtual const SdpRtpmapAttributeList& GetRtpmap() const MOZ_OVERRIDE;
virtual const SdpSctpmapAttributeList& GetSctpmap() const MOZ_OVERRIDE;
// These attributes are effectively simple types, so we'll make life
// easy by just returning their value.
virtual const std::string& GetIcePwd() const MOZ_OVERRIDE;
virtual const std::string& GetIceUfrag() const MOZ_OVERRIDE;
virtual const std::string& GetIdentity() const MOZ_OVERRIDE;
virtual const std::string& GetLabel() const MOZ_OVERRIDE;
virtual unsigned int GetMaxptime() const MOZ_OVERRIDE;
virtual const std::string& GetMid() const MOZ_OVERRIDE;
virtual const std::string& GetMsidSemantic() const MOZ_OVERRIDE;
virtual unsigned int GetPtime() const MOZ_OVERRIDE;
virtual SdpDirectionAttribute::Direction GetDirection() const MOZ_OVERRIDE;
virtual void Serialize(std::ostream&) const MOZ_OVERRIDE;
virtual ~SipccSdpAttributeList();
private:
static const std::string kEmptyString;
static const size_t kNumAttributeTypes = SdpAttribute::kLastAttribute + 1;
// Pass a session-level attribute list if constructing a media-level one,
// otherwise pass nullptr
explicit SipccSdpAttributeList(const SipccSdpAttributeList* sessionLevel);
bool Load(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
void LoadSimpleStrings(sdp_t* sdp, uint16_t level,
SdpErrorHolder& errorHolder);
void LoadSimpleString(sdp_t* sdp, uint16_t level, sdp_attr_e attr,
AttributeType targetType, SdpErrorHolder& errorHolder);
void LoadSimpleNumbers(sdp_t* sdp, uint16_t level,
SdpErrorHolder& errorHolder);
void LoadSimpleNumber(sdp_t* sdp, uint16_t level, sdp_attr_e attr,
AttributeType targetType, SdpErrorHolder& errorHolder);
void LoadFlags(sdp_t* sdp, uint16_t level);
void LoadDirection(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
bool LoadRtpmap(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
bool LoadSctpmap(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
void LoadIceAttributes(sdp_t* sdp, uint16_t level);
bool LoadFingerprint(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
void LoadCandidate(sdp_t* sdp, uint16_t level);
void LoadSetup(sdp_t* sdp, uint16_t level);
bool LoadGroups(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
void LoadFmtp(sdp_t* sdp, uint16_t level);
void LoadMsids(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
void LoadExtmap(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
void LoadRtcpFb(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
static SdpRtpmapAttributeList::CodecType GetCodecType(rtp_ptype type);
bool
AtSessionLevel() const
{
return !mSessionLevel;
}
bool IsAllowedHere(SdpAttribute::AttributeType type) const;
void WarnAboutMisplacedAttribute(SdpAttribute::AttributeType type,
uint32_t lineNumber,
SdpErrorHolder& errorHolder);
const SipccSdpAttributeList* mSessionLevel;
SdpAttribute* mAttributes[kNumAttributeTypes];
SipccSdpAttributeList(const SipccSdpAttributeList& orig) MOZ_DELETE;
SipccSdpAttributeList& operator=(const SipccSdpAttributeList& rhs) MOZ_DELETE;
};
} // namespace mozilla
#endif

View File

@ -0,0 +1,332 @@
/* -*- 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/SipccSdpMediaSection.h"
#include <ostream>
#include "signaling/src/sdp/SdpErrorHolder.h"
#ifdef CRLF
#undef CRLF
#endif
#define CRLF "\r\n"
namespace mozilla
{
unsigned int
SipccSdpMediaSection::GetPort() const
{
return mPort;
}
void
SipccSdpMediaSection::SetPort(unsigned int port)
{
mPort = port;
}
unsigned int
SipccSdpMediaSection::GetPortCount() const
{
return mPortCount;
}
SdpMediaSection::Protocol
SipccSdpMediaSection::GetProtocol() const
{
return mProtocol;
}
const SdpConnection&
SipccSdpMediaSection::GetConnection() const
{
return *mConnection;
}
SdpConnection&
SipccSdpMediaSection::GetConnection()
{
return *mConnection;
}
uint32_t
SipccSdpMediaSection::GetBandwidth(const std::string& type) const
{
auto found = mBandwidths.find(type);
if (found == mBandwidths.end()) {
return 0;
}
return found->second;
}
const std::vector<std::string>&
SipccSdpMediaSection::GetFormats() const
{
return mFormats;
}
const SdpAttributeList&
SipccSdpMediaSection::GetAttributeList() const
{
return mAttributeList;
}
SdpAttributeList&
SipccSdpMediaSection::GetAttributeList()
{
return mAttributeList;
}
SdpDirectionAttribute
SipccSdpMediaSection::GetDirectionAttribute() const
{
return SdpDirectionAttribute(mAttributeList.GetDirection());
}
bool
SipccSdpMediaSection::Load(sdp_t* sdp, uint16_t level,
SdpErrorHolder& errorHolder)
{
switch (sdp_get_media_type(sdp, level)) {
case SDP_MEDIA_AUDIO:
mMediaType = kAudio;
break;
case SDP_MEDIA_VIDEO:
mMediaType = kVideo;
break;
case SDP_MEDIA_APPLICATION:
mMediaType = kApplication;
break;
case SDP_MEDIA_TEXT:
mMediaType = kText;
break;
default:
errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
"Unsupported media section type");
return false;
}
mPort = sdp_get_media_portnum(sdp, level);
int32_t pc = sdp_get_media_portcount(sdp, level);
if (pc == SDP_INVALID_VALUE) {
// SDP_INVALID_VALUE (ie; -2) is used when there is no port count. :(
mPortCount = 0;
} else if (pc > static_cast<int32_t>(UINT16_MAX) || pc < 0) {
errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
"Invalid port count");
return false;
} else {
mPortCount = pc;
}
if (!LoadProtocol(sdp, level, errorHolder)) {
return false;
}
LoadFormats(sdp, level);
if (!mAttributeList.Load(sdp, level, errorHolder)) {
return false;
}
if (!mBandwidths.Load(sdp, level, errorHolder)) {
return false;
}
return LoadConnection(sdp, level, errorHolder);
}
bool
SipccSdpMediaSection::LoadProtocol(sdp_t* sdp, uint16_t level,
SdpErrorHolder& errorHolder)
{
switch (sdp_get_media_transport(sdp, level)) {
case SDP_TRANSPORT_RTPAVP:
mProtocol = kRtpAvp;
break;
case SDP_TRANSPORT_RTPSAVP:
mProtocol = kRtpSavp;
break;
case SDP_TRANSPORT_RTPAVPF:
mProtocol = kRtpAvpf;
break;
case SDP_TRANSPORT_RTPSAVPF:
mProtocol = kRtpSavpf;
break;
case SDP_TRANSPORT_UDPTLSRTPSAVP:
mProtocol = kUdpTlsRtpSavp;
break;
case SDP_TRANSPORT_UDPTLSRTPSAVPF:
mProtocol = kUdpTlsRtpSavpf;
break;
case SDP_TRANSPORT_TCPTLSRTPSAVP:
mProtocol = kTcpTlsRtpSavp;
break;
case SDP_TRANSPORT_TCPTLSRTPSAVPF:
mProtocol = kTcpTlsRtpSavpf;
break;
case SDP_TRANSPORT_DTLSSCTP:
mProtocol = kDtlsSctp;
break;
default:
errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
"Unsupported media transport type");
return false;
}
return true;
}
void
SipccSdpMediaSection::LoadFormats(sdp_t* sdp, uint16_t level)
{
sdp_media_e mtype = sdp_get_media_type(sdp, level);
if (mtype == SDP_MEDIA_APPLICATION) {
uint32_t ptype = sdp_get_media_sctp_port(sdp, level);
std::ostringstream osPayloadType;
osPayloadType << ptype;
mFormats.push_back(osPayloadType.str());
} else if (mtype == SDP_MEDIA_AUDIO || mtype == SDP_MEDIA_VIDEO) {
uint16_t count = sdp_get_media_num_payload_types(sdp, level);
for (uint16_t i = 0; i < count; ++i) {
sdp_payload_ind_e indicator; // we ignore this, which is fine
uint32_t ptype =
sdp_get_media_payload_type(sdp, level, i + 1, &indicator);
std::ostringstream osPayloadType;
// sipcc stores payload types in a funny way. When sipcc and the SDP it
// parsed differ on what payload type number should be used for a given
// codec, sipcc's value goes in the lower byte, and the SDP's value in
// the upper byte. When they do not differ, only the lower byte is used.
// We want what was in the SDP, verbatim.
osPayloadType << GET_DYN_PAYLOAD_TYPE_VALUE(ptype);
mFormats.push_back(osPayloadType.str());
}
}
}
bool
SipccSdpMediaSection::LoadConnection(sdp_t* sdp, uint16_t level,
SdpErrorHolder& errorHolder)
{
if (!sdp_connection_valid(sdp, level)) {
level = SDP_SESSION_LEVEL;
if (!sdp_connection_valid(sdp, level)) {
errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
"Missing c= line");
return false;
}
}
sdp_nettype_e type = sdp_get_conn_nettype(sdp, level);
if (type != SDP_NT_INTERNET) {
errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
"Unsupported network type");
return false;
}
sdp::AddrType addrType;
switch (sdp_get_conn_addrtype(sdp, level)) {
case SDP_AT_IP4:
addrType = sdp::kIPv4;
break;
case SDP_AT_IP6:
addrType = sdp::kIPv6;
break;
default:
errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
"Unsupported address type");
return false;
}
std::string address = sdp_get_conn_address(sdp, level);
int16_t ttl = static_cast<uint16_t>(sdp_get_mcast_ttl(sdp, level));
if (ttl < 0) {
ttl = 0;
}
int32_t numAddr =
static_cast<uint32_t>(sdp_get_mcast_num_of_addresses(sdp, level));
if (numAddr < 0) {
numAddr = 0;
}
mConnection = MakeUnique<SdpConnection>(addrType, address, ttl, numAddr);
return true;
}
void
SipccSdpMediaSection::AddCodec(const std::string& pt, const std::string& name,
uint32_t clockrate, uint16_t channels)
{
mFormats.push_back(pt);
SdpRtpmapAttributeList* rtpmap = new SdpRtpmapAttributeList();
if (mAttributeList.HasAttribute(SdpAttribute::kRtpmapAttribute)) {
const SdpRtpmapAttributeList& old = mAttributeList.GetRtpmap();
for (auto it = old.mRtpmaps.begin(); it != old.mRtpmaps.end(); ++it) {
rtpmap->mRtpmaps.push_back(*it);
}
}
SdpRtpmapAttributeList::CodecType codec = SdpRtpmapAttributeList::kOtherCodec;
if (name == "opus") {
codec = SdpRtpmapAttributeList::kOpus;
} else if (name == "G722") {
codec = SdpRtpmapAttributeList::kG722;
} else if (name == "PCMU") {
codec = SdpRtpmapAttributeList::kPCMU;
} else if (name == "PCMA") {
codec = SdpRtpmapAttributeList::kPCMA;
} else if (name == "VP8") {
codec = SdpRtpmapAttributeList::kVP8;
} else if (name == "H264") {
codec = SdpRtpmapAttributeList::kH264;
}
rtpmap->PushEntry(pt, codec, name, clockrate, channels);
mAttributeList.SetAttribute(rtpmap);
}
void
SipccSdpMediaSection::AddDataChannel(const std::string& pt,
const std::string& name, uint16_t streams)
{
// Only one allowed, for now. This may change as the specs (and deployments)
// evolve.
mFormats.clear();
mFormats.push_back(pt);
SdpSctpmapAttributeList* sctpmap = new SdpSctpmapAttributeList();
sctpmap->PushEntry(pt, name, streams);
mAttributeList.SetAttribute(sctpmap);
}
void
SipccSdpMediaSection::Serialize(std::ostream& os) const
{
os << "m=" << mMediaType << " " << mPort;
if (mPortCount) {
os << "/" << mPortCount;
}
os << " " << mProtocol;
for (auto i = mFormats.begin(); i != mFormats.end(); ++i) {
os << " " << (*i);
}
os << CRLF;
// We dont do i=
if (mConnection) {
os << *mConnection;
}
mBandwidths.Serialize(os);
// We dont do k= because they're evil
os << mAttributeList;
}
} // namespace mozilla

View File

@ -0,0 +1,93 @@
/* -*- 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 _SIPCCSDPMEDIASECTION_H_
#define _SIPCCSDPMEDIASECTION_H_
#include "mozilla/Attributes.h"
#include "mozilla/UniquePtr.h"
#include "signaling/src/sdp/SdpMediaSection.h"
#include "signaling/src/sdp/SipccSdpAttributeList.h"
#include <map>
extern "C" {
#include "signaling/src/sdp/sipcc/sdp.h"
}
namespace mozilla
{
class SipccSdp;
class SdpErrorHolder;
class SipccSdpBandwidths MOZ_FINAL : public std::map<std::string, uint32_t>
{
public:
bool Load(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
void Serialize(std::ostream& os) const;
};
class SipccSdpMediaSection MOZ_FINAL : public SdpMediaSection
{
friend class SipccSdp;
public:
~SipccSdpMediaSection() {}
virtual MediaType
GetMediaType() const MOZ_OVERRIDE
{
return mMediaType;
}
virtual unsigned int GetPort() const MOZ_OVERRIDE;
virtual void SetPort(unsigned int port) MOZ_OVERRIDE;
virtual unsigned int GetPortCount() const MOZ_OVERRIDE;
virtual Protocol GetProtocol() const MOZ_OVERRIDE;
virtual const SdpConnection& GetConnection() const MOZ_OVERRIDE;
virtual SdpConnection& GetConnection() MOZ_OVERRIDE;
virtual uint32_t GetBandwidth(const std::string& type) const MOZ_OVERRIDE;
virtual const std::vector<std::string>& GetFormats() const MOZ_OVERRIDE;
virtual const SdpAttributeList& GetAttributeList() const MOZ_OVERRIDE;
virtual SdpAttributeList& GetAttributeList() MOZ_OVERRIDE;
virtual SdpDirectionAttribute GetDirectionAttribute() const MOZ_OVERRIDE;
virtual void AddCodec(const std::string& pt, const std::string& name,
uint32_t clockrate, uint16_t channels) MOZ_OVERRIDE;
virtual void AddDataChannel(const std::string& pt, const std::string& name,
uint16_t streams) MOZ_OVERRIDE;
virtual void Serialize(std::ostream&) const MOZ_OVERRIDE;
private:
SipccSdpMediaSection(size_t level, const SipccSdpAttributeList* sessionLevel)
: SdpMediaSection(level), mAttributeList(sessionLevel)
{
}
bool Load(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
bool LoadConnection(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
bool LoadProtocol(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
void LoadFormats(sdp_t* sdp, uint16_t level);
// the following values are cached on first get
MediaType mMediaType;
uint16_t mPort;
uint16_t mPortCount;
Protocol mProtocol;
std::vector<std::string> mFormats;
UniquePtr<SdpConnection> mConnection;
SipccSdpBandwidths mBandwidths;
SipccSdpAttributeList mAttributeList;
};
}
#endif

View File

@ -0,0 +1,83 @@
/* -*- 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/SipccSdpParser.h"
#include "signaling/src/sdp/SipccSdp.h"
#include <utility>
extern "C" {
#include "signaling/src/sdp/sipcc/sdp.h"
}
namespace mozilla
{
extern "C" {
void
sipcc_sdp_parser_error_handler(void *context, uint32_t line,
const char *message)
{
SdpErrorHolder *errorHolder = static_cast<SdpErrorHolder *>(context);
std::string err(message);
errorHolder->AddParseError(line, err);
}
} // extern "C"
UniquePtr<Sdp>
SipccSdpParser::Parse(const std::string &sdpText)
{
ClearParseErrors();
sdp_conf_options_t *sipcc_config = sdp_init_config();
if (!sipcc_config) {
return UniquePtr<Sdp>();
}
sdp_nettype_supported(sipcc_config, SDP_NT_INTERNET, true);
sdp_addrtype_supported(sipcc_config, SDP_AT_IP4, true);
sdp_addrtype_supported(sipcc_config, SDP_AT_IP6, true);
sdp_transport_supported(sipcc_config, SDP_TRANSPORT_RTPAVP, true);
sdp_transport_supported(sipcc_config, SDP_TRANSPORT_RTPAVPF, true);
sdp_transport_supported(sipcc_config, SDP_TRANSPORT_RTPSAVP, true);
sdp_transport_supported(sipcc_config, SDP_TRANSPORT_RTPSAVPF, true);
sdp_transport_supported(sipcc_config, SDP_TRANSPORT_UDPTLSRTPSAVP, true);
sdp_transport_supported(sipcc_config, SDP_TRANSPORT_UDPTLSRTPSAVPF, true);
sdp_transport_supported(sipcc_config, SDP_TRANSPORT_TCPTLSRTPSAVP, true);
sdp_transport_supported(sipcc_config, SDP_TRANSPORT_TCPTLSRTPSAVPF, true);
sdp_transport_supported(sipcc_config, SDP_TRANSPORT_DTLSSCTP, true);
sdp_require_session_name(sipcc_config, false);
sdp_config_set_error_handler(sipcc_config, &sipcc_sdp_parser_error_handler,
this);
// Takes ownership of |sipcc_config| iff it succeeds
sdp_t *sdp = sdp_init_description(sipcc_config);
if (!sdp) {
sdp_free_config(sipcc_config);
return UniquePtr<Sdp>();
}
const char *rawString = sdpText.c_str();
sdp_result_e sdpres = sdp_parse(sdp, rawString, sdpText.length());
if (sdpres != SDP_SUCCESS) {
sdp_free_description(sdp);
return UniquePtr<Sdp>();
}
UniquePtr<SipccSdp> sipccSdp(new SipccSdp);
bool success = sipccSdp->Load(sdp, *this);
sdp_free_description(sdp);
if (!success) {
return UniquePtr<Sdp>();
}
return UniquePtr<Sdp>(Move(sipccSdp));
}
} // namespace mozilla

View File

@ -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 _SIPCCSDPPARSER_H_
#define _SIPCCSDPPARSER_H_
#include <string>
#include "mozilla/UniquePtr.h"
#include "signaling/src/sdp/Sdp.h"
#include "signaling/src/sdp/SdpErrorHolder.h"
namespace mozilla
{
class SipccSdpParser MOZ_FINAL : public SdpErrorHolder
{
public:
SipccSdpParser() {}
virtual ~SipccSdpParser() {}
/**
* 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

File diff suppressed because it is too large Load Diff