⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msgheaderscanner.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 3 页
字号:
processMsgHeaderStatusLine(
   SipMessage *                       msg,
   char *                             lineText,
   unsigned int                       lineTextLength,
   MsgHeaderScanner::TextPropBitMask  lineTextPropBitMask)
{
   printf("status line: ");
   printText(lineText, lineTextLength);
   printf("\n");
   return true;
}

static
void
processMsgHeaderFieldNameAndValue(
   SipMessage *                       msg,
   int                                fieldKind,
   const char *                       fieldName,
   unsigned int                       fieldNameLength,
   char *                             valueText,
   unsigned int                       valueTextLength,
   MsgHeaderScanner::TextPropBitMask  valueTextPropBitMask)
{
   printText(fieldName, fieldNameLength);
   printf(": [[[[");
   printText(valueText, valueTextLength);
   printf("]]]]\n");
}

#else //!defined(RESIP_MSG_HEADER_SCANNER_DEBUG) } {


//   Determine a field's kind and whether it allows (comma separated) multi-values.
//   "fieldName" is not empty and contains only legal characters.
//   The text in "fieldName" may be canonicalized (eg, translating % escapes),
//   including shrinking it if necessary.

inline void
lookupMsgHeaderFieldInfo(char * fieldName,
                         unsigned int *fieldNameLength,   
                         MsgHeaderScanner::TextPropBitMask fieldNameTextPropBitMask,
                         int *fieldKind,             
                         bool *isMultiValueAllowed)    
{
   //.jacob. Don't ignore fieldNameTextPropBitMask.
   *fieldKind = Headers::getType(fieldName, *fieldNameLength);
   *isMultiValueAllowed =
      Headers::isCommaTokenizing(static_cast<Headers::Type>(*fieldKind));
}


// "lineText" contains no carriage returns and no line feeds.
// Return true on success, false on failure.

inline bool
processMsgHeaderStatusLine(SipMessage * msg,
                           char * lineText,
                           unsigned int lineTextLength,
                           MsgHeaderScanner::TextPropBitMask lineTextPropBitMask)
{
   //.jacob. Don't ignore valueTextPropBitMask, and don't always return true.
   msg->setStartLine(lineText, lineTextLength);
   return true;
}

// This function is called once for a field with one value.  (The value could be
// several values, but separated by something other than commas.)
// This function is called once for a field with 0 comma-separated values, with
// an empty value.
// This function is called N times for a field with N comma-separated values,
// but with the same value of "fieldName" each time.
// "fieldName" is not empty and contains only legal characters.
// "valueText" may be empty, has no leading whitespace, may contain trailing
// whitespace, contains carriage returns and line feeds only in correct pairs
// and followed by whitespace, and, if the field is multi-valued, contains
// balanced '<'/'>' and '"' pairs, contains ',' only within '<'/'>' or '"'
// pairs, and respects '\\'s within '"' pairs.
// The text in "valueText" may be canonicalized (eg, translating % escapes),
// including shrinking it if necessary.

inline void
processMsgHeaderFieldNameAndValue(SipMessage * msg,
                                  int fieldKind,
                                  const char * fieldName,
                                  unsigned int fieldNameLength,
                                  char * valueText,
                                  unsigned int valueTextLength,
                                  MsgHeaderScanner::TextPropBitMask valueTextPropBitMask)
{
   //.jacob. Don't ignore valueTextPropBitMask, particularly for '\r' & '\n'.
   msg->addHeader(static_cast<Headers::Type>(fieldKind),
                  fieldName,
                  fieldNameLength,
                  valueText,
                  valueTextLength);
}

#endif //!defined(RESIP_MSG_HEADER_SCANNER_DEBUG) }

bool MsgHeaderScanner::mInitialized = false;

MsgHeaderScanner::MsgHeaderScanner()
{
   if (!mInitialized)
   {
      mInitialized = true;
      initialize();
   }
}

void
MsgHeaderScanner::prepareForMessage(SipMessage *  msg)
{
   mMsg = msg;
   mState = sMsgStart;
   mPrevScanChunkNumSavedTextChars = 0;
}

void
MsgHeaderScanner::prepareForFrag(SipMessage *  msg, bool hasStartLine)
{
   mMsg = msg;
   if (hasStartLine)
   {
      mState = sMsgStart;
   }
   else
   {
      mState = sAfterLineBreakAfterStatusLine;
   }
   mPrevScanChunkNumSavedTextChars = 0;
}

MsgHeaderScanner::ScanChunkResult
MsgHeaderScanner::scanChunk(char * chunk,
                            unsigned int chunkLength,
                            char ** unprocessedCharPtr)
{
   MsgHeaderScanner::ScanChunkResult result;
   CharInfo* localCharInfoArray = charInfoArray;
   TransitionInfo (*localStateMachine)[numCharCategories] = stateMachine;
   State localState = mState;
   char *charPtr = chunk + mPrevScanChunkNumSavedTextChars;
   char *termCharPtr = chunk + chunkLength;
   char saveChunkTermChar = *termCharPtr;
   *termCharPtr = chunkTermSentinelChar;
   char *textStartCharPtr;
   MsgHeaderScanner::TextPropBitMask localTextPropBitMask = mTextPropBitMask;
   if (mPrevScanChunkNumSavedTextChars == 0)
   {
      textStartCharPtr = 0;
   }
   else
   {
      textStartCharPtr = chunk;
   }
   --charPtr;  // The loop starts by advancing "charPtr", so pre-adjust it.
   for (;;)
   {
      // BEGIN message header character scan block BEGIN
      // The code in this block is executed once per message header character.
      // This entire file is designed specifically to minimize this block's size.
      ++charPtr;
      CharInfo *charInfo = &localCharInfoArray[((unsigned char) (*charPtr))];
      CharCategory charCategory = charInfo->category;
      localTextPropBitMask |= charInfo->textPropBitMask;
     determineTransitionFromCharCategory:
      TransitionInfo *transitionInfo =
         &(localStateMachine[localState][charCategory]);
      TransitionAction transitionAction = transitionInfo->action;
#if defined(RESIP_MSG_HEADER_SCANNER_DEBUG)  
      printStateTransition(localState, *charPtr, transitionAction);
#endif
      localState = transitionInfo->nextState;
      if (transitionAction == taNone) continue;
      // END message header character scan block END
      // The loop remainder is executed about 4-5 times per message header line.
      switch (transitionAction)
      {
         case taTermStatusLine:
            if (!processMsgHeaderStatusLine(mMsg,
                                            textStartCharPtr,
                                            charPtr - textStartCharPtr,
                                            localTextPropBitMask))
            {
               result = MsgHeaderScanner::scrError;
               *unprocessedCharPtr = charPtr;
               goto endOfFunction;
            }
            textStartCharPtr = 0;
            break;
         case taTermFieldName:
         {
            mFieldNameLength = charPtr - textStartCharPtr;
            bool isMultiValueAllowed;
            lookupMsgHeaderFieldInfo(textStartCharPtr,
                                     &mFieldNameLength,
                                     localTextPropBitMask,
                                     &mFieldKind,
                                     &isMultiValueAllowed);
            mFieldName = textStartCharPtr;
            textStartCharPtr = 0;
            if (isMultiValueAllowed) 
            {
               localState += deltaOfNStateFrom1State;
            }
         }
         break;
         case taBeyondEmptyValue:
            processMsgHeaderFieldNameAndValue(mMsg,
                                              mFieldKind,
                                              mFieldName,
                                              mFieldNameLength,
                                              0,
                                              0,
                                              0);
            goto performStartTextAction;
         case taTermValueAfterLineBreak:
            processMsgHeaderFieldNameAndValue(mMsg,
                                              mFieldKind,
                                              mFieldName,
                                              mFieldNameLength,
                                              textStartCharPtr,
                                              (charPtr - textStartCharPtr) - 2,
                                              localTextPropBitMask);       //^:CRLF
            goto performStartTextAction;
         case taTermValue:
            processMsgHeaderFieldNameAndValue(mMsg,
                                              mFieldKind,
                                              mFieldName,
                                              mFieldNameLength,
                                              textStartCharPtr,
                                              charPtr - textStartCharPtr,
                                              localTextPropBitMask);
            textStartCharPtr = 0;
            break;
         case taStartText:
        performStartTextAction:
            textStartCharPtr = charPtr;
            localTextPropBitMask = 0;
            break;
         case taEndHeader:
            // textStartCharPtr is not 0.  Not currently relevant.
            result = MsgHeaderScanner::scrEnd;
            *unprocessedCharPtr = charPtr + 1;  // The current char is processed.
            goto endOfFunction;
            break;
         case taChunkTermSentinel:
            if (charPtr == termCharPtr)
            {
               // The chunk has been consumed.  Save some state and request another.
               mState = localState;
               if (textStartCharPtr == 0) 
               {
                  mPrevScanChunkNumSavedTextChars = 0;
               }
               else
               {
                  mPrevScanChunkNumSavedTextChars = termCharPtr - textStartCharPtr;
               }
               mTextPropBitMask = localTextPropBitMask;
               result = MsgHeaderScanner::scrNextChunk;
               *unprocessedCharPtr = termCharPtr - mPrevScanChunkNumSavedTextChars;
               goto endOfFunction;
            }
            else
            {
               // The character is not the sentinel.  Treat it like any other.
               charCategory = ccOther;
               goto determineTransitionFromCharCategory;
            }
            break;
         default:
            result = MsgHeaderScanner::scrError;
            *unprocessedCharPtr = charPtr;
            goto endOfFunction;
      }//switch
   }//for
  endOfFunction:
   *termCharPtr = saveChunkTermChar;
   return result;
}

bool
MsgHeaderScanner::initialize()
{
   initCharInfoArray();
   initStateMachine();
   return true;
}


} //namespace resip



#if defined(RESIP_MSG_HEADER_SCANNER_DEBUG) && defined(MSG_SCANNER_STANDALONE)

extern
int
main(unsigned int   numArgs,
     const char * * argVector)
{
   ::resip::MsgHeaderScanner scanner;
   scanner.prepareForMessage(0);
   char *text =
      "status\r\n"
      "bobby: dummy\r\n"
      "allow: foo, bar, \"don,\\\"xyz\r\n zy\", buzz\r\n\r\n";
   unsigned int textLength = strlen(text);
   char chunk[10000];
   strcpy(chunk, text);
   ::resip::MsgHeaderScanner::ScanChunkResult scanChunkResult;
   char *unprocessedCharPtr;
   scanChunkResult = scanner.scanChunk(chunk, 21, &unprocessedCharPtr);
   if (scanChunkResult == ::resip::MsgHeaderScanner::scrNextChunk)
   {
      printf("Scanning another chunk '.");
      ::resip::printText(unprocessedCharPtr, 1);
      printf("'\n");
      scanChunkResult =
         scanner.scanChunk(unprocessedCharPtr,
                           (chunk + textLength) - unprocessedCharPtr,
                           &unprocessedCharPtr);
   }
   if (scanChunkResult != ::resip::MsgHeaderScanner::scrEnd)
   {
      printf("Error %d at character %d.\n",
             scanChunkResult,
             unprocessedCharPtr - chunk);
   }
   return 0;
}

#endif //!defined(RESIP_MSG_HEADER_SCANNER_DEBUG) }

/* ====================================================================
 * The Vovida Software License, Version 1.0 
 * 
 * Copyright (c) 2000-2005
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
 *    and "Vovida Open Communication Application Library (VOCAL)" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact vocal@vovida.org.
 *
 * 4. Products derived from this software may not be called "VOCAL", nor
 *    may "VOCAL" appear in their name, without prior written
 *    permission of Vovida Networks, Inc.
 * 
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 * 
 * ====================================================================
 * 
 * This software consists of voluntary contributions made by Vovida
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
 * Inc.  For more information on Vovida Networks, Inc., please see
 * <http://www.vovida.org/>.
 *
 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -