|
reSIProcate/stack
9694
|
00001 #if !defined(RESIP_MSG_HEADER_SCANNER_HXX) 00002 #define RESIP_MSG_HEADER_SCANNER_HXX 00003 namespace resip 00004 { 00005 00006 class SipMessage; 00007 00009 // This class scans a message header for its status line (the first non-empty 00010 // line) and then any number of field name/value pairs, terminated by an empty 00011 // line. 00012 // The message header text may be divided into arbitrary chunks. 00013 // A single instance may be used to scan any number of message headers. 00014 // 00015 // Its intended usage pattern is as follows: 00016 // 00017 // MsgHeaderScanner scanner; 00018 // for (;;) { 00019 // SipMessage *msg = ... 00020 // scanner.prepareForMessage(msg); 00021 // MsgHeaderScanner::ScanChunkResult scanChunkResult; 00022 // do { 00023 // (Input the next chunk of the message.) 00024 // scanChunkResult = scanner.scanChunk(...); 00025 // } while (scanChunkResult == MsgHeaderScanner::scrNextChunk); 00026 // ... 00027 // }//for 00028 // 00029 // Note that during the input of each message header chunk this class 00030 // encapsulates the full state of the message header scan, so that input may 00031 // be performed in whatever manner desired (eg without blocking). 00032 // 00033 // In this class, "multi-value" refers to associating multiple values with a 00034 // single field name by separating the individual values with commas. 00035 // 00036 // Some assertions about message headers: 00037 // Only space and tab are whitespace characters. 00038 // A carriage return must always be followed by a line feed. 00039 // A line feed must always be preceded by a carriage return. 00040 // A field name always starts at the beginning of a line. 00041 // A value may contain a line break (a carriage return / line feed pair) 00042 // before any whitespace, but not otherwise. (The scanner allows 00043 // whitespace in a few extra places for simplicity.) 00044 // A ',' within '"' pair or '<'/'>' pair does not separate multi-values. 00045 // A '\\' is used only within a '"' pair, and not to escape a carriage 00046 // return or line feed. 00047 // '<'/'>' pairs do not nest, nor contain '"' pairs. 00048 // '('/')' pair comments cannot be combined with any multi-values. 00049 // A multi-value cannot be empty, except as needed to specify 0 multi-values. 00050 00051 class MsgHeaderScanner 00052 { 00053 00054 public: 00055 enum { MaxNumCharsChunkOverflow = 5 }; 00056 static char* allocateBuffer(int size); 00057 00058 enum TextPropBitMaskEnum 00059 { 00060 tpbmContainsLineBreak = 1 << 0, // '\r' or '\n', always paired 00061 tpbmContainsWhitespace = 1 << 1, // ' ' or '\t' 00062 tpbmContainsBackslash = 1 << 2, // '\\' 00063 tpbmContainsPercent = 1 << 3, // '%' 00064 tpbmContainsSemicolon = 1 << 4, // ';' 00065 tpbmContainsParen = 1 << 5 // '(' or ')', possibly mismatched 00066 }; 00067 typedef unsigned char TextPropBitMask; 00068 00069 inline unsigned int getHeaderCount() const { return mNumHeaders;} 00070 00071 private: 00072 00073 // Fields: 00074 SipMessage * mMsg; 00075 unsigned int mNumHeaders; 00076 /*State*/int mState; // Type defined in .cxx file. 00077 int mPrevScanChunkNumSavedTextChars; 00078 MsgHeaderScanner::TextPropBitMask mTextPropBitMask; 00079 const char * mFieldName; 00080 unsigned int mFieldNameLength; 00081 int mFieldKind; 00082 /* 00083 "mState" and "mPrevScanChunkNumSavedTextChars" are meaningful only between 00084 input chunks. 00085 "mTextPropBitMask" is meaningful only between input chunks and only when 00086 scanning a field name or value. 00087 "mFieldName", "mFieldNameLength", and "mFieldKind" are meaningful only 00088 between terminating a field name and finding the termination of its value. 00089 */ 00090 00091 public: 00092 00093 MsgHeaderScanner(); 00094 00095 // Destructor: defined implicitly 00096 void prepareForMessage(SipMessage * msg); 00097 // allow proper parsing of message/sipfrag & msg/external 00098 // presence of start line is determined in SipFrag 00099 void prepareForFrag(SipMessage * msg, bool hasStartLine); 00100 00101 00102 enum ScanChunkResult { 00103 scrEnd, // Message header scan ended. 00104 scrNextChunk, // Another chunk is needed. 00105 scrError // The message header is in error. 00106 }; 00107 00108 00109 // The meaning of "*unprocessedCharPtr" depends on the result: 00110 // scrEnd: The character that terminates the message header. 00111 // scrError: The erroneous character. 00112 // scrNextChunk: The first character of some incomplete text unit. The 00113 // remaining portion of the old chunk must be placed 00114 // in the beginning of the new chunk. 00115 // This method writes a sentinel in the chunk's terminal character. 00116 MsgHeaderScanner::ScanChunkResult scanChunk(char * chunk, 00117 unsigned int chunkLength, 00118 char **unprocessedCharPtr); 00119 00120 // !ah! DEBUG only, write to fd. 00121 // !ah! for documentation generation 00122 static int dumpStateMachine(int fd); 00123 00124 private: 00125 00126 00127 // Copy constructor: declared but not defined 00128 MsgHeaderScanner(const MsgHeaderScanner & from); 00129 00130 // Assignment: declared but not defined 00131 MsgHeaderScanner & operator=(const MsgHeaderScanner & from); 00132 00133 // Automatically called when 1st MsgHeaderScanner constructed. 00134 bool initialize(); 00135 static bool mInitialized; 00136 00137 00138 }; 00139 00140 00142 00143 } // namespace resip 00144 00145 #endif 00146 /* ==================================================================== 00147 * The Vovida Software License, Version 1.0 00148 * 00149 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00150 * 00151 * Redistribution and use in source and binary forms, with or without 00152 * modification, are permitted provided that the following conditions 00153 * are met: 00154 * 00155 * 1. Redistributions of source code must retain the above copyright 00156 * notice, this list of conditions and the following disclaimer. 00157 * 00158 * 2. Redistributions in binary form must reproduce the above copyright 00159 * notice, this list of conditions and the following disclaimer in 00160 * the documentation and/or other materials provided with the 00161 * distribution. 00162 * 00163 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00164 * and "Vovida Open Communication Application Library (VOCAL)" must 00165 * not be used to endorse or promote products derived from this 00166 * software without prior written permission. For written 00167 * permission, please contact vocal@vovida.org. 00168 * 00169 * 4. Products derived from this software may not be called "VOCAL", nor 00170 * may "VOCAL" appear in their name, without prior written 00171 * permission of Vovida Networks, Inc. 00172 * 00173 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00174 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00175 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00176 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00177 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00178 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00179 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00180 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00181 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00182 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00183 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00184 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00185 * DAMAGE. 00186 * 00187 * ==================================================================== 00188 * 00189 * This software consists of voluntary contributions made by Vovida 00190 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00191 * Inc. For more information on Vovida Networks, Inc., please see 00192 * <http://www.vovida.org/>. 00193 * 00194 */
1.7.5.1