📄 msgheaderscanner.cxx
字号:
processMsgHeaderStatusLine( SipMessage * msg, char * lineText, unsigned int lineTextLength, MsgHeaderScanner::TextPropBitMask lineTextPropBitMask){ printf("status line: "); printText(lineText, lineTextLength); printf("\n"); return true;}staticvoidprocessMsgHeaderFieldNameAndValue( 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 voidlookupMsgHeaderFieldInfo(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 boolprocessMsgHeaderStatusLine(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 voidprocessMsgHeaderFieldNameAndValue(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(); }}voidMsgHeaderScanner::prepareForMessage(SipMessage * msg){ mMsg = msg; mState = sMsgStart; mPrevScanChunkNumSavedTextChars = 0;}voidMsgHeaderScanner::prepareForFrag(SipMessage * msg, bool hasStartLine){ mMsg = msg; if (hasStartLine) { mState = sMsgStart; } else { mState = sAfterLineBreakAfterStatusLine; } mPrevScanChunkNumSavedTextChars = 0;}MsgHeaderScanner::ScanChunkResultMsgHeaderScanner::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][(size_t)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;}boolMsgHeaderScanner::initialize(){ initCharInfoArray(); initStateMachine(); return true;}} //namespace resip#if defined(RESIP_MSG_HEADER_SCANNER_DEBUG) && defined(MSG_SCANNER_STANDALONE)externintmain(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 + -