Coverage Report

Created: 2026-08-13 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/resiprocate/resip/stack/SipMessage.hxx
Line
Count
Source
1
#if !defined(RESIP_SIPMESSAGE_HXX)
2
#define RESIP_SIPMESSAGE_HXX 
3
4
#include <sys/types.h>
5
6
#include <list>
7
#include <vector>
8
#include <utility>
9
#include <memory>
10
#include <iterator>
11
#include <type_traits>
12
13
#include "resip/stack/Contents.hxx"
14
#include "resip/stack/Headers.hxx"
15
#include "resip/stack/TransactionMessage.hxx"
16
#include "resip/stack/ParserContainer.hxx"
17
#include "resip/stack/ParserCategories.hxx"
18
#include "resip/stack/SecurityAttributes.hxx"
19
#include "resip/stack/Tuple.hxx"
20
#include "resip/stack/Uri.hxx"
21
#include "resip/stack/MessageDecorator.hxx"
22
#include "resip/stack/Cookie.hxx"
23
#include "resip/stack/WsCookieContext.hxx"
24
#include "rutil/BaseException.hxx"
25
#include "rutil/Data.hxx"
26
#include "rutil/DinkyPool.hxx"
27
#include "rutil/StlPoolAllocator.hxx"
28
#include "rutil/Timer.hxx"
29
#include "rutil/HeapInstanceCounter.hxx"
30
31
namespace resip
32
{
33
34
class Contents;
35
class ExtensionHeader;
36
class SecurityAttributes;
37
38
/**
39
   @ingroup resip_crit
40
   @ingroup message_passing_tu
41
   @brief Represents a SIP message.
42
43
   This is the class that your app will spend the most time working with. This
44
   is because, in the UA core/Transaction User architecture, the vast majority
45
   of interaction is carried out through SIP messaging.
46
47
   When you get a SipMessage, generally the first thing you want to know is 
48
   whether it is a request or a response. This is done by calling 
49
   SipMessage::isRequest() or SipMessage::isResponse().
50
   
51
   Next, it is usually important to determine what the SIP method of the message 
52
   is. This is done by calling SipMessage::method() (this is a convenience 
53
   function that checks the method of the Request-Line if the message is a 
54
   request, or the method of the CSeq if a response).
55
   
56
   At this point, it may become useful to examine the start-line of the message.
57
58
   If the message is a request, you can get the Request-Line (represented by a 
59
   RequestLine&) by calling SipMessage::header(const RequestLineType&)
60
   @code
61
      RequestLine& rLine = sip.header(h_RequestLine);
62
   @endcode
63
64
   If the message is a response, you can get the Status-Line (represented by a StatusLine&) by calling SipMessage::header(const StatusLineType&)
65
   @code
66
      StatusLine& sLine = sip.header(h_StatusLine);
67
   @endcode
68
69
   From here, examination of the various headers is in order. The way the 
70
   underlying code works is very complicated, but fortunately relatively 
71
   painless to use. For each header type, there is a subclass of HeaderBase, and 
72
   a SipMessage::header() function that takes a reference to this subclass. On 
73
   top of this, there is a static instance of each of these subclasses. Examples 
74
   include h_To, h_From, h_CSeq, h_CallId, h_Routes, h_Contacts, h_RecordRoutes, 
75
   etc.
76
77
   @code
78
      NameAddr& to = sip.header(h_To);
79
      NameAddr& from = sip.header(h_From);
80
      CSeqCategory& cseq = sip.header(h_CSeq);
81
      CallId& callId = sip.header(h_CallId);
82
      ParserContainer<NameAddr>& routes = sip.header(h_Routes);
83
      ParserContainer<NameAddr>& contacts = sip.header(h_Contacts);
84
      ParserContainer<NameAddr>& rRoutes = sip.header(h_RecordRoutes);
85
   @endcode
86
87
   Generally speaking, the access token is named in a predictable fashion; all 
88
   non-alphanumeric characters are omitted, the first letter of each word is 
89
   capitalized, and the name is pluralized if the header is multi-valued (since 
90
   this stuff is all macro-generated, sometimes this pluralization isn't quite 
91
   right; h_AllowEventss, h_PAssertedIdentitys).
92
93
   When accessing a single-value header, you need to check whether it 
94
   exists first (unless you want it to be created implicitly). Also, since all
95
   header field values are lazily parsed (see LazyParser), you'll want to make 
96
   sure it is well-formed before attempting to access any portion of it.
97
98
   @code
99
      if(sip.exists(h_Event))
100
      {
101
         Token& event = sip.header(h_Event);
102
         if(event.isWellFormed())
103
         {
104
            // do stuff with event.
105
         }
106
         else
107
         {
108
            // complain bitterly
109
         }
110
      }
111
   @endcode
112
113
   When accessing a multi-value header, it is important to keep in mind that 
114
   it can be empty, even if it exists (for example, "Supported: " has a meaning 
115
   that is distinct from the lack of a Supported header).
116
117
   @code
118
      if(sip.exists(h_Contacts))
119
      {
120
         ParserContainer<NameAddr>& contacts = sip.header(h_Contacts);
121
         if(!contacts.empty())
122
         {
123
            NameAddr& frontContact = contacts.front();
124
            if(frontContact.isWellFormed())
125
            {
126
               // do stuff with frontContact
127
            }
128
            else
129
            {
130
               // complain bitterly
131
            }
132
         }
133
         else
134
         {
135
            // complain bitterly
136
         }
137
      }
138
   @endcode
139
140
   In some cases, you will need to access header-types that are not natively 
141
   supported by the stack (ie, don't have an access-token). ExtensionHeader will
142
   allow you to construct an access-token at runtime that will retrieve the
143
   header field value as a ParserContainer<StringCategory>. Here's an example:
144
145
   @code
146
      // We need to access the FooBar header field value here.
147
      static ExtensionHeader h_FooBar("FooBar");
148
      if(sip.exists(h_FooBar))
149
      {
150
         ParserContainer<StringCategory>& fooBars = sip.header(h_FooBar);
151
      }
152
   @endcode
153
154
*/
155
class SipMessage : public TransactionMessage
156
{
157
   public:
158
      RESIP_HeapCount(SipMessage);
159
#ifndef __SUNPRO_CC
160
      typedef std::list< std::pair<Data, HeaderFieldValueList*>, StlPoolAllocator<std::pair<Data, HeaderFieldValueList*>, PoolBase > > UnknownHeaders;
161
#else
162
      typedef std::list< std::pair<Data, HeaderFieldValueList*> > UnknownHeaders;
163
#endif
164
165
      /**
166
       * @brief List of known SIP headers, searchable by header type.
167
       *
168
       * This container provides access to headers of the SIP message that are known to libresiprocate.
169
       * The headers can be searched by `Headers::Type` enum values and iterated over. The list of headers
170
       * is unordered, and any modifications of the container may invalidate iterators, pointers and references
171
       * into the container. The container does not own the `HeaderFieldValueList` objects, which must be
172
       * explicitly freed on removal (which is handled by `SipMessage`).
173
       *
174
       * Elements of the container can be in an "unused" state, which is when the element was removed but
175
       * not disposed of. "Unused" elements do not participate in the publicly visible set of elements observed
176
       * by users (e.g. they are not found by searching or exposed during iteration). "Unused" elements can be
177
       * reused if the user attempts to insert an element with the matching header type. After that, the reused
178
       * element becomes publicly accessible again.
179
       */
180
      class KnownHeaders
181
      {
182
         private:
183
            /// Small index type that is used to map header type ids onto vector elements
184
            using HeaderIndex = unsigned char;
185
            /// Header index value that indicates invalid index
186
            static constexpr HeaderIndex InvalidHeaderIndex = static_cast<HeaderIndex>(-1);
187
            static_assert(Headers::MAX_HEADERS <= InvalidHeaderIndex, "HeaderIndex type is too small to cover all SIP header types");
188
189
         public:
190
            /// Publicly accessible information about a header
191
            class HeaderInfo
192
            {
193
                  friend class KnownHeaders;
194
195
               private:
196
                  /// Pointer to header values
197
                  HeaderFieldValueList* mValues;
198
                  /// Header type. If `Headers::UNKNOWN`, indicates that this entry is in the "unused" state.
199
                  Headers::Type mType;
200
201
               public:
202
0
                  constexpr HeaderInfo() noexcept : mValues(nullptr), mType(Headers::UNKNOWN) {}
203
1.16k
                  explicit constexpr HeaderInfo(Headers::Type type, HeaderFieldValueList* values = nullptr) noexcept : mValues(values), mType(type) {}
204
205
                  /// Returns header type
206
675k
                  Headers::Type getType() const noexcept { return mType; }
207
208
                  /// Returns header values
209
672k
                  HeaderFieldValueList* getValues() const noexcept { return mValues; }
210
                  /// Sets header values
211
1.16k
                  void setValues(HeaderFieldValueList* values) noexcept { mValues = values; }
212
213
               private:
214
                  /// Sets header type. Only supposed to be used by `KnownHeaders` implementation.
215
0
                  void setType(Headers::Type type) noexcept { mType = type; }
216
            };
217
218
         private:
219
            /// Internal list of header info entries
220
            using TypedHeaders = std::vector<HeaderInfo, StlPoolAllocator<HeaderInfo, PoolBase> >;
221
222
            /// Iterator over used entries in the list
223
            template<typename AdoptedIterator>
224
            class UsedIterator
225
            {
226
                  friend class KnownHeaders;
227
228
               public:
229
                  using iterator_category = std::forward_iterator_tag;
230
                  using difference_type = typename std::iterator_traits<AdoptedIterator>::difference_type;
231
                  using value_type = typename std::iterator_traits<AdoptedIterator>::value_type;
232
                  using reference = typename std::iterator_traits<AdoptedIterator>::reference;
233
                  using pointer = typename std::iterator_traits<AdoptedIterator>::pointer;
234
235
               private:
236
                  /// Adopted iterator into the list of headers
237
                  AdoptedIterator mIterator;
238
                  /// Iterator to the end of the list of headers
239
                  AdoptedIterator mEnd;
240
241
               public:
242
                  constexpr UsedIterator() noexcept : mIterator(), mEnd(mIterator) {}
243
                  UsedIterator(UsedIterator const&) = default;
244
245
                  /// Initializing constructor
246
                  template<
247
                     typename OtherAdoptedIterator1,
248
                     typename OtherAdoptedIterator2,
249
                     typename = typename std::enable_if<
250
                        std::is_constructible<AdoptedIterator, OtherAdoptedIterator1&&>::value && std::is_constructible<AdoptedIterator, OtherAdoptedIterator2&&>::value
251
                     >::type
252
                  >
253
                  explicit constexpr UsedIterator(OtherAdoptedIterator1&& iter, OtherAdoptedIterator2&& end)
254
                     noexcept(std::is_nothrow_constructible<AdoptedIterator, OtherAdoptedIterator1&&>::value &&
255
                        std::is_nothrow_constructible<AdoptedIterator, OtherAdoptedIterator2&&>::value) :
256
691k
                     mIterator(std::forward<OtherAdoptedIterator1>(iter)),
257
691k
                     mEnd(std::forward<OtherAdoptedIterator2>(end))
258
691k
                  {
259
691k
                  }
resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*> >::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*>, std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*>, void>(std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*>&&, std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*>&&)
Line
Count
Source
256
662k
                     mIterator(std::forward<OtherAdoptedIterator1>(iter)),
257
662k
                     mEnd(std::forward<OtherAdoptedIterator2>(end))
258
662k
                  {
259
662k
                  }
resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*> >::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*>&, std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*>, void>(std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*>&, std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*>&&)
Line
Count
Source
256
14.3k
                     mIterator(std::forward<OtherAdoptedIterator1>(iter)),
257
14.3k
                     mEnd(std::forward<OtherAdoptedIterator2>(end))
258
14.3k
                  {
259
14.3k
                  }
resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*> >::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*>, std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*>, void>(std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*>&&, std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*>&&)
Line
Count
Source
256
14.6k
                     mIterator(std::forward<OtherAdoptedIterator1>(iter)),
257
14.6k
                     mEnd(std::forward<OtherAdoptedIterator2>(end))
258
14.6k
                  {
259
14.6k
                  }
260
261
                  /// Convering constructor for mutable -> const iterator conversion
262
                  template<
263
                     typename OtherAdoptedIterator,
264
                     typename = typename std::enable_if<
265
                        !std::is_same<OtherAdoptedIterator, AdoptedIterator>::value && std::is_constructible<AdoptedIterator, OtherAdoptedIterator const&>::value
266
                     >::type
267
                  >
268
                  constexpr UsedIterator(UsedIterator<OtherAdoptedIterator> const& that)
269
                     noexcept(std::is_nothrow_constructible<AdoptedIterator, OtherAdoptedIterator const&>::value) :
270
14.6k
                     mIterator(that.mIterator),
271
14.6k
                     mEnd(that.mEnd)
272
14.6k
                  {
273
14.6k
                  }
274
275
0
                  reference operator*() const noexcept { return *mIterator; }
Unexecuted instantiation: resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*> >::operator*() const
Unexecuted instantiation: resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*> >::operator*() const
276
671k
                  pointer operator->() const noexcept { return mIterator.operator->(); }
resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*> >::operator->() const
Line
Count
Source
276
661k
                  pointer operator->() const noexcept { return mIterator.operator->(); }
resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*> >::operator->() const
Line
Count
Source
276
9.57k
                  pointer operator->() const noexcept { return mIterator.operator->(); }
277
0
                  UsedIterator operator++() { increment(); return *this; }
Unexecuted instantiation: resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*> >::operator++()
Unexecuted instantiation: resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*> >::operator++()
278
0
                  UsedIterator operator++(int) { UsedIterator copy(*this); increment(); return copy; }
279
280
14.6k
                  friend bool operator==(UsedIterator const& left, UsedIterator const& right) noexcept { return left.mIterator == right.mIterator; }
Unexecuted instantiation: resip::operator==(resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*> > const&, resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*> > const&)
resip::operator==(resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*> > const&, resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*> > const&)
Line
Count
Source
280
14.6k
                  friend bool operator==(UsedIterator const& left, UsedIterator const& right) noexcept { return left.mIterator == right.mIterator; }
281
5.03k
                  friend bool operator!=(UsedIterator const& left, UsedIterator const& right) noexcept { return !(left == right); }
Unexecuted instantiation: resip::operator!=(resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*> > const&, resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*> > const&)
resip::operator!=(resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*> > const&, resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*> > const&)
Line
Count
Source
281
5.03k
                  friend bool operator!=(UsedIterator const& left, UsedIterator const& right) noexcept { return !(left == right); }
282
283
               private:
284
                  /// Increments the iterator to the next used entry or end of the list
285
                  void increment() noexcept
286
0
                  {
287
0
                     ++mIterator;
288
0
                     advanceToNextUsedEntry();
289
0
                  }
Unexecuted instantiation: resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*> >::increment()
Unexecuted instantiation: resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*> >::increment()
290
291
                  /// Advances to the next used entry in the list
292
                  void advanceToNextUsedEntry() noexcept
293
0
                  {
294
0
                     while (mIterator != mEnd && mIterator->getType() == Headers::UNKNOWN)
295
0
                        ++mIterator;
296
0
                  }
Unexecuted instantiation: resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo const*> >::advanceToNextUsedEntry()
Unexecuted instantiation: resip::SipMessage::KnownHeaders::UsedIterator<std::__1::__wrap_iter<resip::SipMessage::KnownHeaders::HeaderInfo*> >::advanceToNextUsedEntry()
297
            };
298
299
         public:
300
            using iterator = UsedIterator<TypedHeaders::iterator>;
301
            using const_iterator = UsedIterator<TypedHeaders::const_iterator>;
302
            using value_type = TypedHeaders::value_type;
303
            using reference = TypedHeaders::reference;
304
            using const_reference = TypedHeaders::const_reference;
305
            using pointer = TypedHeaders::pointer;
306
            using const_pointer = TypedHeaders::const_pointer;
307
            using size_type = TypedHeaders::size_type;
308
            using difference_type = TypedHeaders::difference_type;
309
            using allocator_type = TypedHeaders::allocator_type;
310
311
         private:
312
            /// Information about headers
313
            TypedHeaders mHeaders;
314
            /// Number of non-"unused" elements in the container
315
            HeaderIndex mSize;
316
            /// Indices into `mHeaders`. If an element is `InvalidHeaderIndex` it means the corresponding header has no entry in the list.
317
            HeaderIndex mHeaderIndices[Headers::MAX_HEADERS];
318
319
         public:
320
0
            KnownHeaders() noexcept : mSize(0) { resetIndices(); }
321
            explicit KnownHeaders(const allocator_type& alloc)
322
               noexcept(std::is_nothrow_constructible<TypedHeaders, const allocator_type&>::value) :
323
9.86k
               mHeaders(alloc),
324
9.86k
               mSize(0)
325
9.86k
            {
326
9.86k
               resetIndices();
327
9.86k
            }
328
329
            // Not copyable or moveable since the container elements may be associated with a memory pool
330
            KnownHeaders(const KnownHeaders&) = delete;
331
            KnownHeaders& operator=(const KnownHeaders&) = delete;
332
333
            /// Returns `true` if the container is empty. Does not consider "unused" elements.
334
0
            bool empty() const noexcept { return mSize == 0; }
335
            /// Returns the number of elements in the container. Does not consider "unused" elements.
336
0
            size_type size() const noexcept { return static_cast<size_type>(mSize); }
337
            /// Clears the container. Does not free `HeaderFieldValueList` objects but clears them and marks as "unused".
338
            void clear() noexcept;
339
            /**
340
             * @brief Clears the container and invokes the dispose function on every element.
341
             *
342
             * The `disposer` function will be called on all entries, including "unused" ones. It is expected to free any resources
343
             * associated with the entry and must not throw.
344
             */
345
            template<typename Disposer>
346
            void clearAndDispose(Disposer&& disposer) noexcept;
347
348
            /// Iterator access
349
0
            const_iterator cbegin() const noexcept { return begin(); }
350
0
            const_iterator cend() const noexcept { return end(); }
351
352
0
            const_iterator begin() const noexcept { const_iterator it(mHeaders.begin(), mHeaders.end()); it.advanceToNextUsedEntry(); return it; }
353
14.6k
            const_iterator end() const noexcept { return const_iterator(mHeaders.end(), mHeaders.end()); }
354
355
0
            iterator begin() noexcept { iterator it(mHeaders.begin(), mHeaders.end()); it.advanceToNextUsedEntry(); return it; }
356
251
            iterator end() noexcept { return iterator(mHeaders.end(), mHeaders.end()); }
357
358
            /// Reserves internal storage for the given number of entries
359
9.86k
            void reserve(size_type capacity) { mHeaders.reserve(capacity); }
360
            /// Returns capacity of the internal storage
361
0
            size_type capacity() const noexcept { return mHeaders.capacity(); }
362
363
            /// Finds header information, if present in the list. Returns `end()` if not found. Does not produce "unused" entries.
364
            iterator find(Headers::Type type) noexcept;
365
14.6k
            const_iterator find(Headers::Type type) const noexcept { return const_cast<KnownHeaders*>(this)->find(type); }
366
367
            /// Erases an element. Does not free the `HeaderFieldValueList` object but clears it and marks as "unused".
368
            void erase(iterator it) noexcept;
369
370
            /**
371
             * @brief Constructs or reuses a previously erased element for a given header type.
372
             *
373
             * If the header with the given type was previously erased and is in the "unused" state, this call reuses this element.
374
             * Otherwise, the call constructs a new element with the given header type and a pointer to the `HeaderFieldValueList` object
375
             * returned by the `valuesFactory()` function call.
376
             *
377
             * @returns An iterator to the inserted element.
378
             */
379
            template<typename ValuesFactory>
380
            iterator insert(Headers::Type type, ValuesFactory&& valuesFactory);
381
382
         private:
383
            /// Resets all header indices to `InvalidHeaderIndex`
384
            void resetIndices() noexcept;
385
      };
386
387
      explicit SipMessage(const Tuple *receivedTransport = 0);
388
      /// @todo .dlb. public, allows pass by value to compile.
389
      SipMessage(const SipMessage& message);
390
391
      /// @todo .dlb. sure would be nice to have overloaded return value here..
392
      virtual Message* clone() const;
393
394
      SipMessage& operator=(const SipMessage& rhs);
395
      
396
      /// Returns the transaction id from the branch or if 2543, the computed hash.
397
      virtual const Data& getTransactionId() const;
398
399
      /**
400
         @brief Calculates an MD5 hash over the Request-URI, To tag (for
401
         non-INVITE transactions), From tag, Call-ID, CSeq (including
402
         the method), and top Via header.  The hash is used for
403
         transaction matching.
404
      */
405
      const Data& getRFC2543TransactionId() const;
406
      void setRFC2543TransactionId(const Data& tid);
407
      
408
      virtual ~SipMessage();
409
410
      /** @brief Construct a SipMessage object from a string containing a SIP request
411
          or response.
412
          
413
          @param buffer a buffer containing a SIP message
414
          @param isExternal true for a message generated externally, false otherwise.
415
          @return constructed SipMessage object
416
      */
417
      static SipMessage* make(const Data& buffer, bool isExternal = false);
418
      void parseAllHeaders();
419
      
420
      static bool checkContentLength;
421
422
      /**
423
      @brief Base exception for SipMessage related exceptions
424
      */
425
      class Exception final : public BaseException
426
      {
427
         public:
428
            /**
429
            @brief constructor that records an exception message, the file and the line
430
            that the exception occured in.
431
            */
432
            Exception(const Data& msg, const Data& file, const int line)
433
0
               : BaseException(msg, file, line) {}
434
            /**
435
            @brief returns the class name of the exception instance
436
            @return the class name of the instance
437
            */
438
0
            const char* name() const noexcept override { return "SipMessage::Exception"; }
439
      };
440
441
      /// Mark message as internally generated
442
      inline void setFromTU() 
443
0
      {
444
0
         mIsExternal = false;
445
0
      }
446
447
      /// Mark message as externally generated
448
      inline void setFromExternal()
449
0
      {
450
0
         mIsExternal = true;
451
0
      }
452
      
453
      /** 
454
         @brief Check if SipMessage is to be treated as it came off the wire.
455
456
         @return true if the message came from an IP interface or if it was 
457
                 an internally generated response to an internally generated 
458
                 request (ie: 408), false otherwise.
459
      */
460
      inline bool isExternal() const
461
0
      {
462
0
         return mIsExternal;
463
0
      }
464
465
      /** 
466
         @brief Check if SipMessage came off the wire.
467
      
468
         @note differs from isExternal(), since isExternal() also returns true 
469
               for internally generated responses to internally generate requests 
470
               (ie: 408, etc.).  isFromWire only ever returns true if the message
471
               actually came off the wire.
472
473
         @return true if the message came from an IP interface, false otherwise.
474
      */
475
      inline bool isFromWire() const
476
0
      {
477
0
         return mReceivedTransportTuple.getType() != UNKNOWN_TRANSPORT;
478
0
      }
479
      
480
      /// @brief Check if SipMessage is a client transaction
481
      /// @return true if the message is external and is a response or
482
      /// an internally-generated request.
483
      virtual bool isClientTransaction() const;
484
      
485
      /** @brief Generate a string from the SipMessage object
486
      
487
      @return string representation of a SIP message.
488
      */
489
      virtual EncodeStream& encode(EncodeStream& str) const;      
490
      //sipfrags will not output Content Length if there is no body--introduce
491
      //friendship to hide this?
492
      virtual EncodeStream& encodeSipFrag(EncodeStream& str) const;
493
      EncodeStream& encodeEmbedded(EncodeStream& str) const;
494
      
495
      virtual EncodeStream& encodeBrief(EncodeStream& str) const;
496
      EncodeStream& encodeSingleHeader(Headers::Type type, EncodeStream& str) const;
497
498
      /// Returns true if message is a request, false otherwise
499
0
      inline bool isRequest() const {return mRequest;}
500
      /// Returns true if message is a response, false otherwise
501
0
      inline bool isResponse() const {return mResponse;}
502
      /// Returns true if message failed to parse, false otherwise      
503
0
      inline bool isInvalid() const{return mInvalid;}
504
      
505
      /// @brief returns the method type of the message
506
      /// @see MethodTypes
507
      resip::MethodTypes method() const;
508
      /// Returns a string containing the SIP method for the message
509
      const Data& methodStr() const;
510
      
511
      /// Returns a string containing the response reason text
512
0
      const resip::Data* getReason() const{return mReason;}
513
      
514
      /// Returns the RequestLine.  This is only valid for request messages.
515
      const RequestLine& 
516
      header(const RequestLineType& l) const;
517
518
      /// Returns the RequestLine.  This is only valid for request messages.
519
      RequestLine& 
520
      header(const RequestLineType& l);
521
522
      inline const RequestLine& 
523
      const_header(const RequestLineType& l) const
524
0
      {
525
0
         return header(l);
526
0
      }
527
528
      /// Returns the StatusLine.  This is only valid for response messages.
529
      const StatusLine& 
530
      header(const StatusLineType& l) const;
531
532
      /// Returns the StatusLine.  This is only valid for response messages.
533
      StatusLine& 
534
      header(const StatusLineType& l);
535
536
      inline const StatusLine& 
537
      const_header(const StatusLineType& l) const
538
0
      {
539
0
         return header(l);
540
0
      }
541
542
      /// Returns true if the given header field is present, false otherwise
543
      bool exists(const HeaderBase& headerType) const;
544
      /// Returns true if the header field is present and non-empty, false otherwise
545
      bool empty(const HeaderBase& headerType) const;
546
      /// @brief Prevents a header field from being present when the message is prepared
547
      /// for sending to a transport.  This does not free the memory that was 
548
      /// used by the header.
549
      inline void remove(const HeaderBase& headerType)
550
0
      {
551
0
         remove(headerType.getTypeNum());
552
0
      }
553
554
      void remove(Headers::Type type);
555
556
#define defineHeader(_header, _name, _type, _rfc)                       \
557
      const H_##_header::Type& header(const H_##_header& headerType) const; \
558
            H_##_header::Type& header(const H_##_header& headerType); \
559
      inline const H_##_header::Type& const_header(const H_##_header& headerType) const \
560
9.57k
      {\
561
9.57k
         return header(headerType);\
562
9.57k
      }
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ContentDisposition const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ContentEncoding const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_MIMEVersion const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Priority const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Event const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_SubscriptionState const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_SIPETag const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_SIPIfMatch const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ContentId const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ReferSub const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_AnswerMode const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_PrivAnswerMode const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ContentType const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_IdentityInfo const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_From const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_To const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ReplyTo const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ReferTo const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ReferredBy const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_PCalledPartyId const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ContentTransferEncoding const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Organization const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_SecWebSocketKey const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_SecWebSocketKey1 const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_SecWebSocketKey2 const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Origin const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Host const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_SecWebSocketAccept const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Server const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Subject const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_UserAgent const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Timestamp const&) const
resip::SipMessage::const_header(resip::H_ContentLength const&) const
Line
Count
Source
560
9.57k
      {\
561
9.57k
         return header(headerType);\
562
9.57k
      }
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_MaxForwards const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_MinExpires const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_RSeq const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_RetryAfter const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_FlowTimer const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Expires const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_SessionExpires const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_MinSE const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_CallID const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Replaces const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_InReplyTo const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Join const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_TargetDialog const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_AuthenticationInfo const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_CSeq const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Date const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_RAck const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_PChargingVector const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_PChargingFunctionAddresses const&) const
563
564
      
565
#define defineMultiHeader(_header, _name, _type, _rfc)                  \
566
      const H_##_header##s::Type& header(const H_##_header##s& headerType) const; \
567
            H_##_header##s::Type& header(const H_##_header##s& headerType); \
568
      inline const H_##_header##s::Type& const_header(const H_##_header##s& headerType) const \
569
0
      {\
570
0
         return header(headerType);\
571
0
      }
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_AllowEventss const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Identitys const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_AcceptEncodings const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_AcceptLanguages const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Allows const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ContentLanguages const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ProxyRequires const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Requires const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Supporteds const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Unsupporteds const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_SecurityClients const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_SecurityServers const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_SecurityVerifys const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_RequestDispositions const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Reasons const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Privacys const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_PMediaAuthorizations const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Accepts const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_CallInfos const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_AlertInfos const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ErrorInfos const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_RecordRoutes const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Routes const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Contacts const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Paths const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_AcceptContacts const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_RejectContacts const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_PAssertedIdentitys const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_PPreferredIdentitys const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_PAssociatedUris const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ServiceRoutes const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_RemotePartyIds const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_HistoryInfos const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Diversions const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Cookies const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Authorizations const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ProxyAuthenticates const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_ProxyAuthorizations const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_WWWAuthenticates const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Warnings const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_Vias const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_PAccessNetworkInfos const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_PVisitedNetworkIDs const&) const
Unexecuted instantiation: resip::SipMessage::const_header(resip::H_UserToUsers const&) const
572
      
573
      defineHeader(ContentDisposition, "Content-Disposition", Token, "RFC 3261");
574
      defineHeader(ContentEncoding, "Content-Encoding", Token, "RFC 3261");
575
      defineHeader(MIMEVersion, "Mime-Version", Token, "RFC 3261");
576
      defineHeader(Priority, "Priority", Token, "RFC 3261");
577
      defineHeader(Event, "Event", Token, "RFC 3265");
578
      defineHeader(SubscriptionState, "Subscription-State", Token, "RFC 3265");
579
      defineHeader(SIPETag, "SIP-ETag", Token, "RFC 3903");
580
      defineHeader(SIPIfMatch, "SIP-If-Match", Token, "RFC 3903");
581
      defineHeader(ContentId, "Content-ID", Token, "RFC 2045");
582
      defineMultiHeader(AllowEvents, "Allow-Events", Token, "RFC 3265");
583
      defineMultiHeader(Identity, "Identity", IdentityCategory, "RFC 8224");   // Originally defined in RFC 4474 as a single header, but later modified by RFC8224 to be a multiheader
584
      defineMultiHeader(AcceptEncoding, "Accept-Encoding", Token, "RFC 3261");
585
      defineMultiHeader(AcceptLanguage, "Accept-Language", Token, "RFC 3261");
586
      defineMultiHeader(Allow, "Allow", Token, "RFC 3261");
587
      defineMultiHeader(ContentLanguage, "Content-Language", Token, "RFC 3261");
588
      defineMultiHeader(ProxyRequire, "Proxy-Require", Token, "RFC 3261");
589
      defineMultiHeader(Require, "Require", Token, "RFC 3261");
590
      defineMultiHeader(Supported, "Supported", Token, "RFC 3261");
591
      defineMultiHeader(Unsupported, "Unsupported", Token, "RFC 3261");
592
      defineMultiHeader(SecurityClient, "Security-Client", Token, "RFC 3329");
593
      defineMultiHeader(SecurityServer, "Security-Server", Token, "RFC 3329");
594
      defineMultiHeader(SecurityVerify, "Security-Verify", Token, "RFC 3329");
595
      defineMultiHeader(RequestDisposition, "Request-Disposition", Token, "RFC 3841");
596
      defineMultiHeader(Reason, "Reason", Token, "RFC 3326");
597
      defineMultiHeader(Privacy, "Privacy", PrivacyCategory, "RFC 3323");
598
      defineMultiHeader(PMediaAuthorization, "P-Media-Authorization", Token, "RFC 3313");
599
      defineHeader(ReferSub, "Refer-Sub", Token, "RFC 4488");
600
      defineHeader(AnswerMode, "Answer-Mode", Token, "draft-ietf-answermode-04");
601
      defineHeader(PrivAnswerMode, "Priv-Answer-Mode", Token, "draft-ietf-answermode-04");
602
603
      defineMultiHeader(Accept, "Accept", Mime, "RFC 3261");
604
      defineHeader(ContentType, "Content-Type", Mime, "RFC 3261");
605
606
      defineMultiHeader(CallInfo, "Call-Info", GenericUri, "RFC 3261");
607
      defineMultiHeader(AlertInfo, "Alert-Info", GenericUri, "RFC 3261");
608
      defineMultiHeader(ErrorInfo, "Error-Info", GenericUri, "RFC 3261");
609
      defineHeader(IdentityInfo, "Identity-Info", GenericUri, "RFC 4474");
610
611
      defineMultiHeader(RecordRoute, "Record-Route", NameAddr, "RFC 3261");
612
      defineMultiHeader(Route, "Route", NameAddr, "RFC 3261");
613
      defineMultiHeader(Contact, "Contact", NameAddr, "RFC 3261");
614
      defineHeader(From, "From", NameAddr, "RFC 3261");
615
      defineHeader(To, "To", NameAddr, "RFC 3261");
616
      defineHeader(ReplyTo, "Reply-To", NameAddr, "RFC 3261");
617
      defineHeader(ReferTo, "Refer-To", NameAddr, "RFC 3515");
618
      defineHeader(ReferredBy, "Referred-By", NameAddr, "RFC 3892");
619
      defineMultiHeader(Path, "Path", NameAddr, "RFC 3327");
620
      defineMultiHeader(AcceptContact, "Accept-Contact", NameAddr, "RFC 3841");
621
      defineMultiHeader(RejectContact, "Reject-Contact", NameAddr, "RFC 3841");
622
      defineMultiHeader(PAssertedIdentity, "P-Asserted-Identity", NameAddr, "RFC 3325");
623
      defineMultiHeader(PPreferredIdentity, "P-Preferred-Identity", NameAddr, "RFC 3325");
624
      defineHeader(PCalledPartyId, "P-Called-Party-ID", NameAddr, "RFC 3455");
625
      defineMultiHeader(PAssociatedUri, "P-Associated-URI", NameAddr, "RFC 3455");
626
      defineMultiHeader(ServiceRoute, "Service-Route", NameAddr, "RFC 3608");
627
      defineMultiHeader(RemotePartyId, "Remote-Party-ID", NameAddr, "draft-ietf-sip-privacy-04"); // ?bwc? Not in 3323, should we keep?
628
      defineMultiHeader(HistoryInfo, "History-Info", NameAddr, "RFC 4244");
629
      defineMultiHeader(Diversion, "Diversion", NameAddr, "RFC 5806");
630
631
      defineHeader(ContentTransferEncoding, "Content-Transfer-Encoding", StringCategory, "RFC 1521");
632
      defineHeader(Organization, "Organization", StringCategory, "RFC 3261");
633
      defineHeader(SecWebSocketKey, "Sec-WebSocket-Key", StringCategory, "RFC 6455");
634
      defineHeader(SecWebSocketKey1, "Sec-WebSocket-Key1", StringCategory, "draft-hixie- thewebsocketprotocol-76");
635
      defineHeader(SecWebSocketKey2, "Sec-WebSocket-Key2", StringCategory, "draft-hixie- thewebsocketprotocol-76");
636
      defineHeader(Origin, "Origin", StringCategory, "draft-hixie- thewebsocketprotocol-76");
637
      defineHeader(Host, "Host", StringCategory, "draft-hixie- thewebsocketprotocol-76");
638
      defineHeader(SecWebSocketAccept, "Sec-WebSocket-Accept", StringCategory, "RFC 6455");
639
      defineMultiHeader(Cookie, "Cookie", StringCategory, "RFC 6265");
640
      defineHeader(Server, "Server", StringCategory, "RFC 3261");
641
      defineHeader(Subject, "Subject", StringCategory, "RFC 3261");
642
      defineHeader(UserAgent, "User-Agent", StringCategory, "RFC 3261");
643
      defineHeader(Timestamp, "Timestamp", StringCategory, "RFC 3261");
644
645
      defineHeader(ContentLength, "Content-Length", UInt32Category, "RFC 3261");
646
      defineHeader(MaxForwards, "Max-Forwards", UInt32Category, "RFC 3261");
647
      defineHeader(MinExpires, "Min-Expires", UInt32Category, "RFC 3261");
648
      defineHeader(RSeq, "RSeq", UInt32Category, "RFC 3261");
649
650
/// @todo !dlb! this one is not quite right -- can have (comment) after field value
651
      defineHeader(RetryAfter, "Retry-After", UInt32Category, "RFC 3261");
652
      defineHeader(FlowTimer, "Flow-Timer", UInt32Category, "RFC 5626");
653
654
      defineHeader(Expires, "Expires", ExpiresCategory, "RFC 3261");
655
      defineHeader(SessionExpires, "Session-Expires", ExpiresCategory, "RFC 4028");
656
      defineHeader(MinSE, "Min-SE", ExpiresCategory, "RFC 4028");
657
658
      defineHeader(CallID, "Call-ID", CallID, "RFC 3261");
659
      defineHeader(Replaces, "Replaces", CallID, "RFC 3891");
660
      defineHeader(InReplyTo, "In-Reply-To", CallID, "RFC 3261");
661
      defineHeader(Join, "Join", CallId, "RFC 3911");
662
      defineHeader(TargetDialog, "Target-Dialog", CallId, "RFC 4538");
663
664
      defineHeader(AuthenticationInfo, "Authentication-Info", Auth, "RFC 3261");
665
      defineMultiHeader(Authorization, "Authorization", Auth, "RFC 3261");
666
      defineMultiHeader(ProxyAuthenticate, "Proxy-Authenticate", Auth, "RFC 3261");
667
      defineMultiHeader(ProxyAuthorization, "Proxy-Authorization", Auth, "RFC 3261");
668
      defineMultiHeader(WWWAuthenticate, "Www-Authenticate", Auth, "RFC 3261");
669
670
      defineHeader(CSeq, "CSeq", CSeqCategory, "RFC 3261");
671
      defineHeader(Date, "Date", DateCategory, "RFC 3261");
672
      defineMultiHeader(Warning, "Warning", WarningCategory, "RFC 3261");
673
      defineMultiHeader(Via, "Via", Via, "RFC 3261");
674
      defineHeader(RAck, "RAck", RAckCategory, "RFC 3262");
675
676
      defineMultiHeader(PAccessNetworkInfo, "P-Access-Network-Info", Token, "RFC 7315"); // section 5.4.
677
      defineHeader(PChargingVector, "P-Charging-Vector", Token, "RFC 3455");
678
      defineHeader(PChargingFunctionAddresses, "P-Charging-Function-Addresses", Token, "RFC 3455");
679
      defineMultiHeader(PVisitedNetworkID, "P-Visited-Network-ID", TokenOrQuotedStringCategory, "RFC 3455");
680
681
      defineMultiHeader(UserToUser, "User-to-User", TokenOrQuotedStringCategory, "draft-ietf-cuss-sip-uui-17");
682
683
      /// unknown header interface
684
      const StringCategories& header(const ExtensionHeader& symbol) const;
685
      StringCategories& header(const ExtensionHeader& symbol);
686
      bool exists(const ExtensionHeader& symbol) const;
687
      void remove(const ExtensionHeader& symbol);
688
689
      /// typeless header interface
690
      const HeaderFieldValueList* getRawHeader(Headers::Type headerType) const;
691
      void setRawHeader(const HeaderFieldValueList* hfvs, Headers::Type headerType);
692
0
      const KnownHeaders& getRawHeaders() const noexcept { return mKnownHeaders; }
693
0
      const UnknownHeaders& getRawUnknownHeaders() const noexcept { return mUnknownHeaders; }
694
      /**
695
         Return the raw body string (if it exists). The returned HFV
696
         and its underlying memory is owned by the SipMessage, and may
697
         be released when this SipMessage is manipulated.
698
699
         This is a low-level interface; see getContents() for higher level.
700
      **/
701
0
      const HeaderFieldValue& getRawBody() const noexcept { return mContentsHfv; }
702
703
      /**
704
         Remove any existing body/contents, and (if non-empty)
705
         set the body to {body}. It makes full copy of the body
706
         to stored within the SipMessage (since lifetime of
707
         the message is unpredictable).
708
709
         This is a low-level interface; see setContents() for higher level.
710
      **/
711
      void setRawBody(const HeaderFieldValue& body);
712
713
      /** @brief Retrieves the body of a SIP message.
714
        * 
715
        *   In the case of an INVITE request containing SDP, the body would 
716
        *   be an SdpContents.  For a MESSAGE request, the body may be PlainContents,
717
        *   CpimContents, or another subclass of Contents.
718
        * 
719
        * @return pointer to the contents of the SIP message
720
        **/
721
      Contents* getContents() const;
722
      /// Removes the contents from the message
723
      std::unique_ptr<Contents> releaseContents();
724
725
      /// @brief Set the contents of the message
726
      /// @param contents to store in the message
727
      void setContents(const Contents* contents);
728
      /// @brief Set the contents of the message
729
      /// @param contents to store in the message
730
      void setContents(std::unique_ptr<Contents> contents);
731
732
      /// @internal transport interface
733
      void setStartLine(const char* start, int len); 
734
735
      void setBody(const char* start, uint32_t len); 
736
      
737
      /// Add HeaderFieldValue given enum, header name, pointer start, content length
738
      void addHeader(Headers::Type header,
739
                     const char* headerName, int headerLen, 
740
                     const char* start, int len);
741
742
      // Returns the source tuple for the transport that the message was received from
743
      // only makes sense for messages received from the wire.  Differs from Source
744
      // since it contains the transport bind address instead of the actual source 
745
      // address.
746
0
      const Tuple& getReceivedTransportTuple() const { return mReceivedTransportTuple; }
747
748
      /// Set Tuple for transport from whence this message came
749
0
      void setReceivedTransportTuple(const Tuple& transportTuple) { mReceivedTransportTuple = transportTuple;}
750
751
      // Returns the source tuple that the message was received from
752
      // only makes sense for messages received from the wire
753
0
      void setSource(const Tuple& tuple) { mSource = tuple; }
754
      /// @brief Returns the source tuple that the message was received from
755
      /// only makes sense for messages received from the wire
756
0
      const Tuple& getSource() const { return mSource; }
757
      
758
      /// Used by the stateless interface to specify where to send a request/response
759
0
      void setDestination(const Tuple& tuple) { mDestination = tuple; }
760
0
      Tuple& getDestination() { return mDestination; }
761
762
      void addBuffer(char* buf);
763
764
0
      uint64_t getCreatedTimeMicroSec() const {return mCreatedTime;}
765
766
      /// deal with a notion of an "out-of-band" forced target for SIP routing
767
      void setForceTarget(const Uri& uri);
768
      void clearForceTarget();
769
      const Uri& getForceTarget() const;
770
      bool hasForceTarget() const;
771
772
0
      const Data& getTlsDomain() const { return mTlsDomain; }
773
0
      void setTlsDomain(const Data& domain) { mTlsDomain = domain; }
774
775
0
      const std::list<Data>& getTlsPeerNames() const { return mTlsPeerNames; }
776
0
      void setTlsPeerNames(const std::list<Data>& tlsPeerNames) { mTlsPeerNames = tlsPeerNames; }
777
778
0
      const CookieList& getWsCookies() const { return mWsCookies; }
779
0
      void setWsCookies(const CookieList& wsCookies) { mWsCookies = wsCookies; }
780
781
0
      std::shared_ptr<WsCookieContext> getWsCookieContext() const noexcept { return mWsCookieContext; }
782
0
      void setWsCookieContext(std::shared_ptr<WsCookieContext> wsCookieContext) noexcept { mWsCookieContext = wsCookieContext; }
783
784
      Data getCanonicalIdentityString() const;
785
      
786
      SipMessage& mergeUri(const Uri& source);      
787
788
      void setSecurityAttributes(std::unique_ptr<SecurityAttributes>) noexcept;
789
0
      const SecurityAttributes* getSecurityAttributes() const noexcept { return mSecurityAttributes.get(); }
790
791
      /// @brief Call a MessageDecorator to process the message before it is
792
      /// sent to the transport
793
0
      void addOutboundDecorator(std::unique_ptr<MessageDecorator> md){mOutboundDecorators.push_back(md.release());}
794
      void clearOutboundDecorators();
795
      void callOutboundDecorators(const Tuple &src, 
796
                                    const Tuple &dest,
797
                                    const Data& sigcompId);
798
      void rollbackOutboundDecorators();
799
      void copyOutboundDecoratorsToStackCancel(SipMessage& cancel);
800
      void copyOutboundDecoratorsToStackFailureAck(SipMessage& ack);
801
      bool mIsDecorated;
802
803
      bool mIsBadAck200;
804
805
   protected:
806
      // !bwc! Removes or zeros all pointers to heap-allocated memory this
807
      // class owns.
808
      void clear(bool leaveResponseStuff=false);
809
      // !bwc! Frees all heap-allocated memory owned.
810
      void freeMem(bool leaveResponseStuff=false);
811
      // Clears mHeaders and cleans up memory
812
      void clearHeaders();
813
      
814
      // !bwc! Initializes members. Will not free heap-allocated memory.
815
      // Will begin by calling clear().
816
      void init(const SipMessage& rhs);
817
   
818
   private:
819
      void compute2543TransactionHash() const;
820
821
      EncodeStream& 
822
      encode(EncodeStream& str, bool isSipFrag) const;      
823
824
      void copyFrom(const SipMessage& message);
825
826
      HeaderFieldValueList* ensureHeaders(Headers::Type type);
827
      HeaderFieldValueList* ensureHeaders(Headers::Type type) const; // throws if not present
828
829
      HeaderFieldValueList* ensureHeader(Headers::Type type);
830
      HeaderFieldValueList* ensureHeader(Headers::Type type) const; // throws if not present
831
832
      void throwHeaderMissing(Headers::Type type) const;
833
834
      inline HeaderFieldValueList* getEmptyHfvl()
835
10.8k
      {
836
10.8k
         void* ptr(mPool.allocate(sizeof(HeaderFieldValueList)));
837
10.8k
         return new (ptr) HeaderFieldValueList(mPool);
838
10.8k
      }
839
840
      inline HeaderFieldValueList* getCopyHfvl(const HeaderFieldValueList& hfvl)
841
0
      {
842
0
         void* ptr(mPool.allocate(sizeof(HeaderFieldValueList)));
843
0
         return new (ptr) HeaderFieldValueList(hfvl, mPool);
844
0
      }
845
846
      inline void freeHfvl(HeaderFieldValueList* hfvl)
847
10.8k
      {
848
10.8k
         if(hfvl)
849
10.8k
         {
850
10.8k
            hfvl->~HeaderFieldValueList();
851
10.8k
            mPool.deallocate(hfvl);
852
10.8k
         }
853
10.8k
      }
854
855
      template<class T>
856
      ParserContainer<T>* makeParserContainer()
857
      {
858
         void* ptr(mPool.allocate(sizeof(ParserContainer<T>)));
859
         return new (ptr) ParserContainer<T>(mPool);
860
      }
861
862
      template<class T>
863
      ParserContainer<T>* makeParserContainer(HeaderFieldValueList* hfvs,
864
                                             Headers::Type type = Headers::UNKNOWN)
865
290
      {
866
290
         void* ptr(mPool.allocate(sizeof(ParserContainer<T>)));
867
290
         return new (ptr) ParserContainer<T>(hfvs, type, mPool);
868
290
      }
Unexecuted instantiation: resip::ParserContainer<resip::StringCategory>* resip::SipMessage::makeParserContainer<resip::StringCategory>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::Token>* resip::SipMessage::makeParserContainer<resip::Token>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::IdentityCategory>* resip::SipMessage::makeParserContainer<resip::IdentityCategory>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::PrivacyCategory>* resip::SipMessage::makeParserContainer<resip::PrivacyCategory>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::Mime>* resip::SipMessage::makeParserContainer<resip::Mime>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::GenericUri>* resip::SipMessage::makeParserContainer<resip::GenericUri>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::NameAddr>* resip::SipMessage::makeParserContainer<resip::NameAddr>(resip::HeaderFieldValueList*, resip::Headers::Type)
resip::ParserContainer<resip::UInt32Category>* resip::SipMessage::makeParserContainer<resip::UInt32Category>(resip::HeaderFieldValueList*, resip::Headers::Type)
Line
Count
Source
865
290
      {
866
290
         void* ptr(mPool.allocate(sizeof(ParserContainer<T>)));
867
290
         return new (ptr) ParserContainer<T>(hfvs, type, mPool);
868
290
      }
Unexecuted instantiation: resip::ParserContainer<resip::ExpiresCategory>* resip::SipMessage::makeParserContainer<resip::ExpiresCategory>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::CallID>* resip::SipMessage::makeParserContainer<resip::CallID>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::Auth>* resip::SipMessage::makeParserContainer<resip::Auth>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::CSeqCategory>* resip::SipMessage::makeParserContainer<resip::CSeqCategory>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::DateCategory>* resip::SipMessage::makeParserContainer<resip::DateCategory>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::WarningCategory>* resip::SipMessage::makeParserContainer<resip::WarningCategory>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::Via>* resip::SipMessage::makeParserContainer<resip::Via>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::RAckCategory>* resip::SipMessage::makeParserContainer<resip::RAckCategory>(resip::HeaderFieldValueList*, resip::Headers::Type)
Unexecuted instantiation: resip::ParserContainer<resip::TokenOrQuotedStringCategory>* resip::SipMessage::makeParserContainer<resip::TokenOrQuotedStringCategory>(resip::HeaderFieldValueList*, resip::Headers::Type)
869
870
      // indicates this message came from the wire or we want it to look like it 
871
      // came from the wire (ie. internally generated responses to an internally 
872
      // generated request), set by the Transport and setFromTu and setFromExternal APIs
873
      bool mIsExternal;
874
875
      // Sizing so that average SipMessages don't need to allocate heap memory
876
      // To profile current sizing, enable DINKYPOOL_PROFILING in SipMessage.cxx 
877
      // and look for DebugLog message in SipMessage destructor to know when heap
878
      // allocations are occuring and how much of the pool is used.
879
      DinkyPool<3732> mPool;
880
881
      // raw text corresponding to each typed header (not yet parsed)
882
      KnownHeaders mKnownHeaders;
883
      
884
      // raw text corresponding to each unknown header
885
      UnknownHeaders mUnknownHeaders;
886
887
      // For messages received from the wire, this indicates information about 
888
      // the transport the message was received on
889
      Tuple mReceivedTransportTuple;
890
891
      // For messages received from the wire, this indicates where it came
892
      // from. Can be used to get to the Transport and/or reliable Connection
893
      Tuple mSource;
894
895
      // Used by the TU to specify where a message is to go
896
      Tuple mDestination;
897
      
898
      // Raw buffers coming from the Transport. message manages the memory
899
      std::vector<char*> mBufferList;
900
901
      // special case for the first line of message
902
      StartLine* mStartLine;
903
      char mStartLineMem[sizeof(RequestLine) > sizeof(StatusLine) ? sizeof(RequestLine) : sizeof(StatusLine)];
904
905
      // raw text for the contents (all of them)
906
      HeaderFieldValue mContentsHfv;
907
908
      // lazy parser for the contents
909
      mutable Contents* mContents;
910
911
      // cached value of a hash of the transaction id for a message received
912
      // from a 2543 sip element. as per rfc3261 see 17.2.3
913
      mutable Data mRFC2543TransactionId;
914
915
      // is a request or response
916
      bool mRequest;
917
      bool mResponse;
918
919
      bool mInvalid;
920
      resip::Data* mReason;
921
      
922
      uint64_t mCreatedTime;
923
924
      // used when next element is a strict router OR 
925
      // client forces next hop OOB
926
      Uri* mForceTarget;
927
928
      // domain associated with this message for tls cert
929
      Data mTlsDomain;
930
931
      // peers domain associate with this message (MTLS)
932
      std::list<Data> mTlsPeerNames;
933
934
      // cookies associated with this message from the WebSocket Upgrade request
935
      CookieList mWsCookies;
936
937
      // parsed cookie authentication elements associated with this message from the WebSocket Upgrade request
938
      std::shared_ptr<WsCookieContext> mWsCookieContext;
939
940
      std::unique_ptr<SecurityAttributes> mSecurityAttributes;
941
942
      std::vector<MessageDecorator*> mOutboundDecorators;
943
944
      friend class TransportSelector;
945
};
946
947
}
948
949
#undef ensureHeaderTypeUseable
950
#undef ensureSingleHeader
951
#undef ensureMultiHeader
952
#undef defineHeader
953
#undef defineMultiHeader
954
955
#endif
956
957
/* ====================================================================
958
 * The Vovida Software License, Version 1.0 
959
 * 
960
 * Copyright (c) 2026 SIP Spectrum, Inc. https://www.sipspectrum.com
961
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
962
 * 
963
 * Redistribution and use in source and binary forms, with or without
964
 * modification, are permitted provided that the following conditions
965
 * are met:
966
 * 
967
 * 1. Redistributions of source code must retain the above copyright
968
 *    notice, this list of conditions and the following disclaimer.
969
 * 
970
 * 2. Redistributions in binary form must reproduce the above copyright
971
 *    notice, this list of conditions and the following disclaimer in
972
 *    the documentation and/or other materials provided with the
973
 *    distribution.
974
 * 
975
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
976
 *    and "Vovida Open Communication Application Library (VOCAL)" must
977
 *    not be used to endorse or promote products derived from this
978
 *    software without prior written permission. For written
979
 *    permission, please contact vocal@vovida.org.
980
 *
981
 * 4. Products derived from this software may not be called "VOCAL", nor
982
 *    may "VOCAL" appear in their name, without prior written
983
 *    permission of Vovida Networks, Inc.
984
 * 
985
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
986
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
987
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
988
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
989
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
990
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
991
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
992
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
993
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
994
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
995
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
996
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
997
 * DAMAGE.
998
 * 
999
 * ====================================================================
1000
 * 
1001
 * This software consists of voluntary contributions made by Vovida
1002
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1003
 * Inc.  For more information on Vovida Networks, Inc., please see
1004
 * <http://www.vovida.org/>.
1005
 *
1006
 * vi: set shiftwidth=3 expandtab:
1007
 */