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

📄 sdpcontents.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 3 页
字号:
      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 + -