Coverage Report

Created: 2026-02-13 06:31

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.25k
                  explicit constexpr HeaderInfo(Headers::Type type, HeaderFieldValueList* values = nullptr) noexcept : mValues(values), mType(type) {}
204
205
                  /// Returns header type
206
682k
                  Headers::Type getType() const noexcept { return mType; }
207
208
                  /// Returns header values
209
679k
                  HeaderFieldValueList* getValues() const noexcept { return mValues; }
210
                  /// Sets header values
211
1.25k
                  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
715k
                     mIterator(std::forward<OtherAdoptedIterator1>(iter)),
257
715k
                     mEnd(std::forward<OtherAdoptedIterator2>(end))
258
715k
                  {
259
715k
                  }
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
674k
                     mIterator(std::forward<OtherAdoptedIterator1>(iter)),
257
674k
                     mEnd(std::forward<OtherAdoptedIterator2>(end))
258
674k
                  {
259
674k
                  }
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
16.5k
                     mIterator(std::forward<OtherAdoptedIterator1>(iter)),
257
16.5k
                     mEnd(std::forward<OtherAdoptedIterator2>(end))
258
16.5k
                  {
259
16.5k
                  }
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
24.1k
                     mIterator(std::forward<OtherAdoptedIterator1>(iter)),
257
24.1k
                     mEnd(std::forward<OtherAdoptedIterator2>(end))
258
24.1k
                  {
259
24.1k
                  }
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
24.1k
                     mIterator(that.mIterator),
271
24.1k
                     mEnd(that.mEnd)
272
24.1k
                  {
273
24.1k
                  }
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
678k
                  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
666k
                  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
11.0k
                  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
24.1k
                  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
24.1k
                  friend bool operator==(UsedIterator const& left, UsedIterator const& right) noexcept { return left.mIterator == right.mIterator; }
281
13.1k
                  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
13.1k
                  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.32k
               mHeaders(alloc),
324
9.32k
               mSize(0)
325
9.32k
            {
326
9.32k
               resetIndices();
327
9.32k
            }
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
24.1k
            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
7.64k
            iterator end() noexcept { return iterator(mHeaders.end(), mHeaders.end()); }
357
358
            /// Reserves internal storage for the given number of entries
359
9.32k
            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
24.1k
            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
11.0k
      {\
561
11.0k
         return header(headerType);\
562
11.0k
      }
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
11.0k
      {\
561
11.0k
         return header(headerType);\
562
11.0k
      }
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_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", StringCategory, "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
630
      defineHeader(ContentTransferEncoding, "Content-Transfer-Encoding", StringCategory, "RFC 1521");
631
      defineHeader(Organization, "Organization", StringCategory, "RFC 3261");
632
      defineHeader(SecWebSocketKey, "Sec-WebSocket-Key", StringCategory, "RFC 6455");
633
      defineHeader(SecWebSocketKey1, "Sec-WebSocket-Key1", StringCategory, "draft-hixie- thewebsocketprotocol-76");
634
      defineHeader(SecWebSocketKey2, "Sec-WebSocket-Key2", StringCategory, "draft-hixie- thewebsocketprotocol-76");
635
      defineHeader(Origin, "Origin", StringCategory, "draft-hixie- thewebsocketprotocol-76");
636
      defineHeader(Host, "Host", StringCategory, "draft-hixie- thewebsocketprotocol-76");
637
      defineHeader(SecWebSocketAccept, "Sec-WebSocket-Accept", StringCategory, "RFC 6455");
638
      defineMultiHeader(Cookie, "Cookie", StringCategory, "RFC 6265");
639
      defineHeader(Server, "Server", StringCategory, "RFC 3261");
640
      defineHeader(Subject, "Subject", StringCategory, "RFC 3261");
641
      defineHeader(UserAgent, "User-Agent", StringCategory, "RFC 3261");
642
      defineHeader(Timestamp, "Timestamp", StringCategory, "RFC 3261");
643
644
      defineHeader(ContentLength, "Content-Length", UInt32Category, "RFC 3261");
645
      defineHeader(MaxForwards, "Max-Forwards", UInt32Category, "RFC 3261");
646
      defineHeader(MinExpires, "Min-Expires", UInt32Category, "RFC 3261");
647
      defineHeader(RSeq, "RSeq", UInt32Category, "RFC 3261");
648
649
/// @todo !dlb! this one is not quite right -- can have (comment) after field value
650
      defineHeader(RetryAfter, "Retry-After", UInt32Category, "RFC 3261");
651
      defineHeader(FlowTimer, "Flow-Timer", UInt32Category, "RFC 5626");
652
653
      defineHeader(Expires, "Expires", ExpiresCategory, "RFC 3261");
654
      defineHeader(SessionExpires, "Session-Expires", ExpiresCategory, "RFC 4028");
655
      defineHeader(MinSE, "Min-SE", ExpiresCategory, "RFC 4028");
656
657
      defineHeader(CallID, "Call-ID", CallID, "RFC 3261");
658
      defineHeader(Replaces, "Replaces", CallID, "RFC 3891");
659
      defineHeader(InReplyTo, "In-Reply-To", CallID, "RFC 3261");
660
      defineHeader(Join, "Join", CallId, "RFC 3911");
661
      defineHeader(TargetDialog, "Target-Dialog", CallId, "RFC 4538");
662
663
      defineHeader(AuthenticationInfo, "Authentication-Info", Auth, "RFC 3261");
664
      defineMultiHeader(Authorization, "Authorization", Auth, "RFC 3261");
665
      defineMultiHeader(ProxyAuthenticate, "Proxy-Authenticate", Auth, "RFC 3261");
666
      defineMultiHeader(ProxyAuthorization, "Proxy-Authorization", Auth, "RFC 3261");
667
      defineMultiHeader(WWWAuthenticate, "Www-Authenticate", Auth, "RFC 3261");
668
669
      defineHeader(CSeq, "CSeq", CSeqCategory, "RFC 3261");
670
      defineHeader(Date, "Date", DateCategory, "RFC 3261");
671
      defineMultiHeader(Warning, "Warning", WarningCategory, "RFC 3261");
672
      defineMultiHeader(Via, "Via", Via, "RFC 3261");
673
      defineHeader(RAck, "RAck", RAckCategory, "RFC 3262");
674
675
      defineMultiHeader(PAccessNetworkInfo, "P-Access-Network-Info", Token, "RFC 7315"); // section 5.4.
676
      defineHeader(PChargingVector, "P-Charging-Vector", Token, "RFC 3455");
677
      defineHeader(PChargingFunctionAddresses, "P-Charging-Function-Addresses", Token, "RFC 3455");
678
      defineMultiHeader(PVisitedNetworkID, "P-Visited-Network-ID", TokenOrQuotedStringCategory, "RFC 3455");
679
680
      defineMultiHeader(UserToUser, "User-to-User", TokenOrQuotedStringCategory, "draft-ietf-cuss-sip-uui-17");
681
682
      /// unknown header interface
683
      const StringCategories& header(const ExtensionHeader& symbol) const;
684
      StringCategories& header(const ExtensionHeader& symbol);
685
      bool exists(const ExtensionHeader& symbol) const;
686
      void remove(const ExtensionHeader& symbol);
687
688
      /// typeless header interface
689
      const HeaderFieldValueList* getRawHeader(Headers::Type headerType) const;
690
      void setRawHeader(const HeaderFieldValueList* hfvs, Headers::Type headerType);
691
0
      const KnownHeaders& getRawHeaders() const noexcept { return mKnownHeaders; }
692
0
      const UnknownHeaders& getRawUnknownHeaders() const noexcept { return mUnknownHeaders; }
693
      /**
694
         Return the raw body string (if it exists). The returned HFV
695
         and its underlying memory is owned by the SipMessage, and may
696
         be released when this SipMessage is manipulated.
697
698
         This is a low-level interface; see getContents() for higher level.
699
      **/
700
0
      const HeaderFieldValue& getRawBody() const noexcept { return mContentsHfv; }
701
702
      /**
703
         Remove any existing body/contents, and (if non-empty)
704
         set the body to {body}. It makes full copy of the body
705
         to stored within the SipMessage (since lifetime of
706
         the message is unpredictable).
707
708
         This is a low-level interface; see setContents() for higher level.
709
      **/
710
      void setRawBody(const HeaderFieldValue& body);
711
712
      /** @brief Retrieves the body of a SIP message.
713
        * 
714
        *   In the case of an INVITE request containing SDP, the body would 
715
        *   be an SdpContents.  For a MESSAGE request, the body may be PlainContents,
716
        *   CpimContents, or another subclass of Contents.
717
        * 
718
        * @return pointer to the contents of the SIP message
719
        **/
720
      Contents* getContents() const;
721
      /// Removes the contents from the message
722
      std::unique_ptr<Contents> releaseContents();
723
724
      /// @brief Set the contents of the message
725
      /// @param contents to store in the message
726
      void setContents(const Contents* contents);
727
      /// @brief Set the contents of the message
728
      /// @param contents to store in the message
729
      void setContents(std::unique_ptr<Contents> contents);
730
731
      /// @internal transport interface
732
      void setStartLine(const char* start, int len); 
733
734
      void setBody(const char* start, uint32_t len); 
735
      
736
      /// Add HeaderFieldValue given enum, header name, pointer start, content length
737
      void addHeader(Headers::Type header,
738
                     const char* headerName, int headerLen, 
739
                     const char* start, int len);
740
741
      // Returns the source tuple for the transport that the message was received from
742
      // only makes sense for messages received from the wire.  Differs from Source
743
      // since it contains the transport bind address instead of the actual source 
744
      // address.
745
0
      const Tuple& getReceivedTransportTuple() const { return mReceivedTransportTuple; }
746
747
      /// Set Tuple for transport from whence this message came
748
0
      void setReceivedTransportTuple(const Tuple& transportTuple) { mReceivedTransportTuple = transportTuple;}
749
750
      // Returns the source tuple that the message was received from
751
      // only makes sense for messages received from the wire
752
0
      void setSource(const Tuple& tuple) { mSource = tuple; }
753
      /// @brief Returns the source tuple that the message was received from
754
      /// only makes sense for messages received from the wire
755
0
      const Tuple& getSource() const { return mSource; }
756
      
757
      /// Used by the stateless interface to specify where to send a request/response
758
0
      void setDestination(const Tuple& tuple) { mDestination = tuple; }
759
0
      Tuple& getDestination() { return mDestination; }
760
761
      void addBuffer(char* buf);
762
763
0
      uint64_t getCreatedTimeMicroSec() const {return mCreatedTime;}
764
765
      /// deal with a notion of an "out-of-band" forced target for SIP routing
766
      void setForceTarget(const Uri& uri);
767
      void clearForceTarget();
768
      const Uri& getForceTarget() const;
769
      bool hasForceTarget() const;
770
771
0
      const Data& getTlsDomain() const { return mTlsDomain; }
772
0
      void setTlsDomain(const Data& domain) { mTlsDomain = domain; }
773
774
0
      const std::list<Data>& getTlsPeerNames() const { return mTlsPeerNames; }
775
0
      void setTlsPeerNames(const std::list<Data>& tlsPeerNames) { mTlsPeerNames = tlsPeerNames; }
776
777
0
      const CookieList& getWsCookies() const { return mWsCookies; }
778
0
      void setWsCookies(const CookieList& wsCookies) { mWsCookies = wsCookies; }
779
780
0
      std::shared_ptr<WsCookieContext> getWsCookieContext() const noexcept { return mWsCookieContext; }
781
0
      void setWsCookieContext(std::shared_ptr<WsCookieContext> wsCookieContext) noexcept { mWsCookieContext = wsCookieContext; }
782
783
      Data getCanonicalIdentityString() const;
784
      
785
      SipMessage& mergeUri(const Uri& source);      
786
787
      void setSecurityAttributes(std::unique_ptr<SecurityAttributes>) noexcept;
788
0
      const SecurityAttributes* getSecurityAttributes() const noexcept { return mSecurityAttributes.get(); }
789
790
      /// @brief Call a MessageDecorator to process the message before it is
791
      /// sent to the transport
792
0
      void addOutboundDecorator(std::unique_ptr<MessageDecorator> md){mOutboundDecorators.push_back(md.release());}
793
      void clearOutboundDecorators();
794
      void callOutboundDecorators(const Tuple &src, 
795
                                    const Tuple &dest,
796
                                    const Data& sigcompId);
797
      void rollbackOutboundDecorators();
798
      void copyOutboundDecoratorsToStackCancel(SipMessage& cancel);
799
      void copyOutboundDecoratorsToStackFailureAck(SipMessage& ack);
800
      bool mIsDecorated;
801
802
      bool mIsBadAck200;
803
804
   protected:
805
      // !bwc! Removes or zeros all pointers to heap-allocated memory this
806
      // class owns.
807
      void clear(bool leaveResponseStuff=false);
808
      // !bwc! Frees all heap-allocated memory owned.
809
      void freeMem(bool leaveResponseStuff=false);
810
      // Clears mHeaders and cleans up memory
811
      void clearHeaders();
812
      
813
      // !bwc! Initializes members. Will not free heap-allocated memory.
814
      // Will begin by calling clear().
815
      void init(const SipMessage& rhs);
816
   
817
   private:
818
      void compute2543TransactionHash() const;
819
820
      EncodeStream& 
821
      encode(EncodeStream& str, bool isSipFrag) const;      
822
823
      void copyFrom(const SipMessage& message);
824
825
      HeaderFieldValueList* ensureHeaders(Headers::Type type);
826
      HeaderFieldValueList* ensureHeaders(Headers::Type type) const; // throws if not present
827
828
      HeaderFieldValueList* ensureHeader(Headers::Type type);
829
      HeaderFieldValueList* ensureHeader(Headers::Type type) const; // throws if not present
830
831
      void throwHeaderMissing(Headers::Type type) const;
832
833
      inline HeaderFieldValueList* getEmptyHfvl()
834
12.6k
      {
835
12.6k
         void* ptr(mPool.allocate(sizeof(HeaderFieldValueList)));
836
12.6k
         return new (ptr) HeaderFieldValueList(mPool);
837
12.6k
      }
838
839
      inline HeaderFieldValueList* getCopyHfvl(const HeaderFieldValueList& hfvl)
840
0
      {
841
0
         void* ptr(mPool.allocate(sizeof(HeaderFieldValueList)));
842
0
         return new (ptr) HeaderFieldValueList(hfvl, mPool);
843
0
      }
844
845
      inline void freeHfvl(HeaderFieldValueList* hfvl)
846
12.6k
      {
847
12.6k
         if(hfvl)
848
12.6k
         {
849
12.6k
            hfvl->~HeaderFieldValueList();
850
12.6k
            mPool.deallocate(hfvl);
851
12.6k
         }
852
12.6k
      }
853
854
      template<class T>
855
      ParserContainer<T>* makeParserContainer()
856
      {
857
         void* ptr(mPool.allocate(sizeof(ParserContainer<T>)));
858
         return new (ptr) ParserContainer<T>(mPool);
859
      }
860
861
      template<class T>
862
      ParserContainer<T>* makeParserContainer(HeaderFieldValueList* hfvs,
863
                                             Headers::Type type = Headers::UNKNOWN)
864
276
      {
865
276
         void* ptr(mPool.allocate(sizeof(ParserContainer<T>)));
866
276
         return new (ptr) ParserContainer<T>(hfvs, type, mPool);
867
276
      }
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::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
864
276
      {
865
276
         void* ptr(mPool.allocate(sizeof(ParserContainer<T>)));
866
276
         return new (ptr) ParserContainer<T>(hfvs, type, mPool);
867
276
      }
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)
868
869
      // indicates this message came from the wire or we want it to look like it 
870
      // came from the wire (ie. internally generated responses to an internally 
871
      // generated request), set by the Transport and setFromTu and setFromExternal APIs
872
      bool mIsExternal;
873
874
      // Sizing so that average SipMessages don't need to allocate heap memory
875
      // To profile current sizing, enable DINKYPOOL_PROFILING in SipMessage.cxx 
876
      // and look for DebugLog message in SipMessage destructor to know when heap
877
      // allocations are occuring and how much of the pool is used.
878
      DinkyPool<3732> mPool;
879
880
      // raw text corresponding to each typed header (not yet parsed)
881
      KnownHeaders mKnownHeaders;
882
      
883
      // raw text corresponding to each unknown header
884
      UnknownHeaders mUnknownHeaders;
885
886
      // For messages received from the wire, this indicates information about 
887
      // the transport the message was received on
888
      Tuple mReceivedTransportTuple;
889
890
      // For messages received from the wire, this indicates where it came
891
      // from. Can be used to get to the Transport and/or reliable Connection
892
      Tuple mSource;
893
894
      // Used by the TU to specify where a message is to go
895
      Tuple mDestination;
896
      
897
      // Raw buffers coming from the Transport. message manages the memory
898
      std::vector<char*> mBufferList;
899
900
      // special case for the first line of message
901
      StartLine* mStartLine;
902
      char mStartLineMem[sizeof(RequestLine) > sizeof(StatusLine) ? sizeof(RequestLine) : sizeof(StatusLine)];
903
904
      // raw text for the contents (all of them)
905
      HeaderFieldValue mContentsHfv;
906
907
      // lazy parser for the contents
908
      mutable Contents* mContents;
909
910
      // cached value of a hash of the transaction id for a message received
911
      // from a 2543 sip element. as per rfc3261 see 17.2.3
912
      mutable Data mRFC2543TransactionId;
913
914
      // is a request or response
915
      bool mRequest;
916
      bool mResponse;
917
918
      bool mInvalid;
919
      resip::Data* mReason;
920
      
921
      uint64_t mCreatedTime;
922
923
      // used when next element is a strict router OR 
924
      // client forces next hop OOB
925
      Uri* mForceTarget;
926
927
      // domain associated with this message for tls cert
928
      Data mTlsDomain;
929
930
      // peers domain associate with this message (MTLS)
931
      std::list<Data> mTlsPeerNames;
932
933
      // cookies associated with this message from the WebSocket Upgrade request
934
      CookieList mWsCookies;
935
936
      // parsed cookie authentication elements associated with this message from the WebSocket Upgrade request
937
      std::shared_ptr<WsCookieContext> mWsCookieContext;
938
939
      std::unique_ptr<SecurityAttributes> mSecurityAttributes;
940
941
      std::vector<MessageDecorator*> mOutboundDecorators;
942
943
      friend class TransportSelector;
944
};
945
946
}
947
948
#undef ensureHeaderTypeUseable
949
#undef ensureSingleHeader
950
#undef ensureMultiHeader
951
#undef defineHeader
952
#undef defineMultiHeader
953
954
#endif
955
956
/* ====================================================================
957
 * The Vovida Software License, Version 1.0 
958
 * 
959
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
960
 * 
961
 * Redistribution and use in source and binary forms, with or without
962
 * modification, are permitted provided that the following conditions
963
 * are met:
964
 * 
965
 * 1. Redistributions of source code must retain the above copyright
966
 *    notice, this list of conditions and the following disclaimer.
967
 * 
968
 * 2. Redistributions in binary form must reproduce the above copyright
969
 *    notice, this list of conditions and the following disclaimer in
970
 *    the documentation and/or other materials provided with the
971
 *    distribution.
972
 * 
973
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
974
 *    and "Vovida Open Communication Application Library (VOCAL)" must
975
 *    not be used to endorse or promote products derived from this
976
 *    software without prior written permission. For written
977
 *    permission, please contact vocal@vovida.org.
978
 *
979
 * 4. Products derived from this software may not be called "VOCAL", nor
980
 *    may "VOCAL" appear in their name, without prior written
981
 *    permission of Vovida Networks, Inc.
982
 * 
983
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
984
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
985
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
986
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
987
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
988
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
989
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
990
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
991
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
992
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
993
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
994
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
995
 * DAMAGE.
996
 * 
997
 * ====================================================================
998
 * 
999
 * This software consists of voluntary contributions made by Vovida
1000
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1001
 * Inc.  For more information on Vovida Networks, Inc., please see
1002
 * <http://www.vovida.org/>.
1003
 *
1004
 * vi: set shiftwidth=3 expandtab:
1005
 */