1#if !defined(RESIP_SIPMESSAGE_HXX)
2#define RESIP_SIPMESSAGE_HXX
36#if defined(_MSC_VER) && !defined(__clang__)
38#pragma intrinsic(_BitScanForward)
39#if defined(_M_X64) || defined(_M_ARM64)
40#pragma intrinsic(_BitScanForward64)
42#if defined(_M_IX86) || defined(_M_X64)
43#pragma intrinsic(_tzcnt_u32)
46#pragma intrinsic(_tzcnt_u64)
55class SecurityAttributes;
181 typedef std::list< std::pair<Data, HeaderFieldValueList*> >
UnknownHeaders;
214 using HeaderIndex =
unsigned char;
216 static constexpr HeaderIndex InvalidHeaderIndex =
static_cast<HeaderIndex
>(-1);
217 static_assert(
Headers::MAX_HEADERS <= InvalidHeaderIndex,
"HeaderIndex type is too small to cover all SIP header types");
220 using UsedBitMaskWord = std::size_t;
222 static constexpr unsigned int UsedBitMaskWordBits =
static_cast<unsigned int>(std::numeric_limits<UsedBitMaskWord>::digits);
224 static constexpr unsigned int UsedBitMaskWordCount = (
static_cast<unsigned int>(
Headers::MAX_HEADERS) + UsedBitMaskWordBits - 1u) / UsedBitMaskWordBits;
257 using TypedHeaders = std::vector<HeaderInfo, StlPoolAllocator<HeaderInfo, PoolBase> >;
260 template<
typename AdoptedIterator>
263 friend class KnownHeaders;
266 using iterator_category = std::forward_iterator_tag;
267 using difference_type =
typename std::iterator_traits<AdoptedIterator>::difference_type;
268 using value_type =
typename std::iterator_traits<AdoptedIterator>::value_type;
269 using reference =
typename std::iterator_traits<AdoptedIterator>::reference;
270 using pointer =
typename std::iterator_traits<AdoptedIterator>::pointer;
279 constexpr UsedIterator()
noexcept : mIterator(), mEnd(mIterator) {}
280 UsedIterator(UsedIterator
const&) =
default;
286 typename =
typename std::enable_if<
287 std::is_constructible<AdoptedIterator, OtherAdoptedIterator1&&>::value && std::is_constructible<AdoptedIterator, OtherAdoptedIterator2&&>::value
291 noexcept(std::is_nothrow_constructible<AdoptedIterator, OtherAdoptedIterator1&&>::value &&
292 std::is_nothrow_constructible<AdoptedIterator, OtherAdoptedIterator2&&>::value) :
301 typename =
typename std::enable_if<
302 !std::is_same<OtherAdoptedIterator, AdoptedIterator>::value && std::is_constructible<AdoptedIterator, OtherAdoptedIterator const&>::value
306 noexcept(std::is_nothrow_constructible<AdoptedIterator, OtherAdoptedIterator const&>::value) :
307 mIterator(
that.mIterator),
313 pointer operator->()
const noexcept {
return mIterator.operator->(); }
314 UsedIterator& operator++() { increment();
return *
this; }
315 UsedIterator operator++(
int) { UsedIterator copy(*
this); increment();
return copy; }
325 advanceToNextUsedEntry();
329 void advanceToNextUsedEntry()
noexcept
369 using iterator_category = std::forward_iterator_tag;
385 constexpr Iterator()
noexcept : mKnownHeaders(
nullptr), mPos(0
u) {}
386 Iterator(Iterator
const&) =
default;
395 reference operator*()
const noexcept {
return dereference(); }
396 pointer operator->()
const noexcept {
return &dereference(); }
397 Iterator& operator++() { increment();
return *
this; }
398 Iterator operator++(
int) { Iterator copy(*
this); increment();
return copy; }
416 return mKnownHeaders->mHeaders[mKnownHeaders->mHeaderIndices[mPos]];
420 void increment()
noexcept
424 advanceToNextUsedEntry();
427#if defined(_MSC_VER) && !defined(__clang__)
430#pragma warning(disable: 4146)
434 void advanceToNextUsedEntry()
noexcept
442 const UsedBitMaskWord mask =
443 mKnownHeaders->mUsedBitMask[
mask_pos] &
static_cast<UsedBitMaskWord
>(-(
static_cast<UsedBitMaskWord
>(1u) <<
bit_pos));
457#if defined(_MSC_VER) && !defined(__clang__)
468#if defined(__GNUC__) || defined(__clang__)
472#elif defined(_MSC_VER)
477#if defined(_M_IX86) || defined(_M_X64)
482 return static_cast<unsigned int>(
res);
490#elif defined(_M_ARM64)
493 return static_cast<unsigned int>(
res);
506 static unsigned int countrZeroNz(UsedBitMaskWord
bitmask)
noexcept
508 unsigned int res = 0
u;
511 if ((
bitmask & ((
static_cast<UsedBitMaskWord
>(1u) <<
bits) - 1u)) == 0
u)
553 TypedHeaders mHeaders;
559 UsedBitMaskWord mUsedBitMask[UsedBitMaskWordCount];
564 noexcept(std::is_nothrow_constructible<TypedHeaders, const allocator_type&>::value) :
621 template<
typename ValuesFactory>
774#define defineHeader(_header, _name, _type, _rfc) \
775 const H_##_header::Type& header(const H_##_header& headerType) const; \
776 H_##_header::Type& header(const H_##_header& headerType); \
777 inline const H_##_header::Type& const_header(const H_##_header& headerType) const \
779 return header(headerType);\
783#define defineMultiHeader(_header, _name, _type, _rfc) \
784 const H_##_header##s::Type& header(const H_##_header##s& headerType) const; \
785 H_##_header##s::Type& header(const H_##_header##s& headerType); \
786 inline const H_##_header##s::Type& const_header(const H_##_header##s& headerType) const \
788 return header(headerType);\
959 void setContents(std::unique_ptr<Contents> contents);
1039 const Data& sigcompId);
1061 void compute2543TransactionHash()
const;
1088 inline void freeHfvl(HeaderFieldValueList*
hfvl)
1093 mPool.deallocate(
hfvl);
1121 DinkyPool<3732> mPool;
1131 Tuple mReceivedTransportTuple;
1141 std::vector<char*> mBufferList;
1144 StartLine* mStartLine;
1145 char mStartLineMem[
sizeof(RequestLine) >
sizeof(StatusLine) ?
sizeof(RequestLine) :
sizeof(StatusLine)];
1148 HeaderFieldValue mContentsHfv;
1151 mutable Contents* mContents;
1155 mutable Data mRFC2543TransactionId;
1175 std::shared_ptr<const ConnectionInfo> mConnectionInfo;
1177 std::unique_ptr<SecurityAttributes> mSecurityAttributes;
1179 std::vector<MessageDecorator*> mOutboundDecorators;
1186#undef ensureHeaderTypeUseable
1187#undef ensureSingleHeader
1188#undef ensureMultiHeader
1190#undef defineMultiHeader
#define resip_assert(x)
This file needs to work for both C and C++ code.
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.
Base class for all SIP body types.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Represents the "SIP-date" element in the RFC 3261 grammar.
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.
The base-class used for message-passing.
Represents the "media-type" element in the RFC 3261 grammar.
Represents the "name-addr" and the "addr-spec" elements in the RFC 3261 grammar.
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.
Base exception for SipMessage related exceptions.
const char * name() const noexcept override
returns the class name of the exception instance
Exception(const Data &msg, const Data &file, const int line)
constructor that records an exception message, the file and the line that the exception occured in.
Represents a SIP message.
void addBuffer(char *buf)
defineMultiHeader(ProxyAuthorization, "Proxy-Authorization", Auth, "RFC 3261")
defineMultiHeader(Route, "Route", NameAddr, "RFC 3261")
defineMultiHeader(Warning, "Warning", WarningCategory, "RFC 3261")
defineMultiHeader(Accept, "Accept", Mime, "RFC 3261")
defineHeader(CSeq, "CSeq", CSeqCategory, "RFC 3261")
const KnownHeaders & getRawHeaders() const noexcept
defineHeader(PrivAnswerMode, "Priv-Answer-Mode", Token, "draft-ietf-answermode-04")
defineHeader(Timestamp, "Timestamp", StringCategory, "RFC 3261")
defineMultiHeader(HistoryInfo, "History-Info", NameAddr, "RFC 4244")
std::unique_ptr< Contents > releaseContents()
Removes the contents from the message.
defineHeader(AnswerMode, "Answer-Mode", Token, "draft-ietf-answermode-04")
void copyOutboundDecoratorsToStackFailureAck(SipMessage &ack)
defineMultiHeader(Privacy, "Privacy", PrivacyCategory, "RFC 3323")
const std::list< Data > & getTlsPeerNames() const
defineMultiHeader(SecurityServer, "Security-Server", Token, "RFC 3329")
defineMultiHeader(PAssertedIdentity, "P-Asserted-Identity", NameAddr, "RFC 3325")
std::list< std::pair< Data, HeaderFieldValueList * >, StlPoolAllocator< std::pair< Data, HeaderFieldValueList * >, PoolBase > > UnknownHeaders
void setDestination(const Tuple &tuple)
Used by the stateless interface to specify where to send a request/response.
defineHeader(ReplyTo, "Reply-To", NameAddr, "RFC 3261")
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
defineMultiHeader(Authorization, "Authorization", Auth, "RFC 3261")
SipMessage & mergeUri(const Uri &source)
defineHeader(SecWebSocketKey1, "Sec-WebSocket-Key1", StringCategory, "draft-hixie- thewebsocketprotocol-76")
defineHeader(ReferTo, "Refer-To", NameAddr, "RFC 3515")
virtual bool isClientTransaction() const
Check if SipMessage is a client transaction.
void setWsCookieContext(std::shared_ptr< WsCookieContext > wsCookieContext)
defineMultiHeader(Diversion, "Diversion", NameAddr, "RFC 5806")
defineMultiHeader(AcceptEncoding, "Accept-Encoding", Token, "RFC 3261")
const Data & methodStr() const
Returns a string containing the SIP method for the message.
defineHeader(MaxForwards, "Max-Forwards", UInt32Category, "RFC 3261")
Contents * getContents() const
Retrieves the body of a SIP message.
defineMultiHeader(AcceptLanguage, "Accept-Language", Token, "RFC 3261")
void setConnectionInfo(std::shared_ptr< const ConnectionInfo > connectionInfo) noexcept
defineHeader(To, "To", NameAddr, "RFC 3261")
defineMultiHeader(Via, "Via", Via, "RFC 3261")
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)
defineHeader(MIMEVersion, "Mime-Version", Token, "RFC 3261")
defineHeader(TargetDialog, "Target-Dialog", CallId, "RFC 4538")
defineHeader(SecWebSocketKey, "Sec-WebSocket-Key", StringCategory, "RFC 6455")
void setTlsDomain(const Data &domain)
const Data & getTlsSni() const
SNI (TLS server_name) the peer sent in its ClientHello.
void freeMem(bool leaveResponseStuff=false)
defineHeader(ContentId, "Content-ID", Token, "RFC 2045")
defineMultiHeader(Supported, "Supported", Token, "RFC 3261")
defineMultiHeader(ProxyAuthenticate, "Proxy-Authenticate", Auth, "RFC 3261")
defineHeader(ContentType, "Content-Type", Mime, "RFC 3261")
const Tuple & getReceivedTransportTuple() const
defineMultiHeader(ErrorInfo, "Error-Info", GenericUri, "RFC 3261")
defineMultiHeader(RejectContact, "Reject-Contact", NameAddr, "RFC 3841")
const UnknownHeaders & getRawUnknownHeaders() const noexcept
defineHeader(MinExpires, "Min-Expires", UInt32Category, "RFC 3261")
void addOutboundDecorator(std::unique_ptr< MessageDecorator > md)
Call a MessageDecorator to process the message before it is sent to the transport.
defineHeader(Priority, "Priority", Token, "RFC 3261")
void setSecurityAttributes(std::unique_ptr< SecurityAttributes >) noexcept
defineMultiHeader(PPreferredIdentity, "P-Preferred-Identity", NameAddr, "RFC 3325")
defineHeader(Expires, "Expires", ExpiresCategory, "RFC 3261")
defineHeader(RSeq, "RSeq", UInt32Category, "RFC 3261")
defineHeader(SubscriptionState, "Subscription-State", Token, "RFC 3265")
void init(const SipMessage &rhs)
defineHeader(UserAgent, "User-Agent", StringCategory, "RFC 3261")
void setForceTarget(const Uri &uri)
deal with a notion of an "out-of-band" forced target for SIP routing
defineHeader(RetryAfter, "Retry-After", UInt32Category, "RFC 3261")
defineMultiHeader(Identity, "Identity", IdentityCategory, "RFC 8224")
defineHeader(Host, "Host", StringCategory, "draft-hixie- thewebsocketprotocol-76")
defineHeader(Server, "Server", StringCategory, "RFC 3261")
defineHeader(RAck, "RAck", RAckCategory, "RFC 3262")
defineHeader(PCalledPartyId, "P-Called-Party-ID", NameAddr, "RFC 3455")
const RequestLine & header(const RequestLineType &l) const
Returns the RequestLine. This is only valid for request messages.
defineHeader(SIPIfMatch, "SIP-If-Match", Token, "RFC 3903")
defineMultiHeader(PMediaAuthorization, "P-Media-Authorization", Token, "RFC 3313")
defineMultiHeader(CallInfo, "Call-Info", GenericUri, "RFC 3261")
virtual const Data & getTransactionId() const
Returns the transaction id from the branch or if 2543, the computed hash.
defineMultiHeader(WWWAuthenticate, "Www-Authenticate", Auth, "RFC 3261")
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.
defineHeader(AuthenticationInfo, "Authentication-Info", Auth, "RFC 3261")
defineHeader(SIPETag, "SIP-ETag", Token, "RFC 3903")
defineHeader(Replaces, "Replaces", CallID, "RFC 3891")
defineHeader(PChargingFunctionAddresses, "P-Charging-Function-Addresses", Token, "RFC 3455")
EncodeStream & encodeEmbedded(EncodeStream &str) const
defineMultiHeader(UserToUser, "User-to-User", TokenOrQuotedStringCategory, "draft-ietf-cuss-sip-uui-17")
defineMultiHeader(ProxyRequire, "Proxy-Require", Token, "RFC 3261")
defineHeader(ContentDisposition, "Content-Disposition", Token, "RFC 3261")
defineHeader(Organization, "Organization", StringCategory, "RFC 3261")
defineMultiHeader(Path, "Path", NameAddr, "RFC 3327")
bool isResponse() const
Returns true if message is a response, false otherwise.
const RequestLine & const_header(const RequestLineType &l) const
defineMultiHeader(SecurityVerify, "Security-Verify", Token, "RFC 3329")
defineMultiHeader(Allow, "Allow", Token, "RFC 3261")
void setRawBody(const HeaderFieldValue &body)
Remove any existing body/contents, and (if non-empty) set the body to {body}.
defineHeader(FlowTimer, "Flow-Timer", UInt32Category, "RFC 5626")
const resip::Data * getReason() const
Returns a string containing the response reason text.
const Uri & getForceTarget() const
EncodeStream & encodeSingleHeader(Headers::Type type, EncodeStream &str) const
void setFromExternal()
Mark message as externally generated.
bool exists(const HeaderBase &headerType) const
Returns true if the given header field is present, false otherwise.
virtual EncodeStream & encodeSipFrag(EncodeStream &str) const
const Tuple & getSource() const
Returns the source tuple that the message was received from only makes sense for messages received fr...
defineMultiHeader(Contact, "Contact", NameAddr, "RFC 3261")
defineHeader(Event, "Event", Token, "RFC 3265")
defineMultiHeader(RequestDisposition, "Request-Disposition", Token, "RFC 3841")
static bool checkContentLength
bool isFromWire() const
Check if SipMessage came off the wire.
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
defineHeader(SessionExpires, "Session-Expires", ExpiresCategory, "RFC 4028")
const HeaderFieldValue & getRawBody() const noexcept
Return the raw body string (if it exists).
defineHeader(ContentLength, "Content-Length", UInt32Category, "RFC 3261")
defineMultiHeader(ServiceRoute, "Service-Route", NameAddr, "RFC 3608")
defineHeader(Subject, "Subject", StringCategory, "RFC 3261")
virtual EncodeStream & encodeBrief(EncodeStream &str) const
output a brief description to stream
defineMultiHeader(AlertInfo, "Alert-Info", GenericUri, "RFC 3261")
defineHeader(IdentityInfo, "Identity-Info", GenericUri, "RFC 4474")
defineHeader(Origin, "Origin", StringCategory, "draft-hixie- thewebsocketprotocol-76")
defineHeader(CallID, "Call-ID", CallID, "RFC 3261")
defineMultiHeader(RemotePartyId, "Remote-Party-ID", NameAddr, "draft-ietf-sip-privacy-04")
const std::shared_ptr< const ConnectionInfo > & getConnectionInfo() const noexcept
TLS and WebSocket details of the connection this message was received on, shared by every message rec...
void setReceivedTransportTuple(const Tuple &transportTuple)
Set Tuple for transport from whence this message came.
defineMultiHeader(Unsupported, "Unsupported", Token, "RFC 3261")
defineMultiHeader(AcceptContact, "Accept-Contact", NameAddr, "RFC 3841")
defineHeader(Join, "Join", CallId, "RFC 3911")
void copyOutboundDecoratorsToStackCancel(SipMessage &cancel)
defineMultiHeader(PAssociatedUri, "P-Associated-URI", NameAddr, "RFC 3455")
const SecurityAttributes * getSecurityAttributes() const noexcept
defineHeader(SecWebSocketKey2, "Sec-WebSocket-Key2", StringCategory, "draft-hixie- thewebsocketprotocol-76")
defineMultiHeader(SecurityClient, "Security-Client", Token, "RFC 3329")
defineMultiHeader(ContentLanguage, "Content-Language", Token, "RFC 3261")
void rollbackOutboundDecorators()
defineHeader(SecWebSocketAccept, "Sec-WebSocket-Accept", StringCategory, "RFC 6455")
const Data & getTlsDomain() const
const StatusLine & const_header(const StatusLineType &l) const
defineHeader(InReplyTo, "In-Reply-To", CallID, "RFC 3261")
defineMultiHeader(AllowEvents, "Allow-Events", Token, "RFC 3265")
defineMultiHeader(Reason, "Reason", Token, "RFC 3326")
uint64_t getCreatedTimeMicroSec() const
const CookieList & getWsCookies() const
defineHeader(Date, "Date", DateCategory, "RFC 3261")
defineMultiHeader(Cookie, "Cookie", StringCategory, "RFC 6265")
bool isExternal() const
Check if SipMessage is to be treated as it came off the wire.
bool isInvalid() const
Returns true if message failed to parse, false otherwise.
void setSource(const Tuple &tuple)
void clearOutboundDecorators()
defineMultiHeader(Require, "Require", Token, "RFC 3261")
defineHeader(ContentTransferEncoding, "Content-Transfer-Encoding", StringCategory, "RFC 1521")
defineMultiHeader(RecordRoute, "Record-Route", NameAddr, "RFC 3261")
std::shared_ptr< WsCookieContext > getWsCookieContext() const noexcept
defineHeader(MinSE, "Min-SE", ExpiresCategory, "RFC 4028")
void setTlsPeerNames(const std::list< Data > &tlsPeerNames)
const HeaderFieldValueList * getRawHeader(Headers::Type headerType) const
typeless header interface
defineHeader(From, "From", NameAddr, "RFC 3261")
resip::MethodTypes method() const
returns the method type of the message
Data getCanonicalIdentityString() const
defineHeader(PChargingVector, "P-Charging-Vector", Token, "RFC 3455")
RESIP_HeapCount(SipMessage)
void setFromTU()
Mark message as internally generated.
defineMultiHeader(PAccessNetworkInfo, "P-Access-Network-Info", Token, "RFC 7315")
virtual EncodeStream & encode(EncodeStream &str) const
Generate a string from the SipMessage object.
defineMultiHeader(PVisitedNetworkID, "P-Visited-Network-ID", TokenOrQuotedStringCategory, "RFC 3455")
defineHeader(ReferredBy, "Referred-By", NameAddr, "RFC 3892")
defineHeader(ContentEncoding, "Content-Encoding", Token, "RFC 3261")
defineHeader(ReferSub, "Refer-Sub", Token, "RFC 4488")
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).
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.
Represents a numeric-with-comment header field value.
Represents the "SIP-URI" and "SIPS-URI" elements in the RFC 3261 grammar.
Represents the "via-parm" element in the RFC 3261 grammar.
Represents the "warning-value" element in the RFC 3261 grammar.
This file is used to handle compatibility fixes/tweaks so reSIProcate can function on multiple platfo...
dcm! – add UnusedChecking(_enum) below;
unsigned long long uint64_t
ParserContainer< StringCategory > StringCategories
bool operator==(const char *lhs, const Data &rhs)
bool operator!=(const Data &lhs, const Data &rhs)
std::vector< Cookie > CookieList
unsigned __int64 uint64_t