📄 sdpcontents.cxx
字号:
#if defined(HAVE_CONFIG_H)#include "resip/stack/config.hxx"#endif#include "resip/stack/SdpContents.hxx"#include "resip/stack/Helper.hxx"#include "rutil/ParseBuffer.hxx"#include "rutil/DataStream.hxx"#include "resip/stack/Symbols.hxx"#include "rutil/Logger.hxx"#include "rutil/WinLeakCheck.hxx"#define RESIPROCATE_SUBSYSTEM resip::Subsystem::SDPusing namespace resip;using namespace std;const SdpContents SdpContents::Empty;boolSdpContents::init(){ static ContentsFactory<SdpContents> factory; (void)factory; return true;}const char* NetworkType[] = {"???", "IP4", "IP6"};static const Data rtpmap("rtpmap");static const Data fmtp("fmtp");// RFC2327 6. page 9// "parsers should be tolerant and accept records terminated with a single// newline character"void skipEol(ParseBuffer& pb){ while(!pb.eof() && (*pb.position() == Symbols::SPACE[0] || *pb.position() == Symbols::TAB[0])) { pb.skipChar(); } if (*pb.position() == Symbols::LF[0]) { pb.skipChar(); } else { // allow extra 0x0d bytes. while(*pb.position() == Symbols::CR[0]) { pb.skipChar(); } pb.skipChar(Symbols::LF[0]); } }AttributeHelper::AttributeHelper(const AttributeHelper& rhs) : mAttributeList(rhs.mAttributeList), mAttributes(rhs.mAttributes){}AttributeHelper::AttributeHelper(){}AttributeHelper&AttributeHelper::operator=(const AttributeHelper& rhs){ if (this != &rhs) { mAttributeList = rhs.mAttributeList; mAttributes = rhs.mAttributes; } return *this;}boolAttributeHelper::exists(const Data& key) const{ return mAttributes.find(key) != mAttributes.end();}const list<Data>&AttributeHelper::getValues(const Data& key) const{ if (!exists(key)) { static const list<Data> emptyList; return emptyList; } return mAttributes.find(key)->second;}ostream&AttributeHelper::encode(ostream& s) const{ for (std::list<std::pair<Data, Data> >::const_iterator i = mAttributeList.begin(); i != mAttributeList.end(); ++i) { s << "a=" << i->first; if (!i->second.empty()) { s << Symbols::COLON[0] << i->second; } s << Symbols::CRLF; } return s;}voidAttributeHelper::parse(ParseBuffer& pb){ while (!pb.eof() && *pb.position() == 'a') { Data key; Data value; pb.skipChar('a'); const char* anchor = pb.skipChar(Symbols::EQUALS[0]); pb.skipToOneOf(Symbols::COLON, Symbols::CRLF); pb.data(key, anchor); if (!pb.eof() && *pb.position() == Symbols::COLON[0]) { anchor = pb.skipChar(Symbols::COLON[0]); pb.skipToOneOf(Symbols::CRLF); pb.data(value, anchor); } if(!pb.eof()) skipEol(pb); mAttributeList.push_back(std::make_pair(key, value)); mAttributes[key].push_back(value); }}voidAttributeHelper::addAttribute(const Data& key, const Data& value){ mAttributeList.push_back(std::make_pair(key, value)); mAttributes[key].push_back(value);}voidAttributeHelper::clearAttribute(const Data& key){ for (std::list<std::pair<Data, Data> >::iterator i = mAttributeList.begin(); i != mAttributeList.end(); ) { std::list<std::pair<Data, Data> >::iterator j = i++; if (j->first == key) { mAttributeList.erase(j); } } mAttributes.erase(key);}SdpContents::SdpContents() : Contents(getStaticType()){}SdpContents::SdpContents(HeaderFieldValue* hfv, const Mime& contentTypes) : Contents(hfv, contentTypes){}//SdpContents::SdpContents(const SdpContents& rhs)// : Contents(rhs),// mSession(rhs.mSession)//{//}SdpContents::~SdpContents(){}SdpContents&SdpContents::operator=(const SdpContents& rhs){ if (this != &rhs) { Contents::operator=(rhs); mSession = rhs.mSession; } return *this;}Contents*SdpContents::clone() const{ return new SdpContents(*this);}Data SdpContents::getBodyData() const{ checkParsed(); Data d; { DataStream s(d); mSession.encode(s); } return d;}voidSdpContents::parse(ParseBuffer& pb){ mSession.parse(pb);}ostream&SdpContents::encodeParsed(ostream& s) const{ mSession.encode(s); return s;}const Mime&SdpContents::getStaticType(){ static Mime type("application", "sdp"); return type;}static Data nullOrigin("0.0.0.0");SdpContents::Session::Origin::Origin() : mUser(Data::Empty), mSessionId(0), mVersion(0), mAddrType(IP4), mAddress(nullOrigin){}SdpContents::Session::Origin::Origin(const Origin& rhs) : mUser(rhs.mUser), mSessionId(rhs.mSessionId), mVersion(rhs.mVersion), mAddrType(rhs.mAddrType), mAddress(rhs.mAddress){}SdpContents::Session::Origin&SdpContents::Session::Origin::operator=(const Origin& rhs){ if (this != &rhs) { mUser = rhs.mUser; mSessionId = rhs.mSessionId; mVersion = rhs.mVersion; mAddrType = rhs.mAddrType; mAddress = rhs.mAddress; } return *this;}SdpContents::Session::Origin::Origin(const Data& user, const UInt64& sessionId, const UInt64& version, AddrType addr, const Data& address) : mUser(user), mSessionId(sessionId), mVersion(version), mAddrType(addr), mAddress(address){}ostream&SdpContents::Session::Origin::encode(ostream& s) const{ s << "o=" << mUser << Symbols::SPACE[0] << mSessionId << Symbols::SPACE[0] << mVersion << Symbols::SPACE[0] << "IN " << NetworkType[mAddrType] << Symbols::SPACE[0] << mAddress << Symbols::CRLF; return s;}voidSdpContents::Session::Origin::setAddress(const Data& host, AddrType addr){ mAddress = host; mAddrType = addr;}voidSdpContents::Session::Origin::parse(ParseBuffer& pb){ pb.skipChar('o'); const char* anchor = pb.skipChar(Symbols::EQUALS[0]); pb.skipToChar(Symbols::SPACE[0]); pb.data(mUser, anchor); anchor = pb.skipChar(Symbols::SPACE[0]); mSessionId = pb.uInt64(); anchor = pb.skipChar(Symbols::SPACE[0]); mVersion = pb.uInt64(); pb.skipChar(Symbols::SPACE[0]); pb.skipChar('I'); pb.skipChar('N'); anchor = pb.skipChar(Symbols::SPACE[0]); pb.skipToChar(Symbols::SPACE[0]); Data addrType; pb.data(addrType, anchor); if (addrType == NetworkType[IP4]) { mAddrType = IP4; } else if (addrType == NetworkType[IP6]) { mAddrType = IP6; } else { mAddrType = static_cast<AddrType>(0); } anchor = pb.skipChar(Symbols::SPACE[0]); pb.skipToOneOf(Symbols::CRLF); pb.data(mAddress, anchor); skipEol(pb);}SdpContents::Session::Email::Email(const Data& address, const Data& freeText) : mAddress(address), mFreeText(freeText){}SdpContents::Session::Email::Email(const Email& rhs) : mAddress(rhs.mAddress), mFreeText(rhs.mFreeText){}SdpContents::Session::Email&SdpContents::Session::Email::operator=(const Email& rhs){ if (this != &rhs) { mAddress = rhs.mAddress; mFreeText = rhs.mFreeText; } return *this;}ostream&SdpContents::Session::Email::encode(ostream& s) const{ s << "e=" << mAddress; if (!mFreeText.empty()) { s << Symbols::SPACE[0]; s << Symbols::LPAREN[0] << mFreeText << Symbols::RPAREN[0]; } s << Symbols::CRLF; return s;}// helper to parse email and phone numbers with display namevoid parseEorP(ParseBuffer& pb, Data& eOrp, Data& freeText){ // =mjh@isi.edu (Mark Handley) // =mjh@isi.edu // =Mark Handley <mjh@isi.edu> // =<mjh@isi.edu> const char* anchor = pb.skipChar(Symbols::EQUALS[0]); pb.skipToOneOf("<(\n\r"); // find a left angle bracket "<", a left paren "(", or a CR switch (*pb.position()) { case '\n': // Symbols::CR[0] case '\r': // Symbols::LF[0] // mjh@isi.edu // ^ pb.data(eOrp, anchor); break; case '<': // Symbols::LA_QUOTE[0] // Mark Handley <mjh@isi.edu> // ^ // <mjh@isi.edu> // ^ pb.data(freeText, anchor); anchor = pb.skipChar(); pb.skipToEndQuote(Symbols::RA_QUOTE[0]); pb.data(eOrp, anchor); pb.skipChar(Symbols::RA_QUOTE[0]); break; case '(': // Symbols::LPAREN[0] // mjh@isi.edu (Mark Handley) // ^ pb.data(eOrp, anchor); anchor = pb.skipChar(); pb.skipToEndQuote(Symbols::RPAREN[0]); pb.data(freeText, anchor); pb.skipChar(Symbols::RPAREN[0]); break; default: assert(0); }}voidSdpContents::Session::Email::parse(ParseBuffer& pb){ pb.skipChar('e'); parseEorP(pb, mAddress, mFreeText); skipEol(pb);}SdpContents::Session::Phone::Phone(const Data& number, const Data& freeText) : mNumber(number), mFreeText(freeText){}SdpContents::Session::Phone::Phone(const Phone& rhs) : mNumber(rhs.mNumber), mFreeText(rhs.mFreeText){}SdpContents::Session::Phone&SdpContents::Session::Phone::operator=(const Phone& rhs){ if (this != &rhs) { mNumber = rhs.mNumber; mFreeText = rhs.mFreeText; } return *this;}ostream&SdpContents::Session::Phone::encode(ostream& s) const{ s << "p=" << mNumber; if (!mFreeText.empty()) { s << Symbols::SPACE[0]; s << Symbols::LPAREN[0] << mFreeText << Symbols::RPAREN[0]; } s << Symbols::CRLF; return s;}voidSdpContents::Session::Phone::parse(ParseBuffer& pb){ pb.skipChar('p'); parseEorP(pb, mNumber, mFreeText); skipEol(pb);}SdpContents::Session::Connection::Connection(AddrType addType, const Data& address, unsigned long ttl) : mAddrType(addType), mAddress(address), mTTL(ttl){}SdpContents::Session::Connection::Connection() : mAddrType(IP4), mAddress(Data::Empty), mTTL(0){}SdpContents::Session::Connection::Connection(const Connection& rhs) : mAddrType(rhs.mAddrType), mAddress(rhs.mAddress), mTTL(rhs.mTTL){}SdpContents::Session::Connection&SdpContents::Session::Connection::operator=(const Connection& rhs){ if (this != &rhs) { mAddrType = rhs.mAddrType; mAddress = rhs.mAddress; mTTL = rhs.mTTL; } return *this;}ostream&SdpContents::Session::Connection::encode(ostream& s) const{ s << "c=IN " << NetworkType[mAddrType] << Symbols::SPACE[0] << mAddress; if (mTTL) { s << Symbols::SLASH[0] << mTTL; } s << Symbols::CRLF; return s;}voidSdpContents::Session::Connection::setAddress(const Data& host, AddrType addr){ mAddress = host; mAddrType = addr;}voidSdpContents::Session::Connection::parse(ParseBuffer& pb){ pb.skipChar('c'); pb.skipChar(Symbols::EQUALS[0]); pb.skipChar('I'); pb.skipChar('N'); const char* anchor = pb.skipChar(Symbols::SPACE[0]); pb.skipToChar(Symbols::SPACE[0]); Data addrType; pb.data(addrType, anchor); if (addrType == NetworkType[IP4]) { mAddrType = IP4; } else if (addrType == NetworkType[IP6]) { mAddrType = IP6; } else { mAddrType = static_cast<AddrType>(0); } anchor = pb.skipChar(); pb.skipToOneOf(Symbols::SLASH, Symbols::CRLF); pb.data(mAddress, anchor); mTTL = 0; if (mAddrType == IP4 && !pb.eof() && *pb.position() == Symbols::SLASH[0]) { pb.skipChar(); mTTL = pb.integer(); } // multicast dealt with above this parser if (!pb.eof() && *pb.position() != Symbols::SLASH[0]) { skipEol(pb); }}SdpContents::Session::Bandwidth::Bandwidth(const Data& modifier, unsigned long kbPerSecond) : mModifier(modifier), mKbPerSecond(kbPerSecond){}SdpContents::Session::Bandwidth::Bandwidth(const Bandwidth& rhs) : mModifier(rhs.mModifier), mKbPerSecond(rhs.mKbPerSecond){}SdpContents::Session::Bandwidth&SdpContents::Session::Bandwidth::operator=(const Bandwidth& rhs){ if (this != &rhs) { mModifier = rhs.mModifier; mKbPerSecond = rhs.mKbPerSecond; } return *this;}ostream&SdpContents::Session::Bandwidth::encode(ostream& s) const{ s << "b=" << mModifier << Symbols::COLON[0] << mKbPerSecond << Symbols::CRLF; return s;}voidSdpContents::Session::Bandwidth::parse(ParseBuffer& pb){ pb.skipChar('b'); const char* anchor = pb.skipChar(Symbols::EQUALS[0]); pb.skipToOneOf(Symbols::COLON, Symbols::CRLF); if (*pb.position() == Symbols::COLON[0]) { pb.data(mModifier, anchor); anchor = pb.skipChar(Symbols::COLON[0]); mKbPerSecond = pb.integer(); skipEol(pb); } else { pb.fail(__FILE__, __LINE__); }}SdpContents::Session::Time::Time(unsigned long start, unsigned long stop) : mStart(start), mStop(stop){}SdpContents::Session::Time::Time(const Time& rhs) : mStart(rhs.mStart), mStop(rhs.mStop){}SdpContents::Session::Time&SdpContents::Session::Time::operator=(const Time& rhs){ if (this != &rhs) { mStart = rhs.mStart; mStop = rhs.mStop; mRepeats = rhs.mRepeats;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -