Coverage Report

Created: 2026-01-10 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/resiprocate/resip/stack/ParserCategory.hxx
Line
Count
Source
1
#if !defined(RESIP_PARSERCATEGORY_HXX)
2
#define RESIP_PARSERCATEGORY_HXX 
3
4
#include <iosfwd>
5
#include <vector>
6
#include <set>
7
#include "resip/stack/HeaderTypes.hxx"
8
#include "resip/stack/LazyParser.hxx"
9
#include "resip/stack/ParameterTypes.hxx"
10
#include "rutil/Data.hxx"
11
#include "rutil/BaseException.hxx"
12
#include "rutil/StlPoolAllocator.hxx"
13
#include "rutil/PoolBase.hxx"
14
15
#include "rutil/resipfaststreams.hxx"
16
17
#define defineParam(_enum, _name, _type, _RFC_ref_ignored)                      \
18
      const _enum##_Param::DType& param(const _enum##_Param& paramType) const;  \
19
      _enum##_Param::DType& param(const _enum##_Param& paramType)
20
21
namespace resip
22
{
23
class UnknownParameter;
24
class ExtensionParameter;
25
class Parameter;
26
class ParseBuffer;
27
28
/**
29
   @brief Base class for all SIP grammar elements that can have parameters.
30
31
   The pattern for accessing the parameters in a ParserCategory is very similar
32
   to accessing headers in a SipMessage. Each parameter type has an access token
33
   class (a subclass of ParamBase), and a corresponding ParserCategory::param() 
34
   function that takes an instance of that subclass as an argument, and returns
35
   the correct type for that parameter. Common examples of access-token include 
36
   p_tag, p_q, p_lr, p_expires, p_branch, etc.
37
38
   @code
39
      NameAddr& contact = sip.header(h_Contacts).front();
40
      if(contact.exists(p_q))
41
      {
42
         QValueParameter& q = contact.param(p_q);
43
         // do stuff with q
44
      }
45
46
      NameAddr& to = sip.header(h_To);
47
      if(to.exists(p_tag))
48
      {
49
         DataParameter& toTag = to.param(p_tag);
50
         // do stuff with toTag
51
      }
52
53
      Via& topVia = sip.header(h_Vias).front();
54
      if(topVia.exists(p_branch))
55
      {
56
         BranchParameter& branch = topVia.param(p_branch);
57
         // do stuff with branch
58
      }
59
   @endcode
60
61
   Note the calls to ParserCategory::exists() in the code above; calling 
62
   ParserCategory::param() when the relevant parameter doesn't exist will either
63
   cause the parameter to be created, or an exception to be thrown (if you're
64
   working with a const reference).
65
66
   In some cases, you will need to access parameter-types that are not natively 
67
   supported by the stack (ie, don't have an access-token). ExtensionParameter 
68
   will allow you to construct an access-token at runtime that will retrieve the
69
   parameter as a raw Data. Here's an example:
70
71
   @code
72
      // We need to access the foo parameter on the Request-Uri
73
      RequestLine& rLine = sip.header(h_RequestLine);
74
      static ExtensionParameter p_foo("foo");
75
      if(rLine.uri().exists(p_foo))
76
      {
77
         Data& foo = rLine.uri().param(p_foo);
78
      }
79
   @endcode
80
81
   @todo Maybe a better name? IHaveParams? ElemWithParams?
82
   @ingroup resip_crit
83
*/
84
class ParserCategory : public LazyParser
85
{
86
    public:
87
      enum {UnknownParserCategory = -1};
88
89
      // NoCommaTokenizing:        commas do not indicate a new header value
90
      // CommasAllowedOutputMulti: multi headers can be received with commas but
91
      //                           output them on separate lines.
92
      // CommasAllowedOutputCommas: multi headers can be received with commas
93
      //                            and will always output with commas when
94
      //                            parsed.  
95
      enum CommaHandlingMode {NoCommaTokenizing = 0, CommasAllowedOutputMulti = 1, CommasAllowedOutputCommas = 3};
96
97
      /**
98
         @internal
99
         @brief Constructor used by SipMessage. Unless you _really_ know what
100
            you're doing, don't touch this.
101
      */
102
      ParserCategory(const HeaderFieldValue& headerFieldValue, 
103
                     Headers::Type type,
104
                     PoolBase* pool=0);
105
106
      /**
107
         @internal
108
         @brief Constructor used by SipMessage. Unless you _really_ know what
109
            you're doing, don't touch this.
110
      */
111
      ParserCategory(const char* buf, 
112
                     int length, 
113
                     Headers::Type type,
114
                     PoolBase* pool=0);
115
116
      /**
117
         @internal
118
         @brief Copy c'tor.
119
      */
120
      ParserCategory(const ParserCategory& rhs,
121
                     PoolBase* pool=0);
122
123
      /**
124
         @internal
125
         @brief Assignment operator.
126
      */
127
      ParserCategory& operator=(const ParserCategory& rhs);
128
129
      virtual ~ParserCategory();
130
131
      virtual ParserCategory* clone() const = 0;
132
      virtual Parameter* createParam(ParameterTypes::Type type, ParseBuffer& pb, const std::bitset<256>& terminators, PoolBase* pool);
133
134
      // Do a placement new
135
      virtual ParserCategory* clone(void* location) const = 0;
136
137
      // Do a pool allocated new
138
      virtual ParserCategory* clone(PoolBase* pool) const = 0;
139
140
      /**
141
         @brief Checks for the existence of a natively supported parameter.
142
         @param paramType The accessor token for the parameter.
143
         @return true iff the parameter is present.
144
      */
145
      inline bool exists(const ParamBase& paramType) const
146
0
      {
147
0
          checkParsed();
148
0
          return (getParameterByEnum(paramType.getTypeNum()) != NULL);
149
0
      }
150
151
      /**
152
         @brief Removes a natively supported parameter, if the parameter is 
153
            present.
154
         @param paramType The accessor token for the parameter.
155
      */
156
      void remove(const ParamBase& paramType);
157
158
      // !dlb! causes compiler error in windows -- change template to const T*
159
      /**
160
         @brief Const accessor for non-natively-supported parameter types.
161
         @throw ParserCategory::Exception if this parameter doesn't exist.
162
         @param param The runtime constructed parameter accessor.
163
         @return The parameter, as a raw Data.
164
      */
165
      const Data& param(const ExtensionParameter& param) const;
166
      
167
      /**
168
         @brief Accessor for non-natively-supported parameter types.
169
            Will create the parameter if it does not exist.
170
         @param param The runtime constructed parameter accessor.
171
         @return The parameter, as a raw Data.
172
      */
173
      Data& param(const ExtensionParameter& param);
174
175
      /**
176
         @brief Removes a non-natively-supported parameter, if the parameter is 
177
            present.
178
         @param param The accessor token for the parameter.
179
      */
180
      void remove(const ExtensionParameter& param); 
181
182
      /**
183
         @brief Checks for the existence of a non-natively-supported parameter.
184
         @param param The runtime constructed accessor token.
185
         @return true iff the parameter is present.
186
      */
187
      bool exists(const ExtensionParameter& param) const;
188
189
      typedef std::set<ParameterTypes::Type> ParameterTypeSet;      
190
      
191
      static const ParameterTypeSet EmptyParameterTypeSet;      
192
193
      /**
194
         @brief Removes all known parameters except those that are specified in 
195
            set.
196
         @param set The set of parameters to retain, as an enum.
197
         @note This does not remove unknown parameters.
198
      */
199
      void removeParametersExcept(const ParameterTypeSet& set = EmptyParameterTypeSet);
200
      void clearUnknownParameters();
201
202
      /**
203
         @brief Exception class used by ParserCategory.
204
      */
205
      class Exception final : public BaseException
206
      {
207
         public:
208
            Exception(const Data& msg, const Data& file, const int line)
209
0
               : BaseException(msg, file, line) {}
210
211
0
            const char* name() const noexcept override { return "ParserCategory::Exception"; }
212
      };
213
214
      /**
215
         @internal
216
         @brief Causes this ParserCategory to parse parameters out of pb.
217
         @param pb The ParseBuffer to parse params from.
218
      */
219
      void parseParameters(ParseBuffer& pb);
220
221
      /**
222
         @brief Encodes parameters as they should appear on the wire.
223
         @param str The ostream to encode to.
224
         @return str
225
      */
226
      EncodeStream& encodeParameters(EncodeStream& str) const;
227
      
228
      // used to compare 2 parameter lists for equality in an order independent way
229
      /**
230
         @internal
231
         @brief An order-sensitive hash over the set of parameters in this 
232
            ParserCategory.
233
         @return The hash value as a Data.
234
      */
235
      Data commutativeParameterHash() const;
236
      
237
      /**
238
         @internal
239
         @brief Typeless parameter get interface.
240
      */
241
      Parameter* getParameterByEnum(ParameterTypes::Type type) const;
242
243
      /**
244
         @internal
245
         @brief Removes a parameter.
246
         @param type The parameter type.
247
      */
248
      void removeParameterByEnum(ParameterTypes::Type type);
249
250
      /**
251
         @internal
252
         @brief Typeless parameter put interface.
253
      */
254
      void setParameter(const Parameter* parameter);
255
256
      /**
257
         @brief Returns the number of known (natively supported) parameters.
258
      */
259
0
      int numKnownParams() const {return (int)mParameters.size();};
260
261
      /**
262
         @brief Returns the number of unknown parameters.
263
      */
264
0
      int numUnknownParams() const {return (int)mUnknownParameters.size();};
265
266
   protected:
267
      ParserCategory(PoolBase* pool=0);
268
269
      /**
270
         @internal
271
         @brief Adds a recognised parameter to the internal ParameterList.
272
         @param param The parameter to add.
273
         @note Skips duplicate parameters.
274
      */
275
      bool addParameter(Parameter* param);
276
277
      /**
278
         @internal
279
         @brief Adds an unrecognised parameter to the internal ParameterList.
280
         @param unknownParam The parameter to add.
281
         @note Skips duplicate parameters.
282
      */
283
      bool addParameter(UnknownParameter* unknownParam);
284
285
      Parameter* getParameterByData(const Data& data) const;
286
      void removeParameterByData(const Data& data);
287
      inline PoolBase* getPool()
288
1.99M
      {
289
1.99M
         return mPool;
290
1.99M
      }
291
292
      inline void freeParameter(Parameter* p)
293
1.94M
      {
294
1.94M
         if(p)
295
1.94M
         {
296
1.94M
            p->~Parameter();
297
1.94M
            if(mPool)
298
2.12k
            {
299
2.12k
               mPool->deallocate(p);
300
2.12k
               return;
301
2.12k
            }
302
1.93M
            ::operator delete(p);
303
1.93M
         }
304
1.94M
      }
305
306
      virtual const Data& errorContext() const;
307
308
      typedef std::vector<Parameter*, StlPoolAllocator<Parameter*, PoolBase> > ParameterList; 
309
      ParameterList mParameters;
310
      ParameterList mUnknownParameters;
311
      PoolBase* mPool;
312
      Headers::Type mHeaderType;
313
   private:
314
      void clear();
315
      void copyParametersFrom(const ParserCategory& other);
316
      friend EncodeStream& operator<<(EncodeStream&, const ParserCategory&);
317
      friend class NameAddr;
318
};
319
320
EncodeStream&
321
operator<<(EncodeStream&, const ParserCategory& category);
322
323
}
324
325
#undef defineParam
326
327
#endif
328
329
/* ====================================================================
330
 * The Vovida Software License, Version 1.0 
331
 * 
332
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
333
 * 
334
 * Redistribution and use in source and binary forms, with or without
335
 * modification, are permitted provided that the following conditions
336
 * are met:
337
 * 
338
 * 1. Redistributions of source code must retain the above copyright
339
 *    notice, this list of conditions and the following disclaimer.
340
 * 
341
 * 2. Redistributions in binary form must reproduce the above copyright
342
 *    notice, this list of conditions and the following disclaimer in
343
 *    the documentation and/or other materials provided with the
344
 *    distribution.
345
 * 
346
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
347
 *    and "Vovida Open Communication Application Library (VOCAL)" must
348
 *    not be used to endorse or promote products derived from this
349
 *    software without prior written permission. For written
350
 *    permission, please contact vocal@vovida.org.
351
 *
352
 * 4. Products derived from this software may not be called "VOCAL", nor
353
 *    may "VOCAL" appear in their name, without prior written
354
 *    permission of Vovida Networks, Inc.
355
 * 
356
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
357
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
358
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
359
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
360
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
361
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
362
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
363
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
364
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
365
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
366
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
367
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
368
 * DAMAGE.
369
 * 
370
 * ====================================================================
371
 * 
372
 * This software consists of voluntary contributions made by Vovida
373
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
374
 * Inc.  For more information on Vovida Networks, Inc., please see
375
 * <http://www.vovida.org/>.
376
 *
377
 */