Index: pjproject/trunk/pjsip/src/pjsip/sip_parser.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_parser.c	(revision 80)
+++ pjproject/trunk/pjsip/src/pjsip/sip_parser.c	(revision 82)
@@ -50,12 +50,13 @@
 
 #define PJSIP_VERSION		"SIP/2.0"
-#define PJSIP_SYN_ERR_EXCEPTION	1
 
 #define UNREACHED(expr)
 
-//#define IS_NEWLINE(c)	((c)=='\r' || (c)=='\n')
-#define IS_NEWLINE(c)	((c)=='\r')
+#define IS_NEWLINE(c)	((c)=='\r' || (c)=='\n')
 #define IS_SPACE(c)	((c)==' ' || (c)=='\t')
 
+/*
+ * Header parser records.
+ */
 typedef struct handler_rec
 {
@@ -66,11 +67,25 @@
 } handler_rec;
 
-static handler_rec handler[127];
+static handler_rec handler[PJSIP_MAX_HEADER_TYPES];
 static unsigned handler_count;
 static int parser_is_initialized;
+
+/*
+ * URI parser records.
+ */
+typedef struct uri_parser_rec
+{
+    pj_str_t		     scheme;
+    pjsip_parse_uri_func    *parse;
+} uri_parser_rec;
+
+static uri_parser_rec uri_handler[PJSIP_MAX_URI_TYPES];
+static unsigned uri_handler_count;
 
 /*
  * Global vars (also extern).
  */
+int PJSIP_SYN_ERR_EXCEPTION;
+
 const pj_str_t  pjsip_USER_STR      = { "user", 4};
 const pj_str_t  pjsip_METHOD_STR    = { "method", 6};
@@ -247,4 +262,15 @@
     initialized = 1;
 
+    /*
+     * Syntax error exception number.
+     */
+    status = pj_exception_id_alloc("PJSIP: syntax error", 
+				   &PJSIP_SYN_ERR_EXCEPTION);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    /*
+     * Init character input spec (cis)
+     */
+
     pj_cis_buf_init(&cis_buf);
 
@@ -310,4 +336,18 @@
     pj_cis_invert(&pjsip_DISPLAY_SPEC);
 
+    /*
+     * Register URI parsers.
+     */
+
+    status = pjsip_register_uri_parser("sip", &int_parse_sip_url);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_uri_parser("sips", &int_parse_sip_url);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    /*
+     * Register header parsers.
+     */
+
     status = pjsip_register_hdr_parser( "Accept", NULL, &parse_hdr_accept);
     PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
@@ -374,5 +414,8 @@
     PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
 
-    /* Register auth parser. */
+    /* 
+     * Register auth parser. 
+     */
+
     status = pjsip_auth_init_parser();
 
@@ -383,11 +426,8 @@
 {
     if (!parser_is_initialized) {
-	/* Prevent race cond. */
-	pj_enter_critical_section();
 	if (!parser_is_initialized) {
 	    init_parser();
 	    parser_is_initialized = 1;
 	}
-	pj_leave_critical_section();
     }
 }
@@ -399,7 +439,7 @@
  */
 PJ_INLINE(int) compare_handler( const handler_rec *r1, 
-			    const char *name, 
-			    pj_size_t name_len,
-			    pj_uint32_t hash )
+				const char *name, 
+				pj_size_t name_len,
+				pj_uint32_t hash )
 {
     PJ_UNUSED_ARG(name_len);
@@ -539,4 +579,29 @@
 }
 
+/* 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)
+	    return uri_handler[i].parse;
+    }
+    return NULL;
+}
+
+/* Register URI parser. */
+PJ_DEF(pj_status_t) pjsip_register_uri_parser( char *scheme,
+					       pjsip_parse_uri_func *func)
+{
+    if (uri_handler_count >= PJ_ARRAY_SIZE(uri_handler))
+	return PJ_ETOOMANY;
+
+    uri_handler[uri_handler_count].scheme = pj_str((char*)scheme);
+    uri_handler[uri_handler_count].parse = func;
+    ++uri_handler_count;
+
+    return PJ_SUCCESS;
+}
+
 /* Public function to parse SIP message. */
 PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool, 
@@ -548,6 +613,4 @@
     pjsip_parse_ctx context;
 
-    init_sip_parser();
-
     pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, 
                  &on_syntax_error);
@@ -569,6 +632,4 @@
     pj_scanner scanner;
     pjsip_parse_ctx context;
-
-    init_sip_parser();
 
     pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, 
@@ -626,6 +687,4 @@
 	    PJ_USE_EXCEPTION;
 
-	    init_sip_parser();
-
 	    pj_scan_init(&scanner, (char*)line, hdr_end-line, 
 			 PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error);
@@ -694,6 +753,4 @@
     pjsip_uri *uri = NULL;
     PJ_USE_EXCEPTION;
-
-    init_sip_parser();
 
     pj_scan_init(&scanner, buf, size, 0, &on_syntax_error);
@@ -872,4 +929,8 @@
 	    }
 
+	    /* Restore flag. Flag may be set in int_parse_sip_url() */
+	    scanner->skip_ws = PJ_SCAN_AUTOSKIP_WS_HEADER;
+
+	    /* Continue parse next header, if any. */
 	    if (!pj_scan_is_eof(scanner) && !IS_NEWLINE(*scanner->curptr)) {
 		goto parse_headers;
@@ -1019,17 +1080,15 @@
 	next_ch = pj_scan_peek( scanner, &pjsip_DISPLAY_SPEC, &scheme);
 
-	if (next_ch==':' && 
-            (parser_stricmp(scheme, pjsip_SIP_STR)==0 || 
-             parser_stricmp(scheme, pjsip_SIPS_STR)==0)) 
-	{
-	    uri = (pjsip_uri*)
-                int_parse_sip_url( scanner, pool, 
-				   (opt & PJSIP_PARSE_URI_IN_FROM_TO_HDR)== 0);
-
-	} else if (next_ch==':') {
-
-	    /* Not supported. */
-	    PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
-	    UNREACHED({return NULL; /* Not reached. */});
+	if (next_ch==':') {
+	    pjsip_parse_uri_func *func = find_uri_handler(&scheme);
+
+	    if (func == NULL) {
+		/* Unsupported URI scheme */
+		PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
+	    }
+
+	    uri = (*func)( scanner, pool, 
+			  (opt & PJSIP_PARSE_URI_IN_FROM_TO_HDR)== 0);
+
 
 	} else {
@@ -1063,4 +1122,5 @@
 	pj_str_t scheme;
 	int colon;
+	pjsip_parse_uri_func *func;
 
 	/* Get scheme. */
@@ -1070,14 +1130,10 @@
 	}
 
-	if ((parser_stricmp(scheme, pjsip_SIP_STR)==0 || 
-            parser_stricmp(scheme, pjsip_SIPS_STR)==0)) 
-	{
-	    return (pjsip_uri*)int_parse_sip_url( scanner, pool, parse_params);
-
-	} else if (parser_stricmp(scheme, pjsip_TEL_STR)==0) {
-	    PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
-	    UNREACHED({ return NULL; /* Not reached. */ })
+	func = find_uri_handler(&scheme);
+	if (func)  {
+	    return (pjsip_uri*)(*func)(scanner, pool, parse_params);
 
 	} else {
+	    /* Unsupported URI scheme */
 	    PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
 	    UNREACHED({ return NULL; /* Not reached. */ })
@@ -1774,6 +1830,4 @@
     PJ_USE_EXCEPTION;
 
-    init_sip_parser();
-
     pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, 
                  &on_syntax_error);
