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

📄 sipmessage.cxx

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

#include "resip/stack/Contents.hxx"
#include "resip/stack/Embedded.hxx"
#include "resip/stack/OctetContents.hxx"
#include "resip/stack/HeaderFieldValueList.hxx"
#include "resip/stack/SipMessage.hxx"
#include "resip/stack/ExtensionHeader.hxx"
#include "rutil/Coders.hxx"
#include "rutil/CountStream.hxx"
#include "rutil/Logger.hxx"
#include "rutil/MD5Stream.hxx"
#include "rutil/compat.hxx"
#include "rutil/vmd5.hxx"
#include "rutil/Coders.hxx"
#include "rutil/Random.hxx"
#include "rutil/ParseBuffer.hxx"
#include "resip/stack/MsgHeaderScanner.hxx"
#include "rutil/WinLeakCheck.hxx"

using namespace resip;
using namespace std;

#define RESIPROCATE_SUBSYSTEM Subsystem::SIP

bool SipMessage::checkContentLength=true;

SipMessage::SipMessage(const Transport* fromWire)
   : mIsExternal(fromWire != 0),
     mTransport(fromWire),
     mStartLine(0),
     mContentsHfv(0),
     mContents(0),
     mRFC2543TransactionId(),
     mRequest(false),
     mResponse(false),
     mInvalid(false),
     mCreatedTime(Timer::getTimeMicroSec()),
     mForceTarget(0),
     mTlsDomain(Data::Empty)
{
   for (int i = 0; i < Headers::MAX_HEADERS; i++)
   {
      mHeaders[i] = 0;
   }
}

SipMessage::SipMessage(const SipMessage& from)
   : mStartLine(0),
     mContentsHfv(0),
     mContents(0),
     mCreatedTime(Timer::getTimeMicroSec()),
     mForceTarget(0)
{
   for (int i = 0; i < Headers::MAX_HEADERS; i++)
   {
      mHeaders[i] = 0;
   }

   *this = from;
}

Message*
SipMessage::clone() const
{
   return new SipMessage(*this);
}

SipMessage& 
SipMessage::operator=(const SipMessage& rhs)
{
   if (this != &rhs)
   {
      this->cleanUp();

      mIsExternal = rhs.mIsExternal;
      mTransport = rhs.mTransport;
      mSource = rhs.mSource;
      mDestination = rhs.mDestination;
      mStartLine = 0;
      mContentsHfv = 0;
      mContents = 0;
      mRFC2543TransactionId = rhs.mRFC2543TransactionId;
      mRequest = rhs.mRequest;
      mResponse = rhs.mResponse;
      mInvalid = rhs.mInvalid;
      mReason = rhs.mReason;
      mForceTarget = 0;
      mTlsDomain = rhs.mTlsDomain;
      
      for (int i = 0; i < Headers::MAX_HEADERS; i++)
      {
         if (rhs.mHeaders[i] != 0)
         {
            mHeaders[i] = new HeaderFieldValueList(*rhs.mHeaders[i]);
         }
         else
         {
            mHeaders[i] = 0;
         }
      }
  
      for (UnknownHeaders::const_iterator i = rhs.mUnknownHeaders.begin();
           i != rhs.mUnknownHeaders.end(); i++)
      {
         mUnknownHeaders.push_back(pair<Data, HeaderFieldValueList*>(
                                      i->first,
                                      new HeaderFieldValueList(*i->second)));
      }
      if (rhs.mStartLine != 0)
      {
         mStartLine = new HeaderFieldValueList(*rhs.mStartLine); 
      }
      if (rhs.mContents != 0)
      {
         mContents = rhs.mContents->clone();
      }
      else if (rhs.mContentsHfv != 0)
      {
         mContentsHfv = new HeaderFieldValue(*rhs.mContentsHfv, HeaderFieldValue::CopyPadding);
      }
      else
      {
         // no body to copy
      }
      if (rhs.mForceTarget != 0)
      {
         mForceTarget = new Uri(*rhs.mForceTarget);
      }

      if (rhs.mSecurityAttributes.get())
      {

         if (!mSecurityAttributes.get())
         {
            SecurityAttributes* attr = new SecurityAttributes();
            mSecurityAttributes.reset(attr);
         }

         if (rhs.mSecurityAttributes->isEncrypted())
         {
            mSecurityAttributes->setEncrypted();
         }
         mSecurityAttributes->setSignatureStatus(rhs.mSecurityAttributes->getSignatureStatus());
         mSecurityAttributes->setIdentity(rhs.mSecurityAttributes->getIdentity());
         mSecurityAttributes->setIdentityStrength(rhs.mSecurityAttributes->getIdentityStrength());
         mSecurityAttributes->setSigner(rhs.mSecurityAttributes->getSigner());
         mSecurityAttributes->setOutgoingEncryptionLevel(rhs.mSecurityAttributes->getOutgoingEncryptionLevel());
         mSecurityAttributes->setEncryptionPerformed(rhs.mSecurityAttributes->encryptionPerformed());
      }
      else
      {
         if (mSecurityAttributes.get())
         {
            mSecurityAttributes.reset();
         }
      }
      mOutboundDecorators = rhs.mOutboundDecorators;
   }

   return *this;
}

SipMessage::~SipMessage()
{
   cleanUp();
}

void
SipMessage::cleanUp()
{
   for (int i = 0; i < Headers::MAX_HEADERS; i++)
   {
      delete mHeaders[i];
      mHeaders[i] = 0;
   }

   for (UnknownHeaders::iterator i = mUnknownHeaders.begin();
        i != mUnknownHeaders.end(); i++)
   {
      delete i->second;
   }
   mUnknownHeaders.clear();
   
   for (vector<char*>::iterator i = mBufferList.begin();
        i != mBufferList.end(); i++)
   {
      delete [] *i;
   }
   mBufferList.clear();

   delete mStartLine;
   mStartLine = 0;
   delete mContents;
   mContents = 0;
   delete mContentsHfv;
   mContentsHfv = 0;
   delete mForceTarget;
   mForceTarget = 0;
}

SipMessage*
SipMessage::make(const Data& data,  bool isExternal)
{
   Transport* external = (Transport*)(0xFFFF);
   SipMessage* msg = new SipMessage(isExternal ? external : 0);

   size_t len = data.size();
   char *buffer = new char[len + 5];

   msg->addBuffer(buffer);
   memcpy(buffer,data.data(), len);
   MsgHeaderScanner msgHeaderScanner;
   msgHeaderScanner.prepareForMessage(msg);
   
   char *unprocessedCharPtr;
   if (msgHeaderScanner.scanChunk(buffer, len, &unprocessedCharPtr) != MsgHeaderScanner::scrEnd)
   {
      DebugLog(<<"Scanner rejecting buffer as unparsable / fragmented.");
      DebugLog(<< data);
      delete msg; 
      msg = 0; 
      return 0;
   }

   // no pp error
   unsigned int used = unprocessedCharPtr - buffer;

   if (used < len)
   {
      // body is present .. add it up.
      // NB. The Sip Message uses an overlay (again)
      // for the body. It ALSO expects that the body
      // will be contiguous (of course).
      // it doesn't need a new buffer in UDP b/c there
      // will only be one datagram per buffer. (1:1 strict)

      msg->setBody(buffer+used,len-used);
      //DebugLog(<<"added " << len-used << " byte body");
   }

   return msg;
}

void
SipMessage::parseAllHeaders()
{
   for (int i = 0; i < Headers::MAX_HEADERS; i++)
   {
      ParserContainerBase* pc=0;
      if(mHeaders[i])
      {
         ensureHeaders((Headers::Type)i,!Headers::isMulti((Headers::Type)i));
         if(!(pc=mHeaders[i]->getParserContainer()))
         {
            pc = HeaderBase::getInstance((Headers::Type)i)->makeContainer(mHeaders[i]);
            mHeaders[i]->setParserContainer(pc);
         }
      
         pc->parseAll();
      }
   }

   for (UnknownHeaders::iterator i = mUnknownHeaders.begin();
        i != mUnknownHeaders.end(); i++)
   {
      ParserContainerBase* scs=0;
      if(!(scs=i->second->getParserContainer()))
      {
         scs=new ParserContainer<StringCategory>(i->second,Headers::RESIP_DO_NOT_USE);
         i->second->setParserContainer(scs);
      }
      
      scs->parseAll();
   }
   
   assert(mStartLine);
   ParserContainerBase* slc = 0;

   if(!(slc=mStartLine->getParserContainer()))
   {
      if(mRequest)
      {
         slc=new ParserContainer<RequestLine>(mStartLine,Headers::NONE);
      }
      else if(mResponse)
      {
         slc=new ParserContainer<StatusLine>(mStartLine,Headers::NONE);
      }
      else
      {
         assert(0);
      }
      mStartLine->setParserContainer(slc);
   }

   slc->parseAll();
   
   getContents();
}

const Data& 
SipMessage::getTransactionId() const
{
   if (!this->exists(h_Vias) || this->header(h_Vias).empty())
   {
      InfoLog (<< "Bad message with no Vias: " << *this);
      throw Exception("No Via in message", __FILE__,__LINE__);
   }
   
   assert(exists(h_Vias) && !header(h_Vias).empty());
   if( exists(h_Vias) && header(h_Vias).front().exists(p_branch) 
       && header(h_Vias).front().param(p_branch).hasMagicCookie() 
       && (!header(h_Vias).front().param(p_branch).getTransactionId().empty())
     )
   {
      return header(h_Vias).front().param(p_branch).getTransactionId();
   }
   else
   {
      if (mRFC2543TransactionId.empty())
      {
         compute2543TransactionHash();
      }
      return mRFC2543TransactionId;
   }
}

void
SipMessage::compute2543TransactionHash() const
{
   assert (mRFC2543TransactionId.empty());
   
   /*  From rfc3261, 17.2.3
       The INVITE request matches a transaction if the Request-URI, To tag,
       From tag, Call-ID, CSeq, and top Via header field match those of the
       INVITE request which created the transaction.  In this case, the
       INVITE is a retransmission of the original one that created the
       transaction.  

       The ACK request matches a transaction if the Request-URI, From tag,
       Call-ID, CSeq number (not the method), and top Via header field match
       those of the INVITE request which created the transaction, and the To
       tag of the ACK matches the To tag of the response sent by the server
       transaction.  

       Matching is done based on the matching rules defined for each of those
       header fields.  Inclusion of the tag in the To header field in the ACK
       matching process helps disambiguate ACK for 2xx from ACK for other
       responses at a proxy, which may have forwarded both responses (This
       can occur in unusual conditions.  Specifically, when a proxy forked a
       request, and then crashes, the responses may be delivered to another
       proxy, which might end up forwarding multiple responses upstream).  An
       ACK request that matches an INVITE transaction matched by a previous
       ACK is considered a retransmission of that previous ACK.

       For all other request methods, a request is matched to a transaction
       if the Request-URI, To tag, From tag, Call-ID, CSeq (including the
       method), and top Via header field match those of the request that
       created the transaction.  Matching is done based on the matching
   */

   // If it is here and isn't a request, leave the transactionId empty, this
   // will cause the Transaction to send it statelessly

   if (isRequest())
   {
      MD5Stream strm;
      // See section 17.2.3 Matching Requests to Server Transactions in rfc 3261

//#define VONAGE_FIX
#ifndef VONAGE_FIX         
      strm << header(h_RequestLine).uri().scheme();
      strm << header(h_RequestLine).uri().user();
      strm << header(h_RequestLine).uri().host();
      strm << header(h_RequestLine).uri().port();
      strm << header(h_RequestLine).uri().password();
      strm << header(h_RequestLine).uri().commutativeParameterHash();
#endif
      if (exists(h_Vias) && !header(h_Vias).empty())
      {
         strm << header(h_Vias).front().protocolName();
         strm << header(h_Vias).front().protocolVersion();
         strm << header(h_Vias).front().transport();
         strm << header(h_Vias).front().sentHost();
         strm << header(h_Vias).front().sentPort();
         strm << header(h_Vias).front().commutativeParameterHash();
      }
         
      if (header(h_From).exists(p_tag))
      {
         strm << header(h_From).param(p_tag);
      }

      // Only include the totag for non-invite requests
      if (header(h_RequestLine).getMethod() != INVITE && 
          header(h_RequestLine).getMethod() != ACK && 
          header(h_RequestLine).getMethod() != CANCEL &&
          header(h_To).exists(p_tag))
      {
         strm << header(h_To).param(p_tag);
      }

⌨️ 快捷键说明

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