reSIProcate/stack  9694
MsgHeaderScanner.hxx
Go to the documentation of this file.
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  */