⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdpcontents.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 3 页
字号:
#if defined(HAVE_CONFIG_H)
#include "resip/stack/config.hxx"
#endif

#include "resip/stack/SdpContents.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::SDP

using namespace resip;
using namespace std;

const SdpContents SdpContents::Empty;

bool
SdpContents::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)
   : mAttributes(rhs.mAttributes)
{
}

AttributeHelper::AttributeHelper()
{
}

AttributeHelper&
AttributeHelper::operator=(const AttributeHelper& rhs)
{
   if (this != &rhs)
   {
      mAttributes = rhs.mAttributes;
   }
   return *this;
}

bool
AttributeHelper::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 (HashMap< Data, list<Data> >::const_iterator i = mAttributes.begin();
        i != mAttributes.end(); ++i)
   {
      for (list<Data>::const_iterator j = i->second.begin();
           j != i->second.end(); ++j)
      {
         s << "a="
           << i->first;
         if (!j->empty())
         {
            s << Symbols::COLON[0] << *j;
         }
         s << Symbols::CRLF;
      }
   }
   return s;
}

void
AttributeHelper::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);

      mAttributes[key].push_back(value);
   }
}

void
AttributeHelper::addAttribute(const Data& key, const Data& value)
{
   mAttributes[key].push_back(value);
}

void
AttributeHelper::clearAttribute(const Data& key)
{
   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;
}

void
SdpContents::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;
}

void
SdpContents::Session::Origin::setAddress(const Data& host, AddrType addr)
{
    mAddress = host;
    mAddrType = addr;
}

void
SdpContents::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 name
void 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);
   }
}

void
SdpContents::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;
}

void
SdpContents::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;
}

void
SdpContents::Session::Connection::setAddress(const Data& host, AddrType addr)
{
    mAddress = host;
    mAddrType = addr;
}

void
SdpContents::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 (!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;
}

void
SdpContents::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)
{}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -