summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-07-03 22:08:47 +0000
committerBenny Prijono <bennylp@teluu.com>2006-07-03 22:08:47 +0000
commit31d42235239a1291a599b84cc352b7b5b53448b7 (patch)
tree5770b56b29cbd313e47e5067fa3ee4a3b4895240
parented98898bb501d02e69093d34961bf1fb46d2ed4d (diff)
Various performance improvements in PJSIP: (1) optimizing for common case to minimize stricmp() calls (header names, method, URI schemes), (2) added functionality in scanner to parse and unescape in-place, (3) etc..
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@583 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjlib-util/include/pjlib-util/scanner.h13
-rw-r--r--pjlib-util/src/pjlib-util/scanner.c59
-rw-r--r--pjlib-util/src/pjlib-util/scanner_cis_uint.c2
-rw-r--r--pjlib/src/pj/hash.c11
-rw-r--r--pjsip-apps/build/sample_debug.dsp5
-rw-r--r--pjsip/build/test_pjsip.dsp2
-rw-r--r--pjsip/include/pjsip/sip_config.h17
-rw-r--r--pjsip/include/pjsip/sip_parser.h4
-rw-r--r--pjsip/src/pjsip/sip_msg.c4
-rw-r--r--pjsip/src/pjsip/sip_parser.c161
-rw-r--r--pjsip/src/pjsip/sip_tel_uri.c4
-rw-r--r--pjsip/src/pjsip/sip_uri.c2
-rw-r--r--pjsip/src/test-pjsip/msg_test.c3
13 files changed, 242 insertions, 45 deletions
diff --git a/pjlib-util/include/pjlib-util/scanner.h b/pjlib-util/include/pjlib-util/scanner.h
index eb9135fe..57cdced9 100644
--- a/pjlib-util/include/pjlib-util/scanner.h
+++ b/pjlib-util/include/pjlib-util/scanner.h
@@ -332,6 +332,19 @@ PJ_DECL(void) pj_scan_get( pj_scanner *scanner,
/**
+ * Just like #pj_scan_get(), but additionally performs unescaping when
+ * escaped ('%') character is found. The input spec MUST NOT contain the
+ * specification for '%' characted.
+ *
+ * @param scanner The scanner.
+ * @param spec The spec to match input string.
+ * @param out String to store the result.
+ */
+PJ_DECL(void) pj_scan_get_unescape( pj_scanner *scanner,
+ const pj_cis_t *spec, pj_str_t *out);
+
+
+/**
* Get characters between quotes. If current input doesn't match begin_quote,
* syntax error will be thrown. Note that the resulting string will contain
* the enclosing quote.
diff --git a/pjlib-util/src/pjlib-util/scanner.c b/pjlib-util/src/pjlib-util/scanner.c
index 676fd026..cd2a54b2 100644
--- a/pjlib-util/src/pjlib-util/scanner.c
+++ b/pjlib-util/src/pjlib-util/scanner.c
@@ -17,6 +17,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <pjlib-util/scanner.h>
+#include <pj/ctype.h>
#include <pj/string.h>
#include <pj/except.h>
#include <pj/os.h>
@@ -282,6 +283,64 @@ PJ_DEF(void) pj_scan_get( pj_scanner *scanner,
}
+PJ_DEF(void) pj_scan_get_unescape( pj_scanner *scanner,
+ const pj_cis_t *spec, pj_str_t *out)
+{
+ register char *s = scanner->curptr;
+ char *dst = s;
+
+ pj_assert(pj_cis_match(spec,0)==0);
+
+ /* Must not match character '%' */
+ pj_assert(pj_cis_match(spec,'%')==0);
+
+ /* EOF is detected implicitly */
+ if (!pj_cis_match(spec, *s) && *s != '%') {
+ pj_scan_syntax_err(scanner);
+ return;
+ }
+
+ out->ptr = s;
+ do {
+ if (*s == '%') {
+ if (s+3 <= scanner->end) {
+ /* This doesn't check if the hex digits are valid.
+ * If they dont' it will produce garbage characters, but
+ * no harm is done to the application (e.g. no illegal
+ * memory access.
+ */
+ *dst = (pj_uint8_t) ((pj_hex_digit_to_val(*(s+1)) << 4) +
+ pj_hex_digit_to_val(*(s+2)));
+ ++dst;
+ s += 3;
+ } else {
+ *dst++ = *s++;
+ *dst++ = *s++;
+ break;
+ }
+ }
+
+ if (pj_cis_match(spec, *s)) {
+ char *start = s;
+ do {
+ ++s;
+ } while (pj_cis_match(spec, *s));
+
+ if (dst != start) pj_memmove(dst, start, s-start);
+ dst += (s-start);
+ }
+
+ } while (*s == '%');
+
+ scanner->curptr = s;
+ out->slen = (dst - out->ptr);
+
+ if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
+ pj_scan_skip_whitespace(scanner);
+ }
+}
+
+
PJ_DEF(void) pj_scan_get_quote( pj_scanner *scanner,
int begin_quote, int end_quote,
pj_str_t *out)
diff --git a/pjlib-util/src/pjlib-util/scanner_cis_uint.c b/pjlib-util/src/pjlib-util/scanner_cis_uint.c
index 41599835..c12425d5 100644
--- a/pjlib-util/src/pjlib-util/scanner_cis_uint.c
+++ b/pjlib-util/src/pjlib-util/scanner_cis_uint.c
@@ -26,10 +26,12 @@
PJ_DEF(void) pj_cis_buf_init( pj_cis_buf_t *cis_buf)
{
/* Do nothing. */
+ PJ_UNUSED_ARG(cis_buf);
}
PJ_DEF(pj_status_t) pj_cis_init(pj_cis_buf_t *cis_buf, pj_cis_t *cis)
{
+ PJ_UNUSED_ARG(cis_buf);
pj_bzero(cis->cis_buf, sizeof(cis->cis_buf));
return PJ_SUCCESS;
}
diff --git a/pjlib/src/pj/hash.c b/pjlib/src/pj/hash.c
index 1f86317b..10ad9d97 100644
--- a/pjlib/src/pj/hash.c
+++ b/pjlib/src/pj/hash.c
@@ -75,10 +75,21 @@ PJ_DEF(pj_uint32_t) pj_hash_calc_tolower( pj_uint32_t hval,
{
long i;
+#if defined(PJ_HASH_USE_OWN_TOLOWER) && PJ_HASH_USE_OWN_TOLOWER != 0
+ for (i=0; i<key->slen; ++i) {
+ pj_uint8_t c = key->ptr[i];
+ if (c & 64)
+ result[i] = (char)(c | 32);
+ else
+ result[i] = (char)c;
+ hval = hval * PJ_HASH_MULTIPLIER + result[i];
+ }
+#else
for (i=0; i<key->slen; ++i) {
result[i] = (char)pj_tolower(key->ptr[i]);
hval = hval * PJ_HASH_MULTIPLIER + result[i];
}
+#endif
return hval;
}
diff --git a/pjsip-apps/build/sample_debug.dsp b/pjsip-apps/build/sample_debug.dsp
index 1cf451c4..8b7ff9fe 100644
--- a/pjsip-apps/build/sample_debug.dsp
+++ b/pjsip-apps/build/sample_debug.dsp
@@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "../../pjsip/include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../../pjmedia/include" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /I "../../pjsip/include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../../pjmedia/include" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
@@ -51,7 +51,8 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ole32.lib user32.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /map /machine:I386 /out:"../bin/samples/sampledebug_vc6.exe"
+# ADD LINK32 ole32.lib user32.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /map /debug /machine:I386 /out:"../bin/samples/sampledebug_vc6.exe" /fixed:no
+# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "sample_debug - Win32 Debug"
diff --git a/pjsip/build/test_pjsip.dsp b/pjsip/build/test_pjsip.dsp
index 418ee8a8..82f10ac3 100644
--- a/pjsip/build/test_pjsip.dsp
+++ b/pjsip/build/test_pjsip.dsp
@@ -51,7 +51,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib netapi32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /map /debug /machine:I386 /out:"..\bin\test-pjsip-i386-win32-vc6-release.exe"
+# ADD LINK32 dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib netapi32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /map /debug /machine:I386 /out:"..\bin\test-pjsip-i386-win32-vc6-release.exe" /fixed:no
!ELSEIF "$(CFG)" == "test_pjsip - Win32 Debug"
diff --git a/pjsip/include/pjsip/sip_config.h b/pjsip/include/pjsip/sip_config.h
index 535f6697..2d635d62 100644
--- a/pjsip/include/pjsip/sip_config.h
+++ b/pjsip/include/pjsip/sip_config.h
@@ -130,6 +130,23 @@
#endif
+/**
+ * If non-zero, SIP parser will unescape the escape characters ('%')
+ * in the original message, which means that it will modify the
+ * original message. Otherwise the parser will create a copy of
+ * the string and store the unescaped string to the new location.
+ *
+ * Unescaping in-place is faster, but less elegant (and it may
+ * break certain applications). So normally it's disabled, unless
+ * when benchmarking (to show off big performance).
+ *
+ * Default: 0
+ */
+#ifndef PJSIP_UNESCAPE_IN_PLACE
+# define PJSIP_UNESCAPE_IN_PLACE 0
+#endif
+
+
/* Endpoint. */
#define PJSIP_MAX_TIMER_COUNT (2*PJSIP_MAX_TSX_COUNT + 2*PJSIP_MAX_DIALOG_COUNT)
diff --git a/pjsip/include/pjsip/sip_parser.h b/pjsip/include/pjsip/sip_parser.h
index b9e752f0..54dd52df 100644
--- a/pjsip/include/pjsip/sip_parser.h
+++ b/pjsip/include/pjsip/sip_parser.h
@@ -315,10 +315,14 @@ extern pj_cis_t
pjsip_HEX_SPEC, /**< Hexadecimal digits. */
pjsip_PARAM_CHAR_SPEC, /**< For scanning pname (or pvalue when it's
not quoted.) */
+ pjsip_PARAM_CHAR_SPEC_ESC, /**< Variant without the escape ('%') char */
pjsip_HDR_CHAR_SPEC, /**< Chars in hname/havalue in URL. */
+ pjsip_HDR_CHAR_SPEC_ESC, /**< Variant without the escape ('%') char */
pjsip_PROBE_USER_HOST_SPEC, /**< Hostname characters. */
pjsip_PASSWD_SPEC, /**< Password. */
+ pjsip_PASSWD_SPEC_ESC, /**< Variant without the escape ('%') char */
pjsip_USER_SPEC, /**< User */
+ pjsip_USER_SPEC_ESC, /**< Variant without the escape ('%') char */
pjsip_NOT_NEWLINE, /**< For eating up header, basicly any chars
except newlines or zero. */
pjsip_NOT_COMMA_OR_NEWLINE, /**< Array elements. */
diff --git a/pjsip/src/pjsip/sip_msg.c b/pjsip/src/pjsip/sip_msg.c
index 38603bc1..d6a33339 100644
--- a/pjsip/src/pjsip/sip_msg.c
+++ b/pjsip/src/pjsip/sip_msg.c
@@ -196,7 +196,9 @@ PJ_DEF(void) pjsip_method_init_np(pjsip_method *m,
{
int i;
for (i=0; i<PJ_ARRAY_SIZE(method_names); ++i) {
- if (pj_stricmp(str, method_names[i])==0) {
+ if (pj_memcmp(str->ptr, method_names[i]->ptr, str->slen)==0 ||
+ pj_stricmp(str, method_names[i])==0)
+ {
m->id = (pjsip_method_e)i;
m->name = *method_names[i];
return;
diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c
index ab6144fd..a0ef3adc 100644
--- a/pjsip/src/pjsip/sip_parser.c
+++ b/pjsip/src/pjsip/sip_parser.c
@@ -115,10 +115,14 @@ pj_cis_t pjsip_HOST_SPEC, /* For scanning host part. */
pjsip_HEX_SPEC, /* Hexadecimal digits. */
pjsip_PARAM_CHAR_SPEC, /* For scanning pname (or pvalue when
* it's not quoted.) */
+ pjsip_PARAM_CHAR_SPEC_ESC, /* The variant without escaped char */
pjsip_HDR_CHAR_SPEC, /* Chars in hname or hvalue */
+ pjsip_HDR_CHAR_SPEC_ESC, /* Variant without escaped char */
pjsip_PROBE_USER_HOST_SPEC, /* Hostname characters. */
pjsip_PASSWD_SPEC, /* Password. */
+ pjsip_PASSWD_SPEC_ESC, /* Variant without escaped char */
pjsip_USER_SPEC, /* User */
+ pjsip_USER_SPEC_ESC, /* Variant without escaped char */
pjsip_NOT_COMMA_OR_NEWLINE, /* Array separator. */
pjsip_NOT_NEWLINE, /* For eating up header.*/
pjsip_DISPLAY_SPEC; /* Used when searching for display name
@@ -201,7 +205,26 @@ static unsigned long pj_strtoul_mindigit(const pj_str_t *str,
}
/* Case insensitive comparison */
-#define parser_stricmp(s1, s2) (pj_stricmp_alnum(&s1, &s2))
+#define parser_stricmp(s1, s2) (s1.slen!=s2.slen || pj_stricmp_alnum(&s1, &s2))
+
+
+/* Get a token and unescape */
+PJ_INLINE(void) parser_get_and_unescape(pj_scanner *scanner, pj_pool_t *pool,
+ const pj_cis_t *spec,
+ const pj_cis_t *unesc_spec,
+ pj_str_t *token)
+{
+#if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0
+ PJ_UNUSED_ARG(pool);
+ PJ_UNUSED_ARG(spec);
+ pj_scan_get_unescape(scanner, unesc_spec, token);
+#else
+ PJ_UNUSED_ARG(unesc_spec);
+ pj_scan_get(scanner, spec, token);
+ *token = pj_str_unescape(pool, token);
+#endif
+}
+
/* Syntax error handler for parser. */
@@ -313,18 +336,34 @@ static pj_status_t init_parser()
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
pj_cis_add_str(&pjsip_PARAM_CHAR_SPEC, PARAM_CHAR);
+ status = pj_cis_dup(&pjsip_PARAM_CHAR_SPEC_ESC, &pjsip_PARAM_CHAR_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_del_str(&pjsip_PARAM_CHAR_SPEC_ESC, ESCAPED);
+
status = pj_cis_dup(&pjsip_HDR_CHAR_SPEC, &pjsip_ALNUM_SPEC);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
pj_cis_add_str(&pjsip_HDR_CHAR_SPEC, HDR_CHAR);
+ status = pj_cis_dup(&pjsip_HDR_CHAR_SPEC_ESC, &pjsip_HDR_CHAR_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_del_str(&pjsip_HDR_CHAR_SPEC_ESC, ESCAPED);
+
status = pj_cis_dup(&pjsip_USER_SPEC, &pjsip_ALNUM_SPEC);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
pj_cis_add_str( &pjsip_USER_SPEC, UNRESERVED ESCAPED USER_UNRESERVED );
+ status = pj_cis_dup(&pjsip_USER_SPEC_ESC, &pjsip_USER_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_del_str( &pjsip_USER_SPEC_ESC, ESCAPED);
+
status = pj_cis_dup(&pjsip_PASSWD_SPEC, &pjsip_ALNUM_SPEC);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
pj_cis_add_str( &pjsip_PASSWD_SPEC, UNRESERVED ESCAPED PASS);
+ status = pj_cis_dup(&pjsip_PASSWD_SPEC_ESC, &pjsip_PASSWD_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_del_str( &pjsip_PASSWD_SPEC, ESCAPED);
+
status = pj_cis_init(&cis_buf, &pjsip_PROBE_USER_HOST_SPEC);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
pj_cis_add_str( &pjsip_PROBE_USER_HOST_SPEC, "@ \n>");
@@ -459,7 +498,7 @@ PJ_INLINE(int) compare_handler( const handler_rec *r1,
*/
/* Equal length and equal hash. compare the strings. */
- return pj_ansi_strcmp(r1->hname, name);
+ return pj_memcmp(r1->hname, name, name_len);
}
/* Register one handler for one header name. */
@@ -468,9 +507,9 @@ static pj_status_t int_register_parser( const char *name,
{
unsigned pos;
handler_rec rec;
- unsigned i;
if (handler_count >= PJ_ARRAY_SIZE(handler)) {
+ pj_assert(!"Too many handlers!");
return PJ_ETOOMANY;
}
@@ -481,13 +520,12 @@ static pj_status_t int_register_parser( const char *name,
pj_assert(!"Header name is too long!");
return PJ_ENAMETOOLONG;
}
- /* Name is copied in lowercase. */
- for (i=0; i<rec.hname_len; ++i) {
- rec.hname[i] = (char)pj_tolower(name[i]);
- }
- rec.hname[i] = '\0';
- /* Hash value is calculated from the lowercase name. */
- rec.hname_hash = pj_hash_calc(0, rec.hname, PJ_HASH_KEY_STRING);
+ /* Copy name. */
+ pj_memcpy(rec.hname, name, rec.hname_len);
+ rec.hname[rec.hname_len] = '\0';
+
+ /* Calculate hash value. */
+ rec.hname_hash = pj_hash_calc(0, rec.hname, rec.hname_len);
/* Get the pos to insert the new handler. */
for (pos=0; pos < handler_count; ++pos) {
@@ -522,12 +560,37 @@ PJ_DEF(pj_status_t) pjsip_register_hdr_parser( const char *hname,
const char *hshortname,
pjsip_parse_hdr_func *fptr)
{
+ unsigned i, len;
+ char hname_lcase[PJSIP_MAX_HNAME_LEN+1];
pj_status_t status;
+ /* Check that name is not too long */
+ len = pj_ansi_strlen(hname);
+ if (len > PJSIP_MAX_HNAME_LEN) {
+ pj_assert(!"Header name is too long!");
+ return PJ_ENAMETOOLONG;
+ }
+
+ /* Register the normal Mixed-Case name */
status = int_register_parser(hname, fptr);
if (status != PJ_SUCCESS) {
return status;
}
+
+ /* Get the lower-case name */
+ for (i=0; i<len; ++i) {
+ hname_lcase[i] = (char)pj_tolower(hname[i]);
+ }
+ hname_lcase[len] = '\0';
+
+ /* Register the lower-case version of the name */
+ status = int_register_parser(hname_lcase, fptr);
+ if (status != PJ_SUCCESS) {
+ return status;
+ }
+
+
+ /* Register the shortname version of the name */
if (hshortname) {
status = int_register_parser(hshortname, fptr);
if (status != PJ_SUCCESS)
@@ -536,26 +599,15 @@ PJ_DEF(pj_status_t) pjsip_register_hdr_parser( const char *hname,
return PJ_SUCCESS;
}
+
/* Find handler to parse the header name. */
-static pjsip_parse_hdr_func * find_handler(const pj_str_t *hname)
+static pjsip_parse_hdr_func * find_handler_imp(pj_uint32_t hash,
+ const pj_str_t *hname)
{
handler_rec *first;
- char hname_copy[PJSIP_MAX_HNAME_LEN];
- pj_uint32_t hash;
int comp;
unsigned n;
- if (hname->slen >= PJSIP_MAX_HNAME_LEN) {
- /* Guaranteed not to be able to find handler. */
- return NULL;
- }
-
- /* Calculate hash value while converting the header to lowercase.
- * Don't assume that 'hname' is NULL terminated.
- */
- hash = pj_hash_calc_tolower(0, hname_copy, hname);
- hname_copy[hname->slen] = '\0';
-
/* Binary search for the handler. */
comp = -1;
first = &handler[0];
@@ -564,7 +616,7 @@ static pjsip_parse_hdr_func * find_handler(const pj_str_t *hname)
unsigned half = n / 2;
handler_rec *mid = first + half;
- comp = compare_handler(mid, hname_copy, hname->slen, hash);
+ comp = compare_handler(mid, hname->ptr, hname->slen, hash);
if (comp < 0) {
first = ++mid;
n -= half + 1;
@@ -579,12 +631,43 @@ static pjsip_parse_hdr_func * find_handler(const pj_str_t *hname)
return comp==0 ? first->handler : NULL;
}
+
+/* Find handler to parse the header name. */
+static pjsip_parse_hdr_func* find_handler(const pj_str_t *hname)
+{
+ pj_uint32_t hash;
+ char hname_copy[PJSIP_MAX_HNAME_LEN];
+ pj_str_t tmp;
+ pjsip_parse_hdr_func *handler;
+
+ if (hname->slen >= PJSIP_MAX_HNAME_LEN) {
+ /* Guaranteed not to be able to find handler. */
+ return NULL;
+ }
+
+ /* First, common case, try to find handler with exact name */
+ hash = pj_hash_calc(0, hname->ptr, hname->slen);
+ handler = find_handler_imp(hash, hname);
+ if (handler)
+ return handler;
+
+
+ /* If not found, try converting the header name to lowercase and
+ * search again.
+ */
+ hash = pj_hash_calc_tolower(0, hname_copy, hname);
+ tmp.ptr = hname_copy;
+ tmp.slen = hname->slen;
+ return find_handler_imp(hash, &tmp);
+}
+
+
/* Find URI handler. */
static pjsip_parse_uri_func* find_uri_handler(const pj_str_t *scheme)
{
unsigned i;
for (i=0; i<uri_handler_count; ++i) {
- if (pj_stricmp_alnum(&uri_handler[i].scheme, scheme)==0)
+ if (parser_stricmp(uri_handler[i].scheme, (*scheme))==0)
return uri_handler[i].parse;
}
return NULL;
@@ -961,8 +1044,8 @@ void pjsip_parse_param_imp( pj_scanner *scanner, pj_pool_t *pool,
unsigned option)
{
/* pname */
- pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pname);
- *pname = pj_str_unescape(pool, pname);
+ parser_get_and_unescape(scanner, pool, &pjsip_PARAM_CHAR_SPEC,
+ &pjsip_PARAM_CHAR_SPEC_ESC, pname);
/* init pvalue */
pvalue->ptr = NULL;
@@ -980,8 +1063,8 @@ void pjsip_parse_param_imp( pj_scanner *scanner, pj_pool_t *pool,
pvalue->slen -= 2;
}
} else if(pj_cis_match(&pjsip_PARAM_CHAR_SPEC, *scanner->curptr)) {
- pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pvalue);
- *pvalue = pj_str_unescape(pool, pvalue);
+ parser_get_and_unescape(scanner, pool, &pjsip_PARAM_CHAR_SPEC,
+ &pjsip_PARAM_CHAR_SPEC_ESC, pvalue);
}
}
}
@@ -1007,8 +1090,8 @@ static void int_parse_hparam( pj_scanner *scanner, pj_pool_t *pool,
pj_scan_get_char(scanner);
/* hname */
- pj_scan_get(scanner, &pjsip_HDR_CHAR_SPEC, hname);
- *hname = pj_str_unescape(pool, hname);
+ parser_get_and_unescape(scanner, pool, &pjsip_HDR_CHAR_SPEC,
+ &pjsip_HDR_CHAR_SPEC_ESC, hname);
/* Init hvalue */
hvalue->ptr = NULL;
@@ -1020,8 +1103,8 @@ static void int_parse_hparam( pj_scanner *scanner, pj_pool_t *pool,
if (!pj_scan_is_eof(scanner) &&
pj_cis_match(&pjsip_HDR_CHAR_SPEC, *scanner->curptr))
{
- pj_scan_get(scanner, &pjsip_HDR_CHAR_SPEC, hvalue);
- *hvalue = pj_str_unescape(pool, hvalue);
+ parser_get_and_unescape(scanner, pool, &pjsip_HDR_CHAR_SPEC,
+ &pjsip_HDR_CHAR_SPEC, hvalue);
}
}
}
@@ -1063,13 +1146,13 @@ static int int_is_next_user(pj_scanner *scanner)
static void int_parse_user_pass( pj_scanner *scanner, pj_pool_t *pool,
pj_str_t *user, pj_str_t *pass)
{
- pj_scan_get( scanner, &pjsip_USER_SPEC, user);
- *user = pj_str_unescape(pool, user);
+ parser_get_and_unescape(scanner, pool, &pjsip_USER_SPEC,
+ &pjsip_USER_SPEC_ESC, user);
if ( *scanner->curptr == ':') {
pj_scan_get_char( scanner );
- pj_scan_get( scanner, &pjsip_PASSWD_SPEC, pass);
- *pass = pj_str_unescape(pool, pass);
+ parser_get_and_unescape(scanner, pool, &pjsip_PASSWD_SPEC,
+ &pjsip_PASSWD_SPEC_ESC, pass);
} else {
pass->ptr = NULL;
pass->slen = 0;
@@ -1435,7 +1518,7 @@ static void int_parse_contact_param( pjsip_contact_hdr *hdr,
int_parse_param( scanner, pool, &pname, &pvalue);
if (!parser_stricmp(pname, pjsip_Q_STR) && pvalue.slen) {
- char *dot_pos = memchr(pvalue.ptr, '.', pvalue.slen);
+ char *dot_pos = pj_memchr(pvalue.ptr, '.', pvalue.slen);
if (!dot_pos) {
hdr->q1000 = pj_strtoul(&pvalue);
} else {
diff --git a/pjsip/src/pjsip/sip_tel_uri.c b/pjsip/src/pjsip/sip_tel_uri.c
index fd43bc52..34d28b15 100644
--- a/pjsip/src/pjsip/sip_tel_uri.c
+++ b/pjsip/src/pjsip/sip_tel_uri.c
@@ -373,8 +373,12 @@ static void* tel_uri_parse( pj_scanner *scanner, pj_pool_t *pool,
uri = pjsip_tel_uri_create(pool);
/* Get the phone number. */
+#if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0
+ pj_scan_get_unescape(scanner, &pjsip_TEL_NUMBER_SPEC, &uri->number);
+#else
pj_scan_get(scanner, &pjsip_TEL_NUMBER_SPEC, &uri->number);
uri->number = pj_str_unescape(pool, &uri->number);
+#endif
/* Get all parameters. */
if (parse_params && *scanner->curptr==';') {
diff --git a/pjsip/src/pjsip/sip_uri.c b/pjsip/src/pjsip/sip_uri.c
index 37fd3c4f..ddb1e68a 100644
--- a/pjsip/src/pjsip/sip_uri.c
+++ b/pjsip/src/pjsip/sip_uri.c
@@ -103,6 +103,8 @@ PJ_DEF(pj_ssize_t) pjsip_param_print_on( const pjsip_param *param_list,
startbuf = buf;
endbuf = buf + size;
+ PJ_UNUSED_ARG(pname_spec);
+
do {
*buf++ = (char)sep;
copy_advance_escape(buf, p->name, (*pname_spec));
diff --git a/pjsip/src/test-pjsip/msg_test.c b/pjsip/src/test-pjsip/msg_test.c
index f93539fe..d0039047 100644
--- a/pjsip/src/test-pjsip/msg_test.c
+++ b/pjsip/src/test-pjsip/msg_test.c
@@ -50,7 +50,7 @@ struct test_msg
{
/* 'Normal' message with all headers. */
"INVITE sip:user@foo SIP/2.0\n"
- "From: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=123457890123456\r"
+ "from: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=123457890123456\r"
"To: Fellow User <sip:user@foo.bar.domain.com>\r\n"
"Call-ID: 12345678901234567890@bar\r\n"
"Content-Length: 0\r\n"
@@ -790,7 +790,6 @@ int msg_test(void)
char desc[250];
pj_status_t status;
-
status = simple_test();
if (status != PJ_SUCCESS)
return status;