From cec5f4ae2ca9daffcd229f71e693c9910f308050 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Tue, 22 Nov 2005 23:51:50 +0000 Subject: [PATCH] More optimizations for msg parser etc. git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@77 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib-util/build/pjlib_util.dsp | 2 +- pjlib-util/include/pjlib-util/scanner.h | 79 ++++++--- pjlib-util/src/pjlib-util/scanner.c | 166 ++++++++---------- pjlib-util/src/pjlib-util/xml.c | 2 +- pjlib/include/pj/string.h | 24 ++- pjlib/include/pj/string_i.h | 47 ++++- pjlib/src/pjlib-test/string.c | 1 + pjsip/build/pjsip_core.dsp | 2 +- pjsip/include/pjsip/print_util.h | 62 ++----- pjsip/include/pjsip/sip_parser.h | 6 +- pjsip/src/pjsip/sip_endpoint.c | 4 + pjsip/src/pjsip/sip_parser.c | 221 ++++++++++++------------ pjsip/src/pjsip/sip_uri.c | 30 +++- pjsip/src/test-pjsip/msg.c | 16 +- pjsip/src/test-pjsip/test.c | 4 +- 15 files changed, 369 insertions(+), 297 deletions(-) diff --git a/pjlib-util/build/pjlib_util.dsp b/pjlib-util/build/pjlib_util.dsp index 5497aff90..692e32d89 100644 --- a/pjlib-util/build/pjlib_util.dsp +++ b/pjlib-util/build/pjlib_util.dsp @@ -41,7 +41,7 @@ RSC=rc.exe # PROP Intermediate_Dir "./output/pjlib-util-i386-win32-vc6-release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /Ob2 /I "../include" /I "../../pjlib/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /Oy /Ob2 /I "../include" /I "../../pjlib/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe diff --git a/pjlib-util/include/pjlib-util/scanner.h b/pjlib-util/include/pjlib-util/scanner.h index 1a4a69efe..b8f8f7612 100644 --- a/pjlib-util/include/pjlib-util/scanner.h +++ b/pjlib-util/include/pjlib-util/scanner.h @@ -193,12 +193,12 @@ typedef void (*pj_syn_err_func_ptr)(struct pj_scanner *scanner); */ typedef struct pj_scanner { - char *begin; /**< Start of input buffer. */ - char *end; /**< End of input buffer. */ - char *curptr; /**< Current pointer. */ - int line; /**< Current line. */ - int col; /**< Current column. */ - int skip_ws; /**< Skip whitespace flag. */ + char *begin; /**< Start of input buffer. */ + char *end; /**< End of input buffer. */ + char *curptr; /**< Current pointer. */ + int line; /**< Current line. */ + char *start_line; /**< Where current line starts. */ + int skip_ws; /**< Skip whitespace flag. */ pj_syn_err_func_ptr callback; /**< Syntax error callback. */ } pj_scanner; @@ -210,8 +210,8 @@ typedef struct pj_scanner typedef struct pj_scan_state { char *curptr; /**< Current scanner's pointer. */ - int line; /**< Current line. */ - int col; /**< Current column. */ + int line; /**< Current line. */ + char *start_line; /**< Start of current line. */ } pj_scan_state; @@ -325,7 +325,8 @@ PJ_DECL(void) pj_scan_get( pj_scanner *scanner, /** * Get characters between quotes. If current input doesn't match begin_quote, - * syntax error will be thrown. + * syntax error will be thrown. Note that the resulting string will contain + * the enclosing quote. * * @param scanner The scanner. * @param begin_quote The character to begin the quote. @@ -333,8 +334,8 @@ PJ_DECL(void) pj_scan_get( pj_scanner *scanner, * @param out String to store the result. */ PJ_DECL(void) pj_scan_get_quote( pj_scanner *scanner, - int begin_quote, int end_quote, - pj_str_t *out); + int begin_quote, int end_quote, + pj_str_t *out); /** * Get N characters from the scanner. @@ -357,15 +358,6 @@ PJ_DECL(void) pj_scan_get_n( pj_scanner *scanner, PJ_DECL(int) pj_scan_get_char( pj_scanner *scanner ); -/** - * Get a newline from the scanner. A newline is defined as '\\n', or '\\r', or - * "\\r\\n". If current input is not newline, syntax error will be thrown. - * - * @param scanner The scanner. - */ -PJ_DECL(void) pj_scan_get_newline( pj_scanner *scanner ); - - /** * Get characters from the scanner and move the scanner position until the * current character matches the spec. @@ -438,6 +430,34 @@ PJ_DECL(int) pj_scan_strcmp( pj_scanner *scanner, const char *s, int len); */ PJ_DECL(int) pj_scan_stricmp( pj_scanner *scanner, const char *s, int len); +/** + * Perform case insensitive string comparison of string in current position, + * knowing that the string to compare only consists of alphanumeric + * characters. + * + * Note that unlike #pj_scan_stricmp, this function can only return zero or + * -1. + * + * @param scanner The scanner. + * @param s The string to compare with. + * @param len Length of the string to compare with. + * + * @return zero if equal or -1. + * + * @see strnicmp_alnum, pj_stricmp_alnum + */ +PJ_DECL(int) pj_scan_stricmp_alnum( pj_scanner *scanner, const char *s, + int len); + + +/** + * Get a newline from the scanner. A newline is defined as '\\n', or '\\r', or + * "\\r\\n". If current input is not newline, syntax error will be thrown. + * + * @param scanner The scanner. + */ +PJ_DECL(void) pj_scan_get_newline( pj_scanner *scanner ); + /** * Manually skip whitespaces according to flag that was specified when @@ -448,6 +468,13 @@ PJ_DECL(int) pj_scan_stricmp( pj_scanner *scanner, const char *s, int len); PJ_DECL(void) pj_scan_skip_whitespace( pj_scanner *scanner ); +/** + * Skip current line. + * + * @param scanner The scanner. + */ +PJ_DECL(void) pj_scan_skip_line( pj_scanner *scanner ); + /** * Save the full scanner state. * @@ -468,6 +495,18 @@ PJ_DECL(void) pj_scan_save_state( pj_scanner *scanner, pj_scan_state *state); PJ_DECL(void) pj_scan_restore_state( pj_scanner *scanner, pj_scan_state *state); +/** + * Get current column position. + * + * @param scanner The scanner. + * + * @return The column position. + */ +PJ_INLINE(int) pj_scan_get_col( pj_scanner *scanner ) +{ + return scanner->curptr - scanner->start_line; +} + /** * @} */ diff --git a/pjlib-util/src/pjlib-util/scanner.c b/pjlib-util/src/pjlib-util/scanner.c index 77d2db033..f4ef54c6d 100644 --- a/pjlib-util/src/pjlib-util/scanner.c +++ b/pjlib-util/src/pjlib-util/scanner.c @@ -23,9 +23,10 @@ #include #include -#define PJ_SCAN_IS_SPACE(c) ((c)==' ' || (c)=='\t') -#define PJ_SCAN_IS_NEWLINE(c) ((c)=='\r' || (c)=='\n') -#define PJ_SCAN_CHECK_EOF(s) (s != end) +#define PJ_SCAN_IS_SPACE(c) ((c)==' ' || (c)=='\t') +#define PJ_SCAN_IS_NEWLINE(c) ((c)=='\r' || (c)=='\n') +#define PJ_SCAN_IS_PROBABLY_SPACE(c) ((c) <= 32) +#define PJ_SCAN_CHECK_EOF(s) (*s) #if defined(PJ_SCANNER_USE_BITWISE) && PJ_SCANNER_USE_BITWISE != 0 @@ -107,14 +108,12 @@ PJ_DEF(void) pj_scan_init( pj_scanner *scanner, char *bufstart, int buflen, scanner->begin = scanner->curptr = bufstart; scanner->end = bufstart + buflen; scanner->line = 1; - scanner->col = 1; + scanner->start_line = scanner->begin; scanner->callback = callback; scanner->skip_ws = options; if (scanner->skip_ws) pj_scan_skip_whitespace(scanner); - - scanner->col = scanner->curptr - scanner->begin + 1; } @@ -128,25 +127,21 @@ PJ_DEF(void) pj_scan_skip_whitespace( pj_scanner *scanner ) { register char *s = scanner->curptr; - PJ_CHECK_STACK(); - while (PJ_SCAN_IS_SPACE(*s)) { ++s; } - if ((scanner->skip_ws & PJ_SCAN_AUTOSKIP_NEWLINE) && PJ_SCAN_IS_NEWLINE(*s)) { + if (PJ_SCAN_IS_NEWLINE(*s) && (scanner->skip_ws & PJ_SCAN_AUTOSKIP_NEWLINE)) { for (;;) { if (*s == '\r') { ++s; if (*s == '\n') ++s; ++scanner->line; - scanner->col = 1; - scanner->curptr = s; + scanner->curptr = scanner->start_line = s; } else if (*s == '\n') { ++s; ++scanner->line; - scanner->col = 1; - scanner->curptr = s; + scanner->curptr = scanner->start_line = s; } else if (PJ_SCAN_IS_SPACE(*s)) { do { ++s; @@ -159,7 +154,6 @@ PJ_DEF(void) pj_scan_skip_whitespace( pj_scanner *scanner ) if (PJ_SCAN_IS_NEWLINE(*s) && (scanner->skip_ws & PJ_SCAN_AUTOSKIP_WS_HEADER)==PJ_SCAN_AUTOSKIP_WS_HEADER) { /* Check for header continuation. */ - scanner->col += s - scanner->curptr; scanner->curptr = s; if (*s == '\r') { @@ -168,6 +162,8 @@ PJ_DEF(void) pj_scan_skip_whitespace( pj_scanner *scanner ) if (*s == '\n') { ++s; } + scanner->start_line = s; + if (PJ_SCAN_IS_SPACE(*s)) { register char *t = s; do { @@ -175,33 +171,43 @@ PJ_DEF(void) pj_scan_skip_whitespace( pj_scanner *scanner ) } while (PJ_SCAN_IS_SPACE(*t)); ++scanner->line; - scanner->col = t-s; scanner->curptr = t; } } else { - scanner->col += s - scanner->curptr; scanner->curptr = s; } } +PJ_DEF(void) pj_scan_skip_line( pj_scanner *scanner ) +{ + char *s = pj_native_strchr(scanner->curptr, '\n'); + if (!s) { + scanner->curptr = scanner->end; + } else { + scanner->curptr = scanner->start_line = s+1; + scanner->line++; + if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) { + pj_scan_skip_whitespace(scanner); + } + } +} + PJ_DEF(int) pj_scan_peek( pj_scanner *scanner, const pj_cis_t *spec, pj_str_t *out) { register char *s = scanner->curptr; - register char *end = scanner->end; - PJ_CHECK_STACK(); - - if (pj_scan_is_eof(scanner)) { + if (s >= scanner->end) { pj_scan_syntax_err(scanner); return -1; } - while (PJ_SCAN_CHECK_EOF(s) && pj_cis_match(spec, *s)) + /* Don't need to check EOF with PJ_SCAN_CHECK_EOF(s) */ + while (pj_cis_match(spec, *s)) ++s; pj_strset3(out, scanner->curptr, s); - return s < scanner->end ? *s : 0; + return *s; } @@ -210,8 +216,6 @@ PJ_DEF(int) pj_scan_peek_n( pj_scanner *scanner, { char *endpos = scanner->curptr + len; - PJ_CHECK_STACK(); - if (endpos > scanner->end) { pj_scan_syntax_err(scanner); return -1; @@ -227,11 +231,8 @@ PJ_DEF(int) pj_scan_peek_until( pj_scanner *scanner, pj_str_t *out) { register char *s = scanner->curptr; - register char *end = scanner->end; - PJ_CHECK_STACK(); - - if (pj_scan_is_eof(scanner)) { + if (s >= scanner->end) { pj_scan_syntax_err(scanner); return -1; } @@ -240,7 +241,7 @@ PJ_DEF(int) pj_scan_peek_until( pj_scanner *scanner, ++s; pj_strset3(out, scanner->curptr, s); - return s!=scanner->end ? *s : 0; + return *s; } @@ -248,14 +249,11 @@ PJ_DEF(void) pj_scan_get( pj_scanner *scanner, const pj_cis_t *spec, pj_str_t *out) { register char *s = scanner->curptr; - register char *end = scanner->end; - char *start = s; - - PJ_CHECK_STACK(); pj_assert(pj_cis_match(spec,0)==0); - if (pj_scan_is_eof(scanner) || !pj_cis_match(spec, *s)) { + /* EOF is detected implicitly */ + if (!pj_cis_match(spec, *s)) { pj_scan_syntax_err(scanner); return; } @@ -270,10 +268,9 @@ PJ_DEF(void) pj_scan_get( pj_scanner *scanner, pj_strset3(out, scanner->curptr, s); - scanner->col += (s - start); scanner->curptr = s; - if (scanner->skip_ws) { + if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) { pj_scan_skip_whitespace(scanner); } } @@ -284,11 +281,7 @@ PJ_DEF(void) pj_scan_get_quote( pj_scanner *scanner, pj_str_t *out) { register char *s = scanner->curptr; - register char *end = scanner->end; - char *start = s; - PJ_CHECK_STACK(); - /* Check and eat the begin_quote. */ if (*s != begin_quote) { pj_scan_syntax_err(scanner); @@ -300,9 +293,9 @@ PJ_DEF(void) pj_scan_get_quote( pj_scanner *scanner, */ do { /* loop until end_quote is found. */ - do { + while (*s && *s != '\n' && *s != end_quote) { ++s; - } while (s != end && *s != '\n' && *s != end_quote); + } /* check that no backslash character precedes the end_quote. */ if (*s == end_quote) { @@ -318,8 +311,10 @@ PJ_DEF(void) pj_scan_get_quote( pj_scanner *scanner, } /* break from main loop if we have odd number of backslashes */ if (((unsigned)(q-r) & 0x01) == 1) { + ++s; break; } + ++s; } } else { /* end_quote is not preceeded by backslash. break now. */ @@ -340,34 +335,26 @@ PJ_DEF(void) pj_scan_get_quote( pj_scanner *scanner, pj_strset3(out, scanner->curptr, s); - scanner->col += (s - start); scanner->curptr = s; - if (scanner->skip_ws) { + if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) { pj_scan_skip_whitespace(scanner); } } PJ_DEF(void) pj_scan_get_n( pj_scanner *scanner, - unsigned N, pj_str_t *out) + unsigned N, pj_str_t *out) { - register char *s = scanner->curptr; - char *start = scanner->curptr; - - PJ_CHECK_STACK(); - if (scanner->curptr + N > scanner->end) { pj_scan_syntax_err(scanner); return; } - pj_strset(out, s, N); + pj_strset(out, scanner->curptr, N); - s += N; - scanner->col += (s - start); - scanner->curptr = s; + scanner->curptr += N; - if (scanner->skip_ws) { + if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws) { pj_scan_skip_whitespace(scanner); } } @@ -375,20 +362,16 @@ PJ_DEF(void) pj_scan_get_n( pj_scanner *scanner, PJ_DEF(int) pj_scan_get_char( pj_scanner *scanner ) { - char *start = scanner->curptr; - int chr = *start; + int chr = *scanner->curptr; - PJ_CHECK_STACK(); - - if (pj_scan_is_eof(scanner)) { + if (!chr) { pj_scan_syntax_err(scanner); return 0; } ++scanner->curptr; - scanner->col += (scanner->curptr - start); - if (scanner->skip_ws) { + if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws) { pj_scan_skip_whitespace(scanner); } return chr; @@ -397,8 +380,6 @@ PJ_DEF(int) pj_scan_get_char( pj_scanner *scanner ) PJ_DEF(void) pj_scan_get_newline( pj_scanner *scanner ) { - PJ_CHECK_STACK(); - if (!PJ_SCAN_IS_NEWLINE(*scanner->curptr)) { pj_scan_syntax_err(scanner); return; @@ -412,9 +393,9 @@ PJ_DEF(void) pj_scan_get_newline( pj_scanner *scanner ) } ++scanner->line; - scanner->col = 1; + scanner->start_line = scanner->curptr; - if (scanner->skip_ws) { + if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws) { pj_scan_skip_whitespace(scanner); } } @@ -424,12 +405,8 @@ PJ_DEF(void) pj_scan_get_until( pj_scanner *scanner, const pj_cis_t *spec, pj_str_t *out) { register char *s = scanner->curptr; - register char *end = scanner->end; - char *start = s; - PJ_CHECK_STACK(); - - if (pj_scan_is_eof(scanner)) { + if (s >= scanner->end) { pj_scan_syntax_err(scanner); return; } @@ -440,10 +417,9 @@ PJ_DEF(void) pj_scan_get_until( pj_scanner *scanner, pj_strset3(out, scanner->curptr, s); - scanner->col += (s - start); scanner->curptr = s; - if (scanner->skip_ws) { + if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) { pj_scan_skip_whitespace(scanner); } } @@ -453,12 +429,8 @@ PJ_DEF(void) pj_scan_get_until_ch( pj_scanner *scanner, int until_char, pj_str_t *out) { register char *s = scanner->curptr; - register char *end = scanner->end; - char *start = s; - PJ_CHECK_STACK(); - - if (pj_scan_is_eof(scanner)) { + if (s >= scanner->end) { pj_scan_syntax_err(scanner); return; } @@ -469,10 +441,9 @@ PJ_DEF(void) pj_scan_get_until_ch( pj_scanner *scanner, pj_strset3(out, scanner->curptr, s); - scanner->col += (s - start); scanner->curptr = s; - if (scanner->skip_ws) { + if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) { pj_scan_skip_whitespace(scanner); } } @@ -482,26 +453,23 @@ PJ_DEF(void) pj_scan_get_until_chr( pj_scanner *scanner, const char *until_spec, pj_str_t *out) { register char *s = scanner->curptr; - register char *end = scanner->end; - char *start = scanner->curptr; + int speclen; - PJ_CHECK_STACK(); - - if (pj_scan_is_eof(scanner)) { + if (s >= scanner->end) { pj_scan_syntax_err(scanner); return; } - while (PJ_SCAN_CHECK_EOF(s) && !strchr(until_spec, *s)) { + speclen = strlen(until_spec); + while (PJ_SCAN_CHECK_EOF(s) && !memchr(until_spec, *s, speclen)) { ++s; } pj_strset3(out, scanner->curptr, s); - scanner->col += (s - start); scanner->curptr = s; - if (scanner->skip_ws) { + if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) { pj_scan_skip_whitespace(scanner); } } @@ -511,17 +479,14 @@ PJ_DEF(void) pj_scan_advance_n( pj_scanner *scanner, { char *start = scanner->curptr; - PJ_CHECK_STACK(); - if (scanner->curptr + N > scanner->end) { pj_scan_syntax_err(scanner); return; } scanner->curptr += N; - scanner->col += (scanner->curptr - start); - if (skip_ws) { + if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && skip_ws) { pj_scan_skip_whitespace(scanner); } } @@ -546,25 +511,30 @@ PJ_DEF(int) pj_scan_stricmp( pj_scanner *scanner, const char *s, int len) return strnicmp(scanner->curptr, s, len); } +PJ_DEF(int) pj_scan_stricmp_alnum( pj_scanner *scanner, const char *s, + int len) +{ + if (scanner->curptr + len > scanner->end) { + pj_scan_syntax_err(scanner); + return -1; + } + return strnicmp_alnum(scanner->curptr, s, len); +} PJ_DEF(void) pj_scan_save_state( pj_scanner *scanner, pj_scan_state *state) { - PJ_CHECK_STACK(); - state->curptr = scanner->curptr; state->line = scanner->line; - state->col = scanner->col; + state->start_line = scanner->start_line; } PJ_DEF(void) pj_scan_restore_state( pj_scanner *scanner, pj_scan_state *state) { - PJ_CHECK_STACK(); - scanner->curptr = state->curptr; scanner->line = state->line; - scanner->col = state->col; + scanner->start_line = state->start_line; } diff --git a/pjlib-util/src/pjlib-util/xml.c b/pjlib-util/src/pjlib-util/xml.c index 35ec96c53..f502df0e7 100644 --- a/pjlib-util/src/pjlib-util/xml.c +++ b/pjlib-util/src/pjlib-util/xml.c @@ -173,7 +173,7 @@ PJ_DEF(pj_xml_node*) pj_xml_parse( pj_pool_t *pool, char *msg, pj_size_t len) } PJ_CATCH_ANY { PJ_LOG(4,(THIS_FILE, "Syntax error parsing XML in line %d column %d", - scanner.line, scanner.col)); + scanner.line, pj_scan_get_col(&scanner))); } PJ_END; pj_scan_fini( &scanner ); diff --git a/pjlib/include/pj/string.h b/pjlib/include/pj/string.h index 83f6ab73e..d6fe54ce9 100644 --- a/pjlib/include/pj/string.h +++ b/pjlib/include/pj/string.h @@ -342,11 +342,29 @@ PJ_IDECL(int) pj_stricmp(const pj_str_t *str1, const pj_str_t *str2); /** * Perform lowercase comparison to the strings which consists of only * alnum characters. More over, it will only return non-zero if both - * strings are not equal, and is not able to detect which string is - * 'less'. + * strings are not equal, not the usual negative or positive value. * * If non-alnum inputs are given, then the function may mistakenly - * treat two strings as equal while they're not. + * treat two strings as equal. + * + * @param str1 The string to compare. + * @param str2 The string to compare. + * @param len The length to compare. + * + * @return + * - 0 if str1 is equal to str2 + * - (-1) if not equal. + */ +PJ_IDECL(int) strnicmp_alnum(const char *str1, const char *str2, + int len); + +/** + * Perform lowercase comparison to the strings which consists of only + * alnum characters. More over, it will only return non-zero if both + * strings are not equal, not the usual negative or positive value. + * + * If non-alnum inputs are given, then the function may mistakenly + * treat two strings as equal. * * @param str1 The string to compare. * @param str2 The string to compare. diff --git a/pjlib/include/pj/string_i.h b/pjlib/include/pj/string_i.h index f800ba846..91aebfb09 100644 --- a/pjlib/include/pj/string_i.h +++ b/pjlib/include/pj/string_i.h @@ -169,6 +169,39 @@ PJ_IDEF(int) pj_stricmp( const pj_str_t *str1, const pj_str_t *str2) } } +PJ_IDEF(int) strnicmp_alnum( const char *str1, const char *str2, + int len) +{ + if (len==0) + return 0; + else { + register const pj_uint32_t *p1 = (pj_uint32_t*)str1, + *p2 = (pj_uint32_t*)str2; + while (len > 3 && (*p1 & 0x5F5F5F5F)==(*p2 & 0x5F5F5F5F)) + ++p1, ++p2, len-=4; + + if (len > 3) + return -1; +#if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0 + else if (len==3) + return ((*p1 & 0x005F5F5F)==(*p2 & 0x005F5F5F)) ? 0 : -1; + else if (len==2) + return ((*p1 & 0x00005F5F)==(*p2 & 0x00005F5F)) ? 0 : -1; + else if (len==1) + return ((*p1 & 0x0000005F)==(*p2 & 0x0000005F)) ? 0 : -1; +#else + else if (len==3) + return ((*p1 & 0x5F5F5F00)==(*p2 & 0x5F5F5F00)) ? 0 : -1; + else if (len==2) + return ((*p1 & 0x5F5F0000)==(*p2 & 0x5F5F0000)) ? 0 : -1; + else if (len==1) + return ((*p1 & 0x5F000000)==(*p2 & 0x5F000000)) ? 0 : -1; +#endif + else + return 0; + } +} + PJ_IDEF(int) pj_stricmp_alnum(const pj_str_t *str1, const pj_str_t *str2) { register int len = str1->slen; @@ -180,25 +213,25 @@ PJ_IDEF(int) pj_stricmp_alnum(const pj_str_t *str1, const pj_str_t *str2) } else { register const pj_uint32_t *p1 = (pj_uint32_t*)str1->ptr, *p2 = (pj_uint32_t*)str2->ptr; - while (len > 3 && (*p1 & 0x1F1F1F1F)==(*p2 & 0x1F1F1F1F)) + while (len > 3 && (*p1 & 0x5F5F5F5F)==(*p2 & 0x5F5F5F5F)) ++p1, ++p2, len-=4; if (len > 3) return -1; #if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0 else if (len==3) - return ((*p1 & 0x001F1F1F)==(*p2 & 0x001F1F1F)) ? 0 : -1; + return ((*p1 & 0x005F5F5F)==(*p2 & 0x005F5F5F)) ? 0 : -1; else if (len==2) - return ((*p1 & 0x00001F1F)==(*p2 & 0x00001F1F)) ? 0 : -1; + return ((*p1 & 0x00005F5F)==(*p2 & 0x00005F5F)) ? 0 : -1; else if (len==1) - return ((*p1 & 0x0000001F)==(*p2 & 0x0000001F)) ? 0 : -1; + return ((*p1 & 0x0000005F)==(*p2 & 0x0000005F)) ? 0 : -1; #else else if (len==3) - return ((*p1 & 0x1F1F1F00)==(*p2 & 0x1F1F1F00)) ? 0 : -1; + return ((*p1 & 0x5F5F5F00)==(*p2 & 0x5F5F5F00)) ? 0 : -1; else if (len==2) - return ((*p1 & 0x1F1F0000)==(*p2 & 0x1F1F0000)) ? 0 : -1; + return ((*p1 & 0x5F5F0000)==(*p2 & 0x5F5F0000)) ? 0 : -1; else if (len==1) - return ((*p1 & 0x1F000000)==(*p2 & 0x1F000000)) ? 0 : -1; + return ((*p1 & 0x5F000000)==(*p2 & 0x5F000000)) ? 0 : -1; #endif else return 0; diff --git a/pjlib/src/pjlib-test/string.c b/pjlib/src/pjlib-test/string.c index fd94b03c1..ba7c9144d 100644 --- a/pjlib/src/pjlib-test/string.c +++ b/pjlib/src/pjlib-test/string.c @@ -103,6 +103,7 @@ static int stricmp_test(void) len=1; STRTEST( 0, "a",buf+0,-510); STRTEST( 0, "a",buf+1,-512); + STRTEST( -1, "0", "P", -514); /* equal, length=2 * use buffer to simulate non-aligned string. diff --git a/pjsip/build/pjsip_core.dsp b/pjsip/build/pjsip_core.dsp index 11de7fd3d..92a6353f0 100644 --- a/pjsip/build/pjsip_core.dsp +++ b/pjsip/build/pjsip_core.dsp @@ -41,7 +41,7 @@ RSC=rc.exe # PROP Intermediate_Dir ".\output\pjsip-core-i386-win32-vc6-release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /MD /W4 /Zi /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c +# ADD CPP /nologo /MD /W4 /Zi /O2 /Oy /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" diff --git a/pjsip/include/pjsip/print_util.h b/pjsip/include/pjsip/print_util.h index b1362a720..c72d1ab2f 100644 --- a/pjsip/include/pjsip/print_util.h +++ b/pjsip/include/pjsip/print_util.h @@ -19,53 +19,29 @@ #ifndef __PJSIP_PRINT_H__ #define __PJSIP_PRINT_H__ -/* Minimum space left in the buffer */ -#define MIN_SPACE 10 - #define copy_advance_check(buf,str) \ do { \ - if ((str).slen+MIN_SPACE >= (endbuf-buf)) return -1; \ + if ((str).slen >= (endbuf-buf)) return -1; \ pj_memcpy(buf, (str).ptr, (str).slen); \ buf += (str).slen; \ } while (0) -/* -static char *imp_copy_advance_pair(char *buf, char *endbuf, const char *str1, int len1, const pj_str_t *str2) -{ - if (str2->slen) { - int printed = len1+str2->slen; - if (printed+MIN_SPACE >= (endbuf-buf)) return NULL; - pj_memcpy(buf,str1,len1); - pj_memcpy(buf+len1, str2->ptr, str2->slen); - return buf + printed; - } else - return buf; -} -*/ - #define copy_advance_pair_check(buf,str1,len1,str2) \ do { \ if (str2.slen) { \ printed = len1+str2.slen; \ - if (printed+MIN_SPACE >= (endbuf-buf)) return -1; \ + if (printed >= (endbuf-buf)) return -1; \ pj_memcpy(buf,str1,len1); \ pj_memcpy(buf+len1, str2.ptr, str2.slen); \ buf += printed; \ } \ } while (0) -/* -#define copy_advance_pair(buf,str1,len1,str2) \ - do { \ - buf = imp_copy_advance_pair(buf, endbuf, str1, len1, &str2); \ - if (buf == NULL) return -1; \ - } while (0) -*/ #define copy_advance_pair_quote_check(buf,str1,len1,str2,quotebegin,quoteend) \ do { \ if (str2.slen) { \ printed = len1+str2.slen+2; \ - if (printed+MIN_SPACE >= (endbuf-buf)) return -1; \ + if (printed >= (endbuf-buf)) return -1; \ pj_memcpy(buf,str1,len1); \ *(buf+len1)=quotebegin; \ pj_memcpy(buf+len1+1, str2.ptr, str2.slen); \ @@ -76,16 +52,13 @@ static char *imp_copy_advance_pair(char *buf, char *endbuf, const char *str1, in #define copy_advance_pair_escape(buf,str1,len1,str2,unres) \ do { \ - if (str2.slen) { \ - pj_ssize_t esc_len; \ - if (len1+str2.slen+MIN_SPACE >= (endbuf-buf)) return -1; \ - pj_memcpy(buf,str1,len1); \ - buf += len1; \ - esc_len=pj_strncpy2_escape(buf, &str2, (endbuf-buf), &unres); \ - if (esc_len < 0) return -1; \ - buf += esc_len; \ - if (endbuf-buf < MIN_SPACE) return -1; \ - } \ + if (str2.slen) { \ + if (len1+str2.slen >= (endbuf-buf)) return -1; \ + pj_memcpy(buf,str1,len1); \ + printed=pj_strncpy2_escape(buf,&str2,(endbuf-buf-len1),&unres);\ + if (printed < 0) return -1; \ + buf += (printed+len1); \ + } \ } while (0) @@ -97,11 +70,10 @@ static char *imp_copy_advance_pair(char *buf, char *endbuf, const char *str1, in #define copy_advance_escape(buf,str,unres) \ do { \ - pj_ssize_t len = \ + printed = \ pj_strncpy2_escape(buf, &(str), (endbuf-buf), &(unres)); \ - if (len < 0) return -1; \ - buf += len; \ - if (endbuf-buf < MIN_SPACE) return -1; \ + if (printed < 0) return -1; \ + buf += printed; \ } while (0) #define copy_advance_pair_no_check(buf,str1,len1,str2) \ @@ -117,10 +89,10 @@ static char *imp_copy_advance_pair(char *buf, char *endbuf, const char *str1, in #define copy_advance_pair_quote_cond(buf,str1,len1,str2,quotebegin,quoteend) \ do { \ - if (str2.slen && *str2.ptr!=quotebegin) \ - copy_advance_pair_quote(buf,str1,len1,str2,quotebegin,quoteend); \ - else \ - copy_advance_pair(buf,str1,len1,str2); \ + if (str2.slen && *str2.ptr!=quotebegin) \ + copy_advance_pair_quote(buf,str1,len1,str2,quotebegin,quoteend); \ + else \ + copy_advance_pair(buf,str1,len1,str2); \ } while (0) /* diff --git a/pjsip/include/pjsip/sip_parser.h b/pjsip/include/pjsip/sip_parser.h index 389e63422..d6e46e5f8 100644 --- a/pjsip/include/pjsip/sip_parser.h +++ b/pjsip/include/pjsip/sip_parser.h @@ -307,8 +307,10 @@ extern pj_cis_t pjsip_PROBE_USER_HOST_SPEC, /**< Hostname characters. */ pjsip_PASSWD_SPEC, /**< Password. */ pjsip_USER_SPEC, /**< User */ - pjsip_NEWLINE_OR_EOF_SPEC, /**< For eating up header.*/ - pjsip_DISPLAY_SCAN_SPEC; /**< Used when searching for display name. */ + pjsip_NOT_NEWLINE, /**< For eating up header, basicly any chars + except newlines or zero. */ + pjsip_NOT_COMMA_OR_NEWLINE, /**< Array elements. */ + pjsip_DISPLAY_SPEC; /**< Used when searching for display name. */ /* * Various string constants. diff --git a/pjsip/src/pjsip/sip_endpoint.c b/pjsip/src/pjsip/sip_endpoint.c index 53311f366..79cd68a59 100644 --- a/pjsip/src/pjsip/sip_endpoint.c +++ b/pjsip/src/pjsip/sip_endpoint.c @@ -104,6 +104,7 @@ struct pjsip_endpoint static void endpt_transport_callback(pjsip_endpoint*, pj_status_t, pjsip_rx_data*); +void init_sip_parser(void); /* * This is the global handler for memory allocation failure, for pools that @@ -373,6 +374,9 @@ PJ_DEF(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf, endpt->pool = pool; endpt->pf = pf; + /* Init parser. */ + init_sip_parser(); + /* Get name. */ if (name != NULL) { pj_str_t temp; diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c index 49b735b93..6a9828c42 100644 --- a/pjsip/src/pjsip/sip_parser.c +++ b/pjsip/src/pjsip/sip_parser.c @@ -65,7 +65,6 @@ static handler_rec handler[127]; static unsigned handler_count; static int parser_is_initialized; - /* * Global vars (also extern). */ @@ -101,9 +100,9 @@ pj_cis_t pjsip_HOST_SPEC, /* For scanning host part. */ pjsip_PROBE_USER_HOST_SPEC, /* Hostname characters. */ pjsip_PASSWD_SPEC, /* Password. */ pjsip_USER_SPEC, /* User */ - pjsip_ARRAY_ELEMENTS, /* Array separator. */ - pjsip_NEWLINE_OR_EOF_SPEC, /* For eating up header.*/ - pjsip_DISPLAY_SCAN_SPEC; /* Used when searching for display name + pjsip_NOT_COMMA_OR_NEWLINE, /* Array separator. */ + pjsip_NOT_NEWLINE, /* For eating up header.*/ + pjsip_DISPLAY_SPEC; /* Used when searching for display name * in URL. */ @@ -258,14 +257,15 @@ static pj_status_t init_parser() pj_cis_add_alpha( &pjsip_ALNUM_SPEC ); pj_cis_add_num( &pjsip_ALNUM_SPEC ); - status = pj_cis_init(&cis_buf, &pjsip_NEWLINE_OR_EOF_SPEC); + status = pj_cis_init(&cis_buf, &pjsip_NOT_NEWLINE); PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); - pj_cis_add_str(&pjsip_NEWLINE_OR_EOF_SPEC, "\r\n"); - //pj_cs_set(pjsip_NEWLINE_OR_EOF_SPEC, 0); + pj_cis_add_str(&pjsip_NOT_NEWLINE, "\r\n"); + pj_cis_invert(&pjsip_NOT_NEWLINE); - status = pj_cis_init(&cis_buf, &pjsip_ARRAY_ELEMENTS); + status = pj_cis_init(&cis_buf, &pjsip_NOT_COMMA_OR_NEWLINE); PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); - pj_cis_add_str( &pjsip_ARRAY_ELEMENTS, ",\r\n"); + pj_cis_add_str( &pjsip_NOT_COMMA_OR_NEWLINE, ",\r\n"); + pj_cis_invert(&pjsip_NOT_COMMA_OR_NEWLINE); status = pj_cis_dup(&pjsip_TOKEN_SPEC, &pjsip_ALNUM_SPEC); PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); @@ -300,9 +300,10 @@ static pj_status_t init_parser() pj_cis_add_str( &pjsip_PROBE_USER_HOST_SPEC, "@ \n>"); pj_cis_invert( &pjsip_PROBE_USER_HOST_SPEC ); - status = pj_cis_init(&cis_buf, &pjsip_DISPLAY_SCAN_SPEC); + status = pj_cis_init(&cis_buf, &pjsip_DISPLAY_SPEC); PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); - pj_cis_add_str( &pjsip_DISPLAY_SCAN_SPEC, ":\r\n<"); + pj_cis_add_str( &pjsip_DISPLAY_SPEC, ":\r\n<"); + pj_cis_invert(&pjsip_DISPLAY_SPEC); status = pjsip_register_hdr_parser( "Accept", NULL, &parse_hdr_accept); PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); @@ -374,7 +375,7 @@ static pj_status_t init_parser() return status; } -static void init_sip_parser(void) +void init_sip_parser(void) { if (!parser_is_initialized) { /* Prevent race cond. */ @@ -392,23 +393,27 @@ static void init_sip_parser(void) * - <0 if handler is 'less' than the header name. * - >0 if handler is 'greater' than header name. */ -static int compare_handler( const handler_rec *r1, +PJ_INLINE(int) compare_handler( const handler_rec *r1, const char *name, pj_size_t name_len, pj_uint32_t hash ) { - /* Compare length. */ - if (r1->hname_len < name_len) - return -1; - if (r1->hname_len > name_len) - return 1; + PJ_UNUSED_ARG(name_len); - /* Length is equal, compare hashed value. */ + /* Compare hashed value. */ if (r1->hname_hash < hash) return -1; if (r1->hname_hash > hash) return 1; + /* Compare length. */ + /* + if (r1->hname_len < name_len) + return -1; + if (r1->hname_len > name_len) + return 1; + */ + /* Equal length and equal hash. compare the strings. */ return pj_native_strcmp(r1->hname, name); } @@ -609,19 +614,20 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size, /* Find the end of header area by finding an empty line. */ - if ((pos = pj_native_strstr(buf, "\n\r\n")) == NULL) { + pos = pj_native_strstr(buf, "\n\r\n"); + if (pos == NULL) { return PJSIP_EPARTIALMSG; } - + hdr_end = pos+1; body_start = pos+3; /* Find "Content-Length" header the hard way. */ line = pj_native_strchr(buf, '\n'); - while (line && line < hdr_end-14) { + while (line && line < hdr_end) { ++line; if ( ((*line=='C' || *line=='c') && - pj_native_strncasecmp(line, "Content-Length", 14) == 0) || + strnicmp_alnum(line, "Content-Length", 14) == 0) || ((*line=='l' || *line=='L') && (*(line+1)==' ' || *(line+1)=='\t' || *(line+1)==':'))) { @@ -744,22 +750,20 @@ static int generic_print_body (pjsip_msg_body *msg_body, static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx, pjsip_parser_err_report *err_list) { - int ch; pjsip_msg *msg; + pj_str_t hname; pjsip_ctype_hdr *ctype_hdr = NULL; pj_scanner *scanner = ctx->scanner; pj_pool_t *pool = ctx->pool; PJ_USE_EXCEPTION; /* Skip leading newlines. */ - ch = *scanner->curptr; - while (ch=='\r' || ch=='\n') { - pj_scan_get_char(scanner); - ch = *scanner->curptr; + while (*scanner->curptr=='\r' || *scanner->curptr=='\n') { + pj_scan_get_newline(scanner); } /* Parse request or status line */ - if (pj_scan_stricmp( scanner, PJSIP_VERSION, 7) == 0) { + if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION, 7) == 0) { msg = pjsip_msg_create(pool, PJSIP_RESPONSE_MSG); int_parse_status_line( scanner, &msg->line.status ); } else { @@ -768,22 +772,23 @@ static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx, } /* Parse headers. */ - do { - pj_str_t hname; - pjsip_parse_hdr_func * handler; - pjsip_hdr *hdr = NULL; +parse_headers: - /* Get hname. */ - pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &hname); - ch = pj_scan_get_char( scanner ); - if (ch != ':') { - PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); - } - - /* Find handler. */ - handler = find_handler(&hname); - - PJ_TRY { + PJ_TRY + { + do { + pjsip_parse_hdr_func * handler; + pjsip_hdr *hdr = NULL; + + /* Get hname. */ + pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &hname); + if (pj_scan_get_char( scanner ) != ':') { + PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); + } + + /* Find handler. */ + handler = find_handler(&hname); + /* Call the handler if found. * If no handler is found, then treat the header as generic * hname/hvalue pair. @@ -795,46 +800,15 @@ static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx, hdr->type = PJSIP_H_OTHER; hdr->name = hdr->sname = hname; } - + /* Check if we've just parsed a Content-Type header. - * We will check for a message body if we've got Content-Type header. + * We will check for a message body if we've got Content-Type + * header. */ if (hdr->type == PJSIP_H_CONTENT_TYPE) { ctype_hdr = (pjsip_ctype_hdr*)hdr; } - - } - PJ_CATCH_ANY { - /* Exception was thrown during parsing. - * Skip until newline, and parse next header. - */ - pj_str_t token; - hdr = NULL; - - //PJ_LOG(4,("sipparser", - // "Syntax error in line %d col %d (hname=%.*s)", - // scanner->line, scanner->col, hname.slen, hname.ptr)); - - if (err_list) { - pjsip_parser_err_report *err_info; - err_info = pj_pool_alloc(pool, sizeof(*err_info)); - err_info->except_code = PJ_GET_EXCEPTION(); - err_info->line = scanner->line; - err_info->col = scanner->col; - err_info->hname = hname; - - pj_list_insert_before(err_list, err_info); - } - - if (!pj_scan_is_eof(scanner)) { - pj_scan_get_until(scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &token); - parse_hdr_end(scanner); - } - } - PJ_END; - - if (hdr) { /* Single parse of header line can produce multiple headers. * For example, if one Contact: header contains Contact list * separated by comma, then these Contacts will be split into @@ -842,11 +816,44 @@ static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx, * So here we must insert list instead of just insert one header. */ pj_list_insert_nodes_before(&msg->hdr, hdr); + + /* Parse until EOF or an empty line is found. */ + } while (!pj_scan_is_eof(scanner) && + *scanner->curptr != '\r' && *scanner->curptr != '\n'); + + } + PJ_CATCH_ANY + { + /* Exception was thrown during parsing. + * Skip until newline, and parse next header. + */ + pj_str_t token; + + if (err_list) { + pjsip_parser_err_report *err_info; + + err_info = pj_pool_alloc(pool, sizeof(*err_info)); + err_info->except_code = PJ_GET_EXCEPTION(); + err_info->line = scanner->line; + err_info->col = pj_scan_get_col(scanner); + err_info->hname = hname; + + pj_list_insert_before(err_list, err_info); + } + + if (!pj_scan_is_eof(scanner)) { + pj_scan_get(scanner, &pjsip_NOT_NEWLINE, &token); + parse_hdr_end(scanner); } - /* Parse until EOF or an empty line is found. */ - } while (!pj_scan_is_eof(scanner) && - *scanner->curptr != '\r' && *scanner->curptr != '\n'); + if (!pj_scan_is_eof(scanner) && + *scanner->curptr != '\r' && *scanner->curptr != '\n'); + { + goto parse_headers; + } + } + PJ_END; + /* If empty line is found, eat it. */ if (!pj_scan_is_eof(scanner)) { @@ -858,9 +865,10 @@ static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx, /* If we have Content-Type header, treat the rest of the message as body.*/ if (ctype_hdr && scanner->curptr!=scanner->end) { pjsip_msg_body *body = pj_pool_alloc(pool, sizeof(pjsip_msg_body)); - pj_strdup(pool, &body->content_type.type, &ctype_hdr->media.type); - pj_strdup(pool, &body->content_type.subtype, &ctype_hdr->media.subtype); - pj_strdup(pool, &body->content_type.param, &ctype_hdr->media.param); + body->content_type.type = ctype_hdr->media.type; + body->content_type.subtype = ctype_hdr->media.subtype; + body->content_type.param = ctype_hdr->media.param; + body->data = scanner->curptr; body->len = scanner->end - scanner->curptr; body->print_body = &generic_print_body; @@ -1001,16 +1009,12 @@ static pjsip_uri *int_parse_uri_or_name_addr( pj_scanner *scanner, pj_pool_t *po uri = (pjsip_uri*)int_parse_name_addr( scanner, pool ); is_name_addr = 1; } else { - pj_scan_state backtrack; pj_str_t scheme; - int colon; + int next_ch; - pj_scan_save_state( scanner, &backtrack); - pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &scheme); - colon = pj_scan_get_char( scanner ); - pj_scan_restore_state( scanner, &backtrack); + next_ch = pj_scan_peek( scanner, &pjsip_DISPLAY_SPEC, &scheme); - if (colon==':' && + if (next_ch==':' && (parser_stricmp(scheme, pjsip_SIP_STR)==0 || parser_stricmp(scheme, pjsip_SIPS_STR)==0)) { @@ -1018,7 +1022,7 @@ static pjsip_uri *int_parse_uri_or_name_addr( pj_scanner *scanner, pj_pool_t *po int_parse_sip_url( scanner, pool, (opt & PJSIP_PARSE_URI_IN_FROM_TO_HDR)== 0); - } else if (colon==':' && parser_stricmp( scheme, pjsip_TEL_STR)==0) { + } else if (next_ch==':') { /* Not supported. */ PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); @@ -1189,7 +1193,7 @@ static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner, * We're only interested in display name, because SIP URL * will be parser later. */ - next = pj_scan_peek_until(scanner, &pjsip_DISPLAY_SCAN_SPEC, &dummy); + next = pj_scan_peek(scanner, &pjsip_DISPLAY_SPEC, &dummy); if (next == '<') { /* Ok, this is what we're looking for, a display name. */ pj_scan_get_until_ch( scanner, '<', &name_addr->display); @@ -1205,8 +1209,10 @@ static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner, if (has_bracket) pj_scan_get_char(scanner); name_addr->uri = int_parse_uri( scanner, pool, PJ_TRUE ); - if (has_bracket) - pj_scan_get_char(scanner); + if (has_bracket) { + if (pj_scan_get_char(scanner) != '>') + PJ_THROW( PJSIP_SYN_ERR_EXCEPTION); + } return name_addr; } @@ -1222,7 +1228,7 @@ static void int_parse_req_line( pj_scanner *scanner, pj_pool_t *pool, pjsip_method_init_np( &req_line->method, &token); req_line->uri = int_parse_uri(scanner, pool, PJ_TRUE); - if (pj_scan_stricmp( scanner, PJSIP_VERSION, 7) != 0) + if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION, 7) != 0) PJ_THROW( PJSIP_SYN_ERR_EXCEPTION); pj_scan_advance_n (scanner, 7, 1); pj_scan_get_newline( scanner ); @@ -1234,14 +1240,13 @@ static void int_parse_status_line( pj_scanner *scanner, { pj_str_t token; - if (pj_scan_stricmp(scanner, PJSIP_VERSION, 7) != 0) + if (pj_scan_stricmp_alnum(scanner, PJSIP_VERSION, 7) != 0) PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); pj_scan_advance_n( scanner, 7, 1); pj_scan_get( scanner, &pjsip_DIGIT_SPEC, &token); status_line->code = pj_strtoul(&token); - pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC, - &status_line->reason); + pj_scan_get( scanner, &pjsip_NOT_NEWLINE, &status_line->reason); pj_scan_get_newline( scanner ); } @@ -1267,13 +1272,13 @@ void pjsip_parse_end_hdr_imp( pj_scanner *scanner ) static void parse_generic_array_hdr( pjsip_generic_array_hdr *hdr, pj_scanner *scanner) { - pj_scan_get_until( scanner, &pjsip_ARRAY_ELEMENTS, &hdr->values[0]); + pj_scan_get( scanner, &pjsip_NOT_COMMA_OR_NEWLINE, &hdr->values[0]); hdr->count++; while (*scanner->curptr == ',') { pj_scan_get_char(scanner); - pj_scan_get_until( scanner, &pjsip_ARRAY_ELEMENTS, - &hdr->values[hdr->count]); + pj_scan_get( scanner, &pjsip_NOT_COMMA_OR_NEWLINE, + &hdr->values[hdr->count]); hdr->count++; } parse_hdr_end(scanner); @@ -1283,7 +1288,11 @@ static void parse_generic_array_hdr( pjsip_generic_array_hdr *hdr, static void parse_generic_string_hdr( pjsip_generic_string_hdr *hdr, pj_scanner *scanner ) { - pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &hdr->hvalue); + if (pj_cis_match(&pjsip_NOT_NEWLINE, *scanner->curptr)) + pj_scan_get( scanner, &pjsip_NOT_NEWLINE, &hdr->hvalue); + else + hdr->hvalue.slen = 0; + parse_hdr_end(scanner); } @@ -1292,7 +1301,7 @@ static void parse_generic_int_hdr( pjsip_generic_int_hdr *hdr, pj_scanner *scanner ) { pj_str_t tmp; - pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &tmp); + pj_scan_get( scanner, &pjsip_DIGIT_SPEC, &tmp); hdr->ivalue = pj_strtoul(&tmp); parse_hdr_end(scanner); } @@ -1318,7 +1327,7 @@ static pjsip_hdr* parse_hdr_allow(pjsip_parse_ctx *ctx) static pjsip_hdr* parse_hdr_call_id(pjsip_parse_ctx *ctx) { pjsip_cid_hdr *hdr = pjsip_cid_hdr_create(ctx->pool); - pj_scan_get_until( ctx->scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &hdr->id); + pj_scan_get( ctx->scanner, &pjsip_NOT_NEWLINE, &hdr->id); parse_hdr_end(ctx->scanner); if (ctx->rdata) @@ -1700,7 +1709,7 @@ static pjsip_hdr* parse_hdr_via( pjsip_parse_ctx *ctx ) else pj_list_insert_before(first, hdr); - if (pj_scan_stricmp( scanner, PJSIP_VERSION "/", 8) != 0) + if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION "/", 8) != 0) PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); pj_scan_advance_n( scanner, 8, 1); diff --git a/pjsip/src/pjsip/sip_uri.c b/pjsip/src/pjsip/sip_uri.c index a44642540..6c4efb533 100644 --- a/pjsip/src/pjsip/sip_uri.c +++ b/pjsip/src/pjsip/sip_uri.c @@ -89,11 +89,19 @@ PJ_DEF(pj_ssize_t) pjsip_param_print_on( const pjsip_param *param_list, char *buf, pj_size_t size, int sep) { - const pjsip_param *p = param_list->next; - char *startbuf = buf; - char *endbuf = buf + size; + const pjsip_param *p; + char *startbuf; + char *endbuf; + int printed; - while (p != param_list) { + p = param_list->next; + if (p == param_list) + return 0; + + startbuf = buf; + endbuf = buf + size; + + do { *buf++ = (char)sep; copy_advance_escape(buf, p->name, pjsip_PARAM_CHAR_SPEC); if (p->value.slen) { @@ -101,7 +109,8 @@ PJ_DEF(pj_ssize_t) pjsip_param_print_on( const pjsip_param *param_list, copy_advance_escape(buf, p->value, pjsip_PARAM_CHAR_SPEC); } p = p->next; - } + } while (p != param_list); + return buf-startbuf; } @@ -248,6 +257,9 @@ static int pjsip_url_print( pjsip_uri_context_e context, */ //PJ_TODO(SHOULD_DISALLOW_URI_PORT_IN_FROM_TO_HEADER) if (url->port && context != PJSIP_URI_IN_FROMTO_HDR) { + if (endbuf - buf < 10) + return -1; + *buf++ = ':'; printed = pj_utoa(url->port, buf); buf += printed; @@ -270,8 +282,10 @@ static int pjsip_url_print( pjsip_uri_context_e context, /* TTL param is not allowed in From, To, Route, and Record-Route header. */ if (url->ttl_param >= 0 && context != PJSIP_URI_IN_FROMTO_HDR && - context != PJSIP_URI_IN_ROUTING_HDR && (endbuf-buf) > 15) + context != PJSIP_URI_IN_ROUTING_HDR) { + if (endbuf - buf < 15) + return -1; pj_memcpy(buf, ";ttl=", 5); printed = pj_utoa(url->ttl_param, buf+5); buf += printed + 5; @@ -288,6 +302,8 @@ static int pjsip_url_print( pjsip_uri_context_e context, context != PJSIP_URI_IN_CONTACT_HDR) { pj_str_t lr = { ";lr", 3 }; + if (endbuf - buf < 3) + return -1; copy_advance_check(buf, lr); } @@ -300,6 +316,8 @@ static int pjsip_url_print( pjsip_uri_context_e context, /* Header param. */ param = url->header_param.next; while (param != &url->header_param) { + if (endbuf - buf < param->name.slen+2) + return -1; *buf++ = hparam_char; copy_advance_escape(buf, param->name, pjsip_HDR_CHAR_SPEC); if (param->value.slen) { diff --git a/pjsip/src/test-pjsip/msg.c b/pjsip/src/test-pjsip/msg.c index bfa253bde..1f6affdd9 100644 --- a/pjsip/src/test-pjsip/msg.c +++ b/pjsip/src/test-pjsip/msg.c @@ -34,7 +34,7 @@ static pjsip_msg *create_msg1(pj_pool_t *pool); #define FLAG_PARSE_ONLY 4 #define FLAG_PRINT_ONLY 8 -static int flag = FLAG_PARSE_ONLY; +static int flag = 0; struct test_msg { @@ -105,6 +105,7 @@ static pj_timestamp detect_time, parse_time, print_time; static pj_status_t test_entry( pj_pool_t *pool, struct test_msg *entry ) { pjsip_msg *parsed_msg, *ref_msg; + static pjsip_msg *print_msg; pj_status_t status = PJ_SUCCESS; int len; pj_str_t str1, str2; @@ -114,15 +115,18 @@ static pj_status_t test_entry( pj_pool_t *pool, struct test_msg *entry ) pj_size_t msg_size; char msgbuf1[PJSIP_MAX_PKT_LEN]; char msgbuf2[PJSIP_MAX_PKT_LEN]; - enum { BUFLEN = 512 }; entry->len = pj_native_strlen(entry->msg); if (flag & FLAG_PARSE_ONLY) goto parse_msg; - if (flag & FLAG_PRINT_ONLY) + + if (flag & FLAG_PRINT_ONLY) { + if (print_msg == NULL) + print_msg = entry->creator(pool); goto print_msg; + } /* Detect message. */ detect_len = detect_len + entry->len; @@ -144,7 +148,7 @@ static pj_status_t test_entry( pj_pool_t *pool, struct test_msg *entry ) pj_sub_timestamp(&t2, &t1); pj_add_timestamp(&detect_time, &t2); - if (flag & FLAG_PARSE_ONLY) + if (flag & FLAG_DETECT_ONLY) return PJ_SUCCESS; /* Parse message. */ @@ -302,7 +306,9 @@ parse_msg: print_msg: print_len = print_len + entry->len; pj_get_timestamp(&t1); - len = pjsip_msg_print(parsed_msg, msgbuf1, PJSIP_MAX_PKT_LEN); + if (flag && FLAG_PRINT_ONLY) + ref_msg = print_msg; + len = pjsip_msg_print(ref_msg, msgbuf1, PJSIP_MAX_PKT_LEN); if (len < 1) { status = -150; goto on_return; diff --git a/pjsip/src/test-pjsip/test.c b/pjsip/src/test-pjsip/test.c index d598dd5d4..b940ffa19 100644 --- a/pjsip/src/test-pjsip/test.c +++ b/pjsip/src/test-pjsip/test.c @@ -81,8 +81,8 @@ int test_main(void) PJ_LOG(3,("","")); - //DO_TEST(uri_test()); - DO_TEST(msg_test()); + DO_TEST(uri_test()); + //DO_TEST(msg_test()); on_return: