📄 sipmessage.cxx
字号:
#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 + -