Index: pjproject/main/pjsip/src/pjsip/sip_parser.c
===================================================================
--- pjproject/main/pjsip/src/pjsip/sip_parser.c	(revision 3)
+++ pjproject/main/pjsip/src/pjsip/sip_parser.c	(revision 43)
@@ -1,4 +1,3 @@
 /* $Id$
- *
  */
 #include <pjsip/sip_parser.h>
@@ -6,5 +5,7 @@
 #include <pjsip/sip_msg.h>
 #include <pjsip/sip_auth_parser.h>
-#include <pj/scanner.h>
+#include <pjsip/sip_errno.h>
+#include <pjsip/sip_transport.h>        /* rdata structure */
+#include <pjlib-util/scanner.h>
 #include <pj/except.h>
 #include <pj/log.h>
@@ -13,5 +14,6 @@
 #include <pj/pool.h>
 #include <pj/string.h>
-#include <ctype.h>	/* tolower() */
+#include <pj/ctype.h>
+#include <pj/assert.h>
 
 #define RESERVED    ";/?:@&=+$,"
@@ -20,5 +22,6 @@
 #define USER	    "&=+$,;?/"
 #define PASS	    "&=+$,"
-#define TOKEN	    "-.!%*_=`'~+"   /* '+' is because of application/pidf+xml in Content-Type! */
+#define TOKEN	    "-.!%*_=`'~+"   /* '+' is because of application/pidf+xml
+                                     * in Content-Type! */
 #define HOST	    "_-."
 #define HEX_DIGIT   "abcdefABCDEF"
@@ -46,33 +49,39 @@
  * Global vars (also extern).
  */
-const pj_str_t  pjsip_USER_STR = { "user", 4};
-const pj_str_t  pjsip_METHOD_STR = { "method", 6};
+const pj_str_t  pjsip_USER_STR      = { "user", 4};
+const pj_str_t  pjsip_METHOD_STR    = { "method", 6};
 const pj_str_t  pjsip_TRANSPORT_STR = { "transport", 9};
-const pj_str_t  pjsip_MADDR_STR = { "maddr", 5 };
-const pj_str_t  pjsip_LR_STR = { "lr", 2 };
-const pj_str_t  pjsip_SIP_STR = { "sip", 3 };
-const pj_str_t  pjsip_SIPS_STR = { "sips", 4 };
-const pj_str_t  pjsip_TEL_STR = { "tel", 3 };
-const pj_str_t  pjsip_BRANCH_STR = { "branch", 6 };
-const pj_str_t  pjsip_TTL_STR = { "ttl", 3 };
-const pj_str_t  pjsip_PNAME_STR = { "received", 8 };
-const pj_str_t  pjsip_Q_STR = { "q", 1 };
-const pj_str_t  pjsip_EXPIRES_STR = { "expires", 7 };
-const pj_str_t  pjsip_TAG_STR = { "tag", 3 };
-const pj_str_t  pjsip_RPORT_STR = { "rport", 5};
-
-pj_char_spec	pjsip_HOST_SPEC,	    /* For scanning host part. */
-		pjsip_DIGIT_SPEC,	    /* Decimal digits */
-		pjsip_ALPHA_SPEC,	    /* Alpha (A-Z, a-z) */
-		pjsip_ALNUM_SPEC,	    /* Decimal + Alpha. */
-		pjsip_TOKEN_SPEC,	    /* Token. */
-		pjsip_HEX_SPEC,		    /* Hexadecimal digits. */
-		pjsip_PARAM_CHAR_SPEC,	    /* For scanning pname (or pvalue when it's not quoted.) */
-		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 in URL. */
+const pj_str_t  pjsip_MADDR_STR     = { "maddr", 5 };
+const pj_str_t  pjsip_LR_STR        = { "lr", 2 };
+const pj_str_t  pjsip_SIP_STR       = { "sip", 3 };
+const pj_str_t  pjsip_SIPS_STR      = { "sips", 4 };
+const pj_str_t  pjsip_TEL_STR       = { "tel", 3 };
+const pj_str_t  pjsip_BRANCH_STR    = { "branch", 6 };
+const pj_str_t  pjsip_TTL_STR       = { "ttl", 3 };
+const pj_str_t  pjsip_PNAME_STR     = { "received", 8 };
+const pj_str_t  pjsip_Q_STR         = { "q", 1 };
+const pj_str_t  pjsip_EXPIRES_STR   = { "expires", 7 };
+const pj_str_t  pjsip_TAG_STR       = { "tag", 3 };
+const pj_str_t  pjsip_RPORT_STR     = { "rport", 5};
+
+/* Character Input Specification buffer. */
+static pj_cis_buf_t cis_buf;
+
+/* Character Input Specifications. */
+pj_cis_t    pjsip_HOST_SPEC,	        /* For scanning host part. */
+	    pjsip_DIGIT_SPEC,	        /* Decimal digits */
+	    pjsip_ALPHA_SPEC,	        /* Alpha (A-Z, a-z) */
+	    pjsip_ALNUM_SPEC,	        /* Decimal + Alpha. */
+	    pjsip_TOKEN_SPEC,	        /* Token. */
+	    pjsip_HEX_SPEC,	        /* Hexadecimal digits. */
+	    pjsip_PARAM_CHAR_SPEC,      /* For scanning pname (or pvalue when
+                                         * it's not quoted.) */
+	    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
+                                         * in URL. */
 
 
@@ -80,73 +89,56 @@
  * Forward decl.
  */
-static pjsip_msg *	  int_parse_msg( pj_scanner *scanner, 
-					 pj_pool_t *pool, 
-					 pjsip_parser_err_report *err_list);
-static void		  int_parse_param( pj_scanner *scanner, 
-					   pj_str_t *pname, 
-					   pj_str_t *pvalue);
-static void		  int_parse_req_line( pj_scanner *scanner, 
-					      pj_pool_t *pool,
-					      pjsip_request_line *req_line);
-static int		  int_is_next_user( pj_scanner *scanner);
-static void		  int_parse_status_line( pj_scanner *scanner, 
-						 pjsip_status_line *line);
-static void		  int_parse_user_pass( pj_scanner *scanner, 
-					       pj_str_t *user, 
-					       pj_str_t *pass);
-static void		  int_parse_uri_host_port( pj_scanner *scanner, 
-						   pj_str_t *p_host, 
-						   int *p_port);
-static pjsip_uri *	  int_parse_uri_or_name_addr( pj_scanner *scanner, 
-					    pj_pool_t *pool, unsigned option);
-static pjsip_url *	  int_parse_sip_url( pj_scanner *scanner, 
-					     pj_pool_t *pool,
-					     pj_bool_t parse_params);
-static pjsip_name_addr*	  int_parse_name_addr( pj_scanner *scanner, 
-					       pj_pool_t *pool );
-static void		  parse_hdr_end( pj_scanner *scanner );
-static pjsip_accept_hdr*  parse_hdr_accept( pj_scanner *scanner, 
-					    pj_pool_t *pool);
-static pjsip_allow_hdr*   parse_hdr_allow( pj_scanner *scanner, 
-					   pj_pool_t *pool);
-static pjsip_cid_hdr*	  parse_hdr_call_id( pj_scanner *scanner, 
-					     pj_pool_t *pool);
-static pjsip_contact_hdr* parse_hdr_contact( pj_scanner *scanner, 
-					     pj_pool_t *pool);
-static pjsip_clen_hdr*    parse_hdr_content_length( pj_scanner *scanner, 
-						    pj_pool_t *pool);
-static pjsip_ctype_hdr*   parse_hdr_content_type( pj_scanner *scanner, 
-						  pj_pool_t *pool);
-static pjsip_cseq_hdr*    parse_hdr_cseq( pj_scanner *scanner, 
-					  pj_pool_t *pool);
-static pjsip_expires_hdr* parse_hdr_expires( pj_scanner *scanner, 
-					  pj_pool_t *pool);
-static pjsip_from_hdr*    parse_hdr_from( pj_scanner *scanner, 
-					  pj_pool_t *pool);
-static pjsip_max_forwards_hdr*  parse_hdr_max_forwards( pj_scanner *scanner, 
-				        pj_pool_t *pool);
-static pjsip_min_expires_hdr*  parse_hdr_min_expires( pj_scanner *scanner, 
-				        pj_pool_t *pool);
-static pjsip_rr_hdr*      parse_hdr_rr( pj_scanner *scanner, 
-				        pj_pool_t *pool);
-static pjsip_route_hdr*   parse_hdr_route( pj_scanner *scanner, 
-					   pj_pool_t *pool);
-static pjsip_require_hdr* parse_hdr_require( pj_scanner *scanner, 
-				        pj_pool_t *pool);
-static pjsip_retry_after_hdr* parse_hdr_retry_after( pj_scanner *scanner, 
-				        pj_pool_t *pool);
-static pjsip_supported_hdr* parse_hdr_supported( pj_scanner *scanner, 
-				        pj_pool_t *pool);
-static pjsip_to_hdr*	  parse_hdr_to( pj_scanner *scanner, 
-				        pj_pool_t *pool);
-static pjsip_unsupported_hdr* parse_hdr_unsupported( pj_scanner *scanner, 
-				        pj_pool_t *pool);
-static pjsip_via_hdr*	  parse_hdr_via( pj_scanner *scanner, 
-					 pj_pool_t *pool);
-static pjsip_generic_string_hdr* parse_hdr_generic_string( pj_scanner *scanner, 
-					     pj_pool_t *pool);
+static pjsip_msg *  int_parse_msg( pjsip_parse_ctx *ctx, 
+				   pjsip_parser_err_report *err_list);
+static void	    int_parse_param( pj_scanner *scanner, 
+				     pj_str_t *pname, 
+				     pj_str_t *pvalue);
+static void         int_parse_req_line( pj_scanner *scanner, 
+					pj_pool_t *pool,
+					pjsip_request_line *req_line);
+static int          int_is_next_user( pj_scanner *scanner);
+static void	    int_parse_status_line( pj_scanner *scanner, 
+					   pjsip_status_line *line);
+static void	    int_parse_user_pass( pj_scanner *scanner, 
+					 pj_str_t *user, 
+					 pj_str_t *pass);
+static void	    int_parse_uri_host_port( pj_scanner *scanner, 
+					     pj_str_t *p_host, 
+					     int *p_port);
+static pjsip_uri *  int_parse_uri_or_name_addr( pj_scanner *scanner, 
+					        pj_pool_t *pool, 
+                                                unsigned option);
+static pjsip_url *  int_parse_sip_url( pj_scanner *scanner, 
+				       pj_pool_t *pool,
+				       pj_bool_t parse_params);
+static pjsip_name_addr *
+                    int_parse_name_addr( pj_scanner *scanner, 
+					 pj_pool_t *pool );
+static void	    parse_hdr_end( pj_scanner *scanner );
+
+static pjsip_hdr*   parse_hdr_accept( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_allow( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_call_id( pjsip_parse_ctx *ctx);
+static pjsip_hdr*   parse_hdr_contact( pjsip_parse_ctx *ctx);
+static pjsip_hdr*   parse_hdr_content_len( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_content_type( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_cseq( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_expires( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_from( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_max_forwards( pjsip_parse_ctx *ctx);
+static pjsip_hdr*   parse_hdr_min_expires( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_rr( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_route( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_require( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_retry_after( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_supported( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_to( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_unsupported( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_via( pjsip_parse_ctx *ctx );
+static pjsip_hdr*   parse_hdr_generic_string( pjsip_parse_ctx *ctx);
 
 /* Convert non NULL terminated string to integer. */
-static unsigned long pj_strtoul_mindigit(const pj_str_t *str, unsigned mindig)
+static unsigned long pj_strtoul_mindigit(const pj_str_t *str, 
+                                         unsigned mindig)
 {
     unsigned long value;
@@ -164,12 +156,11 @@
 
 /* Case insensitive comparison */
-#define parser_stricmp(str1, str2)  \
-	    (str1.slen != str2.slen ? -1 : \
-		!(memcmp(str1.ptr, str2.ptr, str1.slen)==0 || stricmp(str1.ptr, str2.ptr)==0))
+#define parser_stricmp(str1, str2)  pj_stricmp(&str1, &str2)
+
 
 /* Syntax error handler for parser. */
 static void on_syntax_error(pj_scanner *scanner)
 {
-    PJ_UNUSED_ARG(scanner)
+    PJ_UNUSED_ARG(scanner);
     PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
 }
@@ -177,5 +168,6 @@
 /* Concatenate unrecognized params into single string. */
 void pjsip_concat_param_imp( pj_str_t *param, pj_pool_t *pool, 
-			     const pj_str_t *pname, const pj_str_t *pvalue, int sepchar)
+			     const pj_str_t *pname, const pj_str_t *pvalue, 
+                             int sepchar)
 {
     char *new_param, *p;
@@ -214,73 +206,142 @@
 
 /* Initialize static properties of the parser. */
-static void init_parser()
+static pj_status_t init_parser()
 {
     static int initialized;
+    pj_status_t status;
 
     if (initialized)
-	return;
+	return PJ_SUCCESS;
 
     initialized = 1;
 
-    pj_cs_add_num( pjsip_DIGIT_SPEC );
-    pj_cs_add_alpha( pjsip_ALPHA_SPEC );
+    pj_cis_buf_init(&cis_buf);
+
+    status = pj_cis_init(&cis_buf, &pjsip_DIGIT_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_num(&pjsip_DIGIT_SPEC);
     
-    pj_cs_add_alpha( pjsip_ALNUM_SPEC );
-    pj_cs_add_num( pjsip_ALNUM_SPEC );
-
-    pj_cs_add_str(pjsip_NEWLINE_OR_EOF_SPEC, "\r\n");
+    status = pj_cis_init(&cis_buf, &pjsip_ALPHA_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_alpha( &pjsip_ALPHA_SPEC );
+    
+    status = pj_cis_init(&cis_buf, &pjsip_ALNUM_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    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);
+    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_cs_add_str( pjsip_ARRAY_ELEMENTS, ",\r\n");
-
-    pj_memcpy(pjsip_TOKEN_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec));
-    pj_cs_add_str( pjsip_TOKEN_SPEC, TOKEN);
-
-    pj_memcpy(pjsip_HOST_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec));
-    pj_cs_add_str( pjsip_HOST_SPEC, HOST);
-
-    pj_memcpy(pjsip_HEX_SPEC, pjsip_DIGIT_SPEC, sizeof(pj_char_spec));
-    pj_cs_add_str( pjsip_HEX_SPEC, HEX_DIGIT);
-
-    pj_memcpy(pjsip_PARAM_CHAR_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec));
-    pj_cs_add_str( pjsip_PARAM_CHAR_SPEC, PARAM_CHAR);
-
-    pj_memcpy(pjsip_USER_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec));
-    pj_cs_add_str( pjsip_USER_SPEC, MARK ESCAPED USER );
-
-    pj_memcpy(pjsip_PASSWD_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec));
-    pj_cs_add_str( pjsip_PASSWD_SPEC, MARK ESCAPED PASS);
-
-    pj_cs_add_str( pjsip_PROBE_USER_HOST_SPEC, "@ \n>");
-    pj_cs_invert( pjsip_PROBE_USER_HOST_SPEC );
-
-    pj_cs_add_str( pjsip_DISPLAY_SCAN_SPEC, ":\r\n<");
-
-    pjsip_register_hdr_parser( "Accept", NULL, (pjsip_parse_hdr_func*) &parse_hdr_accept);
-    pjsip_register_hdr_parser( "Allow", NULL, (pjsip_parse_hdr_func*) &parse_hdr_allow);
-    pjsip_register_hdr_parser( "Call-ID", NULL, (pjsip_parse_hdr_func*) &parse_hdr_call_id);
-    pjsip_register_hdr_parser( "Contact", "m", (pjsip_parse_hdr_func*) &parse_hdr_contact);
-    pjsip_register_hdr_parser( "Content-Length", NULL, (pjsip_parse_hdr_func*) &parse_hdr_content_length);
-    pjsip_register_hdr_parser( "Content-Type", NULL, (pjsip_parse_hdr_func*) &parse_hdr_content_type);
-    pjsip_register_hdr_parser( "CSeq", NULL, (pjsip_parse_hdr_func*) &parse_hdr_cseq);
-    pjsip_register_hdr_parser( "Expires", NULL, (pjsip_parse_hdr_func*) &parse_hdr_expires);
-    pjsip_register_hdr_parser( "From", "f", (pjsip_parse_hdr_func*) &parse_hdr_from);
-    pjsip_register_hdr_parser( "Max-Forwards", NULL, (pjsip_parse_hdr_func*) &parse_hdr_max_forwards);
-    pjsip_register_hdr_parser( "Min-Expires", NULL, (pjsip_parse_hdr_func*) &parse_hdr_min_expires);
-    pjsip_register_hdr_parser( "Record-Route", NULL, (pjsip_parse_hdr_func*) &parse_hdr_rr);
-    pjsip_register_hdr_parser( "Route", NULL, (pjsip_parse_hdr_func*) &parse_hdr_route);
-    pjsip_register_hdr_parser( "Require", NULL, (pjsip_parse_hdr_func*) &parse_hdr_require);
-    pjsip_register_hdr_parser( "Retry-After", NULL, (pjsip_parse_hdr_func*) &parse_hdr_retry_after);
-    pjsip_register_hdr_parser( "Supported", "k", (pjsip_parse_hdr_func*) &parse_hdr_supported);
-    pjsip_register_hdr_parser( "To", "t", (pjsip_parse_hdr_func*) &parse_hdr_to);
-    pjsip_register_hdr_parser( "Unsupported", NULL, (pjsip_parse_hdr_func*) &parse_hdr_unsupported);
-    pjsip_register_hdr_parser( "Via", NULL, (pjsip_parse_hdr_func*) &parse_hdr_via);
+    status = pj_cis_init(&cis_buf, &pjsip_ARRAY_ELEMENTS);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_str( &pjsip_ARRAY_ELEMENTS, ",\r\n");
+
+    status = pj_cis_dup(&pjsip_TOKEN_SPEC, &pjsip_ALNUM_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_str( &pjsip_TOKEN_SPEC, TOKEN);
+
+    status = pj_cis_dup(&pjsip_HOST_SPEC, &pjsip_ALNUM_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_str( &pjsip_HOST_SPEC, HOST);
+
+    status = pj_cis_dup(&pjsip_HEX_SPEC, &pjsip_DIGIT_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_str( &pjsip_HEX_SPEC, HEX_DIGIT);
+
+    status = pj_cis_dup(&pjsip_PARAM_CHAR_SPEC, &pjsip_ALNUM_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_str(&pjsip_PARAM_CHAR_SPEC, PARAM_CHAR);
+
+    status = pj_cis_dup(&pjsip_USER_SPEC, &pjsip_ALNUM_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_str( &pjsip_USER_SPEC, MARK ESCAPED USER );
+
+    status = pj_cis_dup(&pjsip_PASSWD_SPEC, &pjsip_ALNUM_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_str( &pjsip_PASSWD_SPEC, MARK ESCAPED PASS);
+
+    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>");
+    pj_cis_invert( &pjsip_PROBE_USER_HOST_SPEC );
+
+    status = pj_cis_init(&cis_buf, &pjsip_DISPLAY_SCAN_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_str( &pjsip_DISPLAY_SCAN_SPEC, ":\r\n<");
+
+    status = pjsip_register_hdr_parser( "Accept", NULL, &parse_hdr_accept);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Allow", NULL, &parse_hdr_allow);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Call-ID", NULL, &parse_hdr_call_id);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Contact", "m", &parse_hdr_contact);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Content-Length", NULL, 
+                                        &parse_hdr_content_len);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Content-Type", NULL, 
+                                        &parse_hdr_content_type);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "CSeq", NULL, &parse_hdr_cseq);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Expires", NULL, &parse_hdr_expires);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "From", "f", &parse_hdr_from);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Max-Forwards", NULL, 
+                                        &parse_hdr_max_forwards);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Min-Expires", NULL, 
+                                        &parse_hdr_min_expires);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Record-Route", NULL, &parse_hdr_rr);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Route", NULL, &parse_hdr_route);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Require", NULL, &parse_hdr_require);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Retry-After", NULL, 
+                                        &parse_hdr_retry_after);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Supported", "k", 
+                                        &parse_hdr_supported);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "To", "t", &parse_hdr_to);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Unsupported", NULL, 
+                                        &parse_hdr_unsupported);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    status = pjsip_register_hdr_parser( "Via", NULL, &parse_hdr_via);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
 
     /* Register auth parser. */
-    pjsip_auth_init_parser();
-
-}
-
-static void init_sip_parser()
+    status = pjsip_auth_init_parser();
+
+    return status;
+}
+
+static void init_sip_parser(void)
 {
     if (!parser_is_initialized) {
@@ -318,9 +379,10 @@
 
     /* Equal length and equal hash. compare the strings. */
-    return strcmp(r1->hname, name);
+    return pj_native_strcmp(r1->hname, name);
 }
 
 /* Register one handler for one header name. */
-static int int_register_parser( const char *name, pjsip_parse_hdr_func *fptr )
+static pj_status_t int_register_parser( const char *name, 
+                                        pjsip_parse_hdr_func *fptr )
 {
     unsigned	pos;
@@ -329,5 +391,5 @@
 
     if (handler_count >= PJ_ARRAY_SIZE(handler)) {
-	return -1;
+	return PJ_ETOOMANY;
     }
 
@@ -336,9 +398,9 @@
     rec.hname_len = strlen(name);
     if (rec.hname_len >= sizeof(rec.hname)) {
-	return -1;
+	return PJ_ENAMETOOLONG;
     }
     /* Name is copied in lowercase. */
     for (i=0; i<rec.hname_len; ++i) {
-	rec.hname[i] = (char)tolower(name[i]);
+	rec.hname[i] = (char)pj_tolower(name[i]);
     }
     rec.hname[i] = '\0';
@@ -349,8 +411,9 @@
     for (pos=0; pos < handler_count; ++pos) {
 	int d;
-	d = compare_handler(&handler[pos], rec.hname, rec.hname_len, rec.hname_hash);
+	d = compare_handler(&handler[pos], rec.hname, rec.hname_len, 
+                            rec.hname_hash);
 	if (d == 0) {
 	    pj_assert(0);
-	    return -1;
+	    return PJ_EEXISTS;
 	}
 	if (d > 0) {
@@ -361,5 +424,6 @@
     /* Shift handlers. */
     if (pos != handler_count) {
-	pj_memmove( &handler[pos+1], &handler[pos], (handler_count-pos)*sizeof(handler_rec));
+	pj_memmove( &handler[pos+1], &handler[pos], 
+                    (handler_count-pos)*sizeof(handler_rec));
     }
     /* Add new handler. */
@@ -367,5 +431,5 @@
     ++handler_count;
 
-    return 0;
+    return PJ_SUCCESS;
 }
 
@@ -377,11 +441,16 @@
 					       pjsip_parse_hdr_func *fptr)
 {
-    if (int_register_parser(hname, fptr)) {
-	return -1;
-    }
-    if (hshortname && int_register_parser(hshortname, fptr)) {
-	return -1;
-    }
-    return 0;
+    pj_status_t status;
+
+    status = int_register_parser(hname, fptr);
+    if (status != PJ_SUCCESS) {
+	return status;
+    }
+    if (hshortname) {
+        status = int_register_parser(hshortname, fptr);
+        if (status != PJ_SUCCESS) 
+	    return status;
+    }
+    return PJ_SUCCESS;
 }
 
@@ -393,15 +462,16 @@
     pj_uint32_t  hash;
     int		 comp;
-    unsigned	 i, n;
+    unsigned	 n;
+
+    if (hname->slen >= PJSIP_MAX_HNAME_LEN) {
+        pj_assert(!"Header name is too long!");
+        return NULL;
+    }
 
     /* Calculate hash value while converting the header to lowercase. 
      * Don't assume that 'hname' is NULL terminated.
      */
-    hash = 0;
-    for (i=0; i<(unsigned)hname->slen; ++i) {
-	hname_copy[i] = (char)tolower(hname->ptr[i]);
-	hash = hash * PJ_HASH_MULTIPLIER + hname_copy[i];
-    }
-    hname_copy[i] = '\0';
+    hash = pj_hash_calc_tolower(0, hname_copy, hname);
+    hname_copy[hname->slen] = '\0';
 
     /* Binary search for the handler. */
@@ -429,17 +499,24 @@
 
 /* Public function to parse SIP message. */
-PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool, char *buf, pj_size_t size,
+PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool, 
+                                    char *buf, pj_size_t size,
 				    pjsip_parser_err_report *err_list)
 {
     pjsip_msg *msg = NULL;
     pj_scanner scanner;
+    pjsip_parse_ctx context;
     PJ_USE_EXCEPTION;
 
     init_sip_parser();
 
-    pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error);
+    pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, 
+                 &on_syntax_error);
+
+    context.scanner = &scanner;
+    context.pool = pool;
+    context.rdata = NULL;
 
     PJ_TRY {
-	msg = int_parse_msg(&scanner, pool, err_list);
+	msg = int_parse_msg(&context, err_list);
     } 
     PJ_DEFAULT {
@@ -450,4 +527,33 @@
     pj_scan_fini(&scanner);
     return msg;
+}
+
+/* Public function to parse as rdata.*/
+PJ_DEF(pjsip_msg *) pjsip_parse_rdata( char *buf, pj_size_t size,
+                                       pjsip_rx_data *rdata )
+{
+    pj_scanner scanner;
+    pjsip_parse_ctx context;
+    PJ_USE_EXCEPTION;
+
+    init_sip_parser();
+
+    pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, 
+                 &on_syntax_error);
+
+    context.scanner = &scanner;
+    context.pool = rdata->pool;
+    context.rdata = rdata;
+
+    PJ_TRY {
+	rdata->msg = int_parse_msg(&context, &rdata->parse_err);
+    } 
+    PJ_DEFAULT {
+	rdata->msg = NULL;
+    }
+    PJ_END
+
+    pj_scan_fini(&scanner);
+    return rdata->msg;
 }
 
@@ -467,11 +573,11 @@
     /* For datagram, the whole datagram IS the message. */
     if (is_datagram) {
-	return PJ_TRUE;
+	return PJ_SUCCESS;
     }
 
 
     /* Find the end of header area by finding an empty line. */
-    if ((pos = strstr(buf, "\n\r\n")) == NULL) {
-	return PJ_FALSE;
+    if ((pos = pj_native_strstr(buf, "\n\r\n")) == NULL) {
+	return PJSIP_EPARTIALMSG;
     }
 
@@ -480,9 +586,11 @@
 
     /* Find "Content-Length" header the hard way. */
-    line = strchr(buf, '\n');
+    line = pj_native_strchr(buf, '\n');
     while (line && line < hdr_end-14) {
 	++line;
-	if ( ((*line=='C' || *line=='c') && strncasecmp(line, "Content-Length", 14) == 0) ||
-	     ((*line=='l' || *line=='L') && (*(line+1)==' ' || *(line+1)=='\t' || *(line+1)==':')))
+	if ( ((*line=='C' || *line=='c') && 
+              pj_native_strncasecmp(line, "Content-Length", 14) == 0) ||
+	     ((*line=='l' || *line=='L') && 
+              (*(line+1)==' ' || *(line+1)=='\t' || *(line+1)==':')))
 	{
 	    /* Try to parse the header. */
@@ -510,5 +618,5 @@
 
 		/* Get number */
-		pj_scan_get(&scanner, pjsip_DIGIT_SPEC, &str_clen);
+		pj_scan_get(&scanner, &pjsip_DIGIT_SPEC, &str_clen);
 
 		/* Get newline. */
@@ -528,22 +636,20 @@
 
 	/* Go to next line. */
-	line = strchr(line, '\n');
+	line = pj_native_strchr(line, '\n');
     }
 
     /* Found Content-Length? */
     if (content_length == -1) {
-	PJ_LOG(4, ("sipparser", "pjsip_find_msg: incoming TCP packet has missing "
-			     "Content-Length header, treated as incomplete."));
-	return PJ_FALSE;
+	return PJSIP_EMISSINGHDR;
     }
 
     /* Enough packet received? */
     *msg_size = (body_start - buf) + content_length;
-    return (*msg_size) <= size;
+    return (*msg_size) <= size ? PJ_SUCCESS : PJSIP_EPARTIALMSG;
 #else
-    PJ_UNUSED_ARG(buf)
-    PJ_UNUSED_ARG(is_datagram)
+    PJ_UNUSED_ARG(buf);
+    PJ_UNUSED_ARG(is_datagram);
     *msg_size = size;
-    return 1;
+    return PJ_SUCCESS;
 #endif
 }
@@ -558,8 +664,5 @@
     pjsip_uri *uri = NULL;
 
-    if (!parser_is_initialized) {
-	init_parser();
-	parser_is_initialized = 1;
-    }
+    init_sip_parser();
 
     pj_scan_init(&scanner, buf, size, 0, &on_syntax_error);
@@ -572,5 +675,7 @@
 
     /* Must have exhausted all inputs. */
-    if (pj_scan_is_eof(&scanner) || *scanner.current=='\r' || *scanner.current=='\n') {
+    if (pj_scan_is_eof(&scanner) || *scanner.curptr=='\r' || 
+                       *scanner.curptr=='\n') 
+    {
 	/* Success. */
 	pj_scan_fini(&scanner);
@@ -587,5 +692,6 @@
  * actual body is laid.
  */
-static int generic_print_body (pjsip_msg_body *msg_body, char *buf, pj_size_t size)
+static int generic_print_body (pjsip_msg_body *msg_body, 
+                               char *buf, pj_size_t size)
 {
     pjsip_msg_body *body = msg_body;
@@ -598,5 +704,5 @@
 
 /* Internal function to parse SIP message */
-static pjsip_msg *int_parse_msg( pj_scanner *scanner, pj_pool_t *pool, 
+static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx,
 				 pjsip_parser_err_report *err_list)
 {
@@ -605,10 +711,12 @@
     pjsip_msg *msg;
     pjsip_ctype_hdr *ctype_hdr = NULL;
+    pj_scanner *scanner = ctx->scanner;
+    pj_pool_t *pool = ctx->pool;
 
     /* Skip leading newlines. */
-    ch = *scanner->current;
+    ch = *scanner->curptr;
     while (ch=='\r' || ch=='\n') {
 	pj_scan_get_char(scanner);
-	ch = *scanner->current;
+	ch = *scanner->curptr;
     }
 
@@ -631,5 +739,5 @@
 
 	/* Get hname. */
-	pj_scan_get( scanner, pjsip_TOKEN_SPEC, &hname);
+	pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &hname);
 	ch = pj_scan_get_char( scanner );
 	if (ch != ':') {
@@ -646,10 +754,9 @@
 	     */
 	    if (handler) {
-		hdr = (*handler)(scanner, pool);
+		hdr = (*handler)(ctx);
 	    } else {
-		pjsip_generic_string_hdr *ghdr = parse_hdr_generic_string(scanner, pool);
-		ghdr->type = PJSIP_H_OTHER;
-		ghdr->name = ghdr->sname = hname;
-		hdr = (pjsip_hdr*)ghdr;
+		hdr = parse_hdr_generic_string(ctx);
+		hdr->type = PJSIP_H_OTHER;
+		hdr->name = hdr->sname = hname;
 	    }
 
@@ -669,6 +776,7 @@
 	    hdr = NULL;
 
-	    PJ_LOG(4,("sipparser", "Syntax error in line %d col %d (hname=%.*s)",
-		      scanner->line, scanner->col, hname.slen, hname.ptr));
+	    //PJ_LOG(4,("sipparser", 
+            //          "Syntax error in line %d col %d (hname=%.*s)",
+	    //	      scanner->line, scanner->col, hname.slen, hname.ptr));
 
 	    if (err_list) {
@@ -685,5 +793,5 @@
 
 	    if (!pj_scan_is_eof(scanner)) {
-		pj_scan_get_until(scanner, pjsip_NEWLINE_OR_EOF_SPEC, &token);
+		pj_scan_get_until(scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &token);
 		parse_hdr_end(scanner);
 	    }
@@ -703,21 +811,21 @@
 	/* Parse until EOF or an empty line is found. */
     } while (!pj_scan_is_eof(scanner) && 
-	      *scanner->current != '\r' && *scanner->current != '\n');
+	      *scanner->curptr != '\r' && *scanner->curptr != '\n');
 
     /* If empty line is found, eat it. */
     if (!pj_scan_is_eof(scanner)) {
-	if (*scanner->current=='\r' || *scanner->current=='\n') {
+	if (*scanner->curptr=='\r' || *scanner->curptr=='\n') {
 	    pj_scan_get_newline(scanner);
 	}
     }
 
-    /* If we have Content-Type header, treat the rest of the message as body. */
+    /* If we have Content-Type header, treat the rest of the message as body.*/
     if (ctype_hdr) {
 	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->data = scanner->current;
-	body->len = scanner->end - scanner->current;
+	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->data = scanner->curptr;
+	body->len = scanner->end - scanner->curptr;
 	body->print_body = &generic_print_body;
 
@@ -734,11 +842,11 @@
 {
     /* pname */
-    pj_scan_get(scanner, pjsip_PARAM_CHAR_SPEC, pname);
+    pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pname);
 
     /* pvalue, if any */
-    if (*scanner->current == '=') {
+    if (*scanner->curptr == '=') {
 	pj_scan_get_char(scanner);
 	/* pvalue can be a quoted string. */
-	if (*scanner->current == '"') {
+	if (*scanner->curptr == '"') {
 	    pj_scan_get_quote( scanner, '"', '"', pvalue);
 	    if (option & PJSIP_PARSE_REMOVE_QUOTE) {
@@ -747,5 +855,5 @@
 	    }
 	} else {
-	    pj_scan_get(scanner, pjsip_PARAM_CHAR_SPEC, pvalue);
+	    pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pvalue);
 	}
     } else {
@@ -770,9 +878,9 @@
 				     pj_str_t *host, int *p_port)
 {
-    pj_scan_get( scanner, pjsip_HOST_SPEC, host);
-    if (*scanner->current == ':') {
+    pj_scan_get( scanner, &pjsip_HOST_SPEC, host);
+    if (*scanner->curptr == ':') {
 	pj_str_t port;
 	pj_scan_get_char(scanner);
-	pj_scan_get(scanner, pjsip_DIGIT_SPEC, &port);
+	pj_scan_get(scanner, &pjsip_DIGIT_SPEC, &port);
 	*p_port = pj_strtoul(&port);
     } else {
@@ -790,5 +898,5 @@
      * must be a username.
      */
-    if (pj_scan_peek( scanner, pjsip_PROBE_USER_HOST_SPEC, &dummy) == '@')
+    if (pj_scan_peek( scanner, &pjsip_PROBE_USER_HOST_SPEC, &dummy) == '@')
 	is_user = 1;
     else
@@ -802,8 +910,8 @@
 				 pj_str_t *user, pj_str_t *pass)
 {
-    pj_scan_get( scanner, pjsip_USER_SPEC, user);
-    if ( *scanner->current == ':') {
+    pj_scan_get( scanner, &pjsip_USER_SPEC, user);
+    if ( *scanner->curptr == ':') {
 	pj_scan_get_char( scanner );
-	pj_scan_get( scanner, pjsip_PASSWD_SPEC, pass);
+	pj_scan_get( scanner, &pjsip_PASSWD_SPEC, pass);
     } else {
 	pass->ptr = NULL;
@@ -816,11 +924,11 @@
 
 /* Parse all types of URI. */
-static pjsip_uri *int_parse_uri_or_name_addr(pj_scanner *scanner, pj_pool_t *pool,
-						  unsigned option)
+static pjsip_uri *int_parse_uri_or_name_addr( pj_scanner *scanner, pj_pool_t *pool,
+					      unsigned opt)
 {
     pjsip_uri *uri;
     int is_name_addr = 0;
 
-    if (*scanner->current=='"' || *scanner->current=='<') {
+    if (*scanner->curptr=='"' || *scanner->curptr=='<') {
 	uri = (pjsip_uri*)int_parse_name_addr( scanner, pool );
 	is_name_addr = 1;
@@ -831,12 +939,15 @@
 
 	pj_scan_save_state( scanner, &backtrack);
-	pj_scan_get( scanner, pjsip_TOKEN_SPEC, &scheme);
+	pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &scheme);
 	colon = pj_scan_get_char( scanner );
 	pj_scan_restore_state( scanner, &backtrack);
 
-	if (colon==':' && (parser_stricmp(scheme, pjsip_SIP_STR)==0 || parser_stricmp(scheme, pjsip_SIPS_STR)==0)) 
+	if (colon==':' && 
+            (parser_stricmp(scheme, pjsip_SIP_STR)==0 || 
+             parser_stricmp(scheme, pjsip_SIPS_STR)==0)) 
 	{
-	    uri = (pjsip_uri*)int_parse_sip_url( scanner, pool, 
-					(option & PJSIP_PARSE_URI_IN_FROM_TO_HDR) == 0 );
+	    uri = (pjsip_uri*)
+                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) {
@@ -853,5 +964,5 @@
 
     /* Should we return the URI object as name address? */
-    if (option & PJSIP_PARSE_URI_AS_NAMEADDR) {
+    if (opt & PJSIP_PARSE_URI_AS_NAMEADDR) {
 	if (is_name_addr == 0) {
 	    pjsip_name_addr *name_addr;
@@ -871,5 +982,5 @@
 				pj_bool_t parse_params)
 {
-    if (*scanner->current=='"' || *scanner->current=='<') {
+    if (*scanner->curptr=='"' || *scanner->curptr=='<') {
 	return (pjsip_uri*)int_parse_name_addr( scanner, pool );
     } else {
@@ -878,12 +989,13 @@
 
 	/* Get scheme. */
-	colon = pj_scan_peek(scanner, pjsip_TOKEN_SPEC, &scheme);
+	colon = pj_scan_peek(scanner, &pjsip_TOKEN_SPEC, &scheme);
 	if (colon != ':') {
 	    PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
 	}
 
-	if ((parser_stricmp(scheme, pjsip_SIP_STR)==0 || parser_stricmp(scheme, pjsip_SIPS_STR)==0)) 
+	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 );
+	    return (pjsip_uri*)int_parse_sip_url( scanner, pool, parse_params);
 
 	} else if (parser_stricmp(scheme, pjsip_TEL_STR)==0) {
@@ -909,5 +1021,5 @@
     scanner->skip_ws = 0;
 
-    pj_scan_get(scanner, pjsip_TOKEN_SPEC, &scheme);
+    pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &scheme);
     colon = pj_scan_get_char(scanner);
     if (colon != ':') {
@@ -938,5 +1050,5 @@
 
     /* Get URL parameters. */
-    while ( parse_params && *scanner->current == ';' ) {
+    while ( parse_params && *scanner->curptr == ';' ) {
 	pj_str_t pname, pvalue;
 
@@ -949,5 +1061,5 @@
 	    url->method_param = pvalue;
 
-	} else if (!parser_stricmp(pname, pjsip_TRANSPORT_STR) && pvalue.slen) {
+	} else if (!parser_stricmp(pname,pjsip_TRANSPORT_STR) && pvalue.slen) {
 	    url->transport_param = pvalue;
 
@@ -967,6 +1079,7 @@
 
     /* Get header params. */
-    if (parse_params && *scanner->current == '?') {
-	pj_scan_get_until(scanner, pjsip_NEWLINE_OR_EOF_SPEC, &url->header_param);
+    if (parse_params && *scanner->curptr == '?') {
+	pj_scan_get_until(scanner, &pjsip_NEWLINE_OR_EOF_SPEC, 
+                          &url->header_param);
     }
 
@@ -985,8 +1098,8 @@
     name_addr = pjsip_name_addr_create(pool);
 
-    if (*scanner->current == '"') {
+    if (*scanner->curptr == '"') {
 	pj_scan_get_quote( scanner, '"', '"', &name_addr->display);
 
-    } else if (*scanner->current != '<') {
+    } else if (*scanner->curptr != '<') {
 	int next;
 	pj_str_t dummy;
@@ -997,5 +1110,5 @@
 	 * will be parser later.
 	 */
-	next = pj_scan_peek_until(scanner, pjsip_DISPLAY_SCAN_SPEC, &dummy);
+	next = pj_scan_peek_until(scanner, &pjsip_DISPLAY_SCAN_SPEC, &dummy);
 	if (next == '<') {
 	    /* Ok, this is what we're looking for, a display name. */
@@ -1009,5 +1122,5 @@
 
     /* Get the SIP-URL */
-    has_bracket = (*scanner->current == '<');
+    has_bracket = (*scanner->curptr == '<');
     if (has_bracket)
 	pj_scan_get_char(scanner);
@@ -1026,5 +1139,5 @@
     pj_str_t token;
 
-    pj_scan_get( scanner, pjsip_TOKEN_SPEC, &token);
+    pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &token);
     pjsip_method_init_np( &req_line->method, &token);
 
@@ -1046,7 +1159,8 @@
     pj_scan_advance_n( scanner, 7, 1);
 
-    pj_scan_get( scanner, pjsip_DIGIT_SPEC, &token);
+    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_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC, 
+                       &status_line->reason);
     pj_scan_get_newline( scanner );
 }
@@ -1057,5 +1171,5 @@
     if (pj_scan_is_eof(scanner)) {
 	;   /* Do nothing. */
-    } else if (*scanner->current == '&') {
+    } else if (*scanner->curptr == '&') {
 	pj_scan_get_char(scanner);
     } else {
@@ -1074,10 +1188,11 @@
 				     pj_scanner *scanner)
 {
-    pj_scan_get_until( scanner, pjsip_ARRAY_ELEMENTS, &hdr->values[0]);
+    pj_scan_get_until( scanner, &pjsip_ARRAY_ELEMENTS, &hdr->values[0]);
     hdr->count++;
 
-    while (*scanner->current == ',') {
+    while (*scanner->curptr == ',') {
 	pj_scan_get_char(scanner);
-	pj_scan_get_until( scanner, pjsip_ARRAY_ELEMENTS, &hdr->values[hdr->count]);
+	pj_scan_get_until( scanner, &pjsip_ARRAY_ELEMENTS, 
+                           &hdr->values[hdr->count]);
 	hdr->count++;
     }
@@ -1089,5 +1204,5 @@
 				      pj_scanner *scanner )
 {
-    pj_scan_get_until( scanner, pjsip_NEWLINE_OR_EOF_SPEC, &hdr->hvalue);
+    pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &hdr->hvalue);
     parse_hdr_end(scanner);
 }
@@ -1098,5 +1213,5 @@
 {
     pj_str_t tmp;
-    pj_scan_get_until( scanner, pjsip_NEWLINE_OR_EOF_SPEC, &tmp);
+    pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &tmp);
     hdr->ivalue = pj_strtoul(&tmp);
     parse_hdr_end(scanner);
@@ -1105,29 +1220,30 @@
 
 /* Parse Accept header. */
-static pjsip_accept_hdr* parse_hdr_accept( pj_scanner *scanner, 
-					    pj_pool_t *pool)
-{
-    pjsip_accept_hdr *accept = pjsip_accept_hdr_create(pool);
-    parse_generic_array_hdr(accept, scanner);
-    return accept;
+static pjsip_hdr* parse_hdr_accept(pjsip_parse_ctx *ctx)
+{
+    pjsip_accept_hdr *accept = pjsip_accept_hdr_create(ctx->pool);
+    parse_generic_array_hdr(accept, ctx->scanner);
+    return (pjsip_hdr*)accept;
 }
 
 /* Parse Allow header. */
-static pjsip_allow_hdr*   parse_hdr_allow( pj_scanner *scanner, 
-					   pj_pool_t *pool)
-{
-    pjsip_allow_hdr *allow = pjsip_allow_hdr_create(pool);
-    parse_generic_array_hdr(allow, scanner);
-    return allow;
+static pjsip_hdr* parse_hdr_allow(pjsip_parse_ctx *ctx)
+{
+    pjsip_allow_hdr *allow = pjsip_allow_hdr_create(ctx->pool);
+    parse_generic_array_hdr(allow, ctx->scanner);
+    return (pjsip_hdr*)allow;
 }
 
 /* Parse Call-ID header. */
-static pjsip_cid_hdr* parse_hdr_call_id( pj_scanner *scanner, 
-					  pj_pool_t *pool)
-{
-    pjsip_cid_hdr *hdr = pjsip_cid_hdr_create(pool);
-    pj_scan_get_until( scanner, pjsip_NEWLINE_OR_EOF_SPEC, &hdr->id);
-    parse_hdr_end(scanner);
-    return hdr;
+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);
+    parse_hdr_end(ctx->scanner);
+
+    if (ctx->rdata)
+        ctx->rdata->call_id = hdr->id;
+
+    return (pjsip_hdr*)hdr;
 }
 
@@ -1137,5 +1253,5 @@
 				     pj_pool_t *pool)
 {
-    while ( *scanner->current == ';' ) {
+    while ( *scanner->curptr == ';' ) {
 	pj_str_t pname, pvalue;
 
@@ -1160,11 +1276,11 @@
 
 /* Parse Contact header. */
-PJ_DEF(pjsip_contact_hdr*) parse_hdr_contact( pj_scanner *scanner, 
-					      pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_contact( pjsip_parse_ctx *ctx )
 {
     pjsip_contact_hdr *first = NULL;
+    pj_scanner *scanner = ctx->scanner;
     
     do {
-	pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(pool);
+	pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(ctx->pool);
 	if (first == NULL)
 	    first = hdr;
@@ -1172,5 +1288,5 @@
 	    pj_list_insert_before(first, hdr);
 
-	if (*scanner->current == '*') {
+	if (*scanner->curptr == '*') {
 	    pj_scan_get_char(scanner);
 	    hdr->star = 1;
@@ -1178,10 +1294,11 @@
 	} else {
 	    hdr->star = 0;
-	    hdr->uri = int_parse_uri_or_name_addr(scanner, pool, PJSIP_PARSE_URI_AS_NAMEADDR);
-
-	    int_parse_contact_param(hdr, scanner, pool);
-	}
-
-	if (*scanner->current != ',')
+	    hdr->uri = int_parse_uri_or_name_addr(scanner, ctx->pool, 
+                                                  PJSIP_PARSE_URI_AS_NAMEADDR);
+
+	    int_parse_contact_param(hdr, scanner, ctx->pool);
+	}
+
+	if (*scanner->curptr != ',')
 	    break;
 
@@ -1191,70 +1308,80 @@
 
     parse_hdr_end(scanner);
-    return first;
+
+    return (pjsip_hdr*)first;
 }
 
 /* Parse Content-Length header. */
-PJ_DEF(pjsip_clen_hdr*) parse_hdr_content_length( pj_scanner *scanner, 
-					          pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_content_len( pjsip_parse_ctx *ctx )
 {
     pj_str_t digit;
     pjsip_clen_hdr *hdr;
 
-    hdr = pjsip_clen_hdr_create(pool);
-    pj_scan_get(scanner, pjsip_DIGIT_SPEC, &digit);
+    hdr = pjsip_clen_hdr_create(ctx->pool);
+    pj_scan_get(ctx->scanner, &pjsip_DIGIT_SPEC, &digit);
     hdr->len = pj_strtoul(&digit);
-    parse_hdr_end(scanner);
-    return hdr;
+    parse_hdr_end(ctx->scanner);
+
+    if (ctx->rdata)
+        ctx->rdata->clen = hdr;
+
+    return (pjsip_hdr*)hdr;
 }
 
 /* Parse Content-Type header. */
-PJ_DEF(pjsip_ctype_hdr*) parse_hdr_content_type( pj_scanner *scanner, 
-					         pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_content_type( pjsip_parse_ctx *ctx )
 {
     pjsip_ctype_hdr *hdr;
-
-    hdr = pjsip_ctype_hdr_create(pool);
+    pj_scanner *scanner = ctx->scanner;
+
+    hdr = pjsip_ctype_hdr_create(ctx->pool);
     
     /* Parse media type and subtype. */
-    pj_scan_get(scanner, pjsip_TOKEN_SPEC, &hdr->media.type);
+    pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &hdr->media.type);
     pj_scan_get_char(scanner);
-    pj_scan_get(scanner, pjsip_TOKEN_SPEC, &hdr->media.subtype);
+    pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &hdr->media.subtype);
 
     /* Parse media parameters */
-    while (*scanner->current == ';') {
+    while (*scanner->curptr == ';') {
 	pj_str_t pname, pvalue;
 	int_parse_param(scanner, &pname, &pvalue);
-	concat_param(&hdr->media.param, pool, &pname, &pvalue);
-    }
-
-    parse_hdr_end(scanner);
-    return hdr;
+	concat_param(&hdr->media.param, ctx->pool, &pname, &pvalue);
+    }
+
+    parse_hdr_end(ctx->scanner);
+
+    if (ctx->rdata)
+        ctx->rdata->ctype = hdr;
+
+    return (pjsip_hdr*)hdr;
 }
 
 /* Parse CSeq header. */
-PJ_DEF(pjsip_cseq_hdr*) parse_hdr_cseq( pj_scanner *scanner, 
-				        pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_cseq( pjsip_parse_ctx *ctx )
 {
     pj_str_t cseq, method;
     pjsip_cseq_hdr *hdr;
 
-    hdr = pjsip_cseq_hdr_create(pool);
-    pj_scan_get( scanner, pjsip_DIGIT_SPEC, &cseq);
+    hdr = pjsip_cseq_hdr_create(ctx->pool);
+    pj_scan_get( ctx->scanner, &pjsip_DIGIT_SPEC, &cseq);
     hdr->cseq = pj_strtoul(&cseq);
 
-    pj_scan_get( scanner, pjsip_TOKEN_SPEC, &method);
+    pj_scan_get( ctx->scanner, &pjsip_TOKEN_SPEC, &method);
     pjsip_method_init_np(&hdr->method, &method);
 
-    parse_hdr_end( scanner );
-    return hdr;
+    parse_hdr_end( ctx->scanner );
+
+    if (ctx->rdata)
+        ctx->rdata->cseq = hdr;
+
+    return (pjsip_hdr*)hdr;
 }
 
 /* Parse Expires header. */
-static pjsip_expires_hdr* parse_hdr_expires(pj_scanner *scanner, 
-					    pj_pool_t *pool)
-{
-    pjsip_expires_hdr *hdr = pjsip_expires_hdr_create(pool);
-    parse_generic_int_hdr(hdr, scanner);
-    return hdr;
+static pjsip_hdr* parse_hdr_expires(pjsip_parse_ctx *ctx)
+{
+    pjsip_expires_hdr *hdr = pjsip_expires_hdr_create(ctx->pool);
+    parse_generic_int_hdr(hdr, ctx->scanner);
+    return (pjsip_hdr*)hdr;
 }
 
@@ -1268,5 +1395,5 @@
 					  PJSIP_PARSE_URI_IN_FROM_TO_HDR);
 
-    while ( *scanner->current == ';' ) {
+    while ( *scanner->curptr == ';' ) {
 	pj_str_t pname, pvalue;
 
@@ -1285,57 +1412,62 @@
 
 /* Parse From: header. */
-PJ_DEF(pjsip_from_hdr*) parse_hdr_from( pj_scanner *scanner, 
-				        pj_pool_t *pool)
-{
-    pjsip_from_hdr *hdr = pjsip_from_hdr_create(pool);
-    parse_hdr_fromto(scanner, pool, hdr);
-    return hdr;
+static pjsip_hdr* parse_hdr_from( pjsip_parse_ctx *ctx )
+{
+    pjsip_from_hdr *hdr = pjsip_from_hdr_create(ctx->pool);
+    parse_hdr_fromto(ctx->scanner, ctx->pool, hdr);
+    if (ctx->rdata)
+        ctx->rdata->from = hdr;
+
+    return (pjsip_hdr*)hdr;
 }
 
 /* Parse Require: header. */
-static pjsip_require_hdr* parse_hdr_require( pj_scanner *scanner, 
-					     pj_pool_t *pool)
-{
-    pjsip_require_hdr *hdr = pjsip_require_hdr_create(pool);
-    parse_generic_array_hdr(hdr, scanner);
-    return hdr;
+static pjsip_hdr* parse_hdr_require( pjsip_parse_ctx *ctx )
+{
+    pjsip_require_hdr *hdr = pjsip_require_hdr_create(ctx->pool);
+    parse_generic_array_hdr(hdr, ctx->scanner);
+
+    if (ctx->rdata && ctx->rdata->require == NULL)
+        ctx->rdata->require = hdr;
+
+    return (pjsip_hdr*)hdr;
 }
 
 /* Parse Retry-After: header. */
-static pjsip_retry_after_hdr* parse_hdr_retry_after(pj_scanner *scanner, 
-						    pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_retry_after(pjsip_parse_ctx *ctx)
 {
     pjsip_retry_after_hdr *hdr;
-    hdr = pjsip_retry_after_hdr_create(pool);
-    parse_generic_int_hdr(hdr, scanner);
-    return hdr;
+    hdr = pjsip_retry_after_hdr_create(ctx->pool);
+    parse_generic_int_hdr(hdr, ctx->scanner);
+    return (pjsip_hdr*)hdr;
 }
 
 /* Parse Supported: header. */
-static pjsip_supported_hdr* parse_hdr_supported(pj_scanner *scanner, 
-						pj_pool_t *pool)
-{
-    pjsip_supported_hdr *hdr = pjsip_supported_hdr_create(pool);
-    parse_generic_array_hdr(hdr, scanner);
-    return hdr;
+static pjsip_hdr* parse_hdr_supported(pjsip_parse_ctx *ctx)
+{
+    pjsip_supported_hdr *hdr = pjsip_supported_hdr_create(ctx->pool);
+    parse_generic_array_hdr(hdr, ctx->scanner);
+    return (pjsip_hdr*)hdr;
 }
 
 
 /* Parse To: header. */
-PJ_DEF(pjsip_to_hdr*) parse_hdr_to( pj_scanner *scanner, 
-				    pj_pool_t *pool)
-{
-    pjsip_to_hdr *hdr = pjsip_to_hdr_create(pool);
-    parse_hdr_fromto(scanner, pool, hdr);
-    return hdr;
+static pjsip_hdr* parse_hdr_to( pjsip_parse_ctx *ctx )
+{
+    pjsip_to_hdr *hdr = pjsip_to_hdr_create(ctx->pool);
+    parse_hdr_fromto(ctx->scanner, ctx->pool, hdr);
+
+    if (ctx->rdata)
+        ctx->rdata->to = hdr;
+
+    return (pjsip_hdr*)hdr;
 }
 
 /* Parse Unsupported: header. */
-static pjsip_unsupported_hdr* parse_hdr_unsupported(pj_scanner *scanner, 
-						    pj_pool_t *pool)
-{
-    pjsip_unsupported_hdr *hdr = pjsip_unsupported_hdr_create(pool);
-    parse_generic_array_hdr(hdr, scanner);
-    return hdr;
+static pjsip_hdr* parse_hdr_unsupported(pjsip_parse_ctx *ctx)
+{
+    pjsip_unsupported_hdr *hdr = pjsip_unsupported_hdr_create(ctx->pool);
+    parse_generic_array_hdr(hdr, ctx->scanner);
+    return (pjsip_hdr*)hdr;
 }
 
@@ -1344,5 +1476,5 @@
 				 pj_pool_t *pool)
 {
-    while ( *scanner->current == ';' ) {
+    while ( *scanner->curptr == ';' ) {
 	pj_str_t pname, pvalue;
 
@@ -1374,21 +1506,23 @@
 
 /* Parse Max-Forwards header. */
-static pjsip_max_forwards_hdr* parse_hdr_max_forwards( pj_scanner *scanner, 
-						       pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_max_forwards( pjsip_parse_ctx *ctx )
 {
     pjsip_max_forwards_hdr *hdr;
-    hdr = pjsip_max_forwards_hdr_create(pool);
-    parse_generic_int_hdr(hdr, scanner);
-    return hdr;
+    hdr = pjsip_max_forwards_hdr_create(ctx->pool);
+    parse_generic_int_hdr(hdr, ctx->scanner);
+
+    if (ctx->rdata)
+        ctx->rdata->max_fwd = hdr;
+
+    return (pjsip_hdr*)hdr;
 }
 
 /* Parse Min-Expires header. */
-static pjsip_min_expires_hdr*  parse_hdr_min_expires(pj_scanner *scanner, 
-						     pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_min_expires(pjsip_parse_ctx *ctx)
 {
     pjsip_min_expires_hdr *hdr;
-    hdr = pjsip_min_expires_hdr_create(pool);
-    parse_generic_int_hdr(hdr, scanner);
-    return hdr;
+    hdr = pjsip_min_expires_hdr_create(ctx->pool);
+    parse_generic_int_hdr(hdr, ctx->scanner);
+    return (pjsip_hdr*)hdr;
 }
 
@@ -1401,16 +1535,18 @@
 
     pj_memcpy(&hdr->name_addr, temp, sizeof(*temp));
-    if (*scanner->current == ';') {
-	pj_scan_get_until(scanner, pjsip_NEWLINE_OR_EOF_SPEC, &hdr->other_param);
+    if (*scanner->curptr == ';') {
+	pj_scan_get_until(scanner, &pjsip_NEWLINE_OR_EOF_SPEC, 
+                          &hdr->other_param);
     }
 }
 
 /* Parse Record-Route header. */
-PJ_DEF(pjsip_rr_hdr*) parse_hdr_rr( pj_scanner *scanner, pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_rr( pjsip_parse_ctx *ctx)
 {
     pjsip_rr_hdr *first = NULL;
+    pj_scanner *scanner = ctx->scanner;
 
     do {
-	pjsip_rr_hdr *hdr = pjsip_rr_hdr_create(pool);
+	pjsip_rr_hdr *hdr = pjsip_rr_hdr_create(ctx->pool);
 	if (!first) {
 	    first = hdr;
@@ -1418,6 +1554,6 @@
 	    pj_list_insert_before(first, hdr);
 	}
-	parse_hdr_rr_route(scanner, pool, hdr);
-	if (*scanner->current == ',') {
+	parse_hdr_rr_route(scanner, ctx->pool, hdr);
+	if (*scanner->curptr == ',') {
 	    pj_scan_get_char(scanner);
 	} else {
@@ -1426,15 +1562,19 @@
     } while (1);
     parse_hdr_end(scanner);
-    return first;
+
+    if (ctx->rdata && ctx->rdata->record_route==NULL)
+        ctx->rdata->record_route = first;
+
+    return (pjsip_hdr*)first;
 }
 
 /* Parse Route: header. */
-PJ_DEF(pjsip_route_hdr*) parse_hdr_route( pj_scanner *scanner, 
-					  pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_route( pjsip_parse_ctx *ctx )
 {
     pjsip_route_hdr *first = NULL;
+    pj_scanner *scanner = ctx->scanner;
 
     do {
-	pjsip_route_hdr *hdr = pjsip_route_hdr_create(pool);
+	pjsip_route_hdr *hdr = pjsip_route_hdr_create(ctx->pool);
 	if (!first) {
 	    first = hdr;
@@ -1442,6 +1582,6 @@
 	    pj_list_insert_before(first, hdr);
 	}
-	parse_hdr_rr_route(scanner, pool, hdr);
-	if (*scanner->current == ',') {
+	parse_hdr_rr_route(scanner, ctx->pool, hdr);
+	if (*scanner->curptr == ',') {
 	    pj_scan_get_char(scanner);
 	} else {
@@ -1450,14 +1590,19 @@
     } while (1);
     parse_hdr_end(scanner);
-    return first;
+
+    if (ctx->rdata && ctx->rdata->route==NULL)
+        ctx->rdata->route = first;
+
+    return (pjsip_hdr*)first;
 }
 
 /* Parse Via: header. */
-PJ_DEF(pjsip_via_hdr*) parse_hdr_via( pj_scanner *scanner, pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_via( pjsip_parse_ctx *ctx )
 {
     pjsip_via_hdr *first = NULL;
+    pj_scanner *scanner = ctx->scanner;
 
     do {
-	pjsip_via_hdr *hdr = pjsip_via_hdr_create(pool);
+	pjsip_via_hdr *hdr = pjsip_via_hdr_create(ctx->pool);
 	if (!first)
 	    first = hdr;
@@ -1470,11 +1615,11 @@
 	pj_scan_advance_n( scanner, 8, 1);
 
-	pj_scan_get( scanner, pjsip_TOKEN_SPEC, &hdr->transport);
-	pj_scan_get( scanner, pjsip_HOST_SPEC, &hdr->sent_by.host);
-
-	if (*scanner->current==':') {
+	pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &hdr->transport);
+	pj_scan_get( scanner, &pjsip_HOST_SPEC, &hdr->sent_by.host);
+
+	if (*scanner->curptr==':') {
 	    pj_str_t digit;
 	    pj_scan_get_char(scanner);
-	    pj_scan_get(scanner, pjsip_DIGIT_SPEC, &digit);
+	    pj_scan_get(scanner, &pjsip_DIGIT_SPEC, &digit);
 	    hdr->sent_by.port = pj_strtoul(&digit);
 	} else {
@@ -1482,7 +1627,7 @@
 	}
 	
-	int_parse_via_param(hdr, scanner, pool);
-
-	if (*scanner->current == '(') {
+	int_parse_via_param(hdr, scanner, ctx->pool);
+
+	if (*scanner->curptr == '(') {
 	    pj_scan_get_char(scanner);
 	    pj_scan_get_until_ch( scanner, ')', &hdr->comment);
@@ -1490,5 +1635,5 @@
 	}
 
-	if (*scanner->current != ',')
+	if (*scanner->curptr != ',')
 	    break;
 
@@ -1498,16 +1643,19 @@
 
     parse_hdr_end(scanner);
-    return first;
+
+    if (ctx->rdata && ctx->rdata->via == NULL)
+        ctx->rdata->via = first;
+
+    return (pjsip_hdr*)first;
 }
 
 /* Parse generic header. */
-PJ_DEF(pjsip_generic_string_hdr*) parse_hdr_generic_string( pj_scanner *scanner, 
-						pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_generic_string( pjsip_parse_ctx *ctx )
 {
     pjsip_generic_string_hdr *hdr;
 
-    hdr = pjsip_generic_string_hdr_create(pool, NULL);
-    parse_generic_string_hdr(hdr, scanner);
-    return hdr;
+    hdr = pjsip_generic_string_hdr_create(ctx->pool, NULL);
+    parse_generic_string_hdr(hdr, ctx->scanner);
+    return (pjsip_hdr*)hdr;
 
 }
@@ -1519,20 +1667,25 @@
     pj_scanner scanner;
     pjsip_hdr *hdr = NULL;
+    pjsip_parse_ctx context;
     PJ_USE_EXCEPTION;
 
     init_sip_parser();
 
-    pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error);
+    pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, 
+                 &on_syntax_error);
+
+    context.scanner = &scanner;
+    context.pool = pool;
+    context.rdata = NULL;
 
     PJ_TRY {
 	pjsip_parse_hdr_func *handler = find_handler(hname);
 	if (handler) {
-	    hdr = (*handler)(&scanner, pool);
+	    hdr = (*handler)(&context);
 	} else {
-	    pjsip_generic_string_hdr *ghdr = parse_hdr_generic_string(&scanner, pool);
-	    ghdr->type = PJSIP_H_OTHER;
-	    pj_strdup(pool, &ghdr->name, hname);
-	    ghdr->sname = ghdr->name;
-	    hdr = (pjsip_hdr*)ghdr;
+	    hdr = parse_hdr_generic_string(&context);
+	    hdr->type = PJSIP_H_OTHER;
+	    pj_strdup(pool, &hdr->name, hname);
+	    hdr->sname = hdr->name;
 	}
 
@@ -1544,5 +1697,5 @@
 
     if (parsed_len) {
-	*parsed_len = (scanner.current - scanner.begin);
+	*parsed_len = (scanner.curptr - scanner.begin);
     }
 
