📄 sdpcontents.cxx
字号:
mProtocol = rhs.mProtocol;
mFormats = rhs.mFormats;
mCodecs = rhs.mCodecs;
mTransport = rhs.mTransport;
mInformation = rhs.mInformation;
mConnections = rhs.mConnections;
mBandwidths = rhs.mBandwidths;
mEncryption = rhs.mEncryption;
mAttributeHelper = rhs.mAttributeHelper;
mRtpMapDone = rhs.mRtpMapDone;
mRtpMap = rhs.mRtpMap;
}
return *this;
}
void
SdpContents::Session::Medium::setPort(int port)
{
mPort = port;
}
void
SdpContents::Session::Medium::setSession(Session* session)
{
mSession = session;
}
void
SdpContents::Session::Medium::parse(ParseBuffer& pb)
{
pb.skipChar('m');
const char* anchor = pb.skipChar(Symbols::EQUALS[0]);
pb.skipToChar(Symbols::SPACE[0]);
pb.data(mName, anchor);
pb.skipChar(Symbols::SPACE[0]);
mPort = pb.integer();
if (*pb.position() == Symbols::SLASH[0])
{
pb.skipChar();
mMulticast = pb.integer();
}
anchor = pb.skipChar(Symbols::SPACE[0]);
pb.skipToOneOf(Symbols::SPACE, Symbols::CRLF);
pb.data(mProtocol, anchor);
while (*pb.position() != Symbols::CR[0] &&
*pb.position() != Symbols::LF[0])
{
anchor = pb.skipChar(Symbols::SPACE[0]);
pb.skipToOneOf(Symbols::SPACE, Symbols::CRLF);
Data format;
pb.data(format, anchor);
addFormat(format);
}
skipEol(pb);
if (!pb.eof() && *pb.position() == 'i')
{
pb.skipChar('i');
anchor = pb.skipChar(Symbols::EQUALS[0]);
pb.skipToOneOf(Symbols::CRLF);
pb.data(mInformation, anchor);
skipEol(pb);
}
while (!pb.eof() && *pb.position() == 'c')
{
addConnection(Connection());
mConnections.back().parse(pb);
if (!pb.eof() && *pb.position() == Symbols::SLASH[0])
{
pb.skipChar();
int num = pb.integer();
Connection& con = mConnections.back();
const Data& addr = con.getAddress();
int i = addr.size() - 1;
for (; i; i--)
{
if (addr[i] == '.')
{
break;
}
}
if (addr[i] == '.')
{
Data before(addr.data(), i);
ParseBuffer subpb(addr.data()+i+1, addr.size()-i-1);
int after = subpb.integer();
for (int i = 0; i < num-1; i++)
{
addConnection(con);
mConnections.back().mAddress = before + Data(after+i);
}
}
skipEol(pb);
}
}
while (!pb.eof() && *pb.position() == 'b')
{
addBandwidth(Bandwidth());
mBandwidths.back().parse(pb);
}
if (!pb.eof() && *pb.position() == 'k')
{
mEncryption.parse(pb);
}
mAttributeHelper.parse(pb);
}
ostream&
SdpContents::Session::Medium::encode(ostream& s) const
{
s << "m="
<< mName << Symbols::SPACE[0]
<< mPort;
if (mMulticast > 1)
{
s << Symbols::SLASH[0] << mMulticast;
}
s << Symbols::SPACE[0]
<< mProtocol;
for (list<Data>::const_iterator i = mFormats.begin();
i != mFormats.end(); ++i)
{
s << Symbols::SPACE[0] << *i;
}
if (!mCodecs.empty())
{
for (list<Codec>::const_iterator i = mCodecs.begin();
i != mCodecs.end(); ++i)
{
s << Symbols::SPACE[0] << i->payloadType();
}
}
s << Symbols::CRLF;
if (!mInformation.empty())
{
s << "i=" << mInformation << Symbols::CRLF;
}
for (list<Connection>::const_iterator i = mConnections.begin();
i != mConnections.end(); ++i)
{
i->encode(s);
}
for (list<Bandwidth>::const_iterator i = mBandwidths.begin();
i != mBandwidths.end(); ++i)
{
i->encode(s);
}
if (mEncryption.getMethod() != Encryption::NoEncryption)
{
mEncryption.encode(s);
}
if (!mCodecs.empty())
{
// add codecs to information and attributes
for (list<Codec>::const_iterator i = mCodecs.begin();
i != mCodecs.end(); ++i)
{
// If codec is static (defined in RFC 3551) we probably shouldn't
// add attributes for it. But some UAs do include them.
//Codec::CodecMap& staticCodecs = Codec::getStaticCodecs();
//if (staticCodecs.find(i->payloadType()) != staticCodecs.end())
//{
// continue;
//}
s << "a=rtpmap:"
<< i->payloadType() << Symbols::SPACE[0] << *i
<< Symbols::CRLF;
if (!i->parameters().empty())
{
s << "a=fmtp:"
<< i->payloadType() << Symbols::SPACE[0] << i->parameters()
<< Symbols::CRLF;
}
}
}
mAttributeHelper.encode(s);
return s;
}
void
SdpContents::Session::Medium::addFormat(const Data& format)
{
mFormats.push_back(format);
}
void
SdpContents::Session::Medium::setConnection(const Connection& connection)
{
mConnections.clear();
addConnection(connection);
}
void
SdpContents::Session::Medium::addConnection(const Connection& connection)
{
mConnections.push_back(connection);
}
void
SdpContents::Session::Medium::setBandwidth(const Bandwidth& bandwidth)
{
mBandwidths.clear();
addBandwidth(bandwidth);
}
void
SdpContents::Session::Medium::addBandwidth(const Bandwidth& bandwidth)
{
mBandwidths.push_back(bandwidth);
}
void
SdpContents::Session::Medium::addAttribute(const Data& key, const Data& value)
{
mAttributeHelper.addAttribute(key, value);
if (key == rtpmap)
{
mRtpMapDone = false;
}
}
const list<SdpContents::Session::Connection>
SdpContents::Session::Medium::getConnections() const
{
list<Connection> connections = const_cast<Medium*>(this)->getMediumConnections();
if (mSession)
{
connections.push_back(mSession->connection());
}
return connections;
}
bool
SdpContents::Session::Medium::exists(const Data& key) const
{
if (mAttributeHelper.exists(key))
{
return true;
}
return mSession && mSession->exists(key);
}
const list<Data>&
SdpContents::Session::Medium::getValues(const Data& key) const
{
if (exists(key))
{
return mAttributeHelper.getValues(key);
}
if (!mSession)
{
assert(false);
static list<Data> error;
return error;
}
return mSession->getValues(key);
}
void
SdpContents::Session::Medium::clearAttribute(const Data& key)
{
mAttributeHelper.clearAttribute(key);
if (key == rtpmap)
{
mRtpMapDone = false;
}
}
void
SdpContents::Session::Medium::clearCodecs()
{
mFormats.clear();
clearAttribute(rtpmap);
clearAttribute(fmtp);
mCodecs.clear();
}
void
SdpContents::Session::Medium::addCodec(const Codec& codec)
{
codecs();
mCodecs.push_back(codec);
}
const list<Codec>&
SdpContents::Session::Medium::codecs() const
{
return const_cast<Medium*>(this)->codecs();
}
list<Codec>&
SdpContents::Session::Medium::codecs()
{
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER < 1310) // CJ TODO fix
assert(0);
#else
if (!mRtpMapDone)
{
// prevent recursion
mRtpMapDone = true;
if (exists(rtpmap))
{
for (list<Data>::const_iterator i = getValues(rtpmap).begin();
i != getValues(rtpmap).end(); ++i)
{
//DebugLog(<< "SdpContents::Session::Medium::getCodec(" << *i << ")");
ParseBuffer pb(i->data(), i->size());
int format = pb.integer();
// pass to codec constructor for parsing
// pass this for other codec attributes
try
{
mRtpMap[format].parse(pb, *this, format);
}
catch (ParseBuffer::Exception&)
{
mRtpMap.erase(format);
}
}
}
for (list<Data>::const_iterator i = mFormats.begin();
i != mFormats.end(); ++i)
{
int mapKey = i->convertInt();
RtpMap::const_iterator ri = mRtpMap.find(mapKey);
if (ri != mRtpMap.end())
{
//DebugLog(<< "SdpContents::Session::Medium::getCodec[](" << ri->second << ")");
mCodecs.push_back(ri->second);
}
else
{
// !kk! Is it a static format?
Codec::CodecMap& staticCodecs = Codec::getStaticCodecs();
Codec::CodecMap::const_iterator ri = staticCodecs.find(mapKey);
if (ri != staticCodecs.end())
{
//DebugLog(<< "Found static codec for format: " << mapKey);
mCodecs.push_back(ri->second);
}
}
}
// don't store twice
mFormats.clear();
mAttributeHelper.clearAttribute(rtpmap);
mAttributeHelper.clearAttribute(fmtp); // parsed out in codec.parse
}
#endif
return mCodecs;
}
const Codec&
SdpContents::Session::Medium::findFirstMatchingCodecs(const std::list<Codec>& codecs, Codec* pMatchingCodec) const
{
static Codec emptyCodec;
std::list<resip::SdpContents::Session::Codec>::const_iterator sIter;
std::list<resip::SdpContents::Session::Codec>::const_iterator sEnd = mCodecs.end();
std::list<resip::SdpContents::Session::Codec>::const_iterator eIter;
std::list<resip::SdpContents::Session::Codec>::const_iterator eEnd = codecs.end();
bool found = false;
for (eIter = codecs.begin(); eIter != eEnd ; ++eIter)
{
for (sIter = mCodecs.begin(); sIter != sEnd; ++sIter)
{
if (*sIter == *eIter)
{
found = true;
if (pMatchingCodec) *pMatchingCodec = *eIter;
return *sIter;
}
}
}
return emptyCodec;
}
int
SdpContents::Session::Medium::findTelephoneEventPayloadType() const
{
const std::list<Codec>& codecList = codecs();
for (std::list<Codec>::const_iterator i = codecList.begin(); i != codecList.end(); i++)
{
if (i->getName() == SdpContents::Session::Codec::TelephoneEvent.getName())
{
return i->payloadType();
}
}
return -1;
}
Codec::Codec(const Data& name,
unsigned long rate,
const Data& parameters)
: mName(name),
mRate(rate),
mPayloadType(-1),
mParameters(parameters)
{
}
Codec::Codec(const Codec& rhs)
: mName(rhs.mName),
mRate(rhs.mRate),
mPayloadType(rhs.mPayloadType),
mParameters(rhs.mParameters)
{
}
Codec::Codec(const Data& name, int payloadType, int rate)
: mName(name),
mRate(rate),
mPayloadType(payloadType),
mParameters()
{
}
Codec&
Codec::operator=(const Codec& rhs)
{
if (this != &rhs)
{
mName = rhs.mName;
mRate = rhs.mRate;
mPayloadType = rhs.mPayloadType;
mParameters = rhs.mParameters;
}
return *this;
}
void
Codec::parse(ParseBuffer& pb,
const SdpContents::Session::Medium& medium,
int payloadType)
{
const char* anchor = pb.skipWhitespace();
pb.skipToChar(Symbols::SLASH[0]);
pb.data(mName, anchor);
pb.skipChar(Symbols::SLASH[0]);
mRate = pb.integer();
mPayloadType = payloadType;
// get parameters if they exist
if (medium.exists(fmtp))
{
for (list<Data>::const_iterator i = medium.getValues(fmtp).begin();
i != medium.getValues(fmtp).end(); ++i)
{
ParseBuffer pb(i->data(), i->size());
int payload = pb.integer();
if (payload == payloadType)
{
const char* anchor = pb.skipWhitespace();
pb.skipToEnd();
pb.data(mParameters, anchor);
break;
}
}
}
}
const Data&
Codec::getName() const
{
return mName;
};
int
Codec::getRate() const
{
return mRate;
};
Codec::CodecMap& Codec::getStaticCodecs()
{
if (! sStaticCodecsCreated)
{
//
// Build map of static codecs as defined in RFC 3551
//
sStaticCodecs = std::auto_ptr<CodecMap>(new CodecMap);
// Audio codecs
sStaticCodecs->insert(make_pair(0,Codec("PCMU",0,8000)));
sStaticCodecs->insert(make_pair(3,Codec("GSM",3,8000)));
sStaticCodecs->insert(make_pair(4,Codec("G723",4,8000)));
sStaticCodecs->insert(make_pair(5,Codec("DVI4",5,8000)));
sStaticCodecs->insert(make_pair(6,Codec("DVI4",6,16000)));
sStaticCodecs->insert(make_pair(7,Codec("LPC",7,8000)));
sStaticCodecs->insert(make_pair(8,Codec("PCMA",8,8000)));
sStaticCodecs->insert(make_pair(9,Codec("G722",9,8000)));
sStaticCodecs->insert(make_pair(10,Codec("L16-2",10,44100)));
sStaticCodecs->insert(make_pair(11,Codec("L16-1",11,44100)));
sStaticCodecs->insert(make_pair(12,Codec("QCELP",12,8000)));
sStaticCodecs->insert(make_pair(13,Codec("CN",13,8000)));
sStaticCodecs->insert(make_pair(14,Codec("MPA",14,90000)));
sStaticCodecs->insert(make_pair(15,Codec("G728",15,8000)));
sStaticCodecs->insert(make_pair(16,Codec("DVI4",16,11025)));
sStaticCodecs->insert(make_pair(17,Codec("DVI4",17,22050)));
sStaticCodecs->insert(make_pair(18,Codec("G729",18,8000)));
// Video or audio/video codecs
sStaticCodecs->insert(make_pair(25,Codec("CelB",25,90000)));
sStaticCodecs->insert(make_pair(26,Codec("JPEG",26,90000)));
sStaticCodecs->insert(make_pair(28,Codec("nv",28,90000)));
sStaticCodecs->insert(make_pair(31,Codec("H261",31,90000)));
sStaticCodecs->insert(make_pair(32,Codec("MPV",32,90000)));
sStaticCodecs->insert(make_pair(33,Codec("MP2T",33,90000)));
sStaticCodecs->insert(make_pair(34,Codec("H263",34,90000)));
sStaticCodecsCreated = true;
}
return *(sStaticCodecs.get());
}
bool
resip::operator==(const Codec& lhs, const Codec& rhs)
{
return (isEqualNoCase(lhs.mName, rhs.mName) && lhs.mRate == rhs.mRate);
}
ostream&
resip::operator<<(ostream& str, const Codec& codec)
{
str << codec.mName;
str << Symbols::SLASH[0];
str << codec.mRate;
return str;
}
const Codec Codec::ULaw_8000("PCMU", 0, 8000);
const Codec Codec::ALaw_8000("PCMA", 8, 8000);
const Codec Codec::G729_8000("G729", 18, 8000);
const Codec Codec::G723_8000("G723", 4, 8000);
const Codec Codec::GSM_8000("GSM", 3, 8000);
const Codec Codec::TelephoneEvent("telephone-event", 101, 8000);
const Codec Codec::FrfDialedDigit("frf-dialed-event",102, 8000);
bool Codec::sStaticCodecsCreated = false;
std::auto_ptr<Codec::CodecMap> Codec::sStaticCodecs;
/* ====================================================================
* The Vovida Software License, Version 1.0
*
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this vector of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this vector of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
* and "Vovida Open Communication Application Library (VOCAL)" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact vocal@vovida.org.
*
* 4. Products derived from this software may not be called "VOCAL", nor
* may "VOCAL" appear in their name, without prior written
* permission of Vovida Networks, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by Vovida
* Networks, Inc. and many individuals on behalf of Vovida Networks,
* Inc. For more information on Vovida Networks, Inc., please see
* <http://www.vovida.org/>.
*
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -