1#if defined(HAVE_CONFIG_H)
26#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
38 elem.getValues()->clear();
43 for (UsedBitMaskWord& word : mUsedBitMask)
53template<
typename Disposer>
76 it->getValues()->clear();
79 mUsedBitMask[
static_cast<unsigned int>(type) / UsedBitMaskWordBits] &=
80 ~(
static_cast<UsedBitMaskWord
>(1u) << (
static_cast<unsigned int>(type) % UsedBitMaskWordBits));
86template<
typename ValuesFactory>
92 if (pos >= mHeaders.size())
94 pos = mHeaders.size();
95 mHeaders.emplace_back(type);
98 mHeaders[pos].setValues(valuesFactory());
105 mHeaderIndices[type] =
static_cast<HeaderIndex
>(pos);
111 mHeaders[pos].setType(type);
115 mUsedBitMask[
static_cast<unsigned int>(type) / UsedBitMaskWordBits] |=
116 static_cast<UsedBitMaskWord
>(1u) << (
static_cast<unsigned int>(type) % UsedBitMaskWordBits);
118 return iterator(mHeaders.begin() + pos, mHeaders.end());
123SipMessage::KnownHeaders::resetIndices() noexcept
125 for (HeaderIndex& index : mHeaderIndices)
127 index = InvalidHeaderIndex;
130 for (UsedBitMaskWord& word : mUsedBitMask)
141 if (mHeaderIndices[type] < mHeaders.size())
143 TypedHeaders::iterator it = mHeaders.begin() + mHeaderIndices[type];
145 return iterator(it, mHeaders.end());
157 mIsExternal(receivedTransportTuple != 0),
167 mCreatedTime(
Timer::getTimeMicroSec()),
168 mTlsDomain(
Data::Empty)
170 if(receivedTransportTuple)
172 mReceivedTransportTuple = *receivedTransportTuple;
186 mCreatedTime(
Timer::getTimeMicroSec())
211#ifdef DINKYPOOL_PROFILING
214 InfoLog(<<
"SipMessage mPool filled up and used " << mPool.
getHeapBytes() <<
" bytes on the heap, consider increasing the mPool size (sizeof SipMessage is " <<
sizeof(
SipMessage) <<
" bytes): msg="
215 << std::endl << *
this);
220 << std::endl << *
this);
229 if(!leaveResponseStuff)
236 mUnknownHeaders.clear();
238 mStartLine =
nullptr;
240 mContentsHfv.
clear();
241 mForceTarget =
nullptr;
243 mOutboundDecorators.clear();
253 mIsExternal = rhs.mIsExternal;
254 mReceivedTransportTuple = rhs.mReceivedTransportTuple;
255 mSource = rhs.mSource;
256 mDestination = rhs.mDestination;
257 mRFC2543TransactionId = rhs.mRFC2543TransactionId;
258 mRequest = rhs.mRequest;
259 mResponse = rhs.mResponse;
260 mInvalid = rhs.mInvalid;
267 mReason =
new Data(*rhs.mReason);
269 mTlsDomain = rhs.mTlsDomain;
270 mConnectionInfo = rhs.mConnectionInfo;
277 mKnownHeaders.
insert(info.getType(), [&] {
return getCopyHfvl(*info.getValues()); });
280 for (UnknownHeaders::const_iterator i = rhs.mUnknownHeaders.begin();
281 i != rhs.mUnknownHeaders.end(); ++i)
283 mUnknownHeaders.push_back(pair<Data, HeaderFieldValueList*>(
285 getCopyHfvl(*i->second)));
287 if (rhs.mStartLine !=
nullptr)
289 mStartLine = rhs.mStartLine->
clone(mStartLineMem);
291 if (rhs.mContents !=
nullptr)
293 mContents = rhs.mContents->
clone();
295 else if (rhs.mContentsHfv.
getBuffer() !=
nullptr)
303 if (rhs.mForceTarget !=
nullptr)
305 mForceTarget =
new Uri(*rhs.mForceTarget);
308 if (rhs.mSecurityAttributes.get())
310 if (!mSecurityAttributes.get())
313 mSecurityAttributes.reset(attr);
318 if (mSecurityAttributes.get())
320 mSecurityAttributes.reset();
324 for(std::vector<MessageDecorator*>::const_iterator i=rhs.mOutboundDecorators.begin(); i!=rhs.mOutboundDecorators.end();++i)
326 mOutboundDecorators.push_back((*i)->clone());
333 for (UnknownHeaders::iterator i = mUnknownHeaders.begin();
334 i != mUnknownHeaders.end(); ++i)
339 if (!leaveResponseStuff)
343 for (
char* buffer : mBufferList)
352 mStartLine =
nullptr;
378 size_t len = data.
size();
379 char *buffer =
new char[len + 5];
382 memcpy(buffer,data.
data(), len);
386 char *unprocessedCharPtr;
389 DebugLog(<<
"Scanner rejecting buffer as unparsable / fragmented.");
397 unsigned int used = (
unsigned int)(unprocessedCharPtr - buffer);
437 for (UnknownHeaders::iterator i = mUnknownHeaders.begin();
438 i != mUnknownHeaders.end(); ++i)
443 scs=makeParserContainer<StringCategory>(i->second,Headers::RESIP_DO_NOT_USE);
444 i->second->setParserContainer(scs);
462 InfoLog (<<
"Bad message with no Vias: " << *
this);
463 throw Exception(
"No Via in message", __FILE__,__LINE__);
468 &&
header(h_Vias).front().param(p_branch).hasMagicCookie()
472 return header(h_Vias).front().param(p_branch).getTransactionId();
476 if (mRFC2543TransactionId.
empty())
478 compute2543TransactionHash();
480 return mRFC2543TransactionId;
485SipMessage::compute2543TransactionHash()
const
537 strm <<
header(h_Vias).front().protocolName();
538 strm <<
header(h_Vias).front().protocolVersion();
539 strm <<
header(h_Vias).front().transport();
540 strm <<
header(h_Vias).front().sentHost();
541 strm <<
header(h_Vias).front().sentPort();
542 strm <<
header(h_Vias).front().commutativeParameterHash();
547 strm <<
header(h_From).param(p_tag);
556 strm <<
header(h_To).param(p_tag);
559 strm <<
header(h_CallID).value();
565 strm <<
header(h_CSeq).sequence();
570 strm <<
header(h_CSeq).sequence();
573 mRFC2543TransactionId = strm.
getHex();
577 InfoLog (<<
"Trying to compute a transaction id on a 2543 response. Drop the response");
579 throw Exception(
"Drop invalid 2543 response", __FILE__, __LINE__);
588 !
header(h_Vias).front().param(p_branch).hasMagicCookie() ||
591 if (mRFC2543TransactionId.
empty())
593 compute2543TransactionHash();
596 return mRFC2543TransactionId;
618 header(h_CSeq).sequence();
625 WarningLog( <<
"Computing Identity on message with no Date header" );
628 header(h_Date).dayOfMonth();
632 if ( !
empty(h_Contacts) )
634 if (
header(h_Contacts).front().isAllContacts() )
640 strm <<
header(h_Contacts).front().
uri();
646 if (mContents !=
nullptr)
650 else if (mContentsHfv.
getBuffer() !=
nullptr)
652 mContentsHfv.
encode(strm);
657 DebugLog( <<
"Identity Canonical String is: " << result );
666 mRFC2543TransactionId = tid;
781 if (!
empty(h_Contacts))
789 str <<
" MALFORMED CONTACT ";
793 str <<
header(h_CSeq).sequence();
795 if (!mTlsDomain.
empty())
797 str <<
tlsdEB << mTlsDomain;
807 return ((mIsExternal && mResponse) || (!mIsExternal && mRequest));
813 return encode(str,
false);
827 if (mStartLine !=
nullptr)
834 if (mContents !=
nullptr)
839 else if (mContentsHfv.
getBuffer() !=
nullptr)
853 if (info.getType() != Headers::ContentLength)
855 info.getValues()->encode(info.getType(), str);
859 for (UnknownHeaders::const_iterator i = mUnknownHeaders.begin();
860 i != mUnknownHeaders.end(); ++i)
862 i->second->encode(i->first, str);
865 if(!isSipFrag || !contents.
empty())
867 str <<
"Content-Length: " << contents.
size() <<
"\r\n";
879 auto it = mKnownHeaders.
find(type);
880 if (it != mKnownHeaders.
end())
882 it->getValues()->encode(type, str);
893 if (info.getType() != Headers::ContentLength)
908 for (UnknownHeaders::const_iterator i = mUnknownHeaders.begin();
909 i != mUnknownHeaders.end(); ++i)
920 i->second->encodeEmbedded(i->first, str);
923 if (mContents !=
nullptr || mContentsHfv.
getBuffer() !=
nullptr)
937 if (mContents !=
nullptr)
960 mBufferList.push_back(buf);
966 if (len >= 4 && !strncasecmp(st,
"SIP/",4))
969 mStartLine =
new (mStartLineMem)
StatusLine(st, len);
976 mStartLine =
new (mStartLineMem)
RequestLine(st, len);
1013 if(
exists(h_ContentLength))
1032 mReason->
append(
"Malformed Content-Length",24);
1033 InfoLog(<<
"Malformed Content-Length. Ignoring. " << e);
1034 header(h_ContentLength).value()=len;
1039 if(len > contentLength)
1041 InfoLog(<< (len-contentLength) <<
" extra bytes after body. Ignoring these bytes.");
1043 else if(len < contentLength)
1045 InfoLog(<<
"Content Length (" << contentLength <<
") is "
1046 << (contentLength-len) <<
" bytes larger than body (" << len <<
")!"
1047 <<
" (We are supposed to 400 this) ");
1060 mReason->
append(
"Bad Content-Length (larger than datagram)",41);
1061 header(h_ContentLength).value()=len;
1066 mContentsHfv.
init(start,contentLength,
false);
1070 InfoLog(<<
"Message has a body, but no Content-Length header.");
1071 mContentsHfv.
init(start,len,
false);
1076 mContentsHfv.
init(start,len,
false);
1084 mContentsHfv = body;
1091 Contents* contentsP = contents.release();
1094 mContents =
nullptr;
1095 mContentsHfv.
clear();
1097 if (contentsP ==
nullptr)
1101 remove(h_ContentDisposition);
1102 remove(h_ContentTransferEncoding);
1103 remove(h_ContentLanguages);
1107 mContents = contentsP;
1110 if (mContents->
exists(h_ContentDisposition))
1112 header(h_ContentDisposition) = mContents->
header(h_ContentDisposition);
1114 if (mContents->
exists(h_ContentTransferEncoding))
1116 header(h_ContentTransferEncoding) = mContents->
header(h_ContentTransferEncoding);
1118 if (mContents->
exists(h_ContentLanguages))
1120 header(h_ContentLanguages) = mContents->
header(h_ContentLanguages);
1122 if (mContents->
exists(h_ContentType))
1124 header(h_ContentType) = mContents->
header(h_ContentType);
1150 if (mContents ==
nullptr && mContentsHfv.
getBuffer() !=
nullptr)
1152 if (
empty(h_ContentType) ||
1155 StackLog(<<
"SipMessage::getContents: ContentType header does not exist - implies no contents");
1158 DebugLog(<<
"SipMessage::getContents: "
1165 InfoLog(<<
"SipMessage::getContents: got content type ("
1169 <<
") that is not known, "
1170 <<
"returning as opaque application/octet-stream");
1180 if (!
empty(h_ContentDisposition))
1184 if (!
empty(h_ContentTransferEncoding))
1186 mContents->
header(h_ContentTransferEncoding) =
const_header(h_ContentTransferEncoding);
1188 if (!
empty(h_ContentLanguages))
1192 if (!
empty(h_ContentType))
1206 unique_ptr<Contents> ret(c ? c->
clone() :
nullptr);
1209 if (ret !=
nullptr && !ret->isWellFormed())
1222 for (UnknownHeaders::const_iterator i = mUnknownHeaders.begin();
1223 i != mUnknownHeaders.end(); ++i)
1240 throw Exception(
"Missing extension header", __FILE__, __LINE__);
1249 for (UnknownHeaders::iterator i = mUnknownHeaders.begin();
1250 i != mUnknownHeaders.end(); ++i)
1257 hfvs->
setParserContainer(makeParserContainer<StringCategory>(hfvs, Headers::RESIP_DO_NOT_USE));
1265 hfvs->
setParserContainer(makeParserContainer<StringCategory>(hfvs, Headers::RESIP_DO_NOT_USE));
1266 mUnknownHeaders.push_back(make_pair(headerName.
getName(), hfvs));
1273 for (UnknownHeaders::const_iterator i = mUnknownHeaders.begin();
1274 i != mUnknownHeaders.end(); ++i)
1287 for (UnknownHeaders::iterator i = mUnknownHeaders.begin();
1288 i != mUnknownHeaders.end(); ++i)
1292 freeHfvl(i->second);
1293 mUnknownHeaders.erase(i);
1301 const char* value,
uint32_t valueLen)
1312 hfvl->
push_back(value, valueLen,
false);
1317#ifdef PEDANTIC_STACK
1318 if (hfvl->
size() == 1)
1330 mReason->
append(
"Multiple values in single-value header ", 39);
1337 hfvl->
push_back(value, valueLen,
false);
1343 for (UnknownHeaders::iterator i = mUnknownHeaders.begin();
1344 i != mUnknownHeaders.end(); ++i)
1346 if (i->first.size() == headerNameLen &&
1347 strncasecmp(i->first.data(), headerName, headerNameLen) == 0)
1352 i->second->push_back(value, valueLen,
false);
1362 hfvs->
push_back(value, valueLen,
false);
1364 mUnknownHeaders.push_back(pair<Data, HeaderFieldValueList*>(
Data(headerName, headerNameLen),
1373 if (mStartLine ==
nullptr)
1385 if (mStartLine ==
nullptr)
1397 if (mStartLine ==
nullptr)
1402 return *
static_cast<StatusLine*
>(mStartLine);
1409 if (mStartLine ==
nullptr)
1414 return *
static_cast<StatusLine*
>(mStartLine);
1420 return mKnownHeaders.
insert(type, [
this] {
return getEmptyHfvl(); })->getValues();
1426 auto it = mKnownHeaders.
find(type);
1427 if (it == mKnownHeaders.
end())
1429 throwHeaderMissing(type);
1431 return it->getValues();
1475 return it == mKnownHeaders.
end() || it->getValues()->parsedEmpty();
1481 auto it = mKnownHeaders.
find(type);
1482 if (it != mKnownHeaders.
end())
1483 mKnownHeaders.
erase(it);
1486#ifndef PARTIAL_TEMPLATE_SPECIALIZATION
1489#define defineHeader(_header, _name, _type, _rfc) \
1490const H_##_header::Type& \
1491SipMessage::header(const H_##_header& headerType) const \
1493 HeaderFieldValueList* hfvs = ensureHeader(headerType.getTypeNum()); \
1494 if (hfvs->getParserContainer() == nullptr) \
1496 SipMessage* nc_this(const_cast<SipMessage*>(this)); \
1497 hfvs->setParserContainer(nc_this->makeParserContainer<H_##_header::Type>(hfvs, headerType.getTypeNum())); \
1499 return static_cast<ParserContainer<H_##_header::Type>*>(hfvs->getParserContainer())->front(); \
1503SipMessage::header(const H_##_header& headerType) \
1505 HeaderFieldValueList* hfvs = ensureHeader(headerType.getTypeNum()); \
1506 if (hfvs->getParserContainer() == nullptr) \
1508 hfvs->setParserContainer(makeParserContainer<H_##_header::Type>(hfvs, headerType.getTypeNum())); \
1510 return static_cast<ParserContainer<H_##_header::Type>*>(hfvs->getParserContainer())->front(); \
1513#undef defineMultiHeader
1514#define defineMultiHeader(_header, _name, _type, _rfc) \
1515const H_##_header##s::Type& \
1516SipMessage::header(const H_##_header##s& headerType) const \
1518 HeaderFieldValueList* hfvs = ensureHeaders(headerType.getTypeNum()); \
1519 if (hfvs->getParserContainer() == nullptr) \
1521 SipMessage* nc_this(const_cast<SipMessage*>(this)); \
1522 hfvs->setParserContainer(nc_this->makeParserContainer<H_##_header##s::ContainedType>(hfvs, headerType.getTypeNum())); \
1524 return *static_cast<H_##_header##s::Type*>(hfvs->getParserContainer()); \
1527H_##_header##s::Type& \
1528SipMessage::header(const H_##_header##s& headerType) \
1530 HeaderFieldValueList* hfvs = ensureHeaders(headerType.getTypeNum()); \
1531 if (hfvs->getParserContainer() == nullptr) \
1533 hfvs->setParserContainer(makeParserContainer<H_##_header##s::ContainedType>(hfvs, headerType.getTypeNum())); \
1535 return *static_cast<H_##_header##s::Type*>(hfvs->getParserContainer()); \
1653 auto it = mKnownHeaders.
find(headerType);
1654 if (it != mKnownHeaders.
end())
1656 return it->getValues();
1665 auto it = mKnownHeaders.
find(headerType);
1666 if (it != mKnownHeaders.
end())
1668 *it->getValues() = *hfvs;
1672 bool constructed =
false;
1673 it = mKnownHeaders.
insert(headerType, [&]
1676 return getCopyHfvl(*hfvs);
1681 *it->getValues() = *hfvs;
1687 it->getValues()->
push_back(
nullptr, 0,
false);
1696 *mForceTarget = uri;
1700 mForceTarget =
new Uri(uri);
1707 delete mForceTarget;
1708 mForceTarget =
nullptr;
1715 return *mForceTarget;
1721 return (mForceTarget !=
nullptr);
1730 if (source.
exists(p_method))
1748 h_AuthenticationInfo.merge(*
this, source.
embedded());
1749 h_ContentTransferEncoding.merge(*
this, source.
embedded());
1750 h_Event.merge(*
this, source.
embedded());
1751 h_Expires.merge(*
this, source.
embedded());
1752 h_SessionExpires.merge(*
this, source.
embedded());
1753 h_MinSE.merge(*
this, source.
embedded());
1754 h_InReplyTo.merge(*
this, source.
embedded());
1755 h_MaxForwards.merge(*
this, source.
embedded());
1756 h_MinExpires.merge(*
this, source.
embedded());
1757 h_Priority.merge(*
this, source.
embedded());
1758 h_ReferTo.merge(*
this, source.
embedded());
1759 h_ReferredBy.merge(*
this, source.
embedded());
1760 h_Replaces.merge(*
this, source.
embedded());
1761 h_ReplyTo.merge(*
this, source.
embedded());
1762 h_RetryAfter.merge(*
this, source.
embedded());
1763 h_Server.merge(*
this, source.
embedded());
1764 h_SIPETag.merge(*
this, source.
embedded());
1765 h_SIPIfMatch.merge(*
this, source.
embedded());
1766 h_Subject.merge(*
this, source.
embedded());
1767 h_SubscriptionState.merge(*
this, source.
embedded());
1768 h_To.merge(*
this, source.
embedded());
1769 h_Warnings.merge(*
this, source.
embedded());
1771 h_SecurityClients.merge(*
this, source.
embedded());
1772 h_SecurityServers.merge(*
this, source.
embedded());
1773 h_SecurityVerifys.merge(*
this, source.
embedded());
1775 h_Authorizations.merge(*
this, source.
embedded());
1776 h_ProxyAuthenticates.merge(*
this, source.
embedded());
1777 h_WWWAuthenticates.merge(*
this, source.
embedded());
1778 h_ProxyAuthorizations.merge(*
this, source.
embedded());
1780 h_AlertInfos.merge(*
this, source.
embedded());
1782 h_CallInfos.merge(*
this, source.
embedded());
1783 h_ErrorInfos.merge(*
this, source.
embedded());
1784 h_ProxyRequires.merge(*
this, source.
embedded());
1785 h_Requires.merge(*
this, source.
embedded());
1786 h_Unsupporteds.merge(*
this, source.
embedded());
1787 h_AnswerMode.merge(*
this, source.
embedded());
1788 h_PrivAnswerMode.merge(*
this, source.
embedded());
1790 h_RSeq.merge(*
this, source.
embedded());
1791 h_RAck.merge(*
this, source.
embedded());
1800 mSecurityAttributes = std::move(sec);
1803const std::list<Data>&
1806 static const std::list<Data>
empty;
1807 return mConnectionInfo ? mConnectionInfo->mTlsPeerNames :
empty;
1813 return mConnectionInfo ? mConnectionInfo->mTlsSni :
Data::Empty;
1820 return mConnectionInfo ? mConnectionInfo->mWsCookies :
empty;
1823std::shared_ptr<WsCookieContext>
1826 return mConnectionInfo ? mConnectionInfo->mWsCookieContext :
nullptr;
1831static std::shared_ptr<ConnectionInfo>
1834 return current ? std::make_shared<ConnectionInfo>(*current) : std::make_shared<ConnectionInfo>();
1841 info->mTlsPeerNames = tlsPeerNames;
1842 mConnectionInfo = std::move(info);
1849 info->mWsCookies = wsCookies;
1850 mConnectionInfo = std::move(info);
1857 info->mWsCookieContext = std::move(wsCookieContext);
1858 mConnectionInfo = std::move(info);
1864 const Data& sigcompId)
1870 decorator->decorateMessage(*
this, src, dest, sigcompId);
1880 while (!mOutboundDecorators.empty())
1882 delete mOutboundDecorators.back();
1883 mOutboundDecorators.pop_back();
1892 for (std::vector<MessageDecorator*>::reverse_iterator r = mOutboundDecorators.rbegin();
1893 r != mOutboundDecorators.rend(); ++r)
1895 (*r)->rollbackMessage(*
this);
1906 if (decorator->copyToStackCancels())
1918 if (decorator->copyToStackFailureAcks())
#define WarningLog(args_)
#define resip_assert(x)
This file needs to work for both C and C++ code.
static const Data ftuEB(" from(tu)")
static const Data tlsdEB(" tlsd=")
static const Data contactEB(" contact=")
static const Data requestEB("SipReq: ")
static const Data tidEB(" tid=")
static std::shared_ptr< ConnectionInfo > copyConnectionInfo(const std::shared_ptr< const ConnectionInfo > ¤t)
static const Data responseEB("SipResp: ")
static const Data wireEB(" from(wire)")
static const Data cseqEB(" cseq=")
static const Data slashEB(" / ")
Represents the "credentials" and "challenge" elements in the SIP grammar.
The abstract base-class for all exceptions thrown by resip code.
Represents a CSeq header field value (this doesn't have an official name in the RFC 3261 grammar).
Represents the "callid" element in the SIP grammar.
static HashMap< Mime, ContentsFactoryBase * > & getFactoryMap()
Base class for all SIP body types.
bool exists(const HeaderBase &headerType) const
checks to see if a header is present
const H_ContentType::Type & header(const H_ContentType &headerType) const
returns the value of the Content-Type header Throws an Contents::Exception if the header doesn't exis...
const Mime & getType() const
getter for mime type of message
virtual Contents * clone() const =0
returns a copy of a Contents object
An iostream that operates on an existing Data.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
static const Data Empty
Constant that represents a zero-length data.
Data & append(const char *str, size_type len)
Appends the specified number of bytes to the end of this Data.
bool empty() const noexcept
Checks whether the Data is empty.
size_type size() const noexcept
Returns the number of bytes in this Data.
const char * data() const noexcept
Returns a pointer to the contents of this Data.
Represents the "SIP-date" element in the RFC 3261 grammar.
Used to accumlate data written to the stream in a DigestBuffer and convert the data to Digest.
Data getHex()
Calls flush() on itself and returns the Digest data in hex format.
size_t getPoolSizeBytes() const
size_t getPoolBytes() const
size_t getHeapBytes() const
static Data encode(const Data &input)
Represents the header field value for an Expires-type header.
Represents the "absoluteURI" element in the RFC 3261 grammar.
Represents an Identity header from RFC8824.
EncodeStream & encode(EncodeStream &str) const
Encodes this element to a stream, in the fashion it should be represented on the wire.
The base-class used for message-passing.
Represents the "media-type" element in the RFC 3261 grammar.
const Data & subType() const
const Data & type() const
Represents the "name-addr" and the "addr-spec" elements in the RFC 3261 grammar.
static const Mime & getStaticType()
BaseException used to indicate parse failures.
Data commutativeParameterHash() const
Abstract Base class implemented in derived class ParserContainer.
virtual void parseAll()=0
pure virtual function to be implemented in derived classes The intention is to provide an ability to ...
Container class for ParserCategory, used by SipMessage to represent multi-valued headers (Contact,...
Represents the "token" element in the RFC 3261 grammar.
Represents the RAck header field value defined in the RFC 3262 grammar.
Represents the "Request-Line" element in the RFC 3261 grammar.
Data & unknownMethodName()
MethodTypes getMethod() const
virtual EncodeStream & encodeParsed(EncodeStream &str) const
Base exception for SipMessage related exceptions.
Represents a SIP message.
void addBuffer(char *buf)
std::unique_ptr< Contents > releaseContents()
Removes the contents from the message.
void copyOutboundDecoratorsToStackFailureAck(SipMessage &ack)
const std::list< Data > & getTlsPeerNames() const
void setRFC2543TransactionId(const Data &tid)
void setContents(const Contents *contents)
Set the contents of the message.
void setStartLine(const char *start, uint32_t len)
static SipMessage * make(const Data &buffer, bool isExternal=false)
Construct a SipMessage object from a string containing a SIP request or response.
bool isRequest() const
Returns true if message is a request, false otherwise.
const Data & getRFC2543TransactionId() const
Calculates an MD5 hash over the Request-URI, To tag (for non-INVITE transactions),...
void setWsCookies(const CookieList &wsCookies)
bool hasForceTarget() const
SipMessage & mergeUri(const Uri &source)
virtual bool isClientTransaction() const
Check if SipMessage is a client transaction.
void setWsCookieContext(std::shared_ptr< WsCookieContext > wsCookieContext)
const Data & methodStr() const
Returns a string containing the SIP method for the message.
Contents * getContents() const
Retrieves the body of a SIP message.
void setBody(const char *start, uint32_t len)
void callOutboundDecorators(const Tuple &src, const Tuple &dest, const Data &sigcompId)
void setRawHeader(const HeaderFieldValueList *hfvs, Headers::Type headerType)
const Data & getTlsSni() const
SNI (TLS server_name) the peer sent in its ClientHello.
void freeMem(bool leaveResponseStuff=false)
void addOutboundDecorator(std::unique_ptr< MessageDecorator > md)
Call a MessageDecorator to process the message before it is sent to the transport.
void setSecurityAttributes(std::unique_ptr< SecurityAttributes >) noexcept
void init(const SipMessage &rhs)
void setForceTarget(const Uri &uri)
deal with a notion of an "out-of-band" forced target for SIP routing
bool empty(const HeaderBase &headerType) const
Returns true if the header field is present and non-empty, false otherwise.
const RequestLine & header(const RequestLineType &l) const
Returns the RequestLine. This is only valid for request messages.
virtual const Data & getTransactionId() const
Returns the transaction id from the branch or if 2543, the computed hash.
void addHeader(Headers::Type header, const char *headerName, uint32_t headerNameLen, const char *value, uint32_t valuelen)
Add HeaderFieldValue given enum, header name and value.
EncodeStream & encodeEmbedded(EncodeStream &str) const
bool isResponse() const
Returns true if message is a response, false otherwise.
const RequestLine & const_header(const RequestLineType &l) const
void setRawBody(const HeaderFieldValue &body)
Remove any existing body/contents, and (if non-empty) set the body to {body}.
const Uri & getForceTarget() const
SipMessage(const Tuple *receivedTransport=0)
EncodeStream & encodeSingleHeader(Headers::Type type, EncodeStream &str) const
bool exists(const HeaderBase &headerType) const
Returns true if the given header field is present, false otherwise.
virtual EncodeStream & encodeSipFrag(EncodeStream &str) const
static bool checkContentLength
void remove(const HeaderBase &headerType)
Prevents a header field from being present when the message is prepared for sending to a transport.
virtual Message * clone() const
virtual EncodeStream & encodeBrief(EncodeStream &str) const
output a brief description to stream
void copyOutboundDecoratorsToStackCancel(SipMessage &cancel)
void rollbackOutboundDecorators()
void clear(bool leaveResponseStuff=false)
const CookieList & getWsCookies() const
bool isExternal() const
Check if SipMessage is to be treated as it came off the wire.
void clearOutboundDecorators()
std::shared_ptr< WsCookieContext > getWsCookieContext() const noexcept
SipMessage & operator=(const SipMessage &rhs)
void setTlsPeerNames(const std::list< Data > &tlsPeerNames)
const HeaderFieldValueList * getRawHeader(Headers::Type headerType) const
typeless header interface
resip::MethodTypes method() const
returns the method type of the message
Data getCanonicalIdentityString() const
virtual EncodeStream & encode(EncodeStream &str) const
Generate a string from the SipMessage object.
virtual StartLine * clone() const =0
Represents the "Status-Line" element in the RFC 3261 grammar.
A dirt-simple lightweight stl pool allocator meant for use in short-lifetime objects.
Represents the "header-value" element in the RFC 3261 grammar (ie, an unknown header field value).
static const char * SPACE
static const char * QUESTION
static const char * AMPERSAND
This class is used to get the current system time.
Generically represents a token whose value can be wrapped and encoded using double quotes.
Represents the "token" element in the RFC 3261 grammar.
Represents a network address.
void setType(TransportType type)
Represents a numeric-with-comment header field value.
Represents the "SIP-URI" and "SIPS-URI" elements in the RFC 3261 grammar.
bool exists(const Param< Uri > ¶mType) const
void remove(const Param< Uri > ¶mType)
const Data & param(const ExtensionParameter ¶m) const
Const accessor for non-natively-supported parameter types.
Represents the "via-parm" element in the RFC 3261 grammar.
Represents the "warning-value" element in the RFC 3261 grammar.
An ostream that operates on an existing Data.
This file is used to handle compatibility fixes/tweaks so reSIProcate can function on multiple platfo...
dcm! – add UnusedChecking(_enum) below;
StatusLineType h_StatusLine
bool isEqualNoCase(const Data &left, const Data &right)
const Data & getMethodName(MethodTypes t)
RequestLineType h_RequestLine
ParserContainer< StringCategory > StringCategories
MethodTypes getMethodType(const Data &name)
std::vector< Cookie > CookieList
H_AllowEventss h_AllowEvents