📄 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::SIPbool SipMessage::checkContentLength=true;SipMessage::SipMessage(const Transport* fromWire) : mIsDecorated(false), mIsBadAck200(false), 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(); mIsDecorated = rhs.mIsDecorated; mIsBadAck200 = rhs.mIsBadAck200; 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();}voidSipMessage::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;}voidSipMessage::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; }}voidSipMessage::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); } strm << header(h_CallID).value();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -