Coverage Report

Created: 2026-06-07 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/resiprocate/resip/stack/MsgHeaderScanner.hxx
Line
Count
Source
1
#if !defined(RESIP_MSG_HEADER_SCANNER_HXX)
2
#define RESIP_MSG_HEADER_SCANNER_HXX
3
4
#include <stdlib.h>
5
6
namespace resip 
7
{
8
9
class SipMessage;
10
11
///////////////////////////////////////////////////////////////////////////////
12
// This class scans a message header for its status line (the first non-empty
13
// line) and then any number of field name/value pairs, terminated by an empty
14
// line.
15
// The message header text may be divided into arbitrary chunks.
16
// A single instance may be used to scan any number of message headers.
17
//
18
// Its intended usage pattern is as follows:
19
//
20
//     MsgHeaderScanner scanner;
21
//     for (;;) {
22
//       SipMessage *msg = ...
23
//       scanner.prepareForMessage(msg);
24
//       MsgHeaderScanner::ScanChunkResult scanChunkResult;
25
//       do {
26
//         (Input the next chunk of the message.)
27
//         scanChunkResult = scanner.scanChunk(...);
28
//       } while (scanChunkResult == MsgHeaderScanner::scrNextChunk);
29
//       ...
30
//     }//for
31
//
32
// Note that during the input of each message header chunk this class
33
// encapsulates the full state of the message header scan, so that input may
34
// be performed in whatever manner desired (eg without blocking).
35
//
36
// In this class, "multi-value" refers to associating multiple values with a
37
// single field name by separating the individual values with commas.
38
//
39
// Some assertions about message headers:
40
//     Only space and tab are whitespace characters.
41
//     A carriage return must always be followed by a line feed.
42
//     A line feed must always be preceded by a carriage return.
43
//     A field name always starts at the beginning of a line.
44
//     A value may contain a line break (a carriage return / line feed pair)
45
//         before any whitespace, but not otherwise.  (The scanner allows
46
//         whitespace in a few extra places for simplicity.)
47
//     A ',' within '"' pair or '<'/'>' pair does not separate multi-values.
48
//     A '\\' is used only within a '"' pair, and not to escape a carriage
49
//         return or line feed.
50
//     '<'/'>' pairs do not nest, nor contain '"' pairs.
51
//    '('/')' pair comments cannot be combined with any multi-values.
52
//     A multi-value cannot be empty, except as needed to specify 0 multi-values.
53
54
class MsgHeaderScanner
55
{
56
      
57
   public:
58
      enum { MaxNumCharsChunkOverflow = 5 };
59
      static char* allocateBuffer(size_t size);
60
      
61
      enum TextPropBitMaskEnum 
62
      {
63
         tpbmContainsLineBreak  = 1 << 0,     // '\r' or '\n', always paired
64
         tpbmContainsWhitespace = 1 << 1,     // ' ' or '\t'
65
         tpbmContainsBackslash  = 1 << 2,     // '\\'
66
         tpbmContainsPercent    = 1 << 3,     // '%'
67
         tpbmContainsSemicolon  = 1 << 4,     // ';'
68
         tpbmContainsParen      = 1 << 5      // '(' or ')', possibly mismatched
69
      };
70
      typedef unsigned char TextPropBitMask;
71
    
72
0
      inline unsigned int getHeaderCount() const { return mNumHeaders;} 
73
74
   private:
75
    
76
      // Fields:
77
      SipMessage *                       mMsg;
78
      unsigned int                       mNumHeaders;
79
      /*State*/int                       mState;      // Type defined in .cxx file.
80
      int                                mPrevScanChunkNumSavedTextChars;
81
      MsgHeaderScanner::TextPropBitMask  mTextPropBitMask;
82
      const char *                       mFieldName;
83
      unsigned int                       mFieldNameLength;
84
      int                                mFieldKind;
85
      /*
86
        "mState" and "mPrevScanChunkNumSavedTextChars" are meaningful only between
87
        input chunks.
88
        "mTextPropBitMask" is meaningful only between input chunks and only when
89
        scanning a field name or value.
90
        "mFieldName", "mFieldNameLength", and "mFieldKind" are meaningful only
91
        between terminating a field name and finding the termination of its value.
92
      */
93
    
94
   public:
95
    
96
      MsgHeaderScanner();
97
    
98
      // Destructor: defined implicitly
99
      void prepareForMessage(SipMessage *  msg);
100
      // allow proper parsing of message/sipfrag & msg/external
101
      // presence of start line is determined in SipFrag
102
      void prepareForFrag(SipMessage *  msg, bool hasStartLine);
103
 
104
      
105
      enum ScanChunkResult {
106
         scrEnd,       // Message header scan ended.
107
         scrNextChunk, // Another chunk is needed.
108
         scrError      // The message header is in error.
109
      };
110
    
111
112
      //       The meaning of "*unprocessedCharPtr" depends on the result:
113
      //       scrEnd:       The character that terminates the message header.
114
      //       scrError:     The erroneous character.
115
      //       scrNextChunk: The first character of some incomplete text unit.  The
116
      //       remaining portion of the old chunk must be placed
117
      //       in the beginning of the new chunk.
118
      //       This method writes a sentinel in the chunk's terminal character.
119
      MsgHeaderScanner::ScanChunkResult scanChunk(char * chunk,
120
                                                  unsigned int chunkLength,
121
                                                  char **unprocessedCharPtr); 
122
    
123
      // !ah! DEBUG only, write to fd.
124
      // !ah! for documentation generation
125
      static int dumpStateMachine(int fd); 
126
127
   private:
128
129
130
      // Copy constructor: declared but not defined
131
      MsgHeaderScanner(const MsgHeaderScanner & from);
132
133
      // Assignment: declared but not defined
134
      MsgHeaderScanner & operator=(const MsgHeaderScanner & from);
135
136
      // Automatically called when 1st MsgHeaderScanner constructed.
137
      bool initialize();
138
      static bool mInitialized;
139
140
141
};
142
143
144
///////////////////////////////////////////////////////////////////////////////
145
146
} // namespace resip
147
148
#endif
149
/* ====================================================================
150
 * The Vovida Software License, Version 1.0 
151
 * 
152
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
153
 * 
154
 * Redistribution and use in source and binary forms, with or without
155
 * modification, are permitted provided that the following conditions
156
 * are met:
157
 * 
158
 * 1. Redistributions of source code must retain the above copyright
159
 *    notice, this list of conditions and the following disclaimer.
160
 * 
161
 * 2. Redistributions in binary form must reproduce the above copyright
162
 *    notice, this list of conditions and the following disclaimer in
163
 *    the documentation and/or other materials provided with the
164
 *    distribution.
165
 * 
166
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
167
 *    and "Vovida Open Communication Application Library (VOCAL)" must
168
 *    not be used to endorse or promote products derived from this
169
 *    software without prior written permission. For written
170
 *    permission, please contact vocal@vovida.org.
171
 *
172
 * 4. Products derived from this software may not be called "VOCAL", nor
173
 *    may "VOCAL" appear in their name, without prior written
174
 *    permission of Vovida Networks, Inc.
175
 * 
176
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
177
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
178
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
179
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
180
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
181
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
182
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
183
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
184
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
185
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
186
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
187
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
188
 * DAMAGE.
189
 * 
190
 * ====================================================================
191
 * 
192
 * This software consists of voluntary contributions made by Vovida
193
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
194
 * Inc.  For more information on Vovida Networks, Inc., please see
195
 * <http://www.vovida.org/>.
196
 *
197
 */