📄 sdpcontents.cxx
字号:
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]) { // Note: we only get here if there was a /<number of addresses> // parameter following the connection address. 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] == '.' || addr[i] == ':') // ipv4 or ipv6 { break; } } if (addr[i] == '.') // add a number of ipv4 connections { Data before(addr.data(), i+1); ParseBuffer subpb(addr.data()+i+1, addr.size()-i-1); int after = subpb.integer(); for (int i = 1; i < num; i++) { addConnection(con); mConnections.back().mAddress = before + Data(after+i); } } if (addr[i] == ':') // add a number of ipv6 connections { Data before(addr.data(), i+1); int after = Helper::hex2integer(addr.data()+i+1); char hexstring[9]; for (int i = 1; i < num; i++) { addConnection(con); memset(hexstring, 0, sizeof(hexstring)); Helper::integer2hex(hexstring, after+i, false /* supress leading zeros */); mConnections.back().mAddress = before + Data(hexstring); } } 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;}voidSdpContents::Session::Medium::addFormat(const Data& format){ mFormats.push_back(format);}voidSdpContents::Session::Medium::setConnection(const Connection& connection){ mConnections.clear(); addConnection(connection);}voidSdpContents::Session::Medium::addConnection(const Connection& connection){ mConnections.push_back(connection);}voidSdpContents::Session::Medium::setBandwidth(const Bandwidth& bandwidth){ mBandwidths.clear(); addBandwidth(bandwidth);}voidSdpContents::Session::Medium::addBandwidth(const Bandwidth& bandwidth){ mBandwidths.push_back(bandwidth);}voidSdpContents::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 there are connections specified at the medium level, then check if a session level // connection is present - if so then return it if (connections.empty() && mSession && !mSession->connection().getAddress().empty()) { connections.push_back(mSession->connection()); } return connections;}boolSdpContents::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 (mAttributeHelper.exists(key)) { return mAttributeHelper.getValues(key); } if (!mSession) { assert(false); static list<Data> error; return error; } return mSession->getValues(key);}voidSdpContents::Session::Medium::clearAttribute(const Data& key){ mAttributeHelper.clearAttribute(key); if (key == rtpmap) { mRtpMapDone = false; }}voidSdpContents::Session::Medium::clearCodecs(){ mFormats.clear(); clearAttribute(rtpmap); clearAttribute(fmtp); mCodecs.clear();}voidSdpContents::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 (ParseException& e) { ErrLog(<<"Caught exception: "<< e); 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>& codecList, Codec* pMatchingCodec) const{ const std::list<Codec>& internalCodecList = codecs(); static Codec emptyCodec; std::list<resip::SdpContents::Session::Codec>::const_iterator sIter; std::list<resip::SdpContents::Session::Codec>::const_iterator sEnd = internalCodecList.end(); std::list<resip::SdpContents::Session::Codec>::const_iterator eIter; std::list<resip::SdpContents::Session::Codec>::const_iterator eEnd = codecList.end(); bool found = false; for (eIter = codecList.begin(); eIter != eEnd ; ++eIter) { for (sIter = internalCodecList.begin(); sIter != sEnd; ++sIter) { if (*sIter == *eIter) { found = true; if (pMatchingCodec) { *pMatchingCodec = *eIter; } return *sIter; } } } return emptyCodec;}const Codec& SdpContents::Session::Medium::findFirstMatchingCodecs(const Medium& medium, Codec* pMatchingCodec) const{ if (&medium == this) { return codecs().front(); } else { return findFirstMatchingCodecs(medium.codecs(), pMatchingCodec); }}intSdpContents::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, const Data& encodingParameters) : mName(name), mRate(rate), mPayloadType(-1), mParameters(parameters), mEncodingParameters(encodingParameters){}Codec::Codec(const Codec& rhs) : mName(rhs.mName), mRate(rhs.mRate), mPayloadType(rhs.mPayloadType), mParameters(rhs.mParameters), mEncodingParameters(rhs.mEncodingParameters){}Codec::Codec(const Data& name, int payloadType, int rate) : mName(name), mRate(rate), mPayloadType(payloadType){}Codec&Codec::operator=(const Codec& rhs){ if (this != &rhs) { mName = rhs.mName; mRate = rhs.mRate; mPayloadType = rhs.mPayloadType; mParameters = rhs.mParameters; mEncodingParameters = rhs.mEncodingParameters; } return *this;}voidCodec::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(); pb.skipToChar(Symbols::SLASH[0]); if(!pb.eof() && *pb.position() == Symbols::SLASH[0]) { anchor = pb.skipChar(Symbols::SLASH[0]); pb.skipToEnd(); pb.data(mEncodingParameters, anchor); } 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;}intCodec::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());}boolresip::operator==(const Codec& lhs, const Codec& rhs){ static Data defaultEncodingParameters(Data("1")); // Default for audio streams (1-Channel) return (isEqualNoCase(lhs.mName, rhs.mName) && lhs.mRate == rhs.mRate && (lhs.mEncodingParameters == rhs.mEncodingParameters || (lhs.mEncodingParameters.empty() && rhs.mEncodingParameters == defaultEncodingParameters) || (lhs.mEncodingParameters == defaultEncodingParameters && rhs.mEncodingParameters.empty())));}ostream&resip::operator<<(ostream& str, const Codec& codec){ str << codec.mName; str << Symbols::SLASH[0]; str << codec.mRate; if(!codec.mEncodingParameters.empty()) { str << Symbols::SLASH[0]; str << codec.mEncodingParameters; } 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);const Codec Codec::CN("CN", 13, 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 + -