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

📄 msgheaderscanner.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 3 页
字号:
#if defined(HAVE_CONFIG_H)
#include "resip/stack/config.hxx"
#endif

#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include "resip/stack/HeaderTypes.hxx"
#include "resip/stack/SipMessage.hxx"
#include "resip/stack/MsgHeaderScanner.hxx"
#include "rutil/WinLeakCheck.hxx"

namespace resip 
{

///////////////////////////////////////////////////////////////////////////////
//   Any character could be used as the chunk terminating sentinel, as long as
//   it would otherwise be character category "other".  The null character
//   was chosen because it is unlikely to occur naturally -- but it's OK if it
//   does.

enum { chunkTermSentinelChar = '\0' };

enum CharCategoryEnum
{
   ccChunkTermSentinel,
   ccOther,
   ccFieldName,
   ccWhitespace,
   ccColon,
   ccDoubleQuotationMark,
   ccLeftAngleBracket,
   ccRightAngleBracket,
   ccBackslash,
   ccComma,
   ccCarriageReturn,
   ccLineFeed,
   numCharCategories
};
typedef char CharCategory;

char* 
MsgHeaderScanner::allocateBuffer(int size)
{
   return new char[size + MaxNumCharsChunkOverflow];
}

struct CharInfo
{
      CharCategory category;
      MsgHeaderScanner::TextPropBitMask textPropBitMask;
};
    
static CharInfo charInfoArray[UCHAR_MAX+1];
    
static inline int c2i(unsigned char c)
{
   return static_cast<int>(c); 
}

static void initCharInfoArray()
{
   for(unsigned int charIndex = 0; charIndex <= UCHAR_MAX; ++charIndex) 
   {
      charInfoArray[charIndex].category = ccOther;
      charInfoArray[charIndex].textPropBitMask = 0;
   }

   for(const char *charPtr = "abcdefghijklmnopqrstuvwxyz"
          "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.!%*_+`'~";
       *charPtr;
       ++charPtr)
   {
      charInfoArray[c2i(*charPtr)].category = ccFieldName;
   }

   charInfoArray[c2i(' ')].category  = ccWhitespace;
   charInfoArray[c2i('\t')].category = ccWhitespace;
   charInfoArray[c2i(':')].category  = ccColon;
   charInfoArray[c2i('"')].category  = ccDoubleQuotationMark;
   charInfoArray[c2i('<')].category  = ccLeftAngleBracket;
   charInfoArray[c2i('>')].category  = ccRightAngleBracket;
   charInfoArray[c2i('\\')].category  = ccBackslash;
   charInfoArray[c2i(',')].category  = ccComma;
   charInfoArray[c2i('\r')].category = ccCarriageReturn;
   charInfoArray[c2i('\n')].category = ccLineFeed;
   // Assert: "chunkTermSentinelChar"'s category is still the default "ccOther".
   charInfoArray[c2i(chunkTermSentinelChar)].category = ccChunkTermSentinel;
   // Init text property bit masks.
   charInfoArray[c2i('\r')].textPropBitMask =
      MsgHeaderScanner::tpbmContainsLineBreak;
   charInfoArray[c2i('\n')].textPropBitMask =
      MsgHeaderScanner::tpbmContainsLineBreak;
   charInfoArray[c2i(' ')].textPropBitMask =
      MsgHeaderScanner::tpbmContainsWhitespace;
   charInfoArray[c2i('\t')].textPropBitMask =
      MsgHeaderScanner::tpbmContainsWhitespace;
   charInfoArray[c2i('\\')].textPropBitMask =
      MsgHeaderScanner::tpbmContainsBackslash;
   charInfoArray[c2i('%')].textPropBitMask =
      MsgHeaderScanner::tpbmContainsPercent;
   charInfoArray[c2i(';')].textPropBitMask =
      MsgHeaderScanner::tpbmContainsSemicolon;
   charInfoArray[c2i('(')].textPropBitMask =
      MsgHeaderScanner::tpbmContainsParen;
   charInfoArray[c2i(')')].textPropBitMask =
      MsgHeaderScanner::tpbmContainsParen;
}

///////////////////////////////////////////////////////////////////////////////
//   States marked '1' scan normal values.  States marked 'N' scan multi-values.

enum StateEnum
{
   sMsgStart,
   sHalfLineBreakAtMsgStart,
   sScanStatusLine,
   sHalfLineBreakAfterStatusLine,
   sAfterLineBreakAfterStatusLine,
   sScanFieldName,
   sScanWhitespaceAfter1FieldName,
   sScanWhitespaceAfterNFieldName,
   sScanWhitespaceOr1Value,
   sScanWhitespaceOrNValue,
   sHalfLineBreakInWhitespaceBefore1Value,
   sHalfLineBreakInWhitespaceBeforeNValue,
   sAfterLineBreakInWhitespaceBefore1Value,
   sAfterLineBreakInWhitespaceBeforeNValue,
   sScan1Value,
   sScanNValue,
   sHalfLineBreakIn1Value,
   sHalfLineBreakInNValue,
   sAfterLineBreakIn1Value,
   sAfterLineBreakInNValue,
   sScanNValueInQuotes,
   sAfterEscCharInQuotesInNValue,
   sHalfLineBreakInQuotesInNValue,
   sAfterLineBreakInQuotesInNValue,
   sScanNValueInAngles,
   sHalfLineBreakInAnglesInNValue,
   sAfterLineBreakInAnglesInNValue,
   sHalfLineBreakAfterLineBreak,
   numStates
};

typedef char State;

// For each '1' state, the 'N' state is "deltaOfNStateFrom1State" larger.
enum { deltaOfNStateFrom1State = 1 };

/////
    
enum TransitionActionEnum {
   taNone,
   taTermStatusLine,       // The current character terminates the status
   //     line.
   taTermFieldName,        // The current character terminates a field name.
   //     If the field supports multi-values, shift
   //     the state machine into multi-value scanning.
   taBeyondEmptyValue,     // The current character terminates an empty value.
   //     Implies taStartText.
   taTermValueAfterLineBreak, 
   // The previous two characters are a linebreak
   //      terminating a value.  Implies taStartText.
   taTermValue,            // The current character terminates a value.
   taStartText,            // The current character starts a text unit.
   //     (The status line, a field name, or a value.)
   taEndHeader,            // The current character mEnds_ the header.
   taChunkTermSentinel,    // Either the current character terminates the
   //    current chunk or it is an ordinary character.
   taError                 // The input is erroneous.
};
typedef char TransitionAction;


struct TransitionInfo
{
      TransitionAction  action;
      State             nextState;
};

static TransitionInfo stateMachine[numStates][numCharCategories];

inline void specTransition(State state,
                           CharCategory charCategory,
                           TransitionAction action,
                           State nextState)
{
   stateMachine[c2i(state)][c2i(charCategory)].action = action;
   stateMachine[c2i(state)][c2i(charCategory)].nextState = nextState;
}

static void specDefaultTransition(State state,
                                  TransitionAction action,
                                  State nextState)
{
   for (int charCategory = 0;
        charCategory < numCharCategories;
        ++charCategory) 
   {
      specTransition(state, charCategory, action, nextState);
   }
   specTransition(state, ccCarriageReturn, taError, state);
   specTransition(state, ccLineFeed, taError, state);
   specTransition(state, ccChunkTermSentinel, taChunkTermSentinel, state);
}

static void specHalfLineBreakState(State halfLineBreakState,
                                   State  afterLineBreakState)
{
   specDefaultTransition(halfLineBreakState, taError, halfLineBreakState);
   specTransition(halfLineBreakState, ccLineFeed, taNone, afterLineBreakState);
}


//   Single-value (1) scanning and multi-value (N) scanning involves several nearly
//   identical states.
//   "stateDelta" is either 0 or "deltaOfNStateFrom1State".

static void specXValueStates(int  stateDelta)
{
   specDefaultTransition(sScanWhitespaceAfter1FieldName + stateDelta,
                         taError,
                         sScanWhitespaceAfter1FieldName + stateDelta);
   specTransition(sScanWhitespaceAfter1FieldName + stateDelta,
                  ccWhitespace,
                  taNone,
                  sScanWhitespaceAfter1FieldName + stateDelta);
   specTransition(sScanWhitespaceAfter1FieldName + stateDelta,
                  ccColon,
                  taNone,
                  sScanWhitespaceOr1Value + stateDelta);
   specDefaultTransition(sScanWhitespaceOr1Value + stateDelta,
                         taStartText,
                         sScan1Value + stateDelta);
   specTransition(sScanWhitespaceOr1Value + stateDelta,
                  ccWhitespace,
                  taNone,
                  sScanWhitespaceOr1Value + stateDelta);
   if (stateDelta == deltaOfNStateFrom1State)
   {
      specTransition(sScanWhitespaceOr1Value + stateDelta,
                     ccComma,
                     taError,
                     sScanWhitespaceOr1Value + stateDelta);
      specTransition(sScanWhitespaceOr1Value + stateDelta,
                     ccLeftAngleBracket,
                     taStartText,
                     sScanNValueInAngles);
      specTransition(sScanWhitespaceOr1Value + stateDelta,
                     ccDoubleQuotationMark,
                     taStartText,
                     sScanNValueInQuotes);
   }
   specTransition(sScanWhitespaceOr1Value + stateDelta,
                  ccCarriageReturn,
                  taNone,
                  sHalfLineBreakInWhitespaceBefore1Value + stateDelta);
   specHalfLineBreakState(sHalfLineBreakInWhitespaceBefore1Value + stateDelta,
                          sAfterLineBreakInWhitespaceBefore1Value + stateDelta);
   specDefaultTransition(sAfterLineBreakInWhitespaceBefore1Value + stateDelta,
                         taError,
                         sAfterLineBreakInWhitespaceBefore1Value + stateDelta);
   specTransition(sAfterLineBreakInWhitespaceBefore1Value + stateDelta,
                  ccFieldName,
                  taBeyondEmptyValue,
                  sScanFieldName);
   specTransition(sAfterLineBreakInWhitespaceBefore1Value + stateDelta,
                  ccWhitespace,
                  taNone,
                  sScanWhitespaceOr1Value + stateDelta);
   specTransition(sAfterLineBreakInWhitespaceBefore1Value + stateDelta,
                  ccCarriageReturn,
                  taBeyondEmptyValue,
                  sHalfLineBreakAfterLineBreak);
   specDefaultTransition(sScan1Value + stateDelta,
                         taNone,
                         sScan1Value + stateDelta);
   if (stateDelta == deltaOfNStateFrom1State)
   {
      specTransition(sScan1Value + stateDelta,
                     ccComma,
                     taTermValue,
                     sScanWhitespaceOr1Value + stateDelta);
      specTransition(sScan1Value + stateDelta,
                     ccLeftAngleBracket,
                     taNone,
                     sScanNValueInAngles);
      specTransition(sScan1Value + stateDelta,
                     ccDoubleQuotationMark,
                     taNone,
                     sScanNValueInQuotes);
   }
   specTransition(sScan1Value + stateDelta,
                  ccCarriageReturn,
                  taNone,
                  sHalfLineBreakIn1Value + stateDelta);
   specHalfLineBreakState(sHalfLineBreakIn1Value + stateDelta,
                          sAfterLineBreakIn1Value + stateDelta);
   specDefaultTransition(sAfterLineBreakIn1Value + stateDelta,
                         taError,
                         sAfterLineBreakIn1Value + stateDelta);
   specTransition(sAfterLineBreakIn1Value + stateDelta,
                  ccFieldName,
                  taTermValueAfterLineBreak,
                  sScanFieldName);
   specTransition(sAfterLineBreakIn1Value + stateDelta,
                  ccWhitespace,
                  taNone,
                  sScan1Value + stateDelta);
   specTransition(sAfterLineBreakIn1Value + stateDelta,
                  ccCarriageReturn,
                  taTermValueAfterLineBreak,
                  sHalfLineBreakAfterLineBreak);
}

static void initStateMachine()
{
   // By convention, error transitions maintain the same state.
   specDefaultTransition(sMsgStart, taStartText, sScanStatusLine);
   specTransition(sMsgStart,
                  ccCarriageReturn,
                  taNone,
                  sHalfLineBreakAtMsgStart);
   specTransition(sMsgStart, ccLineFeed, taError, sMsgStart);
   specHalfLineBreakState(sHalfLineBreakAtMsgStart, sMsgStart);
   specDefaultTransition(sScanStatusLine, taNone, sScanStatusLine);
   specTransition(sScanStatusLine,
                  ccCarriageReturn,
                  taTermStatusLine,
                  sHalfLineBreakAfterStatusLine);
   specHalfLineBreakState(sHalfLineBreakAfterStatusLine,
                          sAfterLineBreakAfterStatusLine);
   specDefaultTransition(sAfterLineBreakAfterStatusLine,
                         taError,
                         sAfterLineBreakAfterStatusLine);
   specTransition(sAfterLineBreakAfterStatusLine,
                  ccFieldName,
                  taStartText,
                  sScanFieldName);
   specTransition(sAfterLineBreakAfterStatusLine,
                  ccWhitespace,
                  taError,
                  sAfterLineBreakAfterStatusLine);
   specTransition(sAfterLineBreakAfterStatusLine,
                  ccCarriageReturn,
                  taNone,
                  sHalfLineBreakAfterLineBreak);
   specDefaultTransition(sScanFieldName, taError, sScanFieldName);
   specTransition(sScanFieldName, ccFieldName, taNone, sScanFieldName);
   specTransition(sScanFieldName,
                  ccWhitespace,
                  taTermFieldName,
                  sScanWhitespaceAfter1FieldName);
   specTransition(sScanFieldName,
                  ccColon,
                  taTermFieldName,
                  sScanWhitespaceOr1Value);
   specXValueStates(0);
   specXValueStates(deltaOfNStateFrom1State);
   specDefaultTransition(sScanNValueInQuotes, taNone, sScanNValueInQuotes);
   specTransition(sScanNValueInQuotes,
                  ccDoubleQuotationMark,
                  taNone,
                  sScanNValue);
   specTransition(sScanNValueInQuotes,
                  ccBackslash,
                  taNone,
                  sAfterEscCharInQuotesInNValue);
   specTransition(sScanNValueInQuotes,
                  ccCarriageReturn,
                  taNone,
                  sHalfLineBreakInQuotesInNValue);
   specDefaultTransition(sAfterEscCharInQuotesInNValue,
                         taNone,
                         sScanNValueInQuotes);
   specHalfLineBreakState(sHalfLineBreakInQuotesInNValue,
                          sAfterLineBreakInQuotesInNValue);
   specDefaultTransition(sAfterLineBreakInQuotesInNValue,
                         taError,
                         sAfterLineBreakInQuotesInNValue);
   specTransition(sAfterLineBreakInQuotesInNValue,
                  ccWhitespace,
                  taNone,
                  sScanNValueInQuotes);
   specDefaultTransition(sScanNValueInAngles, taNone, sScanNValueInAngles);
   specTransition(sScanNValueInAngles,
                  ccRightAngleBracket,

⌨️ 快捷键说明

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