Index: pjproject/trunk/pjlib/build/pjlib_test.dsp
===================================================================
--- pjproject/trunk/pjlib/build/pjlib_test.dsp	(revision 104)
+++ pjproject/trunk/pjlib/build/pjlib_test.dsp	(revision 105)
@@ -51,5 +51,5 @@
 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 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 /nologo /subsystem:console /debug /machine:I386 /out:"../bin/pjlib-test-i386-win32-vc6-release.exe"
+# ADD LINK32 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 /nologo /subsystem:console /profile /debug /machine:I386 /out:"../bin/pjlib-test-i386-win32-vc6-release.exe"
 
 !ELSEIF  "$(CFG)" == "pjlib_test - Win32 Debug"
Index: pjproject/trunk/pjsip/build/test_pjsip.dsp
===================================================================
--- pjproject/trunk/pjsip/build/test_pjsip.dsp	(revision 104)
+++ pjproject/trunk/pjsip/build/test_pjsip.dsp	(revision 105)
@@ -94,5 +94,5 @@
 # Begin Source File
 
-SOURCE="..\src\test-pjsip\msg.c"
+SOURCE="..\src\test-pjsip\msg_test.c"
 # End Source File
 # Begin Source File
@@ -102,5 +102,5 @@
 # Begin Source File
 
-SOURCE="..\src\test-pjsip\uri.c"
+SOURCE="..\src\test-pjsip\uri_test.c"
 # End Source File
 # End Group
Index: pjproject/trunk/pjsip/include/pjsip/sip_config.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_config.h	(revision 104)
+++ pjproject/trunk/pjsip/include/pjsip/sip_config.h	(revision 105)
@@ -30,6 +30,6 @@
 #define PJSIP_MAX_TRANSPORTS		(PJ_IOQUEUE_MAX_HANDLES)
 #define PJSIP_MAX_PKT_LEN		1500
-#define PJSIP_POOL_LEN_RDATA		2500
-#define PJSIP_POOL_INC_RDATA		512
+#define PJSIP_POOL_RDATA_LEN		4000
+#define PJSIP_POOL_RDATA_INC		4000
 #define PJSIP_POOL_LEN_TRANSPORT	512
 #define PJSIP_POOL_INC_TRANSPORT	512
Index: pjproject/trunk/pjsip/include/pjsip/sip_endpoint.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_endpoint.h	(revision 104)
+++ pjproject/trunk/pjsip/include/pjsip/sip_endpoint.h	(revision 105)
@@ -249,5 +249,5 @@
 PJ_DECL(void) pjsip_endpt_resolve( pjsip_endpoint *endpt,
 				   pj_pool_t *pool,
-				   pjsip_host_port *target,
+				   pjsip_host_info *target,
 				   void *token,
 				   pjsip_resolver_callback *cb);
@@ -281,5 +281,6 @@
 PJ_DECL(pj_status_t) pjsip_endpt_alloc_transport( pjsip_endpoint *endpt,
 						  pjsip_transport_type_e type,
-						  const pj_sockaddr_in *remote,
+						  const pj_sockaddr *remote,
+						  int addr_len,
 						  pjsip_transport **p_transport);
 
Index: pjproject/trunk/pjsip/include/pjsip/sip_resolve.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_resolve.h	(revision 104)
+++ pjproject/trunk/pjsip/include/pjsip/sip_resolve.h	(revision 105)
@@ -60,5 +60,8 @@
 
 	/** The server's address. */
-	pj_sockaddr_in		addr;
+	pj_sockaddr		addr;
+
+	/** Address length. */
+	int			addr_len;
 
     } entry[PJSIP_MAX_RESOLVED_ADDRESSES];
@@ -108,5 +111,5 @@
 PJ_DECL(void) pjsip_resolve( pjsip_resolver_t *resolver,
 			     pj_pool_t *pool,
-			     pjsip_host_port *target,
+			     pjsip_host_info *target,
 			     void *token,
 			     pjsip_resolver_callback *cb);
Index: pjproject/trunk/pjsip/include/pjsip/sip_transaction.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_transaction.h	(revision 104)
+++ pjproject/trunk/pjsip/include/pjsip/sip_transaction.h	(revision 105)
@@ -108,5 +108,5 @@
      */
     pjsip_tsx_transport_state_e	transport_state;/**< Transport's state.     */
-    pjsip_host_port		dest_name;      /**< Destination address.   */
+    pjsip_host_info		dest_name;      /**< Destination address.   */
     pjsip_server_addresses	remote_addr;    /**< Addresses resolved.    */
     int				current_addr;   /**< Address currently used. */
Index: pjproject/trunk/pjsip/include/pjsip/sip_transport.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_transport.h	(revision 104)
+++ pjproject/trunk/pjsip/include/pjsip/sip_transport.h	(revision 105)
@@ -175,8 +175,14 @@
 
 	/** The source address from which the packet was received. */
-	pj_sockaddr_in		 addr;
+	pj_sockaddr		 src_addr;
 
 	/** The length of the source address. */
-	int			 addr_len;
+	int			 src_addr_len;
+
+	/** The IP source address string (NULL terminated). */
+	char			 src_name[16];
+
+	/** The IP source port number. */
+	int			 src_port;
 
     } pkt_info;
@@ -408,12 +414,19 @@
     int			    tracing;	    /**< Tracing enabled?	    */
 
-    pjsip_transport_type_e  type;	    /**< Transport type.	    */
-    char		    type_name[8];   /**< Type name.		    */
+    /** Key for indexing this transport in hash table. */
+    struct {
+	pjsip_transport_type_e  type;	    /**< Transport type.	    */
+	pj_sockaddr		rem_addr;   /**< Remote addr (zero for UDP) */
+    } key;
+
+    char		   *type_name;	    /**< Type name.		    */
     unsigned		    flag;	    /**< #pjsip_transport_flags_e   */
-
-    pj_sockaddr_in	    local_addr;	    /**< Bound address.		    */
-    pj_sockaddr_in	    public_addr;    /**< STUN addres.		    */
-    pj_sockaddr_in	    rem_addr;	    /**< Remote addr (zero for UDP) */
-
+    char		   *info;	    /**< Transport info/description.*/
+
+    int			    addr_len;	    /**< Length of addresses.	    */
+    pj_sockaddr		    local_addr;	    /**< Bound address.		    */
+    pjsip_host_port	    local_name;	    /**< Published name (eg. STUN). */
+    pjsip_host_port	    remote_name;    /**< Remote address name.	    */
+    
     pjsip_endpoint	   *endpt;	    /**< Endpoint instance.	    */
     pjsip_tpmgr		   *tpmgr;	    /**< Transport manager.	    */
@@ -429,4 +442,5 @@
      *			    caller when pending send operation completes.
      * @param rem_addr	    The remote destination address.
+     * @param addr_len	    Size of remote address.
      * @param callback	    If supplied, the callback will be called
      *			    once a pending transmission has completed. If
@@ -447,5 +461,6 @@
     pj_status_t (*send_msg)(pjsip_transport *transport, 
 			    pjsip_tx_data *tdata,
-			    const pj_sockaddr_in *rem_addr,
+			    const pj_sockaddr_t *rem_addr,
+			    int addr_len,
 			    void *token,
 			    void (*callback)(pjsip_transport *transport,
@@ -523,6 +538,6 @@
     unsigned		    flag;
 
-    pj_sockaddr_in	    local_addr;
-    pj_sockaddr_in	    public_addr;
+    pj_sockaddr		    local_addr;
+    pjsip_host_port	    addr_name;
 
     /**
@@ -532,5 +547,5 @@
 				    pjsip_tpmgr *mgr,
 				    pjsip_endpoint *endpt,
-				    const pj_sockaddr_in *rem_addr,
+				    const pj_sockaddr *rem_addr,
 				    pjsip_transport **transport);
 
@@ -608,7 +623,8 @@
  */
 PJ_DECL(pj_status_t) pjsip_tpmgr_alloc_transport( pjsip_tpmgr *mgr,
-					   pjsip_transport_type_e type,
-					   const pj_sockaddr_in *remote,
-					   pjsip_transport **p_transport );
+						  pjsip_transport_type_e type,
+						  const pj_sockaddr_t *remote,
+						  int addr_len,
+						  pjsip_transport **p_transport );
 
 
@@ -618,5 +634,6 @@
 PJ_DECL(pj_status_t) pjsip_transport_send( pjsip_transport *tr, 
 					   pjsip_tx_data *tdata,
-					   const pj_sockaddr_in *addr,
+					   const pj_sockaddr_t *addr,
+					   int addr_len,
 					   void *token,
 					   void (*cb)(void *token, 
Index: pjproject/trunk/pjsip/include/pjsip/sip_transport_udp.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_transport_udp.h	(revision 104)
+++ pjproject/trunk/pjsip/include/pjsip/sip_transport_udp.h	(revision 105)
@@ -29,5 +29,7 @@
  * @param endpt		The SIP endpoint.
  * @param local		Local address to bind.
- * @param pub_addr	Public address to advertise.
+ * @param a_name	Published address (only the host and port portion is 
+ *			used). If this argument is NULL, then the bound address
+ *			will be used as the published address.
  * @param async_cnt	Number of simultaneous async operations.
  * @param p_transport	Pointer to receive the transport.
@@ -39,5 +41,5 @@
 PJ_DECL(pj_status_t) pjsip_udp_transport_start(pjsip_endpoint *endpt,
 					       const pj_sockaddr_in *local,
-					       const pj_sockaddr_in *pub_addr,
+					       const pjsip_host_port *a_name,
 					       unsigned async_cnt,
 					       pjsip_transport **p_transport);
@@ -48,5 +50,6 @@
  * @param endpt		The SIP endpoint.
  * @param sock		UDP socket to use.
- * @param pub_addr	Public address to advertise.
+ * @param a_name	Published address (only the host and port portion is 
+ *			used).
  * @param async_cnt	Number of simultaneous async operations.
  * @param p_transport	Pointer to receive the transport.
@@ -58,5 +61,5 @@
 PJ_DECL(pj_status_t) pjsip_udp_transport_attach(pjsip_endpoint *endpt,
 						pj_sock_t sock,
-						const pj_sockaddr_in *pub_addr,
+						const pjsip_host_port *a_name,
 						unsigned async_cnt,
 						pjsip_transport **p_transport);
Index: pjproject/trunk/pjsip/include/pjsip/sip_types.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_types.h	(revision 104)
+++ pjproject/trunk/pjsip/include/pjsip/sip_types.h	(revision 105)
@@ -146,9 +146,17 @@
 typedef struct pjsip_host_port
 {
-    unsigned flag;	/**< Flags of pjsip_transport_flags_e (not used in Via). */
-    unsigned type;	/**< Transport type (pjsip_transport_type_e), or zero. */
-    pj_str_t host;	/**< Host part. */
+    pj_str_t host;	/**< Host part or IP address. */
     int	     port;	/**< Port number. */
 } pjsip_host_port;
+
+/**
+ * Host information.
+ */
+typedef struct pjsip_host_info
+{
+    unsigned		    flag;   /**< Flags of pjsip_transport_flags_e. */
+    pjsip_transport_type_e  type;   /**< Transport type. */
+    pjsip_host_port	    addr;   /**< Address information. */
+} pjsip_host_info;
 
 
Index: pjproject/trunk/pjsip/include/pjsip/sip_util.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_util.h	(revision 104)
+++ pjproject/trunk/pjsip/include/pjsip/sip_util.h	(revision 105)
@@ -181,5 +181,5 @@
 					     const pjsip_transport *tr,
 					     const pjsip_via_hdr *via,
-					     pjsip_host_port *addr);
+					     pjsip_host_info *addr);
 
 /**
Index: pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c	(revision 104)
+++ pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c	(revision 105)
@@ -726,6 +726,6 @@
 
     if (status != PJ_SUCCESS) {
-	const char *src_addr = pj_inet_ntoa(rdata->pkt_info.addr.sin_addr);
-	int port = pj_ntohs(rdata->pkt_info.addr.sin_port);
+	const char *src_addr = rdata->pkt_info.src_name;
+	int port = rdata->pkt_info.src_port;
 	PJSIP_ENDPT_LOG_ERROR((endpt, "transport", status,
 			       "Src.addr=%s:%d, packet:--\n"
@@ -741,18 +741,16 @@
      */
     if (msg->type == PJSIP_RESPONSE_MSG) {
-	const pj_sockaddr_in *addr;
-	const char *addr_addr;
+	const pj_str_t *addr_addr;
 	int port = rdata->msg_info.via->sent_by.port;
 	pj_bool_t mismatch = PJ_FALSE;
 	if (port == 0) {
 	    int type;
-	    type = rdata->tp_info.transport->type;
+	    type = rdata->tp_info.transport->key.type;
 	    port = pjsip_transport_get_default_port_for_type(type);
 	}
-	addr = &rdata->tp_info.transport->public_addr;
-	addr_addr = pj_inet_ntoa(addr->sin_addr);
-	if (pj_strcmp2(&rdata->msg_info.via->sent_by.host, addr_addr) != 0)
+	addr_addr = &rdata->tp_info.transport->local_name.host;
+	if (pj_strcmp(&rdata->msg_info.via->sent_by.host, addr_addr) != 0)
 	    mismatch = PJ_TRUE;
-	else if (port != pj_ntohs(addr->sin_port)) {
+	else if (port != rdata->tp_info.transport->local_name.port) {
 	    /* Port or address mismatch, we should discard response */
 	    /* But we saw one implementation (we don't want to name it to 
@@ -762,5 +760,5 @@
 	     * both the port in sent-by and rport. We try to be lenient here!
 	     */
-	    if (rdata->msg_info.via->rport_param != pj_sockaddr_in_get_port(addr))
+	    if (rdata->msg_info.via->rport_param != rdata->tp_info.transport->local_name.port)
 		mismatch = PJ_TRUE;
 	    else {
@@ -959,5 +957,5 @@
 PJ_DEF(void) pjsip_endpt_resolve( pjsip_endpoint *endpt,
 				  pj_pool_t *pool,
-				  pjsip_host_port *target,
+				  pjsip_host_info *target,
 				  void *token,
 				  pjsip_resolver_callback *cb)
@@ -988,10 +986,11 @@
 PJ_DEF(pj_status_t) pjsip_endpt_alloc_transport( pjsip_endpoint *endpt,
 						  pjsip_transport_type_e type,
-						  const pj_sockaddr_in *remote,
+						  const pj_sockaddr *remote,
+						  int addr_len,
 						  pjsip_transport **p_transport)
 {
     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_alloc_transport()"));
-    return pjsip_tpmgr_alloc_transport( endpt->transport_mgr, type, remote,
-					p_transport);
+    return pjsip_tpmgr_alloc_transport( endpt->transport_mgr, type, 
+					remote, addr_len, p_transport);
 }
 
Index: pjproject/trunk/pjsip/src/pjsip/sip_resolve.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_resolve.c	(revision 104)
+++ pjproject/trunk/pjsip/src/pjsip/sip_resolve.c	(revision 105)
@@ -57,5 +57,5 @@
 PJ_DEF(void) pjsip_resolve( pjsip_resolver_t *resolver,
 			    pj_pool_t *pool,
-			    pjsip_host_port *target,
+			    pjsip_host_info *target,
 			    void *token,
 			    pjsip_resolver_callback *cb)
@@ -73,5 +73,5 @@
 
     /* Is it IP address or hostname?. */
-    is_ip_addr = is_str_ip(&target->host);
+    is_ip_addr = is_str_ip(&target->addr.host);
 
     /* Set the transport type if not explicitly specified. 
@@ -79,5 +79,5 @@
      */
     if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
-	if (is_ip_addr || (target->port != 0)) {
+	if (is_ip_addr || (target->addr.port != 0)) {
 #if PJ_HAS_TCP
 	    if (target->flag & PJSIP_TRANSPORT_SECURE) 
@@ -104,15 +104,17 @@
 
     /* Set the port number if not specified. */
-    if (target->port == 0) {
-	target->port = pjsip_transport_get_default_port_for_type(type);
+    if (target->addr.port == 0) {
+	target->addr.port = pjsip_transport_get_default_port_for_type(type);
     }
 
     /* Resolve hostname. */
     if (!is_ip_addr) {
-	status = pj_sockaddr_in_init(&svr_addr.entry[0].addr, &target->host, 
-				     (pj_uint16_t)target->port);
+	status = pj_sockaddr_in_init((pj_sockaddr_in*)&svr_addr.entry[0].addr, 
+				     &target->addr.host, 
+				     (pj_uint16_t)target->addr.port);
     } else {
-	status = pj_sockaddr_in_init(&svr_addr.entry[0].addr, &target->host, 
-				     (pj_uint16_t)target->port);
+	status = pj_sockaddr_in_init((pj_sockaddr_in*)&svr_addr.entry[0].addr, 
+				      &target->addr.host, 
+				     (pj_uint16_t)target->addr.port);
 	pj_assert(status == PJ_SUCCESS);
     }
@@ -121,4 +123,5 @@
     svr_addr.count = (status == PJ_SUCCESS) ? 1 : 0;
     svr_addr.entry[0].type = type;
+    svr_addr.entry[0].addr_len = sizeof(pj_sockaddr_in);
     (*cb)(status, token, &svr_addr);
 }
Index: pjproject/trunk/pjsip/src/pjsip/sip_transaction.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_transaction.c	(revision 104)
+++ pjproject/trunk/pjsip/src/pjsip/sip_transaction.c	(revision 105)
@@ -499,5 +499,5 @@
 static pj_status_t tsx_process_route( pjsip_transaction *tsx,
 				      pjsip_tx_data *tdata,
-				      pjsip_host_port *send_addr )
+				      pjsip_host_info *send_addr )
 {
     const pjsip_uri *new_request_uri, *target_uri;
@@ -596,6 +596,6 @@
 	const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri);
 	send_addr->flag |= (PJSIP_TRANSPORT_SECURE | PJSIP_TRANSPORT_RELIABLE);
-	pj_strdup(tdata->pool, &send_addr->host, &url->host);
-        send_addr->port = url->port;
+	pj_strdup(tdata->pool, &send_addr->addr.host, &url->host);
+        send_addr->addr.port = url->port;
 	send_addr->type = 
             pjsip_transport_get_type_from_name(&url->transport_param);
@@ -604,6 +604,6 @@
 	pjsip_uri *uri = (pjsip_uri*) target_uri;
 	const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri);
-	pj_strdup(tdata->pool, &send_addr->host, &url->host);
-	send_addr->port = url->port;
+	pj_strdup(tdata->pool, &send_addr->addr.host, &url->host);
+	send_addr->addr.port = url->port;
 	send_addr->type = 
             pjsip_transport_get_type_from_name(&url->transport_param);
@@ -651,6 +651,6 @@
     struct tsx_lock_data lck;
 
-    pj_memcpy(addr, tsx->dest_name.host.ptr, tsx->dest_name.host.slen);
-    addr[tsx->dest_name.host.slen] = '\0';
+    pj_memcpy(addr, tsx->dest_name.addr.host.ptr, tsx->dest_name.addr.host.slen);
+    addr[tsx->dest_name.addr.host.slen] = '\0';
 
 
@@ -658,9 +658,9 @@
 	PJ_LOG(4, (tsx->obj_name, "%s connected to %s:%d",
 				  tr->type_name,
-				  addr, tsx->dest_name.port));
+				  addr, tsx->dest_name.addr.port));
     } else {
 	PJ_LOG(4, (tsx->obj_name, "%s unable to connect to %s:%d, status=%d", 
 				  tr->type_name,
-				  addr, tsx->dest_name.port, status));
+				  addr, tsx->dest_name.addr.port, status));
     }
 
@@ -738,11 +738,8 @@
 
     /* Create/find the transport for the remote address. */
-    PJ_LOG(5,(tsx->obj_name, "tsx getting transport for %s:%d",
-			     pj_inet_ntoa(addr->entry[0].addr.sin_addr),
-			     pj_ntohs(addr->entry[0].addr.sin_port)));
-
     tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_CONNECTING;
     status = pjsip_endpt_alloc_transport( tsx->endpt, addr->entry[0].type,
 					  &addr->entry[0].addr,
+					  addr->entry[0].addr_len,
 					  &tp);
     tsx_transport_callback(tp, tsx, status);
@@ -852,7 +849,7 @@
      */
     PJ_LOG(5,(tsx->obj_name, "tsx resolving destination %.*s:%d",
-			     tsx->dest_name.host.slen, 
-			     tsx->dest_name.host.ptr,
-			     tsx->dest_name.port));
+			     tsx->dest_name.addr.host.slen, 
+			     tsx->dest_name.addr.host.ptr,
+			     tsx->dest_name.addr.port));
 
     tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_RESOLVING;
@@ -942,7 +939,7 @@
 	tsx->current_addr = 0;
 	tsx->remote_addr.count = 1;
-	tsx->remote_addr.entry[0].type = tsx->transport->type;
+	tsx->remote_addr.entry[0].type = tsx->transport->key.type;
 	pj_memcpy(&tsx->remote_addr.entry[0].addr, 
-		  &rdata->pkt_info.addr, rdata->pkt_info.addr_len);
+		  &rdata->pkt_info.src_addr, rdata->pkt_info.src_addr_len);
 	
     } else {
@@ -965,7 +962,7 @@
 	 */
 	PJ_LOG(5,(tsx->obj_name, "tsx resolving destination %.*s:%d",
-				 tsx->dest_name.host.slen, 
-				 tsx->dest_name.host.ptr,
-				 tsx->dest_name.port));
+				 tsx->dest_name.addr.host.slen, 
+				 tsx->dest_name.addr.host.ptr,
+				 tsx->dest_name.addr.port));
 
 	tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_RESOLVING;
@@ -1024,5 +1021,5 @@
 {
     pjsip_msg *msg;
-    pjsip_host_port dest_addr;
+    pjsip_host_info dest_addr;
     pjsip_via_hdr *via;
     struct tsx_lock_data lck;
@@ -1060,6 +1057,6 @@
     if (dest_addr.type == tsx->dest_name.type &&
 	dest_addr.flag == tsx->dest_name.flag &&
-	dest_addr.port == tsx->dest_name.port &&
-	pj_stricmp(&dest_addr.host, &tsx->dest_name.host) == 0)
+	dest_addr.addr.port == tsx->dest_name.addr.port &&
+	pj_stricmp(&dest_addr.addr.host, &tsx->dest_name.addr.host) == 0)
     {
 	/* Equal destination. We can use current transport. */
@@ -1072,10 +1069,10 @@
     /* New destination; we'll have to resolve host and create new transport. */
     pj_memcpy(&tsx->dest_name, &dest_addr, sizeof(dest_addr));
-    pj_strdup(tsx->pool, &tsx->dest_name.host, &dest_addr.host);
+    pj_strdup(tsx->pool, &tsx->dest_name.addr.host, &dest_addr.addr.host);
 
     PJ_LOG(5,(tsx->obj_name, "tsx resolving destination %.*s:%d",
-			     tsx->dest_name.host.slen, 
-			     tsx->dest_name.host.ptr,
-			     tsx->dest_name.port));
+			     tsx->dest_name.addr.host.slen, 
+			     tsx->dest_name.addr.host.ptr,
+			     tsx->dest_name.addr.port));
 
     tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_RESOLVING;
@@ -1216,5 +1213,4 @@
 	 */
 	if (tdata->msg->type == PJSIP_REQUEST_MSG) {
-	    const pj_sockaddr_in *addr_name;
 	    pjsip_via_hdr *via = (pjsip_via_hdr*) 
 		pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
@@ -1226,10 +1222,9 @@
 	    /* Don't update Via sent-by on retransmission. */
 	    if (via->sent_by.host.slen == 0) {
-		addr_name = &tsx->transport->public_addr;
 		pj_strdup2(tdata->pool, &via->transport, 
 			   tsx->transport->type_name);
-		pj_strdup2(tdata->pool, &via->sent_by.host, 
-			   pj_inet_ntoa(addr_name->sin_addr));
-		via->sent_by.port = pj_ntohs(addr_name->sin_port);
+		pj_strdup(tdata->pool, &via->sent_by.host, 
+			  &tsx->transport->local_name.host);
+		via->sent_by.port = tsx->transport->local_name.port;
 	    }
 	}
@@ -1243,4 +1238,5 @@
 	status = pjsip_transport_send(tsx->transport, tdata,
 			&tsx->remote_addr.entry[tsx->current_addr].addr,
+			tsx->remote_addr.entry[tsx->current_addr].addr_len,
 			tsx, &tsx_on_send_complete);
 	if (status != PJ_SUCCESS && status != PJ_EPENDING) {
Index: pjproject/trunk/pjsip/src/pjsip/sip_transport.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_transport.c	(revision 104)
+++ pjproject/trunk/pjsip/src/pjsip/sip_transport.c	(revision 105)
@@ -47,6 +47,4 @@
 };
 
-
-
 /*****************************************************************************
  *
@@ -82,4 +80,11 @@
     unsigned i;
 
+    /* Sanity check. 
+     * Check that transport_names[] are indexed on transport type. 
+     */
+    PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==
+		     PJSIP_TRANSPORT_UDP, PJSIP_TRANSPORT_UNSPECIFIED);
+
+    /* Get transport type from name. */
     for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) {
 	if (pj_stricmp(name, &transport_names[i].name) == 0) {
@@ -101,4 +106,11 @@
     unsigned i;
 
+    /* Sanity check. 
+     * Check that transport_names[] are indexed on transport type. 
+     */
+    PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==
+		     PJSIP_TRANSPORT_UDP, PJSIP_TRANSPORT_UNSPECIFIED);
+
+    /* Get the transport type for the specified flags. */
     for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) {
 	if (transport_names[i].flag == flag) {
@@ -114,5 +126,14 @@
 pjsip_transport_get_flag_from_type( pjsip_transport_type_e type )
 {
+    /* Sanity check. 
+     * Check that transport_names[] are indexed on transport type. 
+     */
+    PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==
+		     PJSIP_TRANSPORT_UDP, 0);
+
+    /* Check that argument is valid. */
     PJ_ASSERT_RETURN(type < PJ_ARRAY_SIZE(transport_names), 0);
+
+    /* Return transport flag. */
     return transport_names[type].flag;
 }
@@ -124,5 +145,14 @@
 pjsip_transport_get_default_port_for_type(pjsip_transport_type_e type)
 {
+    /* Sanity check. 
+     * Check that transport_names[] are indexed on transport type. 
+     */
+    PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==
+		     PJSIP_TRANSPORT_UDP, 0);
+
+    /* Check that argument is valid. */
     PJ_ASSERT_RETURN(type < PJ_ARRAY_SIZE(transport_names), 5060);
+
+    /* Return the port. */
     return transport_names[type].port;
 }
@@ -225,15 +255,4 @@
  *****************************************************************************/
 
-/*
- * Transport key for indexing in the hash table.
- */
-typedef struct transport_key
-{
-    pj_uint8_t	type;
-    pj_uint8_t	zero;
-    pj_uint16_t	port;
-    pj_uint32_t	addr;
-} transport_key;
-
 
 /*****************************************************************************
@@ -270,5 +289,6 @@
 PJ_DEF(pj_status_t) pjsip_transport_send(  pjsip_transport *tr, 
 					   pjsip_tx_data *tdata,
-					   const pj_sockaddr_in *addr,
+					   const pj_sockaddr *addr,
+					   int addr_len,
 					   void *token,
 					   void (*cb)(void *token, 
@@ -318,5 +338,5 @@
 
     /* Send to transport. */
-    status = (*tr->send_msg)(tr, tdata,  addr, (void*)tdata, 
+    status = (*tr->send_msg)(tr, tdata,  addr, addr_len, (void*)tdata, 
 			     &transport_send_callback);
 
@@ -396,5 +416,5 @@
 					      pjsip_transport *tp )
 {
-    transport_key key;
+    int key_len;
 
     /* Init. */
@@ -407,11 +427,7 @@
      * Register to hash table.
      */
-    key.type = (pj_uint8_t)tp->type;
-    key.zero = 0;
-    key.addr = pj_ntohl(tp->rem_addr.sin_addr.s_addr);
-    key.port = pj_ntohs(tp->rem_addr.sin_port);
-
+    key_len = sizeof(tp->key.type) + tp->addr_len;
     pj_lock_acquire(mgr->lock);
-    pj_hash_set(tp->pool, mgr->table, &key, sizeof(key), tp);
+    pj_hash_set(tp->pool, mgr->table, &tp->key, key_len, tp);
     pj_lock_release(mgr->lock);
 
@@ -426,6 +442,7 @@
 						pjsip_transport *tp)
 {
-    transport_key key;
-
+    int key_len;
+
+    /* Must have no user. */
     PJ_ASSERT_RETURN(pj_atomic_get(tp->ref_cnt) == 0, PJSIP_EBUSY);
 
@@ -445,10 +462,6 @@
      * Unregister from hash table.
      */
-    key.type = (pj_uint8_t)tp->type;
-    key.zero = 0;
-    key.addr = pj_ntohl(tp->rem_addr.sin_addr.s_addr);
-    key.port = pj_ntohs(tp->rem_addr.sin_port);
-
-    pj_hash_set(tp->pool, mgr->table, &key, sizeof(key), NULL);
+    key_len = sizeof(tp->key.type) + tp->addr_len;
+    pj_hash_set(tp->pool, mgr->table, &tp->key, key_len, NULL);
 
     pj_lock_release(mgr->lock);
@@ -602,5 +615,4 @@
 {
     pjsip_transport *tr = rdata->tp_info.transport;
-    pj_str_t s;
 
     char *current_pkt;
@@ -683,8 +695,10 @@
   	 * MUST add received parameter to the via.
 	 */
-	s = pj_str(pj_inet_ntoa(rdata->pkt_info.addr.sin_addr));
-	if (pj_strcmp(&s, &rdata->msg_info.via->sent_by.host) != 0) {
-	    pj_strdup(rdata->tp_info.pool, 
-		      &rdata->msg_info.via->recvd_param, &s);
+	if (pj_strcmp2(&rdata->msg_info.via->sent_by.host, 
+		       rdata->pkt_info.src_name) != 0) 
+	{
+	    pj_strdup2(rdata->tp_info.pool, 
+		       &rdata->msg_info.via->recvd_param, 
+		       rdata->pkt_info.src_name);
 	}
 
@@ -693,6 +707,5 @@
 	 */
 	if (rdata->msg_info.via->rport_param == 0) {
-	    rdata->msg_info.via->rport_param = 
-		pj_ntohs(rdata->pkt_info.addr.sin_port);
+	    rdata->msg_info.via->rport_param = rdata->pkt_info.src_port;
 	}
 
@@ -736,8 +749,14 @@
 PJ_DEF(pj_status_t) pjsip_tpmgr_alloc_transport( pjsip_tpmgr *mgr,
 						 pjsip_transport_type_e type,
-						 const pj_sockaddr_in *remote,
+						 const pj_sockaddr_t *remote,
+						 int addr_len,
 						 pjsip_transport **p_transport)
 {
-    transport_key key;
+    struct transport_key
+    {
+	pjsip_transport_type_e	type;
+	pj_sockaddr		addr;
+    } key;
+    int key_len;
     pjsip_transport *transport;
     pjsip_tpfactory *factory;
@@ -746,20 +765,29 @@
     pj_lock_acquire(mgr->lock);
 
+    key_len = sizeof(key.type) + addr_len;
+
     /* First try to get exact destination. */
-    key.type = (pj_uint8_t)type;
-    key.zero = 0;
-    key.addr = pj_ntohl(remote->sin_addr.s_addr);
-    key.port = pj_ntohs(remote->sin_port);
-
-    transport = pj_hash_get(mgr->table, &key, sizeof(key));
-    if (transport != NULL) {
+    key.type = type;
+    pj_memcpy(&key.addr, remote, addr_len);
+
+    transport = pj_hash_get(mgr->table, &key, key_len);
+    if (transport == NULL) {
 	unsigned flag = pjsip_transport_get_flag_from_type(type);
-	
-	/* For datagram transports, try lookup with zero address. */
-	if (flag & PJSIP_TRANSPORT_DATAGRAM) {
-	    key.addr = 0;
-	    key.port = 0;
-
-	    transport = pj_hash_get(mgr->table, &key, sizeof(key));
+	const pj_sockaddr *remote_addr = (const pj_sockaddr*)remote;
+
+	/* For datagram transports, try lookup with zero address. 
+	 */
+	if ( (flag & PJSIP_TRANSPORT_DATAGRAM) && 
+	     (remote_addr->sa_family == PJ_AF_INET)) 
+	{
+	    pj_sockaddr_in *addr = (pj_sockaddr_in*)&key.addr;
+
+	    pj_memset(addr, 0, sizeof(pj_sockaddr_in));
+	    addr->sin_family = PJ_AF_INET;
+	    addr->sin_addr.s_addr = 0;
+	    addr->sin_port = 0;
+
+	    key_len = sizeof(key.type) + sizeof(pj_sockaddr_in);
+	    transport = pj_hash_get(mgr->table, &key, key_len);
 	}
     }
@@ -816,20 +844,9 @@
 
 	do {
-	    char src_addr[128], dst_addr[128];
-	    int src_port, dst_port;
-	    pjsip_transport *t;
-
-	    t = pj_hash_this(mgr->table, itr);
-	    pj_native_strcpy(src_addr, pj_inet_ntoa(t->local_addr.sin_addr));
-	    src_port = pj_ntohs(t->local_addr.sin_port);
-
-	    pj_native_strcpy(dst_addr, pj_inet_ntoa(t->rem_addr.sin_addr));
-	    dst_port = pj_ntohs(t->rem_addr.sin_port);
-
-	    PJ_LOG(3, (THIS_FILE, "  %s %s %s:%d --> %s:%d (refcnt=%d)", 
-		       t->type_name,
+	    pjsip_transport *t = pj_hash_this(mgr->table, itr);
+
+	    PJ_LOG(3, (THIS_FILE, "  %s %s (refcnt=%d)", 
 		       t->obj_name,
-		       src_addr, src_port,
-		       dst_addr, dst_port,
+		       t->info,
 		       pj_atomic_get(t->ref_cnt)));
 
Index: pjproject/trunk/pjsip/src/pjsip/sip_transport_udp.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_transport_udp.c	(revision 104)
+++ pjproject/trunk/pjsip/src/pjsip/sip_transport_udp.c	(revision 105)
@@ -41,12 +41,12 @@
 
 /*
- * on_read_complete()
+ * udp_on_read_complete()
  *
  * This is callback notification from ioqueue that a pending recvfrom()
  * operation has completed.
  */
-static void on_read_complete( pj_ioqueue_key_t *key, 
-			      pj_ioqueue_op_key_t *op_key, 
-			      pj_ssize_t bytes_read)
+static void udp_on_read_complete( pj_ioqueue_key_t *key, 
+				  pj_ioqueue_op_key_t *op_key, 
+				  pj_ssize_t bytes_read)
 {
     enum { MAX_IMMEDIATE_PACKET = 10 };
@@ -73,8 +73,14 @@
 	if (bytes_read > 0) {
 	    pj_size_t size_eaten;
-
+	    const pj_sockaddr_in *src_addr = 
+		(pj_sockaddr_in*)&rdata->pkt_info.src_addr;
+
+	    /* Init pkt_info part. */
 	    rdata->pkt_info.len = bytes_read;
 	    rdata->pkt_info.zero = 0;
 	    pj_gettimeofday(&rdata->pkt_info.timestamp);
+	    pj_native_strcpy(rdata->pkt_info.src_name,
+			     pj_inet_ntoa(src_addr->sin_addr));
+	    rdata->pkt_info.src_port = pj_ntohs(src_addr->sin_port);
 
 	    size_eaten = 
@@ -110,10 +116,10 @@
 	/* Read next packet. */
 	bytes_read = sizeof(rdata->pkt_info.packet);
-	rdata->pkt_info.addr_len = sizeof(rdata->pkt_info.addr);
+	rdata->pkt_info.src_addr_len = sizeof(rdata->pkt_info.src_addr);
 	status = pj_ioqueue_recvfrom(key, op_key, 
 				     rdata->pkt_info.packet,
 				     &bytes_read, flags,
-				     &rdata->pkt_info.addr, 
-				     &rdata->pkt_info.addr_len);
+				     &rdata->pkt_info.src_addr, 
+				     &rdata->pkt_info.src_addr_len);
 
 	if (status == PJ_SUCCESS) {
@@ -150,12 +156,12 @@
 
 /*
- * on_write_complete()
+ * udp_on_write_complete()
  *
  * This is callback notification from ioqueue that a pending sendto()
  * operation has completed.
  */
-static void on_write_complete( pj_ioqueue_key_t *key, 
-			       pj_ioqueue_op_key_t *op_key,
-			       pj_ssize_t bytes_sent)
+static void udp_on_write_complete( pj_ioqueue_key_t *key, 
+				   pj_ioqueue_op_key_t *op_key,
+				   pj_ssize_t bytes_sent)
 {
     struct udp_transport *tp = pj_ioqueue_get_user_data(key);
@@ -170,16 +176,17 @@
 
 /*
- * transport_send_msg()
+ * udp_send_msg()
  *
  * This function is called by transport manager (by transport->send_msg())
  * to send outgoing message.
  */
-static pj_status_t transport_send_msg( pjsip_transport *transport,
-				       pjsip_tx_data *tdata,
-				       const pj_sockaddr_in *rem_addr,
-				       void *token,
-				       void (*callback)(pjsip_transport*,
-							void *token,
-							pj_ssize_t))
+static pj_status_t udp_send_msg( pjsip_transport *transport,
+				 pjsip_tx_data *tdata,
+				 const pj_sockaddr_t *rem_addr,
+				 int addr_len,
+				 void *token,
+				 void (*callback)(pjsip_transport*,
+						  void *token,
+						  pj_ssize_t))
 {
     struct udp_transport *tp = (struct udp_transport*)transport;
@@ -198,13 +205,13 @@
     return pj_ioqueue_sendto(tp->key, (pj_ioqueue_op_key_t*)&tdata->op_key,
 			     tdata->buf.start, &size, 0,
-			     rem_addr, (rem_addr ? sizeof(pj_sockaddr_in):0));
-}
-
-/*
- * transport_destroy()
+			     rem_addr, addr_len);
+}
+
+/*
+ * udp_destroy()
  *
  * This function is called by transport manager (by transport->destroy()).
  */
-static pj_status_t transport_destroy( pjsip_transport *transport )
+static pj_status_t udp_destroy( pjsip_transport *transport )
 {
     struct udp_transport *tp = (struct udp_transport*)transport;
@@ -250,5 +257,5 @@
 PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt,
 						pj_sock_t sock,
-						const pj_sockaddr_in *pub_addr,
+						const pjsip_host_port *a_name,
 						unsigned async_cnt,
 						pjsip_transport **p_transport)
@@ -259,31 +266,20 @@
     pj_ioqueue_callback ioqueue_cb;
     unsigned i;
-    int addrlen;
     pj_status_t status;
 
     /* Create pool. */
     pool = pjsip_endpt_create_pool(endpt, "udp%p", PJSIP_POOL_LEN_TRANSPORT, 
-			       PJSIP_POOL_INC_TRANSPORT);
+				   PJSIP_POOL_INC_TRANSPORT);
     if (!pool)
 	return PJ_ENOMEM;
 
+    /* Create the UDP transport object. */
     tp = pj_pool_zalloc(pool, sizeof(struct udp_transport));
+
+    /* Save pool. */
     tp->base.pool = pool;
-    tp->base.endpt = endpt;
-
-    /* Init type, type_name, and flag */
-    tp->base.type = PJSIP_TRANSPORT_UDP;
-    pj_native_strcpy(tp->base.type_name, "UDP");
-    tp->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP);
-
-    /* Init addresses. */
-    addrlen = sizeof(tp->base.local_addr);
-    status = pj_sock_getsockname(sock, &tp->base.local_addr, &addrlen);
-    if (status != PJ_SUCCESS) {
-	pjsip_endpt_destroy_pool(endpt, pool);
-	return status;
-    }
-    pj_memcpy(&tp->base.public_addr, pub_addr, sizeof(pj_sockaddr_in));
-    tp->base.rem_addr.sin_family = PJ_AF_INET;
+
+    /* Object name. */
+    pj_sprintf(tp->base.obj_name, "udp%p", tp);
 
     /* Init reference counter. */
@@ -296,4 +292,47 @@
     if (status != PJ_SUCCESS)
 	goto on_error;
+
+    /* Set type. */
+    tp->base.key.type = PJSIP_TRANSPORT_UDP;
+
+    /* Remote address is left zero (except the family) */
+    tp->base.key.rem_addr.sa_family = PJ_AF_INET;
+
+    /* Type name. */
+    tp->base.type_name = "UDP";
+
+    /* Transport flag */
+    tp->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP);
+
+
+    /* Length of addressess. */
+    tp->base.addr_len = sizeof(pj_sockaddr_in);
+
+    /* Init local address. */
+    status = pj_sock_getsockname(sock, &tp->base.local_addr, 
+				 &tp->base.addr_len);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    /* Init address name (published address) */
+    pj_strdup_with_null(pool, &tp->base.local_name.host, &a_name->host);
+    tp->base.local_name.port = a_name->port;
+
+    /* Init remote name. */
+    tp->base.remote_name.host = pj_str("0.0.0.0");
+    tp->base.remote_name.port = 0;
+
+    /* Transport info. */
+    tp->base.info = pj_pool_alloc(pool, 80);
+    pj_sprintf(tp->base.info, "udp %s:%d [published as %s:%d]",
+			      pj_inet_ntoa(((pj_sockaddr_in*)&tp->base.local_addr)->sin_addr),
+			      pj_ntohs(((pj_sockaddr_in*)&tp->base.local_addr)->sin_port),
+			      tp->base.local_name.host,
+			      tp->base.local_name.port);
+
+    /* Set endpoint. */
+    tp->base.endpt = endpt;
+
+    /* Transport manager and timer will be initialized by tpmgr */
 
     /* Attach socket. */
@@ -303,6 +342,6 @@
     ioqueue = pjsip_endpt_get_ioqueue(endpt);
     pj_memset(&ioqueue_cb, 0, sizeof(ioqueue_cb));
-    ioqueue_cb.on_read_complete = &on_read_complete;
-    ioqueue_cb.on_write_complete = &on_write_complete;
+    ioqueue_cb.on_read_complete = &udp_on_read_complete;
+    ioqueue_cb.on_write_complete = &udp_on_write_complete;
     status = pj_ioqueue_register_sock(pool, ioqueue, tp->sock, tp, 
 				      &ioqueue_cb, &tp->key);
@@ -311,6 +350,6 @@
 
     /* Set functions. */
-    tp->base.send_msg = &transport_send_msg;
-    tp->base.destroy = &transport_destroy;
+    tp->base.send_msg = &udp_send_msg;
+    tp->base.destroy = &udp_destroy;
 
     /* This is a permanent transport, so we initialize the ref count
@@ -331,6 +370,6 @@
     for (i=0; i<async_cnt; ++i) {
 	pj_pool_t *rdata_pool = pjsip_endpt_create_pool(endpt, "rtd%p", 
-							PJSIP_POOL_LEN_RDATA,
-							PJSIP_POOL_INC_RDATA);
+							PJSIP_POOL_RDATA_LEN,
+							PJSIP_POOL_RDATA_INC);
 	if (!rdata_pool) {
 	    pj_atomic_set(tp->base.ref_cnt, 0);
@@ -340,4 +379,6 @@
 
 	tp->rdata[i] = pj_pool_zalloc(rdata_pool, sizeof(pjsip_rx_data));
+
+	/* Init tp_info part. */
 	tp->rdata[i]->tp_info.pool = rdata_pool;
 	tp->rdata[i]->tp_info.transport = &tp->base;
@@ -353,15 +394,15 @@
 
 	size = sizeof(tp->rdata[i]->pkt_info.packet);
-	tp->rdata[i]->pkt_info.addr_len = sizeof(tp->rdata[i]->pkt_info.addr);
+	tp->rdata[i]->pkt_info.src_addr_len = sizeof(tp->rdata[i]->pkt_info.src_addr);
 	status = pj_ioqueue_recvfrom(tp->key, 
 				     &tp->rdata[i]->tp_info.op_key.op_key,
 				     tp->rdata[i]->pkt_info.packet,
 				     &size, PJ_IOQUEUE_ALWAYS_ASYNC,
-				     &tp->rdata[i]->pkt_info.addr,
-				     &tp->rdata[i]->pkt_info.addr_len);
+				     &tp->rdata[i]->pkt_info.src_addr,
+				     &tp->rdata[i]->pkt_info.src_addr_len);
 	if (status == PJ_SUCCESS) {
 	    pj_assert(!"Shouldn't happen because PJ_IOQUEUE_ALWAYS_ASYNC!");
-	    on_read_complete(tp->key, &tp->rdata[i]->tp_info.op_key.op_key, 
-			     size);
+	    udp_on_read_complete(tp->key, &tp->rdata[i]->tp_info.op_key.op_key,
+				 size);
 	} else if (status != PJ_EPENDING) {
 	    /* Error! */
@@ -376,5 +417,5 @@
 
 on_error:
-    transport_destroy((pjsip_transport*)tp);
+    udp_destroy((pjsip_transport*)tp);
     return status;
 }
@@ -383,9 +424,9 @@
  * pjsip_udp_transport_start()
  *
- * Start an UDP transport/listener.
+ * Create a UDP socket in the specified address and start a transport.
  */
 PJ_DEF(pj_status_t) pjsip_udp_transport_start( pjsip_endpoint *endpt,
 					       const pj_sockaddr_in *local,
-					       const pj_sockaddr_in *pub_addr,
+					       const pjsip_host_port *a_name,
 					       unsigned async_cnt,
 					       pjsip_transport **p_transport)
@@ -393,4 +434,6 @@
     pj_sock_t sock;
     pj_status_t status;
+    char addr_buf[16];
+    pjsip_host_port bound_name;
 
     status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock);
@@ -404,5 +447,12 @@
     }
 
-    return pjsip_udp_transport_attach( endpt, sock, pub_addr, async_cnt, 
+    if (a_name == NULL) {
+	a_name = &bound_name;
+	bound_name.host.ptr = addr_buf;
+	pj_strcpy2(&bound_name.host, pj_inet_ntoa(local->sin_addr));
+	bound_name.port = pj_ntohs(local->sin_port);
+    }
+
+    return pjsip_udp_transport_attach( endpt, sock, a_name, async_cnt, 
 				       p_transport );
 }
Index: pjproject/trunk/pjsip/src/pjsip/sip_util.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_util.c	(revision 104)
+++ pjproject/trunk/pjsip/src/pjsip/sip_util.c	(revision 105)
@@ -677,5 +677,5 @@
 					    const pjsip_transport *req_transport,
 					    const pjsip_via_hdr *via,
-					    pjsip_host_port *send_addr)
+					    pjsip_host_info *send_addr)
 {
     /* Determine the destination address (section 18.2.2):
@@ -689,25 +689,23 @@
      */
     send_addr->flag = req_transport->flag;
-    send_addr->type = req_transport->type;
+    send_addr->type = req_transport->key.type;
 
     if (PJSIP_TRANSPORT_IS_RELIABLE(req_transport)) {
-	const pj_sockaddr_in *remote_addr;
-	remote_addr = &req_transport->rem_addr;
-	pj_strdup2(pool, &send_addr->host, 
-		   pj_inet_ntoa(remote_addr->sin_addr));
-	send_addr->port = pj_sockaddr_in_get_port(remote_addr);
+	pj_strdup( pool, &send_addr->addr.host, 
+		   &req_transport->remote_name.host);
+	send_addr->addr.port = req_transport->remote_name.port;
 
     } else {
 	/* Set the host part */
 	if (via->maddr_param.slen) {
-	    pj_strdup(pool, &send_addr->host, &via->maddr_param);
+	    pj_strdup(pool, &send_addr->addr.host, &via->maddr_param);
 	} else if (via->recvd_param.slen) {
-	    pj_strdup(pool, &send_addr->host, &via->recvd_param);
+	    pj_strdup(pool, &send_addr->addr.host, &via->recvd_param);
 	} else {
-	    pj_strdup(pool, &send_addr->host, &via->sent_by.host);
+	    pj_strdup(pool, &send_addr->addr.host, &via->sent_by.host);
 	}
 
 	/* Set the port */
-	send_addr->port = via->sent_by.port;
+	send_addr->addr.port = via->sent_by.port;
     }
 
Index: pjproject/trunk/pjsip/src/test-pjsip/msg.c
===================================================================
--- pjproject/trunk/pjsip/src/test-pjsip/msg.c	(revision 104)
+++ 	(revision )
@@ -1,746 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
- */
-#include "test.h"
-#include <pjsip_core.h>
-#include <pjlib.h>
-
-#define POOL_SIZE	8000
-#define LOOP		10000
-#define AVERAGE_MSG_LEN	800
-
-static pjsip_msg *create_msg0(pj_pool_t *pool);
-static pjsip_msg *create_msg1(pj_pool_t *pool);
-
-#define STATUS_PARTIAL		1
-#define STATUS_SYNTAX_ERROR	2
-
-#define FLAG_DETECT_ONLY	1
-#define FLAG_PARSE_ONLY		4
-#define FLAG_PRINT_ONLY		8
-
-static int flag = 0;
-
-struct test_msg
-{
-    char	 msg[1024];
-    pjsip_msg *(*creator)(pj_pool_t *pool);
-    pj_size_t	 len;
-    int		 expected_status;
-} test_array[] = 
-{
-{
-    /* '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=1234578901234567890\r"
-    "To: Fellow User <sip:user@foo.bar.domain.com>\r\n"
-    "Call-ID: 12345678901234567890@bar\r\n"
-    "Content-Length: 0\r\n"
-    "CSeq: 123456 INVITE\n"
-    "Contact: <sip:joe@bar> ; q=0.5;expires=3600,sip:user@host;q=0.500\r"
-    "  ,sip:user2@host2\n"
-    "Content-Type: text/html ; charset=ISO-8859-4\r"
-    "Route: <sip:bigbox3.site3.atlanta.com;lr>,\r\n"
-    "  <sip:server10.biloxi.com;lr>\r"
-    "Record-Route: <sip:server10.biloxi.com>,\r\n"
-    "  <sip:bigbox3.site3.atlanta.com;lr>\n"
-    "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1\n"
-    "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n"
-    " ;received=192.0.2.1\r\n"
-    "Via: SIP/2.0/UDP 10.2.1.1, SIP/2.0/TCP 192.168.1.1\n"
-    "Organization: \r"
-    "Max-Forwards: 70\n"
-    "X-Header: \r\n"
-    "\r\n",
-    &create_msg0,
-    PJ_SUCCESS
-},
-{
-    /* Typical response message. */
-    "SIP/2.0 200 OK\r\n"
-    "Via: SIP/2.0/SCTP server10.biloxi.com;branch=z9hG4bKnashds8;rport;received=192.0.2.1\r\n"
-    "Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2\r\n"
-    "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds ;received=192.0.2.3\r\n"
-    "Route: <sip:proxy.sipprovider.com>\r\n"
-    "Route: <sip:proxy.supersip.com:5060>\r\n"
-    "Max-Forwards: 70\r\n"
-    "To: Bob <sip:bob@biloxi.com>;tag=a6c85cf\r\n"
-    "From: Alice <sip:alice@atlanta.com>;tag=1928301774\r\n"
-    "Call-ID: a84b4c76e66710@pc33.atlanta.com\r\n"
-    "CSeq: 314159 INVITE\r\n"
-    "Contact: <sips:bob@192.0.2.4>\r\n"
-    "Content-Type: application/sdp\r\n"
-    "Content-Length: 150\r\n"
-    "\r\n"
-    "v=0\r\n"
-    "o=alice 53655765 2353687637 IN IP4 pc33.atlanta.com\r\n"
-    "s=-\r\n"
-    "t=0 0\r\n"
-    "c=IN IP4 pc33.atlanta.com\r\n"
-    "m=audio 3456 RTP/AVP 0 1 3 99\r\n"
-    "a=rtpmap:0 PCMU/8000\r\n",
-    &create_msg1,
-    PJ_SUCCESS
-}
-};
-
-static pj_highprec_t detect_len, parse_len, print_len;
-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;
-    pjsip_hdr *hdr1, *hdr2;
-    pj_timestamp t1, t2;
-    pjsip_parser_err_report err_list;
-    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 (print_msg == NULL)
-	    print_msg = entry->creator(pool);
-	goto print_msg;
-    }
-
-    /* Detect message. */
-    detect_len = detect_len + entry->len;
-    pj_get_timestamp(&t1);
-    status = pjsip_find_msg(entry->msg, entry->len, PJ_FALSE, &msg_size);
-    if (status != PJ_SUCCESS) {
-	if (status!=PJSIP_EPARTIALMSG || 
-	    entry->expected_status!=STATUS_PARTIAL)
-	{
-	    app_perror("   error: unable to detect message", status);
-	    return -5;
-	}
-    }
-    if (msg_size != entry->len) {
-	PJ_LOG(3,("", "   error: size mismatch"));
-	return -6;
-    }
-    pj_get_timestamp(&t2);
-    pj_sub_timestamp(&t2, &t1);
-    pj_add_timestamp(&detect_time, &t2);
-
-    if (flag & FLAG_DETECT_ONLY)
-	return PJ_SUCCESS;
-    
-    /* Parse message. */
-parse_msg:
-    parse_len = parse_len + entry->len;
-    pj_get_timestamp(&t1);
-    pj_list_init(&err_list);
-    parsed_msg = pjsip_parse_msg(pool, entry->msg, entry->len, &err_list);
-    if (parsed_msg == NULL) {
-	if (entry->expected_status != STATUS_SYNTAX_ERROR) {
-	    status = -10;
-	    if (err_list.next != &err_list) {
-		PJ_LOG(3,("", "   Syntax error in line %d col %d",
-			      err_list.next->line, err_list.next->col));
-	    }
-	    goto on_return;
-	}
-    }
-    pj_get_timestamp(&t2);
-    pj_sub_timestamp(&t2, &t1);
-    pj_add_timestamp(&parse_time, &t2);
-
-    if (flag & FLAG_PARSE_ONLY)
-	return PJ_SUCCESS;
-
-    /* Create reference message. */
-    ref_msg = entry->creator(pool);
-
-    /* Create buffer for comparison. */
-    str1.ptr = pj_pool_alloc(pool, BUFLEN);
-    str2.ptr = pj_pool_alloc(pool, BUFLEN);
-
-    /* Compare message type. */
-    if (parsed_msg->type != ref_msg->type) {
-	status = -20;
-	goto on_return;
-    }
-
-    /* Compare request or status line. */
-    if (parsed_msg->type == PJSIP_REQUEST_MSG) {
-	pjsip_method *m1 = &parsed_msg->line.req.method;
-	pjsip_method *m2 = &ref_msg->line.req.method;
-
-	if (pjsip_method_cmp(m1, m2) != 0) {
-	    status = -30;
-	    goto on_return;
-	}
-	status = pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI,
-			       parsed_msg->line.req.uri, 
-			       ref_msg->line.req.uri);
-	if (status != PJ_SUCCESS) {
-	    app_perror("   error: request URI mismatch", status);
-	    status = -31;
-	    goto on_return;
-	}
-    } else {
-	if (parsed_msg->line.status.code != ref_msg->line.status.code) {
-	    PJ_LOG(3,("", "   error: status code mismatch"));
-	    status = -32;
-	    goto on_return;
-	}
-	if (pj_strcmp(&parsed_msg->line.status.reason, 
-		      &ref_msg->line.status.reason) != 0) 
-	{
-	    PJ_LOG(3,("", "   error: status text mismatch"));
-	    status = -33;
-	    goto on_return;
-	}
-    }
-
-    /* Compare headers. */
-    hdr1 = parsed_msg->hdr.next;
-    hdr2 = ref_msg->hdr.next;
-
-    while (hdr1 != &parsed_msg->hdr && hdr2 != &ref_msg->hdr) {
-	len = hdr1->vptr->print_on(hdr1, str1.ptr, BUFLEN);
-	if (len < 1) {
-	    status = -40;
-	    goto on_return;
-	}
-	str1.ptr[len] = '\0';
-	str1.slen = len;
-
-	len = hdr2->vptr->print_on(hdr2, str2.ptr, BUFLEN);
-	if (len < 1) {
-	    status = -50;
-	    goto on_return;
-	}
-	str2.ptr[len] = '\0';
-	str2.slen = len;
-
-	if (pj_strcmp(&str1, &str2) != 0) {
-	    status = -60;
-	    PJ_LOG(3,("", "   error: header string mismatch:\n"
-		          "   h1='%s'\n"
-			  "   h2='%s'\n",
-			  str1.ptr, str2.ptr));
-	    goto on_return;
-	}
-
-	hdr1 = hdr1->next;
-	hdr2 = hdr2->next;
-    }
-
-    if (hdr1 != &parsed_msg->hdr || hdr2 != &ref_msg->hdr) {
-	status = -70;
-	goto on_return;
-    }
-
-    /* Compare body? */
-    if (parsed_msg->body==NULL && ref_msg->body==NULL)
-	goto print_msg;
-
-    /* Compare msg body length. */
-    if (parsed_msg->body->len != ref_msg->body->len) {
-	status = -80;
-	goto on_return;
-    }
-
-    /* Compare msg body content type. */
-    if (pj_strcmp(&parsed_msg->body->content_type.type,
-	          &ref_msg->body->content_type.type) != 0) {
-	status = -90;
-	goto on_return;
-    }
-    if (pj_strcmp(&parsed_msg->body->content_type.subtype,
-	          &ref_msg->body->content_type.subtype) != 0) {
-	status = -100;
-	goto on_return;
-    }
-
-    /* Compare body content. */
-    str1.slen = parsed_msg->body->print_body(parsed_msg->body,
-					     msgbuf1, sizeof(msgbuf1));
-    if (str1.slen < 1) {
-	status = -110;
-	goto on_return;
-    }
-    str1.ptr = msgbuf1;
-
-    str2.slen = ref_msg->body->print_body(ref_msg->body,
-					  msgbuf2, sizeof(msgbuf2));
-    if (str2.slen < 1) {
-	status = -120;
-	goto on_return;
-    }
-    str2.ptr = msgbuf2;
-
-    if (pj_strcmp(&str1, &str2) != 0) {
-	status = -140;
-	goto on_return;
-    }
-    
-    /* Print message. */
-print_msg:
-    print_len = print_len + entry->len;
-    pj_get_timestamp(&t1);
-    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;
-    }
-    pj_get_timestamp(&t2);
-    pj_sub_timestamp(&t2, &t1);
-    pj_add_timestamp(&print_time, &t2);
-
-
-    status = PJ_SUCCESS;
-
-on_return:
-    return status;
-}
-
-
-static pjsip_msg *create_msg0(pj_pool_t *pool)
-{
-
-    pjsip_msg *msg;
-    pjsip_name_addr *name_addr;
-    pjsip_url *url;
-    pjsip_fromto_hdr *fromto;
-    pjsip_cid_hdr *cid;
-    pjsip_clen_hdr *clen;
-    pjsip_cseq_hdr *cseq;
-    pjsip_contact_hdr *contact;
-    pjsip_ctype_hdr *ctype;
-    pjsip_routing_hdr *routing;
-    pjsip_via_hdr *via;
-    pjsip_generic_string_hdr *generic;
-    pj_str_t str;
-
-    msg = pjsip_msg_create(pool, PJSIP_REQUEST_MSG);
-
-    /* "INVITE sip:user@foo SIP/2.0\n" */
-    pjsip_method_set(&msg->line.req.method, PJSIP_INVITE_METHOD);
-    url = pjsip_url_create(pool, 0);
-    msg->line.req.uri = (pjsip_uri*)url;
-    pj_strdup2(pool, &url->user, "user");
-    pj_strdup2(pool, &url->host, "foo");
-
-    /* "From: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=1234578901234567890\r" */
-    fromto = pjsip_from_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)fromto);
-    pj_strdup2(pool, &fromto->tag, "1234578901234567890");
-    name_addr = pjsip_name_addr_create(pool);
-    fromto->uri = (pjsip_uri*)name_addr;
-    pj_strdup2(pool, &name_addr->display, "Hi I'm Joe");
-    url = pjsip_url_create(pool, 0);
-    name_addr->uri = (pjsip_uri*)url;
-    pj_strdup2(pool, &url->user, "joe.user");
-    pj_strdup2(pool, &url->host, "bar.otherdomain.com");
-
-    /* "To: Fellow User <sip:user@foo.bar.domain.com>\r\n" */
-    fromto = pjsip_to_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)fromto);
-    name_addr = pjsip_name_addr_create(pool);
-    fromto->uri = (pjsip_uri*)name_addr;
-    pj_strdup2(pool, &name_addr->display, "Fellow User");
-    url = pjsip_url_create(pool, 0);
-    name_addr->uri = (pjsip_uri*)url;
-    pj_strdup2(pool, &url->user, "user");
-    pj_strdup2(pool, &url->host, "foo.bar.domain.com");
-
-    /* "Call-ID: 12345678901234567890@bar\r\n" */
-    cid = pjsip_cid_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)cid);
-    pj_strdup2(pool, &cid->id, "12345678901234567890@bar");
-
-    /* "Content-Length: 0\r\n" */
-    clen = pjsip_clen_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)clen);
-    clen->len = 0;
-
-    /* "CSeq: 123456 INVITE\n" */
-    cseq = pjsip_cseq_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)cseq);
-    cseq->cseq = 123456;
-    pjsip_method_set(&cseq->method, PJSIP_INVITE_METHOD);
-
-    /* "Contact: <sip:joe@bar>;q=0.5;expires=3600*/
-    contact = pjsip_contact_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact);
-    contact->q1000 = 500;
-    contact->expires = 3600;
-    name_addr = pjsip_name_addr_create(pool);
-    contact->uri = (pjsip_uri*)name_addr;
-    url = pjsip_url_create(pool, 0);
-    name_addr->uri = (pjsip_uri*)url;
-    pj_strdup2(pool, &url->user, "joe");
-    pj_strdup2(pool, &url->host, "bar");
-
-    /*, sip:user@host;q=0.500\r" */
-    contact = pjsip_contact_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact);
-    contact->q1000 = 500;
-    name_addr = pjsip_name_addr_create(pool);
-    contact->uri = (pjsip_uri*)name_addr;
-    url = pjsip_url_create(pool, 0);
-    name_addr->uri = (pjsip_uri*)url;
-    pj_strdup2(pool, &url->user, "user");
-    pj_strdup2(pool, &url->host, "host");
-
-    /* "  ,sip:user2@host2\n" */
-    contact = pjsip_contact_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact);
-    name_addr = pjsip_name_addr_create(pool);
-    contact->uri = (pjsip_uri*)name_addr;
-    url = pjsip_url_create(pool, 0);
-    name_addr->uri = (pjsip_uri*)url;
-    pj_strdup2(pool, &url->user, "user2");
-    pj_strdup2(pool, &url->host, "host2");
-
-    /* "Content-Type: text/html; charset=ISO-8859-4\r" */
-    ctype = pjsip_ctype_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)ctype);
-    pj_strdup2(pool, &ctype->media.type, "text");
-    pj_strdup2(pool, &ctype->media.subtype, "html");
-    pj_strdup2(pool, &ctype->media.param, ";charset=ISO-8859-4");
-
-    /* "Route: <sip:bigbox3.site3.atlanta.com;lr>,\r\n" */
-    routing = pjsip_route_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing);
-    url = pjsip_url_create(pool, 0);
-    routing->name_addr.uri = (pjsip_uri*)url;
-    pj_strdup2(pool, &url->host, "bigbox3.site3.atlanta.com");
-    url->lr_param = 1;
-
-    /* "  <sip:server10.biloxi.com;lr>\r" */
-    routing = pjsip_route_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing);
-    url = pjsip_url_create(pool, 0);
-    routing->name_addr.uri = (pjsip_uri*)url;
-    pj_strdup2(pool, &url->host, "server10.biloxi.com");
-    url->lr_param = 1;
-
-    /* "Record-Route: <sip:server10.biloxi.com>,\r\n" */
-    routing = pjsip_rr_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing);
-    url = pjsip_url_create(pool, 0);
-    routing->name_addr.uri = (pjsip_uri*)url;
-    pj_strdup2(pool, &url->host, "server10.biloxi.com");
-    url->lr_param = 0;
-
-    /* "  <sip:bigbox3.site3.atlanta.com;lr>\n" */
-    routing = pjsip_rr_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing);
-    url = pjsip_url_create(pool, 0);
-    routing->name_addr.uri = (pjsip_uri*)url;
-    pj_strdup2(pool, &url->host, "bigbox3.site3.atlanta.com");
-    url->lr_param = 1;
-
-    /* "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1\n" */
-    via = pjsip_via_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
-    pj_strdup2(pool, &via->transport, "SCTP");
-    pj_strdup2(pool, &via->sent_by.host, "bigbox3.site3.atlanta.com");
-    pj_strdup2(pool, &via->branch_param, "z9hG4bK77ef4c2312983.1");
-
-    /* "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n"
-	" ;received=192.0.2.1\r\n" */
-    via = pjsip_via_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
-    pj_strdup2(pool, &via->transport, "UDP");
-    pj_strdup2(pool, &via->sent_by.host, "pc33.atlanta.com");
-    pj_strdup2(pool, &via->branch_param, "z9hG4bKnashds8");
-    pj_strdup2(pool, &via->recvd_param, "192.0.2.1");
-
-
-    /* "Via: SIP/2.0/UDP 10.2.1.1, */ 
-    via = pjsip_via_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
-    pj_strdup2(pool, &via->transport, "UDP");
-    pj_strdup2(pool, &via->sent_by.host, "10.2.1.1");
-    
-    
-    /*SIP/2.0/TCP 192.168.1.1\n" */
-    via = pjsip_via_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
-    pj_strdup2(pool, &via->transport, "TCP");
-    pj_strdup2(pool, &via->sent_by.host, "192.168.1.1");
-
-    /* "Organization: \r" */
-    str.ptr = "Organization";
-    str.slen = 12;
-    generic = pjsip_generic_string_hdr_create(pool, &str);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic);
-    generic->hvalue.ptr = NULL;
-    generic->hvalue.slen = 0;
-
-    /* "Max-Forwards: 70\n" */
-    str.ptr = "Max-Forwards";
-    str.slen = 12;
-    generic = pjsip_generic_string_hdr_create(pool, &str);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic);
-    str.ptr = "70";
-    str.slen = 2;
-    generic->hvalue = str;
-
-    /* "X-Header: \r\n" */
-    str.ptr = "X-Header";
-    str.slen = 8;
-    generic = pjsip_generic_string_hdr_create(pool, &str);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic);
-    str.ptr = NULL;
-    str.slen = 0;
-    generic->hvalue = str;
-
-    return msg;
-}
-
-static pjsip_msg *create_msg1(pj_pool_t *pool)
-{
-    pjsip_via_hdr *via;
-    pjsip_route_hdr *route;
-    pjsip_name_addr *name_addr;
-    pjsip_url *url;
-    pjsip_max_forwards_hdr *max_fwd;
-    pjsip_to_hdr *to;
-    pjsip_from_hdr *from;
-    pjsip_contact_hdr *contact;
-    pjsip_ctype_hdr *ctype;
-    pjsip_cid_hdr *cid;
-    pjsip_clen_hdr *clen;
-    pjsip_cseq_hdr *cseq;
-    pjsip_msg *msg = pjsip_msg_create(pool, PJSIP_RESPONSE_MSG);
-    pjsip_msg_body *body;
-
-    //"SIP/2.0 200 OK\r\n"
-    msg->line.status.code = 200;
-    msg->line.status.reason = pj_str("OK");
-
-    //"Via: SIP/2.0/SCTP server10.biloxi.com;branch=z9hG4bKnashds8;rport;received=192.0.2.1\r\n"
-    via = pjsip_via_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
-    via->transport = pj_str("SCTP");
-    via->sent_by.host = pj_str("server10.biloxi.com");
-    via->branch_param = pj_str("z9hG4bKnashds8");
-    via->rport_param = 0;
-    via->recvd_param = pj_str("192.0.2.1");
-
-    //"Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2\r\n"
-    via = pjsip_via_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
-    via->transport = pj_str("UDP");
-    via->sent_by.host = pj_str("bigbox3.site3.atlanta.com");
-    via->branch_param = pj_str("z9hG4bK77ef4c2312983.1");
-    via->recvd_param = pj_str("192.0.2.2");
-
-    //"Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds ;received=192.0.2.3\r\n"
-    via = pjsip_via_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
-    via->transport = pj_str("UDP");
-    via->sent_by.host = pj_str("pc33.atlanta.com");
-    via->branch_param = pj_str("z9hG4bK776asdhds");
-    via->recvd_param = pj_str("192.0.2.3");
-
-    //"Route: <sip:proxy.sipprovider.com>\r\n"
-    route = pjsip_route_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)route);
-    url = pjsip_url_create(pool, PJ_FALSE);
-    route->name_addr.uri = (pjsip_uri*)url;
-    url->host = pj_str("proxy.sipprovider.com");
-    
-    //"Route: <sip:proxy.supersip.com:5060>\r\n"
-    route = pjsip_route_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)route);
-    url = pjsip_url_create(pool, PJ_FALSE);
-    route->name_addr.uri = (pjsip_uri*)url;
-    url->host = pj_str("proxy.supersip.com");
-    url->port = 5060;
-
-    //"Max-Forwards: 70\r\n"
-    max_fwd = pjsip_max_forwards_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)max_fwd);
-    max_fwd->ivalue = 70;
-
-    //"To: Bob <sip:bob@biloxi.com>;tag=a6c85cf\r\n"
-    to = pjsip_to_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)to);
-    name_addr = pjsip_name_addr_create(pool);
-    name_addr->display = pj_str("Bob");
-    to->uri = (pjsip_uri*)name_addr;
-    url = pjsip_url_create(pool, PJ_FALSE);
-    name_addr->uri = (pjsip_uri*)url;
-    url->user = pj_str("bob");
-    url->host = pj_str("biloxi.com");
-    to->tag = pj_str("a6c85cf");
-
-    //"From: Alice <sip:alice@atlanta.com>;tag=1928301774\r\n"
-    from = pjsip_from_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)from);
-    name_addr = pjsip_name_addr_create(pool);
-    name_addr->display = pj_str("Alice");
-    from->uri = (pjsip_uri*)name_addr;
-    url = pjsip_url_create(pool, PJ_FALSE);
-    name_addr->uri = (pjsip_uri*)url;
-    url->user = pj_str("alice");
-    url->host = pj_str("atlanta.com");
-    from->tag = pj_str("1928301774");
-
-    //"Call-ID: a84b4c76e66710@pc33.atlanta.com\r\n"
-    cid = pjsip_cid_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)cid);
-    cid->id = pj_str("a84b4c76e66710@pc33.atlanta.com");
-
-    //"CSeq: 314159 INVITE\r\n"
-    cseq = pjsip_cseq_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)cseq);
-    cseq->cseq = 314159;
-    pjsip_method_set(&cseq->method, PJSIP_INVITE_METHOD);
-
-    //"Contact: <sips:bob@192.0.2.4>\r\n"
-    contact = pjsip_contact_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact);
-    name_addr = pjsip_name_addr_create(pool);
-    contact->uri = (pjsip_uri*)name_addr;
-    url = pjsip_url_create(pool, PJ_TRUE);
-    name_addr->uri = (pjsip_uri*)url;
-    url->user = pj_str("bob");
-    url->host = pj_str("192.0.2.4");
-
-    //"Content-Type: application/sdp\r\n"
-    ctype = pjsip_ctype_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)ctype);
-    ctype->media.type = pj_str("application");
-    ctype->media.subtype = pj_str("sdp");
-
-    //"Content-Length: 150\r\n"
-    clen = pjsip_clen_hdr_create(pool);
-    pjsip_msg_add_hdr(msg, (pjsip_hdr*)clen);
-    clen->len = 150;
-
-    // Body
-    body = pj_pool_zalloc(pool, sizeof(*body));
-    msg->body = body;
-    body->content_type.type = pj_str("application");
-    body->content_type.subtype = pj_str("sdp");
-    body->data = 
-	"v=0\r\n"
-	"o=alice 53655765 2353687637 IN IP4 pc33.atlanta.com\r\n"
-	"s=-\r\n"
-	"t=0 0\r\n"
-	"c=IN IP4 pc33.atlanta.com\r\n"
-	"m=audio 3456 RTP/AVP 0 1 3 99\r\n"
-	"a=rtpmap:0 PCMU/8000\r\n";
-    body->len = pj_native_strlen(body->data);
-    body->print_body = &pjsip_print_text_body;
-
-    return msg;
-}
-
-/*****************************************************************************/
-
-pj_status_t msg_test(void)
-{
-    pj_status_t status;
-    pj_pool_t *pool;
-    int i, loop;
-    pj_timestamp zero;
-    pj_time_val elapsed;
-    pj_highprec_t avg_detect, avg_parse, avg_print, kbytes;
-
-    PJ_LOG(3,("", "  simple test.."));
-    for (i=0; i<PJ_ARRAY_SIZE(test_array); ++i) {
-	pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE);
-	status = test_entry( pool, &test_array[i] );
-	pjsip_endpt_destroy_pool(endpt, pool);
-
-	if (status != PJ_SUCCESS)
-	    return status;
-    }
-
-    PJ_LOG(3,("", "  benchmarking.."));
-    detect_len = parse_len = print_len = 0;
-    zero.u64 = detect_time.u64 = parse_time.u64 = print_time.u64 = 0;
-    
-    for (loop=0; loop<LOOP; ++loop) {
-	for (i=0; i<PJ_ARRAY_SIZE(test_array); ++i) {
-	    pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE);
-	    status = test_entry( pool, &test_array[i] );
-	    pjsip_endpt_destroy_pool(endpt, pool);
-
-	    if (status != PJ_SUCCESS)
-		return status;
-	}
-    }
-
-    kbytes = detect_len;
-    pj_highprec_mod(kbytes, 1000000);
-    pj_highprec_div(kbytes, 100000);
-    elapsed = pj_elapsed_time(&zero, &detect_time);
-    avg_detect = pj_elapsed_usec(&zero, &detect_time);
-    pj_highprec_mul(avg_detect, AVERAGE_MSG_LEN);
-    pj_highprec_div(avg_detect, detect_len);
-    avg_detect = 1000000 / avg_detect;
-
-    PJ_LOG(3,("", "    %u.%u MB detected in %d.%03ds (avg=%d msg detection/sec)", 
-		  (unsigned)(detect_len/1000000), (unsigned)kbytes,
-		  elapsed.sec, elapsed.msec,
-		  (unsigned)avg_detect));
-
-    kbytes = parse_len;
-    pj_highprec_mod(kbytes, 1000000);
-    pj_highprec_div(kbytes, 100000);
-    elapsed = pj_elapsed_time(&zero, &parse_time);
-    avg_parse = pj_elapsed_usec(&zero, &parse_time);
-    pj_highprec_mul(avg_parse, AVERAGE_MSG_LEN);
-    pj_highprec_div(avg_parse, parse_len);
-    avg_parse = 1000000 / avg_parse;
-
-    PJ_LOG(3,("", "    %u.%u MB parsed in %d.%03ds (avg=%d msg parsing/sec)", 
-		  (unsigned)(parse_len/1000000), (unsigned)kbytes,
-		  elapsed.sec, elapsed.msec,
-		  (unsigned)avg_parse));
-
-    kbytes = print_len;
-    pj_highprec_mod(kbytes, 1000000);
-    pj_highprec_div(kbytes, 100000);
-    elapsed = pj_elapsed_time(&zero, &print_time);
-    avg_print = pj_elapsed_usec(&zero, &print_time);
-    pj_highprec_mul(avg_print, AVERAGE_MSG_LEN);
-    pj_highprec_div(avg_print, print_len);
-    avg_print = 1000000 / avg_print;
-
-    PJ_LOG(3,("", "    %u.%u MB printed in %d.%03ds (avg=%d msg print/sec)", 
-		  (unsigned)(print_len/1000000), (unsigned)kbytes,
-		  elapsed.sec, elapsed.msec,
-		  (unsigned)avg_print));
-
-    return status;
-}
-
-/*****************************************************************************/
Index: pjproject/trunk/pjsip/src/test-pjsip/msg_test.c
===================================================================
--- pjproject/trunk/pjsip/src/test-pjsip/msg_test.c	(revision 105)
+++ pjproject/trunk/pjsip/src/test-pjsip/msg_test.c	(revision 105)
@@ -0,0 +1,746 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pjsip_core.h>
+#include <pjlib.h>
+
+#define POOL_SIZE	8000
+#define LOOP		10000
+#define AVERAGE_MSG_LEN	800
+
+static pjsip_msg *create_msg0(pj_pool_t *pool);
+static pjsip_msg *create_msg1(pj_pool_t *pool);
+
+#define STATUS_PARTIAL		1
+#define STATUS_SYNTAX_ERROR	2
+
+#define FLAG_DETECT_ONLY	1
+#define FLAG_PARSE_ONLY		4
+#define FLAG_PRINT_ONLY		8
+
+static int flag = 0;
+
+struct test_msg
+{
+    char	 msg[1024];
+    pjsip_msg *(*creator)(pj_pool_t *pool);
+    pj_size_t	 len;
+    int		 expected_status;
+} test_array[] = 
+{
+{
+    /* '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=1234578901234567890\r"
+    "To: Fellow User <sip:user@foo.bar.domain.com>\r\n"
+    "Call-ID: 12345678901234567890@bar\r\n"
+    "Content-Length: 0\r\n"
+    "CSeq: 123456 INVITE\n"
+    "Contact: <sip:joe@bar> ; q=0.5;expires=3600,sip:user@host;q=0.500\r"
+    "  ,sip:user2@host2\n"
+    "Content-Type: text/html ; charset=ISO-8859-4\r"
+    "Route: <sip:bigbox3.site3.atlanta.com;lr>,\r\n"
+    "  <sip:server10.biloxi.com;lr>\r"
+    "Record-Route: <sip:server10.biloxi.com>,\r\n"
+    "  <sip:bigbox3.site3.atlanta.com;lr>\n"
+    "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1\n"
+    "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n"
+    " ;received=192.0.2.1\r\n"
+    "Via: SIP/2.0/UDP 10.2.1.1, SIP/2.0/TCP 192.168.1.1\n"
+    "Organization: \r"
+    "Max-Forwards: 70\n"
+    "X-Header: \r\n"
+    "\r\n",
+    &create_msg0,
+    PJ_SUCCESS
+},
+{
+    /* Typical response message. */
+    "SIP/2.0 200 OK\r\n"
+    "Via: SIP/2.0/SCTP server10.biloxi.com;branch=z9hG4bKnashds8;rport;received=192.0.2.1\r\n"
+    "Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2\r\n"
+    "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds ;received=192.0.2.3\r\n"
+    "Route: <sip:proxy.sipprovider.com>\r\n"
+    "Route: <sip:proxy.supersip.com:5060>\r\n"
+    "Max-Forwards: 70\r\n"
+    "To: Bob <sip:bob@biloxi.com>;tag=a6c85cf\r\n"
+    "From: Alice <sip:alice@atlanta.com>;tag=1928301774\r\n"
+    "Call-ID: a84b4c76e66710@pc33.atlanta.com\r\n"
+    "CSeq: 314159 INVITE\r\n"
+    "Contact: <sips:bob@192.0.2.4>\r\n"
+    "Content-Type: application/sdp\r\n"
+    "Content-Length: 150\r\n"
+    "\r\n"
+    "v=0\r\n"
+    "o=alice 53655765 2353687637 IN IP4 pc33.atlanta.com\r\n"
+    "s=-\r\n"
+    "t=0 0\r\n"
+    "c=IN IP4 pc33.atlanta.com\r\n"
+    "m=audio 3456 RTP/AVP 0 1 3 99\r\n"
+    "a=rtpmap:0 PCMU/8000\r\n",
+    &create_msg1,
+    PJ_SUCCESS
+}
+};
+
+static pj_highprec_t detect_len, parse_len, print_len;
+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;
+    pjsip_hdr *hdr1, *hdr2;
+    pj_timestamp t1, t2;
+    pjsip_parser_err_report err_list;
+    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 (print_msg == NULL)
+	    print_msg = entry->creator(pool);
+	goto print_msg;
+    }
+
+    /* Detect message. */
+    detect_len = detect_len + entry->len;
+    pj_get_timestamp(&t1);
+    status = pjsip_find_msg(entry->msg, entry->len, PJ_FALSE, &msg_size);
+    if (status != PJ_SUCCESS) {
+	if (status!=PJSIP_EPARTIALMSG || 
+	    entry->expected_status!=STATUS_PARTIAL)
+	{
+	    app_perror("   error: unable to detect message", status);
+	    return -5;
+	}
+    }
+    if (msg_size != entry->len) {
+	PJ_LOG(3,("", "   error: size mismatch"));
+	return -6;
+    }
+    pj_get_timestamp(&t2);
+    pj_sub_timestamp(&t2, &t1);
+    pj_add_timestamp(&detect_time, &t2);
+
+    if (flag & FLAG_DETECT_ONLY)
+	return PJ_SUCCESS;
+    
+    /* Parse message. */
+parse_msg:
+    parse_len = parse_len + entry->len;
+    pj_get_timestamp(&t1);
+    pj_list_init(&err_list);
+    parsed_msg = pjsip_parse_msg(pool, entry->msg, entry->len, &err_list);
+    if (parsed_msg == NULL) {
+	if (entry->expected_status != STATUS_SYNTAX_ERROR) {
+	    status = -10;
+	    if (err_list.next != &err_list) {
+		PJ_LOG(3,("", "   Syntax error in line %d col %d",
+			      err_list.next->line, err_list.next->col));
+	    }
+	    goto on_return;
+	}
+    }
+    pj_get_timestamp(&t2);
+    pj_sub_timestamp(&t2, &t1);
+    pj_add_timestamp(&parse_time, &t2);
+
+    if (flag & FLAG_PARSE_ONLY)
+	return PJ_SUCCESS;
+
+    /* Create reference message. */
+    ref_msg = entry->creator(pool);
+
+    /* Create buffer for comparison. */
+    str1.ptr = pj_pool_alloc(pool, BUFLEN);
+    str2.ptr = pj_pool_alloc(pool, BUFLEN);
+
+    /* Compare message type. */
+    if (parsed_msg->type != ref_msg->type) {
+	status = -20;
+	goto on_return;
+    }
+
+    /* Compare request or status line. */
+    if (parsed_msg->type == PJSIP_REQUEST_MSG) {
+	pjsip_method *m1 = &parsed_msg->line.req.method;
+	pjsip_method *m2 = &ref_msg->line.req.method;
+
+	if (pjsip_method_cmp(m1, m2) != 0) {
+	    status = -30;
+	    goto on_return;
+	}
+	status = pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI,
+			       parsed_msg->line.req.uri, 
+			       ref_msg->line.req.uri);
+	if (status != PJ_SUCCESS) {
+	    app_perror("   error: request URI mismatch", status);
+	    status = -31;
+	    goto on_return;
+	}
+    } else {
+	if (parsed_msg->line.status.code != ref_msg->line.status.code) {
+	    PJ_LOG(3,("", "   error: status code mismatch"));
+	    status = -32;
+	    goto on_return;
+	}
+	if (pj_strcmp(&parsed_msg->line.status.reason, 
+		      &ref_msg->line.status.reason) != 0) 
+	{
+	    PJ_LOG(3,("", "   error: status text mismatch"));
+	    status = -33;
+	    goto on_return;
+	}
+    }
+
+    /* Compare headers. */
+    hdr1 = parsed_msg->hdr.next;
+    hdr2 = ref_msg->hdr.next;
+
+    while (hdr1 != &parsed_msg->hdr && hdr2 != &ref_msg->hdr) {
+	len = hdr1->vptr->print_on(hdr1, str1.ptr, BUFLEN);
+	if (len < 1) {
+	    status = -40;
+	    goto on_return;
+	}
+	str1.ptr[len] = '\0';
+	str1.slen = len;
+
+	len = hdr2->vptr->print_on(hdr2, str2.ptr, BUFLEN);
+	if (len < 1) {
+	    status = -50;
+	    goto on_return;
+	}
+	str2.ptr[len] = '\0';
+	str2.slen = len;
+
+	if (pj_strcmp(&str1, &str2) != 0) {
+	    status = -60;
+	    PJ_LOG(3,("", "   error: header string mismatch:\n"
+		          "   h1='%s'\n"
+			  "   h2='%s'\n",
+			  str1.ptr, str2.ptr));
+	    goto on_return;
+	}
+
+	hdr1 = hdr1->next;
+	hdr2 = hdr2->next;
+    }
+
+    if (hdr1 != &parsed_msg->hdr || hdr2 != &ref_msg->hdr) {
+	status = -70;
+	goto on_return;
+    }
+
+    /* Compare body? */
+    if (parsed_msg->body==NULL && ref_msg->body==NULL)
+	goto print_msg;
+
+    /* Compare msg body length. */
+    if (parsed_msg->body->len != ref_msg->body->len) {
+	status = -80;
+	goto on_return;
+    }
+
+    /* Compare msg body content type. */
+    if (pj_strcmp(&parsed_msg->body->content_type.type,
+	          &ref_msg->body->content_type.type) != 0) {
+	status = -90;
+	goto on_return;
+    }
+    if (pj_strcmp(&parsed_msg->body->content_type.subtype,
+	          &ref_msg->body->content_type.subtype) != 0) {
+	status = -100;
+	goto on_return;
+    }
+
+    /* Compare body content. */
+    str1.slen = parsed_msg->body->print_body(parsed_msg->body,
+					     msgbuf1, sizeof(msgbuf1));
+    if (str1.slen < 1) {
+	status = -110;
+	goto on_return;
+    }
+    str1.ptr = msgbuf1;
+
+    str2.slen = ref_msg->body->print_body(ref_msg->body,
+					  msgbuf2, sizeof(msgbuf2));
+    if (str2.slen < 1) {
+	status = -120;
+	goto on_return;
+    }
+    str2.ptr = msgbuf2;
+
+    if (pj_strcmp(&str1, &str2) != 0) {
+	status = -140;
+	goto on_return;
+    }
+    
+    /* Print message. */
+print_msg:
+    print_len = print_len + entry->len;
+    pj_get_timestamp(&t1);
+    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;
+    }
+    pj_get_timestamp(&t2);
+    pj_sub_timestamp(&t2, &t1);
+    pj_add_timestamp(&print_time, &t2);
+
+
+    status = PJ_SUCCESS;
+
+on_return:
+    return status;
+}
+
+
+static pjsip_msg *create_msg0(pj_pool_t *pool)
+{
+
+    pjsip_msg *msg;
+    pjsip_name_addr *name_addr;
+    pjsip_url *url;
+    pjsip_fromto_hdr *fromto;
+    pjsip_cid_hdr *cid;
+    pjsip_clen_hdr *clen;
+    pjsip_cseq_hdr *cseq;
+    pjsip_contact_hdr *contact;
+    pjsip_ctype_hdr *ctype;
+    pjsip_routing_hdr *routing;
+    pjsip_via_hdr *via;
+    pjsip_generic_string_hdr *generic;
+    pj_str_t str;
+
+    msg = pjsip_msg_create(pool, PJSIP_REQUEST_MSG);
+
+    /* "INVITE sip:user@foo SIP/2.0\n" */
+    pjsip_method_set(&msg->line.req.method, PJSIP_INVITE_METHOD);
+    url = pjsip_url_create(pool, 0);
+    msg->line.req.uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->user, "user");
+    pj_strdup2(pool, &url->host, "foo");
+
+    /* "From: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=1234578901234567890\r" */
+    fromto = pjsip_from_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)fromto);
+    pj_strdup2(pool, &fromto->tag, "1234578901234567890");
+    name_addr = pjsip_name_addr_create(pool);
+    fromto->uri = (pjsip_uri*)name_addr;
+    pj_strdup2(pool, &name_addr->display, "Hi I'm Joe");
+    url = pjsip_url_create(pool, 0);
+    name_addr->uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->user, "joe.user");
+    pj_strdup2(pool, &url->host, "bar.otherdomain.com");
+
+    /* "To: Fellow User <sip:user@foo.bar.domain.com>\r\n" */
+    fromto = pjsip_to_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)fromto);
+    name_addr = pjsip_name_addr_create(pool);
+    fromto->uri = (pjsip_uri*)name_addr;
+    pj_strdup2(pool, &name_addr->display, "Fellow User");
+    url = pjsip_url_create(pool, 0);
+    name_addr->uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->user, "user");
+    pj_strdup2(pool, &url->host, "foo.bar.domain.com");
+
+    /* "Call-ID: 12345678901234567890@bar\r\n" */
+    cid = pjsip_cid_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)cid);
+    pj_strdup2(pool, &cid->id, "12345678901234567890@bar");
+
+    /* "Content-Length: 0\r\n" */
+    clen = pjsip_clen_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)clen);
+    clen->len = 0;
+
+    /* "CSeq: 123456 INVITE\n" */
+    cseq = pjsip_cseq_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)cseq);
+    cseq->cseq = 123456;
+    pjsip_method_set(&cseq->method, PJSIP_INVITE_METHOD);
+
+    /* "Contact: <sip:joe@bar>;q=0.5;expires=3600*/
+    contact = pjsip_contact_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact);
+    contact->q1000 = 500;
+    contact->expires = 3600;
+    name_addr = pjsip_name_addr_create(pool);
+    contact->uri = (pjsip_uri*)name_addr;
+    url = pjsip_url_create(pool, 0);
+    name_addr->uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->user, "joe");
+    pj_strdup2(pool, &url->host, "bar");
+
+    /*, sip:user@host;q=0.500\r" */
+    contact = pjsip_contact_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact);
+    contact->q1000 = 500;
+    name_addr = pjsip_name_addr_create(pool);
+    contact->uri = (pjsip_uri*)name_addr;
+    url = pjsip_url_create(pool, 0);
+    name_addr->uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->user, "user");
+    pj_strdup2(pool, &url->host, "host");
+
+    /* "  ,sip:user2@host2\n" */
+    contact = pjsip_contact_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact);
+    name_addr = pjsip_name_addr_create(pool);
+    contact->uri = (pjsip_uri*)name_addr;
+    url = pjsip_url_create(pool, 0);
+    name_addr->uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->user, "user2");
+    pj_strdup2(pool, &url->host, "host2");
+
+    /* "Content-Type: text/html; charset=ISO-8859-4\r" */
+    ctype = pjsip_ctype_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)ctype);
+    pj_strdup2(pool, &ctype->media.type, "text");
+    pj_strdup2(pool, &ctype->media.subtype, "html");
+    pj_strdup2(pool, &ctype->media.param, ";charset=ISO-8859-4");
+
+    /* "Route: <sip:bigbox3.site3.atlanta.com;lr>,\r\n" */
+    routing = pjsip_route_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing);
+    url = pjsip_url_create(pool, 0);
+    routing->name_addr.uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->host, "bigbox3.site3.atlanta.com");
+    url->lr_param = 1;
+
+    /* "  <sip:server10.biloxi.com;lr>\r" */
+    routing = pjsip_route_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing);
+    url = pjsip_url_create(pool, 0);
+    routing->name_addr.uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->host, "server10.biloxi.com");
+    url->lr_param = 1;
+
+    /* "Record-Route: <sip:server10.biloxi.com>,\r\n" */
+    routing = pjsip_rr_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing);
+    url = pjsip_url_create(pool, 0);
+    routing->name_addr.uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->host, "server10.biloxi.com");
+    url->lr_param = 0;
+
+    /* "  <sip:bigbox3.site3.atlanta.com;lr>\n" */
+    routing = pjsip_rr_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing);
+    url = pjsip_url_create(pool, 0);
+    routing->name_addr.uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->host, "bigbox3.site3.atlanta.com");
+    url->lr_param = 1;
+
+    /* "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1\n" */
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    pj_strdup2(pool, &via->transport, "SCTP");
+    pj_strdup2(pool, &via->sent_by.host, "bigbox3.site3.atlanta.com");
+    pj_strdup2(pool, &via->branch_param, "z9hG4bK77ef4c2312983.1");
+
+    /* "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n"
+	" ;received=192.0.2.1\r\n" */
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    pj_strdup2(pool, &via->transport, "UDP");
+    pj_strdup2(pool, &via->sent_by.host, "pc33.atlanta.com");
+    pj_strdup2(pool, &via->branch_param, "z9hG4bKnashds8");
+    pj_strdup2(pool, &via->recvd_param, "192.0.2.1");
+
+
+    /* "Via: SIP/2.0/UDP 10.2.1.1, */ 
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    pj_strdup2(pool, &via->transport, "UDP");
+    pj_strdup2(pool, &via->sent_by.host, "10.2.1.1");
+    
+    
+    /*SIP/2.0/TCP 192.168.1.1\n" */
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    pj_strdup2(pool, &via->transport, "TCP");
+    pj_strdup2(pool, &via->sent_by.host, "192.168.1.1");
+
+    /* "Organization: \r" */
+    str.ptr = "Organization";
+    str.slen = 12;
+    generic = pjsip_generic_string_hdr_create(pool, &str);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic);
+    generic->hvalue.ptr = NULL;
+    generic->hvalue.slen = 0;
+
+    /* "Max-Forwards: 70\n" */
+    str.ptr = "Max-Forwards";
+    str.slen = 12;
+    generic = pjsip_generic_string_hdr_create(pool, &str);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic);
+    str.ptr = "70";
+    str.slen = 2;
+    generic->hvalue = str;
+
+    /* "X-Header: \r\n" */
+    str.ptr = "X-Header";
+    str.slen = 8;
+    generic = pjsip_generic_string_hdr_create(pool, &str);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic);
+    str.ptr = NULL;
+    str.slen = 0;
+    generic->hvalue = str;
+
+    return msg;
+}
+
+static pjsip_msg *create_msg1(pj_pool_t *pool)
+{
+    pjsip_via_hdr *via;
+    pjsip_route_hdr *route;
+    pjsip_name_addr *name_addr;
+    pjsip_url *url;
+    pjsip_max_forwards_hdr *max_fwd;
+    pjsip_to_hdr *to;
+    pjsip_from_hdr *from;
+    pjsip_contact_hdr *contact;
+    pjsip_ctype_hdr *ctype;
+    pjsip_cid_hdr *cid;
+    pjsip_clen_hdr *clen;
+    pjsip_cseq_hdr *cseq;
+    pjsip_msg *msg = pjsip_msg_create(pool, PJSIP_RESPONSE_MSG);
+    pjsip_msg_body *body;
+
+    //"SIP/2.0 200 OK\r\n"
+    msg->line.status.code = 200;
+    msg->line.status.reason = pj_str("OK");
+
+    //"Via: SIP/2.0/SCTP server10.biloxi.com;branch=z9hG4bKnashds8;rport;received=192.0.2.1\r\n"
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    via->transport = pj_str("SCTP");
+    via->sent_by.host = pj_str("server10.biloxi.com");
+    via->branch_param = pj_str("z9hG4bKnashds8");
+    via->rport_param = 0;
+    via->recvd_param = pj_str("192.0.2.1");
+
+    //"Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2\r\n"
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    via->transport = pj_str("UDP");
+    via->sent_by.host = pj_str("bigbox3.site3.atlanta.com");
+    via->branch_param = pj_str("z9hG4bK77ef4c2312983.1");
+    via->recvd_param = pj_str("192.0.2.2");
+
+    //"Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds ;received=192.0.2.3\r\n"
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    via->transport = pj_str("UDP");
+    via->sent_by.host = pj_str("pc33.atlanta.com");
+    via->branch_param = pj_str("z9hG4bK776asdhds");
+    via->recvd_param = pj_str("192.0.2.3");
+
+    //"Route: <sip:proxy.sipprovider.com>\r\n"
+    route = pjsip_route_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)route);
+    url = pjsip_url_create(pool, PJ_FALSE);
+    route->name_addr.uri = (pjsip_uri*)url;
+    url->host = pj_str("proxy.sipprovider.com");
+    
+    //"Route: <sip:proxy.supersip.com:5060>\r\n"
+    route = pjsip_route_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)route);
+    url = pjsip_url_create(pool, PJ_FALSE);
+    route->name_addr.uri = (pjsip_uri*)url;
+    url->host = pj_str("proxy.supersip.com");
+    url->port = 5060;
+
+    //"Max-Forwards: 70\r\n"
+    max_fwd = pjsip_max_forwards_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)max_fwd);
+    max_fwd->ivalue = 70;
+
+    //"To: Bob <sip:bob@biloxi.com>;tag=a6c85cf\r\n"
+    to = pjsip_to_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)to);
+    name_addr = pjsip_name_addr_create(pool);
+    name_addr->display = pj_str("Bob");
+    to->uri = (pjsip_uri*)name_addr;
+    url = pjsip_url_create(pool, PJ_FALSE);
+    name_addr->uri = (pjsip_uri*)url;
+    url->user = pj_str("bob");
+    url->host = pj_str("biloxi.com");
+    to->tag = pj_str("a6c85cf");
+
+    //"From: Alice <sip:alice@atlanta.com>;tag=1928301774\r\n"
+    from = pjsip_from_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)from);
+    name_addr = pjsip_name_addr_create(pool);
+    name_addr->display = pj_str("Alice");
+    from->uri = (pjsip_uri*)name_addr;
+    url = pjsip_url_create(pool, PJ_FALSE);
+    name_addr->uri = (pjsip_uri*)url;
+    url->user = pj_str("alice");
+    url->host = pj_str("atlanta.com");
+    from->tag = pj_str("1928301774");
+
+    //"Call-ID: a84b4c76e66710@pc33.atlanta.com\r\n"
+    cid = pjsip_cid_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)cid);
+    cid->id = pj_str("a84b4c76e66710@pc33.atlanta.com");
+
+    //"CSeq: 314159 INVITE\r\n"
+    cseq = pjsip_cseq_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)cseq);
+    cseq->cseq = 314159;
+    pjsip_method_set(&cseq->method, PJSIP_INVITE_METHOD);
+
+    //"Contact: <sips:bob@192.0.2.4>\r\n"
+    contact = pjsip_contact_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact);
+    name_addr = pjsip_name_addr_create(pool);
+    contact->uri = (pjsip_uri*)name_addr;
+    url = pjsip_url_create(pool, PJ_TRUE);
+    name_addr->uri = (pjsip_uri*)url;
+    url->user = pj_str("bob");
+    url->host = pj_str("192.0.2.4");
+
+    //"Content-Type: application/sdp\r\n"
+    ctype = pjsip_ctype_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)ctype);
+    ctype->media.type = pj_str("application");
+    ctype->media.subtype = pj_str("sdp");
+
+    //"Content-Length: 150\r\n"
+    clen = pjsip_clen_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)clen);
+    clen->len = 150;
+
+    // Body
+    body = pj_pool_zalloc(pool, sizeof(*body));
+    msg->body = body;
+    body->content_type.type = pj_str("application");
+    body->content_type.subtype = pj_str("sdp");
+    body->data = 
+	"v=0\r\n"
+	"o=alice 53655765 2353687637 IN IP4 pc33.atlanta.com\r\n"
+	"s=-\r\n"
+	"t=0 0\r\n"
+	"c=IN IP4 pc33.atlanta.com\r\n"
+	"m=audio 3456 RTP/AVP 0 1 3 99\r\n"
+	"a=rtpmap:0 PCMU/8000\r\n";
+    body->len = pj_native_strlen(body->data);
+    body->print_body = &pjsip_print_text_body;
+
+    return msg;
+}
+
+/*****************************************************************************/
+
+pj_status_t msg_test(void)
+{
+    pj_status_t status;
+    pj_pool_t *pool;
+    int i, loop;
+    pj_timestamp zero;
+    pj_time_val elapsed;
+    pj_highprec_t avg_detect, avg_parse, avg_print, kbytes;
+
+    PJ_LOG(3,("", "  simple test.."));
+    for (i=0; i<PJ_ARRAY_SIZE(test_array); ++i) {
+	pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE);
+	status = test_entry( pool, &test_array[i] );
+	pjsip_endpt_destroy_pool(endpt, pool);
+
+	if (status != PJ_SUCCESS)
+	    return status;
+    }
+
+    PJ_LOG(3,("", "  benchmarking.."));
+    detect_len = parse_len = print_len = 0;
+    zero.u64 = detect_time.u64 = parse_time.u64 = print_time.u64 = 0;
+    
+    for (loop=0; loop<LOOP; ++loop) {
+	for (i=0; i<PJ_ARRAY_SIZE(test_array); ++i) {
+	    pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE);
+	    status = test_entry( pool, &test_array[i] );
+	    pjsip_endpt_destroy_pool(endpt, pool);
+
+	    if (status != PJ_SUCCESS)
+		return status;
+	}
+    }
+
+    kbytes = detect_len;
+    pj_highprec_mod(kbytes, 1000000);
+    pj_highprec_div(kbytes, 100000);
+    elapsed = pj_elapsed_time(&zero, &detect_time);
+    avg_detect = pj_elapsed_usec(&zero, &detect_time);
+    pj_highprec_mul(avg_detect, AVERAGE_MSG_LEN);
+    pj_highprec_div(avg_detect, detect_len);
+    avg_detect = 1000000 / avg_detect;
+
+    PJ_LOG(3,("", "    %u.%u MB detected in %d.%03ds (avg=%d msg detection/sec)", 
+		  (unsigned)(detect_len/1000000), (unsigned)kbytes,
+		  elapsed.sec, elapsed.msec,
+		  (unsigned)avg_detect));
+
+    kbytes = parse_len;
+    pj_highprec_mod(kbytes, 1000000);
+    pj_highprec_div(kbytes, 100000);
+    elapsed = pj_elapsed_time(&zero, &parse_time);
+    avg_parse = pj_elapsed_usec(&zero, &parse_time);
+    pj_highprec_mul(avg_parse, AVERAGE_MSG_LEN);
+    pj_highprec_div(avg_parse, parse_len);
+    avg_parse = 1000000 / avg_parse;
+
+    PJ_LOG(3,("", "    %u.%u MB parsed in %d.%03ds (avg=%d msg parsing/sec)", 
+		  (unsigned)(parse_len/1000000), (unsigned)kbytes,
+		  elapsed.sec, elapsed.msec,
+		  (unsigned)avg_parse));
+
+    kbytes = print_len;
+    pj_highprec_mod(kbytes, 1000000);
+    pj_highprec_div(kbytes, 100000);
+    elapsed = pj_elapsed_time(&zero, &print_time);
+    avg_print = pj_elapsed_usec(&zero, &print_time);
+    pj_highprec_mul(avg_print, AVERAGE_MSG_LEN);
+    pj_highprec_div(avg_print, print_len);
+    avg_print = 1000000 / avg_print;
+
+    PJ_LOG(3,("", "    %u.%u MB printed in %d.%03ds (avg=%d msg print/sec)", 
+		  (unsigned)(print_len/1000000), (unsigned)kbytes,
+		  elapsed.sec, elapsed.msec,
+		  (unsigned)avg_print));
+
+    return status;
+}
+
+/*****************************************************************************/
Index: pjproject/trunk/pjsip/src/test-pjsip/uri.c
===================================================================
--- pjproject/trunk/pjsip/src/test-pjsip/uri.c	(revision 104)
+++ 	(revision )
@@ -1,876 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
- */
-#include "test.h"
-#include <pjsip_core.h>
-#include <pjlib.h>
-
-
-#define ALPHANUM    "abcdefghijklmnopqrstuvwxyz" \
-		    "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
-		    "0123456789"
-#define MARK	    "-_.!~*'()"
-#define USER_CHAR   ALPHANUM MARK "&=+$,;?/"
-#define PASS_CHAR   ALPHANUM MARK "&=+$,"
-#define PARAM_CHAR  ALPHANUM MARK "[]/:&+$"
-
-#define POOL_SIZE	8000
-#define LOOP_COUNT	10000
-#define AVERAGE_URL_LEN	80
-#define THREAD_COUNT	4
-
-static pj_highprec_t parse_len, print_len, cmp_len;
-static pj_timestamp parse_time, print_time, cmp_time;
-
-
-/* URI creator functions. */
-static pjsip_uri *create_uri0( pj_pool_t *pool );
-static pjsip_uri *create_uri1( pj_pool_t *pool );
-static pjsip_uri *create_uri2( pj_pool_t *pool );
-static pjsip_uri *create_uri3( pj_pool_t *pool );
-static pjsip_uri *create_uri4( pj_pool_t *pool );
-static pjsip_uri *create_uri5( pj_pool_t *pool );
-static pjsip_uri *create_uri6( pj_pool_t *pool );
-static pjsip_uri *create_uri7( pj_pool_t *pool );
-static pjsip_uri *create_uri8( pj_pool_t *pool );
-static pjsip_uri *create_uri9( pj_pool_t *pool );
-static pjsip_uri *create_uri10( pj_pool_t *pool );
-static pjsip_uri *create_uri11( pj_pool_t *pool );
-static pjsip_uri *create_uri12( pj_pool_t *pool );
-static pjsip_uri *create_uri13( pj_pool_t *pool );
-static pjsip_uri *create_uri14( pj_pool_t *pool );
-static pjsip_uri *create_uri15( pj_pool_t *pool );
-static pjsip_uri *create_uri16( pj_pool_t *pool );
-static pjsip_uri *create_uri17( pj_pool_t *pool );
-static pjsip_uri *create_uri25( pj_pool_t *pool );
-static pjsip_uri *create_uri26( pj_pool_t *pool );
-static pjsip_uri *create_uri27( pj_pool_t *pool );
-static pjsip_uri *create_uri28( pj_pool_t *pool );
-static pjsip_uri *create_uri29( pj_pool_t *pool );
-static pjsip_uri *create_uri30( pj_pool_t *pool );
-static pjsip_uri *create_uri31( pj_pool_t *pool );
-static pjsip_uri *create_uri32( pj_pool_t *pool );
-static pjsip_uri *create_uri33( pj_pool_t *pool );
-static pjsip_uri *create_uri34( pj_pool_t *pool );
-static pjsip_uri *create_uri35( pj_pool_t *pool );
-static pjsip_uri *create_dummy( pj_pool_t *pool );
-
-#define ERR_NOT_EQUAL	-1001
-#define ERR_SYNTAX_ERR	-1002
-
-struct uri_test
-{
-    pj_status_t	     status;
-    char	     str[PJSIP_MAX_URL_SIZE];
-    pjsip_uri	    *(*creator)(pj_pool_t *pool);
-    const char	    *printed;
-    pj_size_t	     len;
-} uri_test_array[] = 
-{
-    {
-	PJ_SUCCESS,
-	"sip:localhost",
-	&create_uri0
-    },
-    {
-	PJ_SUCCESS,
-	"sip:user@localhost",
-	&create_uri1
-    },
-    {
-	PJ_SUCCESS,
-	"sip:user:password@localhost:5060",
-	&create_uri2,    },
-    {
-	/* Port is specified should not match unspecified port. */
-	ERR_NOT_EQUAL,
-	"sip:localhost:5060",
-	&create_uri3
-    },
-    {
-	/* All recognized parameters. */
-	PJ_SUCCESS,
-	"sip:localhost;transport=tcp;user=ip;ttl=255;lr;maddr=127.0.0.1;method=ACK",
-	&create_uri4
-    },
-    {
-	/* Params mixed with other params and header params. */
-	PJ_SUCCESS,
-	"sip:localhost;pickup=hurry;user=phone;message=I%20am%20sorry"
-	"?Subject=Hello%20There&Server=SIP%20Server",
-	&create_uri5
-    },
-    {
-	/* SIPS. */
-	PJ_SUCCESS,
-	"sips:localhost",
-	&create_uri6,
-    },
-    {
-	/* Name address */
-	PJ_SUCCESS,
-	"<sip:localhost>",
-	&create_uri7
-    },
-    {
-	/* Name address with display name and SIPS scheme with some redundant
-	 * whitespaced.
-	 */
-	PJ_SUCCESS,
-	"  Power Administrator  <sips:localhost>",
-	&create_uri8
-    },
-    {
-	/* Name address. */
-	PJ_SUCCESS,
-	" \"User\" <sip:user@localhost:5071>",
-	&create_uri9
-    },
-    {
-	/* Escaped sequence in display name (display=Strange User\"\\\"). */
-	PJ_SUCCESS,
-	" \"Strange User\\\"\\\\\\\"\" <sip:localhost>",
-	&create_uri10,
-    },
-    {
-	/* Errorneous escaping in display name. */
-	ERR_SYNTAX_ERR,
-	" \"Rogue User\\\" <sip:localhost>",
-	&create_uri11,
-    },
-    {
-	/* Dangling quote in display name, but that should be OK. */
-	PJ_SUCCESS,
-	"Strange User\" <sip:localhost>",
-	&create_uri12,
-    },
-    {
-	/* Special characters in parameter value must be quoted. */
-	PJ_SUCCESS,
-	"sip:localhost;pvalue=\"hello world\"",
-	&create_uri13,
-    },
-    {
-	/* Excercise strange character sets allowed in display, user, password,
-	 * host, and port. 
-	 */
-	PJ_SUCCESS,
-	"This is -. !% *_+`'~ me <sip:a19A&=+$,;?/%2c:%40a&Zz=+$,@"
-	"my_proxy09.MY-domain.com:9801>",
-	&create_uri14,
-    },
-    {
-	/* Another excercise to the allowed character sets to the hostname. */
-	PJ_SUCCESS,
-	"sip:" ALPHANUM "-_.com",
-	&create_uri15,
-    },
-    {
-	/* Another excercise to the allowed character sets to the username 
-	 * and password.
-	 */
-	PJ_SUCCESS,
-	"sip:" USER_CHAR ":" PASS_CHAR "@host",
-	&create_uri16,
-    },
-    {
-	/* Excercise to the pname and pvalue, and mixup of other-param
-	 * between 'recognized' params.
-	 */
-	PJ_SUCCESS,
-	"sip:host;user=ip;" PARAM_CHAR "%21=" PARAM_CHAR "%21"
-	";lr;other=1;transport=sctp;other2",
-	&create_uri17,
-    },
-    {
-	/* 18: This should trigger syntax error. */
-	ERR_SYNTAX_ERR,
-	"sip:",
-	&create_dummy,
-    },
-    {
-	/* 19: Syntax error: whitespace after scheme. */
-	ERR_SYNTAX_ERR,
-	"sip :host",
-	&create_dummy,
-    },
-    {
-	/* 20: Syntax error: whitespace before hostname. */
-	ERR_SYNTAX_ERR,
-	"sip: host",
-	&create_dummy,
-    },
-    {
-	/* 21: Syntax error: invalid port. */
-	ERR_SYNTAX_ERR,
-	"sip:user:password",
-	&create_dummy,
-    },
-    {
-	/* 22: Syntax error: no host. */
-	ERR_SYNTAX_ERR,
-	"sip:user@",
-	&create_dummy,
-    },
-    {
-	/* 23: Syntax error: no user/host. */
-	ERR_SYNTAX_ERR,
-	"sip:@",
-	&create_dummy,
-    },
-    {
-	/* 24: Syntax error: empty string. */
-	ERR_SYNTAX_ERR,
-	"",
-	&create_dummy,
-    },
-    {
-	/* 25: Simple tel: URI with global context */
-	PJ_SUCCESS,
-	"tel:+1-201-555-0123",
-	&create_uri25,
-	"tel:+1-201-555-0123"
-    },
-    {
-	/* 26: Simple tel: URI with local context */
-	PJ_SUCCESS,
-	"tel:7042;phone-context=example.com",
-	&create_uri26,
-	"tel:7042;phone-context=example.com"
-    },
-    {
-	/* 27: Simple tel: URI with local context */
-	PJ_SUCCESS,
-	"tel:863-1234;phone-context=+1-914-555",
-	&create_uri27,
-	"tel:863-1234;phone-context=+1-914-555"
-    },
-    {
-	/* 28: Comparison between local and global number */
-	ERR_NOT_EQUAL,
-	"tel:+1",
-	&create_uri28,
-	"tel:+1"
-    },
-    {
-	/* 29: tel: with some visual chars and spaces */
-	PJ_SUCCESS,
-	"tel:(44).1234-*#+Deaf",
-	&create_uri29,
-	"tel:(44).1234-*#+Deaf"
-    },
-    {
-	/* 30: isub parameters */
-	PJ_SUCCESS,
-	"tel:+1;isub=/:@&$,-_.!~*'()[]/:&$aA1%21+=",
-	&create_uri30,
-	"tel:+1;isub=/:@&$,-_.!~*'()[]/:&$aA1%21+%3d"
-    },
-    {
-	/* 31: extension number parsing and encoding */
-	PJ_SUCCESS,
-	"tel:+1;ext=+123",
-	&create_uri31,
-	"tel:+1;ext=%2b123"
-    },
-    {
-	/* 32: context parameter parsing and encoding */
-	PJ_SUCCESS,
-	"tel:911;phone-context=+1-911",
-	&create_uri32,
-	"tel:911;phone-context=+1-911"
-    },
-    {
-	/* 33: case-insensitive comparison */
-	PJ_SUCCESS,
-	"tel:911;phone-context=emergency.example.com",
-	&create_uri33,
-	"tel:911;phone-context=emergency.example.com"
-    },
-    {
-	/* 34: parameter only appears in one URL */
-	ERR_NOT_EQUAL,
-	"tel:911;p1=p1;p2=p2",
-	&create_uri34,
-	"tel:911;p1=p1;p2=p2"
-    },
-    
-};
-
-static pjsip_uri *create_uri0(pj_pool_t *pool)
-{
-    /* "sip:localhost" */
-    pjsip_url *url = pjsip_url_create(pool, 0);
-
-    pj_strdup2(pool, &url->host, "localhost");
-    return (pjsip_uri*)url;
-}
-
-static pjsip_uri *create_uri1(pj_pool_t *pool)
-{
-    /* "sip:user@localhost" */
-    pjsip_url *url = pjsip_url_create(pool, 0);
-
-    pj_strdup2( pool, &url->user, "user");
-    pj_strdup2( pool, &url->host, "localhost");
-
-    return (pjsip_uri*) url;
-}
-
-static pjsip_uri *create_uri2(pj_pool_t *pool)
-{
-    /* "sip:user:password@localhost:5060" */
-    pjsip_url *url = pjsip_url_create(pool, 0);
-
-    pj_strdup2( pool, &url->user, "user");
-    pj_strdup2( pool, &url->passwd, "password");
-    pj_strdup2( pool, &url->host, "localhost");
-    url->port = 5060;
-
-    return (pjsip_uri*) url;
-}
-
-static pjsip_uri *create_uri3(pj_pool_t *pool)
-{
-    /* Like: "sip:localhost:5060", but without the port. */
-    pjsip_url *url = pjsip_url_create(pool, 0);
-
-    pj_strdup2(pool, &url->host, "localhost");
-    return (pjsip_uri*)url;
-}
-
-static pjsip_uri *create_uri4(pj_pool_t *pool)
-{
-    /* "sip:localhost;transport=tcp;user=ip;ttl=255;lr;maddr=127.0.0.1;method=ACK" */
-    pjsip_url *url = pjsip_url_create(pool, 0);
-
-    pj_strdup2(pool, &url->host, "localhost");
-    pj_strdup2(pool, &url->transport_param, "tcp");
-    pj_strdup2(pool, &url->user_param, "ip");
-    url->ttl_param = 255;
-    url->lr_param = 1;
-    pj_strdup2(pool, &url->maddr_param, "127.0.0.1");
-    pj_strdup2(pool, &url->method_param, "ACK");
-
-    return (pjsip_uri*)url;
-}
-
-#define param_add(list,pname,pvalue)  \
-	do { \
-	    pjsip_param *param; \
-	    param=pj_pool_alloc(pool, sizeof(pjsip_param)); \
-	    param->name = pj_str(pname); \
-	    param->value = pj_str(pvalue); \
-	    pj_list_insert_before(&list, param); \
-	} while (0)
-
-static pjsip_uri *create_uri5(pj_pool_t *pool)
-{
-    /* "sip:localhost;pickup=hurry;user=phone;message=I%20am%20sorry"
-       "?Subject=Hello%20There&Server=SIP%20Server" 
-     */
-    pjsip_url *url = pjsip_url_create(pool, 0);
-
-    pj_strdup2(pool, &url->host, "localhost");
-    pj_strdup2(pool, &url->user_param, "phone");
-
-    //pj_strdup2(pool, &url->other_param, ";pickup=hurry;message=I%20am%20sorry");
-    param_add(url->other_param, "pickup", "hurry");
-    param_add(url->other_param, "message", "I am sorry");
-
-    //pj_strdup2(pool, &url->header_param, "?Subject=Hello%20There&Server=SIP%20Server");
-    param_add(url->header_param, "Subject", "Hello There");
-    param_add(url->header_param, "Server", "SIP Server");
-    return (pjsip_uri*)url;
-
-}
-
-static pjsip_uri *create_uri6(pj_pool_t *pool)
-{
-    /* "sips:localhost" */
-    pjsip_url *url = pjsip_url_create(pool, 1);
-
-    pj_strdup2(pool, &url->host, "localhost");
-    return (pjsip_uri*)url;
-}
-
-static pjsip_uri *create_uri7(pj_pool_t *pool)
-{
-    /* "<sip:localhost>" */
-    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
-    pjsip_url *url;
-
-    url = pjsip_url_create(pool, 0);
-    name_addr->uri = (pjsip_uri*) url;
-
-    pj_strdup2(pool, &url->host, "localhost");
-    return (pjsip_uri*)name_addr;
-}
-
-static pjsip_uri *create_uri8(pj_pool_t *pool)
-{
-    /* "  Power Administrator <sips:localhost>" */
-    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
-    pjsip_url *url;
-
-    url = pjsip_url_create(pool, 1);
-    name_addr->uri = (pjsip_uri*) url;
-
-    pj_strdup2(pool, &name_addr->display, "Power Administrator");
-    pj_strdup2(pool, &url->host, "localhost");
-    return (pjsip_uri*)name_addr;
-}
-
-static pjsip_uri *create_uri9(pj_pool_t *pool)
-{
-    /* " \"User\" <sip:user@localhost:5071>" */
-    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
-    pjsip_url *url;
-
-    url = pjsip_url_create(pool, 0);
-    name_addr->uri = (pjsip_uri*) url;
-
-    pj_strdup2(pool, &name_addr->display, "User");
-    pj_strdup2(pool, &url->user, "user");
-    pj_strdup2(pool, &url->host, "localhost");
-    url->port = 5071;
-    return (pjsip_uri*)name_addr;
-}
-
-static pjsip_uri *create_uri10(pj_pool_t *pool)
-{
-    /* " \"Strange User\\\"\\\\\\\"\" <sip:localhost>" */
-    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
-    pjsip_url *url;
-
-    url = pjsip_url_create(pool, 0);
-    name_addr->uri = (pjsip_uri*) url;
-
-    pj_strdup2(pool, &name_addr->display, "Strange User\\\"\\\\\\\"");
-    pj_strdup2(pool, &url->host, "localhost");
-    return (pjsip_uri*)name_addr;
-}
-
-static pjsip_uri *create_uri11(pj_pool_t *pool)
-{
-    /* " \"Rogue User\\\" <sip:localhost>" */
-    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
-    pjsip_url *url;
-
-    url = pjsip_url_create(pool, 0);
-    name_addr->uri = (pjsip_uri*) url;
-
-    pj_strdup2(pool, &name_addr->display, "Rogue User\\");
-    pj_strdup2(pool, &url->host, "localhost");
-    return (pjsip_uri*)name_addr;
-}
-
-static pjsip_uri *create_uri12(pj_pool_t *pool)
-{
-    /* "Strange User\" <sip:localhost>" */
-    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
-    pjsip_url *url;
-
-    url = pjsip_url_create(pool, 0);
-    name_addr->uri = (pjsip_uri*) url;
-
-    pj_strdup2(pool, &name_addr->display, "Strange User\"");
-    pj_strdup2(pool, &url->host, "localhost");
-    return (pjsip_uri*)name_addr;
-}
-
-static pjsip_uri *create_uri13(pj_pool_t *pool)
-{
-    /* "sip:localhost;pvalue=\"hello world\"" */
-    pjsip_url *url;
-    url = pjsip_url_create(pool, 0);
-    pj_strdup2(pool, &url->host, "localhost");
-    //pj_strdup2(pool, &url->other_param, ";pvalue=\"hello world\"");
-    param_add(url->other_param, "pvalue", "hello world");
-    return (pjsip_uri*)url;
-}
-
-static pjsip_uri *create_uri14(pj_pool_t *pool)
-{
-    /* "This is -. !% *_+`'~ me <sip:a19A&=+$,;?/%2c:%40a&Zz=+$,@my_proxy09.my-domain.com:9801>" */
-    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
-    pjsip_url *url;
-
-    url = pjsip_url_create(pool, 0);
-    name_addr->uri = (pjsip_uri*) url;
-
-    pj_strdup2(pool, &name_addr->display, "This is -. !% *_+`'~ me");
-    pj_strdup2(pool, &url->user, "a19A&=+$,;?/,");
-    pj_strdup2(pool, &url->passwd, "@a&Zz=+$,");
-    pj_strdup2(pool, &url->host, "my_proxy09.MY-domain.com");
-    url->port = 9801;
-    return (pjsip_uri*)name_addr;
-}
-
-static pjsip_uri *create_uri15(pj_pool_t *pool)
-{
-    /* "sip:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.com" */
-    pjsip_url *url;
-    url = pjsip_url_create(pool, 0);
-    pj_strdup2(pool, &url->host, ALPHANUM "-_.com");
-    return (pjsip_uri*)url;
-}
-
-static pjsip_uri *create_uri16(pj_pool_t *pool)
-{
-    /* "sip:" USER_CHAR ":" PASS_CHAR "@host" */
-    pjsip_url *url;
-    url = pjsip_url_create(pool, 0);
-    pj_strdup2(pool, &url->user, USER_CHAR);
-    pj_strdup2(pool, &url->passwd, PASS_CHAR);
-    pj_strdup2(pool, &url->host, "host");
-    return (pjsip_uri*)url;
-}
-
-static pjsip_uri *create_uri17(pj_pool_t *pool)
-{
-    /* "sip:host;user=ip;" PARAM_CHAR "%21=" PARAM_CHAR "%21;lr;other=1;transport=sctp;other2" */
-    pjsip_url *url;
-    url = pjsip_url_create(pool, 0);
-    pj_strdup2(pool, &url->host, "host");
-    pj_strdup2(pool, &url->user_param, "ip");
-    pj_strdup2(pool, &url->transport_param, "sctp");
-    param_add(url->other_param, PARAM_CHAR "!", PARAM_CHAR "!");
-    param_add(url->other_param, "other", "1");
-    param_add(url->other_param, "other2", "");
-    url->lr_param = 1;
-    return (pjsip_uri*)url;
-}
-
-
-static pjsip_uri *create_uri25(pj_pool_t *pool)
-{
-    /* "tel:+1-201-555-0123" */
-    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
-
-    uri->number = pj_str("+1-201-555-0123");
-    return (pjsip_uri*)uri;
-}
-
-static pjsip_uri *create_uri26(pj_pool_t *pool)
-{
-    /* tel:7042;phone-context=example.com */
-    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
-
-    uri->number = pj_str("7042");
-    uri->context = pj_str("example.com");
-    return (pjsip_uri*)uri;
-}
-
-static pjsip_uri *create_uri27(pj_pool_t *pool)
-{
-    /* "tel:863-1234;phone-context=+1-914-555" */
-    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
-
-    uri->number = pj_str("863-1234");
-    uri->context = pj_str("+1-914-555");
-    return (pjsip_uri*)uri;
-}
-
-/* "tel:1" */
-static pjsip_uri *create_uri28(pj_pool_t *pool)
-{
-    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
-
-    uri->number = pj_str("1");
-    return (pjsip_uri*)uri;
-}
-
-/* "tel:(44).1234-*#+Deaf" */
-static pjsip_uri *create_uri29(pj_pool_t *pool)
-{
-    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
-
-    uri->number = pj_str("(44).1234-*#+Deaf");
-    return (pjsip_uri*)uri;    
-}
-
-/* "tel:+1;isub=/:@&$,-_.!~*'()[]/:&$aA1%21+=" */
-static pjsip_uri *create_uri30(pj_pool_t *pool)
-{
-    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
-
-    uri->number = pj_str("+1");
-    uri->isub_param = pj_str("/:@&$,-_.!~*'()[]/:&$aA1%21+=");
-    return (pjsip_uri*)uri;    
-}
-
-/* "tel:+1;ext=+123" */
-static pjsip_uri *create_uri31(pj_pool_t *pool)
-{
-    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
-
-    uri->number = pj_str("+1");
-    uri->ext_param = pj_str("+123");
-    return (pjsip_uri*)uri;    
-}
-
-/* "tel:911;phone-context=+1-911" */
-static pjsip_uri *create_uri32(pj_pool_t *pool)
-{
-    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
-
-    uri->number = pj_str("911");
-    uri->context = pj_str("+1-911");
-    return (pjsip_uri*)uri;    
-}
-
-/* "tel:911;phone-context=emergency.example.com" */
-static pjsip_uri *create_uri33(pj_pool_t *pool)
-{
-    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
-
-    uri->number = pj_str("911");
-    uri->context = pj_str("EMERGENCY.EXAMPLE.COM");
-    return (pjsip_uri*)uri;    
-}
-
-/* "tel:911;p1=p1;p2=p2" */
-static pjsip_uri *create_uri34(pj_pool_t *pool)
-{
-    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
-    pjsip_param *p;
-
-    uri->number = pj_str("911");
-    
-    p = pj_pool_alloc(pool, sizeof(*p));
-    p->name = p->value = pj_str("p1");
-    pj_list_insert_before(&uri->other_param, p);
-
-    return (pjsip_uri*)uri;    
-}
-
-
-static pjsip_uri *create_dummy(pj_pool_t *pool)
-{
-    PJ_UNUSED_ARG(pool);
-    return NULL;
-}
-
-/*****************************************************************************/
-
-/*
- * Test one test entry.
- */
-static pj_status_t do_uri_test(pj_pool_t *pool, struct uri_test *entry)
-{
-    pj_status_t status;
-    int len;
-    pjsip_uri *parsed_uri, *ref_uri;
-    pj_str_t s1 = {NULL, 0}, s2 = {NULL, 0};
-    pj_timestamp t1, t2;
-
-    entry->len = pj_native_strlen(entry->str);
-
-    /* Parse URI text. */
-    pj_get_timestamp(&t1);
-    parse_len = parse_len + entry->len;
-    parsed_uri = pjsip_parse_uri(pool, entry->str, entry->len, 0);
-    if (!parsed_uri) {
-	/* Parsing failed. If the entry says that this is expected, then
-	 * return OK.
-	 */
-	status = entry->status==ERR_SYNTAX_ERR ? PJ_SUCCESS : -10;
-	if (status != 0) {
-	    PJ_LOG(3,("", "   uri parse error!\n"
-			  "   uri='%s'\n",
-			  entry->str));
-	}
-	goto on_return;
-    }
-    pj_get_timestamp(&t2);
-    pj_sub_timestamp(&t2, &t1);
-    pj_add_timestamp(&parse_time, &t2);
-
-    /* Create the reference URI. */
-    ref_uri = entry->creator(pool);
-
-    /* Print both URI. */
-    s1.ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
-    s2.ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
-
-    pj_get_timestamp(&t1);
-    len = pjsip_uri_print( PJSIP_URI_IN_OTHER, parsed_uri, s1.ptr, PJSIP_MAX_URL_SIZE);
-    if (len < 1) {
-	status = -20;
-	goto on_return;
-    }
-    s1.ptr[len] = '\0';
-    s1.slen = len;
-
-    print_len = print_len + len;
-    pj_get_timestamp(&t2);
-    pj_sub_timestamp(&t2, &t1);
-    pj_add_timestamp(&print_time, &t2);
-
-    len = pjsip_uri_print( PJSIP_URI_IN_OTHER, ref_uri, s2.ptr, PJSIP_MAX_URL_SIZE);
-    if (len < 1) {
-	status = -30;
-	goto on_return;
-    }
-    s2.ptr[len] = '\0';
-    s2.slen = len;
-
-    /* Full comparison of parsed URI with reference URI. */
-    pj_get_timestamp(&t1);
-    status = pjsip_uri_cmp(PJSIP_URI_IN_OTHER, parsed_uri, ref_uri);
-    if (status != 0) {
-	/* Not equal. See if this is the expected status. */
-	status = entry->status==ERR_NOT_EQUAL ? PJ_SUCCESS : -40;
-	if (status != 0) {
-	    PJ_LOG(3,("", "   uri comparison mismatch, status=%d:\n"
-			  "    uri1='%s'\n"
-			  "    uri2='%s'",
-			  status, s1.ptr, s2.ptr));
-	}
-	goto on_return;
-
-    } else {
-	/* Equal. See if this is the expected status. */
-	status = entry->status==PJ_SUCCESS ? PJ_SUCCESS : -50;
-	if (status != PJ_SUCCESS) {
-	    goto on_return;
-	}
-    }
-
-    cmp_len = cmp_len + len;
-    pj_get_timestamp(&t2);
-    pj_sub_timestamp(&t2, &t1);
-    pj_add_timestamp(&cmp_time, &t2);
-
-    /* Compare text. */
-    if (entry->printed) {
-	if (pj_strcmp2(&s1, entry->printed) != 0) {
-	    /* Not equal. */
-	    PJ_LOG(3,("", "   uri print mismatch:\n"
-			  "    printed='%s'\n"
-			  "    expectd='%s'",
-			  s1.ptr, entry->printed));
-	    status = -60;
-	}
-    } else {
-	if (pj_strcmp(&s1, &s2) != 0) {
-	    /* Not equal. */
-	    PJ_LOG(3,("", "   uri print mismatch:\n"
-			  "    uri1='%s'\n"
-			  "    uri2='%s'",
-			  s1.ptr, s2.ptr));
-	    status = -70;
-	}
-    }
-
-on_return:
-    return status;
-}
-
-pj_status_t uri_test()
-{
-    unsigned i, loop;
-    pj_pool_t *pool;
-    pj_status_t status;
-    pj_timestamp zero;
-    pj_time_val elapsed;
-    pj_highprec_t avg_parse, avg_print, avg_cmp, kbytes;
-
-    zero.u32.hi = zero.u32.lo = 0;
-
-    PJ_LOG(3,("", "  simple test"));
-    pool = pjsip_endpt_create_pool(endpt, "", POOL_SIZE, POOL_SIZE);
-    for (i=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) {
-	status = do_uri_test(pool, &uri_test_array[i]);
-	if (status != PJ_SUCCESS) {
-	    PJ_LOG(3,("uri_test", "  error %d when testing entry %d",
-		      status, i));
-	    goto on_return;
-	}
-    }
-    pjsip_endpt_destroy_pool(endpt, pool);
-
-    PJ_LOG(3,("", "  benchmarking..."));
-    parse_len = print_len = cmp_len = 0;
-    parse_time.u32.hi = parse_time.u32.lo = 0;
-    print_time.u32.hi = print_time.u32.lo = 0;
-    cmp_time.u32.hi = cmp_time.u32.lo = 0;
-    for (loop=0; loop<LOOP_COUNT; ++loop) {
-	pool = pjsip_endpt_create_pool(endpt, "", POOL_SIZE, POOL_SIZE);
-	for (i=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) {
-	    status = do_uri_test(pool, &uri_test_array[i]);
-	    if (status != PJ_SUCCESS) {
-		PJ_LOG(3,("uri_test", "  error %d when testing entry %d",
-			  status, i));
-		pjsip_endpt_destroy_pool(endpt, pool);
-		goto on_return;
-	    }
-	}
-	pjsip_endpt_destroy_pool(endpt, pool);
-    }
-
-    kbytes = parse_len;
-    pj_highprec_mod(kbytes, 1000000);
-    pj_highprec_div(kbytes, 100000);
-    elapsed = pj_elapsed_time(&zero, &parse_time);
-    avg_parse = pj_elapsed_usec(&zero, &parse_time);
-    pj_highprec_mul(avg_parse, AVERAGE_URL_LEN);
-    pj_highprec_div(avg_parse, parse_len);
-    avg_parse = 1000000 / avg_parse;
-
-    PJ_LOG(3,("", "    %u.%u MB of urls parsed in %d.%03ds (avg=%d urls/sec)", 
-		  (unsigned)(parse_len/1000000), (unsigned)kbytes,
-		  elapsed.sec, elapsed.msec,
-		  (unsigned)avg_parse));
-
-    kbytes = print_len;
-    pj_highprec_mod(kbytes, 1000000);
-    pj_highprec_div(kbytes, 100000);
-    elapsed = pj_elapsed_time(&zero, &print_time);
-    avg_print = pj_elapsed_usec(&zero, &print_time);
-    pj_highprec_mul(avg_print, AVERAGE_URL_LEN);
-    pj_highprec_div(avg_print, parse_len);
-    avg_print = 1000000 / avg_print;
-
-    PJ_LOG(3,("", "    %u.%u MB of urls printed in %d.%03ds (avg=%d urls/sec)", 
-		  (unsigned)(print_len/1000000), (unsigned)kbytes,
-		  elapsed.sec, elapsed.msec,
-		  (unsigned)avg_print));
-
-    kbytes = cmp_len;
-    pj_highprec_mod(kbytes, 1000000);
-    pj_highprec_div(kbytes, 100000);
-    elapsed = pj_elapsed_time(&zero, &cmp_time);
-    avg_cmp = pj_elapsed_usec(&zero, &cmp_time);
-    pj_highprec_mul(avg_cmp, AVERAGE_URL_LEN);
-    pj_highprec_div(avg_cmp, cmp_len);
-    avg_cmp = 1000000 / avg_cmp;
-
-    PJ_LOG(3,("", "    %u.%u MB of urls compared in %d.%03ds (avg=%d urls/sec)", 
-		  (unsigned)(cmp_len/1000000), (unsigned)kbytes,
-		  elapsed.sec, elapsed.msec,
-		  (unsigned)avg_cmp));
-
-    PJ_LOG(3,("", "  multithreaded test"));
-
-
-on_return:
-    return status;
-}
-
Index: pjproject/trunk/pjsip/src/test-pjsip/uri_test.c
===================================================================
--- pjproject/trunk/pjsip/src/test-pjsip/uri_test.c	(revision 105)
+++ pjproject/trunk/pjsip/src/test-pjsip/uri_test.c	(revision 105)
@@ -0,0 +1,876 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pjsip_core.h>
+#include <pjlib.h>
+
+
+#define ALPHANUM    "abcdefghijklmnopqrstuvwxyz" \
+		    "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+		    "0123456789"
+#define MARK	    "-_.!~*'()"
+#define USER_CHAR   ALPHANUM MARK "&=+$,;?/"
+#define PASS_CHAR   ALPHANUM MARK "&=+$,"
+#define PARAM_CHAR  ALPHANUM MARK "[]/:&+$"
+
+#define POOL_SIZE	8000
+#define LOOP_COUNT	10000
+#define AVERAGE_URL_LEN	80
+#define THREAD_COUNT	4
+
+static pj_highprec_t parse_len, print_len, cmp_len;
+static pj_timestamp parse_time, print_time, cmp_time;
+
+
+/* URI creator functions. */
+static pjsip_uri *create_uri0( pj_pool_t *pool );
+static pjsip_uri *create_uri1( pj_pool_t *pool );
+static pjsip_uri *create_uri2( pj_pool_t *pool );
+static pjsip_uri *create_uri3( pj_pool_t *pool );
+static pjsip_uri *create_uri4( pj_pool_t *pool );
+static pjsip_uri *create_uri5( pj_pool_t *pool );
+static pjsip_uri *create_uri6( pj_pool_t *pool );
+static pjsip_uri *create_uri7( pj_pool_t *pool );
+static pjsip_uri *create_uri8( pj_pool_t *pool );
+static pjsip_uri *create_uri9( pj_pool_t *pool );
+static pjsip_uri *create_uri10( pj_pool_t *pool );
+static pjsip_uri *create_uri11( pj_pool_t *pool );
+static pjsip_uri *create_uri12( pj_pool_t *pool );
+static pjsip_uri *create_uri13( pj_pool_t *pool );
+static pjsip_uri *create_uri14( pj_pool_t *pool );
+static pjsip_uri *create_uri15( pj_pool_t *pool );
+static pjsip_uri *create_uri16( pj_pool_t *pool );
+static pjsip_uri *create_uri17( pj_pool_t *pool );
+static pjsip_uri *create_uri25( pj_pool_t *pool );
+static pjsip_uri *create_uri26( pj_pool_t *pool );
+static pjsip_uri *create_uri27( pj_pool_t *pool );
+static pjsip_uri *create_uri28( pj_pool_t *pool );
+static pjsip_uri *create_uri29( pj_pool_t *pool );
+static pjsip_uri *create_uri30( pj_pool_t *pool );
+static pjsip_uri *create_uri31( pj_pool_t *pool );
+static pjsip_uri *create_uri32( pj_pool_t *pool );
+static pjsip_uri *create_uri33( pj_pool_t *pool );
+static pjsip_uri *create_uri34( pj_pool_t *pool );
+static pjsip_uri *create_uri35( pj_pool_t *pool );
+static pjsip_uri *create_dummy( pj_pool_t *pool );
+
+#define ERR_NOT_EQUAL	-1001
+#define ERR_SYNTAX_ERR	-1002
+
+struct uri_test
+{
+    pj_status_t	     status;
+    char	     str[PJSIP_MAX_URL_SIZE];
+    pjsip_uri	    *(*creator)(pj_pool_t *pool);
+    const char	    *printed;
+    pj_size_t	     len;
+} uri_test_array[] = 
+{
+    {
+	PJ_SUCCESS,
+	"sip:localhost",
+	&create_uri0
+    },
+    {
+	PJ_SUCCESS,
+	"sip:user@localhost",
+	&create_uri1
+    },
+    {
+	PJ_SUCCESS,
+	"sip:user:password@localhost:5060",
+	&create_uri2,    },
+    {
+	/* Port is specified should not match unspecified port. */
+	ERR_NOT_EQUAL,
+	"sip:localhost:5060",
+	&create_uri3
+    },
+    {
+	/* All recognized parameters. */
+	PJ_SUCCESS,
+	"sip:localhost;transport=tcp;user=ip;ttl=255;lr;maddr=127.0.0.1;method=ACK",
+	&create_uri4
+    },
+    {
+	/* Params mixed with other params and header params. */
+	PJ_SUCCESS,
+	"sip:localhost;pickup=hurry;user=phone;message=I%20am%20sorry"
+	"?Subject=Hello%20There&Server=SIP%20Server",
+	&create_uri5
+    },
+    {
+	/* SIPS. */
+	PJ_SUCCESS,
+	"sips:localhost",
+	&create_uri6,
+    },
+    {
+	/* Name address */
+	PJ_SUCCESS,
+	"<sip:localhost>",
+	&create_uri7
+    },
+    {
+	/* Name address with display name and SIPS scheme with some redundant
+	 * whitespaced.
+	 */
+	PJ_SUCCESS,
+	"  Power Administrator  <sips:localhost>",
+	&create_uri8
+    },
+    {
+	/* Name address. */
+	PJ_SUCCESS,
+	" \"User\" <sip:user@localhost:5071>",
+	&create_uri9
+    },
+    {
+	/* Escaped sequence in display name (display=Strange User\"\\\"). */
+	PJ_SUCCESS,
+	" \"Strange User\\\"\\\\\\\"\" <sip:localhost>",
+	&create_uri10,
+    },
+    {
+	/* Errorneous escaping in display name. */
+	ERR_SYNTAX_ERR,
+	" \"Rogue User\\\" <sip:localhost>",
+	&create_uri11,
+    },
+    {
+	/* Dangling quote in display name, but that should be OK. */
+	PJ_SUCCESS,
+	"Strange User\" <sip:localhost>",
+	&create_uri12,
+    },
+    {
+	/* Special characters in parameter value must be quoted. */
+	PJ_SUCCESS,
+	"sip:localhost;pvalue=\"hello world\"",
+	&create_uri13,
+    },
+    {
+	/* Excercise strange character sets allowed in display, user, password,
+	 * host, and port. 
+	 */
+	PJ_SUCCESS,
+	"This is -. !% *_+`'~ me <sip:a19A&=+$,;?/%2c:%40a&Zz=+$,@"
+	"my_proxy09.MY-domain.com:9801>",
+	&create_uri14,
+    },
+    {
+	/* Another excercise to the allowed character sets to the hostname. */
+	PJ_SUCCESS,
+	"sip:" ALPHANUM "-_.com",
+	&create_uri15,
+    },
+    {
+	/* Another excercise to the allowed character sets to the username 
+	 * and password.
+	 */
+	PJ_SUCCESS,
+	"sip:" USER_CHAR ":" PASS_CHAR "@host",
+	&create_uri16,
+    },
+    {
+	/* Excercise to the pname and pvalue, and mixup of other-param
+	 * between 'recognized' params.
+	 */
+	PJ_SUCCESS,
+	"sip:host;user=ip;" PARAM_CHAR "%21=" PARAM_CHAR "%21"
+	";lr;other=1;transport=sctp;other2",
+	&create_uri17,
+    },
+    {
+	/* 18: This should trigger syntax error. */
+	ERR_SYNTAX_ERR,
+	"sip:",
+	&create_dummy,
+    },
+    {
+	/* 19: Syntax error: whitespace after scheme. */
+	ERR_SYNTAX_ERR,
+	"sip :host",
+	&create_dummy,
+    },
+    {
+	/* 20: Syntax error: whitespace before hostname. */
+	ERR_SYNTAX_ERR,
+	"sip: host",
+	&create_dummy,
+    },
+    {
+	/* 21: Syntax error: invalid port. */
+	ERR_SYNTAX_ERR,
+	"sip:user:password",
+	&create_dummy,
+    },
+    {
+	/* 22: Syntax error: no host. */
+	ERR_SYNTAX_ERR,
+	"sip:user@",
+	&create_dummy,
+    },
+    {
+	/* 23: Syntax error: no user/host. */
+	ERR_SYNTAX_ERR,
+	"sip:@",
+	&create_dummy,
+    },
+    {
+	/* 24: Syntax error: empty string. */
+	ERR_SYNTAX_ERR,
+	"",
+	&create_dummy,
+    },
+    {
+	/* 25: Simple tel: URI with global context */
+	PJ_SUCCESS,
+	"tel:+1-201-555-0123",
+	&create_uri25,
+	"tel:+1-201-555-0123"
+    },
+    {
+	/* 26: Simple tel: URI with local context */
+	PJ_SUCCESS,
+	"tel:7042;phone-context=example.com",
+	&create_uri26,
+	"tel:7042;phone-context=example.com"
+    },
+    {
+	/* 27: Simple tel: URI with local context */
+	PJ_SUCCESS,
+	"tel:863-1234;phone-context=+1-914-555",
+	&create_uri27,
+	"tel:863-1234;phone-context=+1-914-555"
+    },
+    {
+	/* 28: Comparison between local and global number */
+	ERR_NOT_EQUAL,
+	"tel:+1",
+	&create_uri28,
+	"tel:+1"
+    },
+    {
+	/* 29: tel: with some visual chars and spaces */
+	PJ_SUCCESS,
+	"tel:(44).1234-*#+Deaf",
+	&create_uri29,
+	"tel:(44).1234-*#+Deaf"
+    },
+    {
+	/* 30: isub parameters */
+	PJ_SUCCESS,
+	"tel:+1;isub=/:@&$,-_.!~*'()[]/:&$aA1%21+=",
+	&create_uri30,
+	"tel:+1;isub=/:@&$,-_.!~*'()[]/:&$aA1%21+%3d"
+    },
+    {
+	/* 31: extension number parsing and encoding */
+	PJ_SUCCESS,
+	"tel:+1;ext=+123",
+	&create_uri31,
+	"tel:+1;ext=%2b123"
+    },
+    {
+	/* 32: context parameter parsing and encoding */
+	PJ_SUCCESS,
+	"tel:911;phone-context=+1-911",
+	&create_uri32,
+	"tel:911;phone-context=+1-911"
+    },
+    {
+	/* 33: case-insensitive comparison */
+	PJ_SUCCESS,
+	"tel:911;phone-context=emergency.example.com",
+	&create_uri33,
+	"tel:911;phone-context=emergency.example.com"
+    },
+    {
+	/* 34: parameter only appears in one URL */
+	ERR_NOT_EQUAL,
+	"tel:911;p1=p1;p2=p2",
+	&create_uri34,
+	"tel:911;p1=p1;p2=p2"
+    },
+    
+};
+
+static pjsip_uri *create_uri0(pj_pool_t *pool)
+{
+    /* "sip:localhost" */
+    pjsip_url *url = pjsip_url_create(pool, 0);
+
+    pj_strdup2(pool, &url->host, "localhost");
+    return (pjsip_uri*)url;
+}
+
+static pjsip_uri *create_uri1(pj_pool_t *pool)
+{
+    /* "sip:user@localhost" */
+    pjsip_url *url = pjsip_url_create(pool, 0);
+
+    pj_strdup2( pool, &url->user, "user");
+    pj_strdup2( pool, &url->host, "localhost");
+
+    return (pjsip_uri*) url;
+}
+
+static pjsip_uri *create_uri2(pj_pool_t *pool)
+{
+    /* "sip:user:password@localhost:5060" */
+    pjsip_url *url = pjsip_url_create(pool, 0);
+
+    pj_strdup2( pool, &url->user, "user");
+    pj_strdup2( pool, &url->passwd, "password");
+    pj_strdup2( pool, &url->host, "localhost");
+    url->port = 5060;
+
+    return (pjsip_uri*) url;
+}
+
+static pjsip_uri *create_uri3(pj_pool_t *pool)
+{
+    /* Like: "sip:localhost:5060", but without the port. */
+    pjsip_url *url = pjsip_url_create(pool, 0);
+
+    pj_strdup2(pool, &url->host, "localhost");
+    return (pjsip_uri*)url;
+}
+
+static pjsip_uri *create_uri4(pj_pool_t *pool)
+{
+    /* "sip:localhost;transport=tcp;user=ip;ttl=255;lr;maddr=127.0.0.1;method=ACK" */
+    pjsip_url *url = pjsip_url_create(pool, 0);
+
+    pj_strdup2(pool, &url->host, "localhost");
+    pj_strdup2(pool, &url->transport_param, "tcp");
+    pj_strdup2(pool, &url->user_param, "ip");
+    url->ttl_param = 255;
+    url->lr_param = 1;
+    pj_strdup2(pool, &url->maddr_param, "127.0.0.1");
+    pj_strdup2(pool, &url->method_param, "ACK");
+
+    return (pjsip_uri*)url;
+}
+
+#define param_add(list,pname,pvalue)  \
+	do { \
+	    pjsip_param *param; \
+	    param=pj_pool_alloc(pool, sizeof(pjsip_param)); \
+	    param->name = pj_str(pname); \
+	    param->value = pj_str(pvalue); \
+	    pj_list_insert_before(&list, param); \
+	} while (0)
+
+static pjsip_uri *create_uri5(pj_pool_t *pool)
+{
+    /* "sip:localhost;pickup=hurry;user=phone;message=I%20am%20sorry"
+       "?Subject=Hello%20There&Server=SIP%20Server" 
+     */
+    pjsip_url *url = pjsip_url_create(pool, 0);
+
+    pj_strdup2(pool, &url->host, "localhost");
+    pj_strdup2(pool, &url->user_param, "phone");
+
+    //pj_strdup2(pool, &url->other_param, ";pickup=hurry;message=I%20am%20sorry");
+    param_add(url->other_param, "pickup", "hurry");
+    param_add(url->other_param, "message", "I am sorry");
+
+    //pj_strdup2(pool, &url->header_param, "?Subject=Hello%20There&Server=SIP%20Server");
+    param_add(url->header_param, "Subject", "Hello There");
+    param_add(url->header_param, "Server", "SIP Server");
+    return (pjsip_uri*)url;
+
+}
+
+static pjsip_uri *create_uri6(pj_pool_t *pool)
+{
+    /* "sips:localhost" */
+    pjsip_url *url = pjsip_url_create(pool, 1);
+
+    pj_strdup2(pool, &url->host, "localhost");
+    return (pjsip_uri*)url;
+}
+
+static pjsip_uri *create_uri7(pj_pool_t *pool)
+{
+    /* "<sip:localhost>" */
+    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
+    pjsip_url *url;
+
+    url = pjsip_url_create(pool, 0);
+    name_addr->uri = (pjsip_uri*) url;
+
+    pj_strdup2(pool, &url->host, "localhost");
+    return (pjsip_uri*)name_addr;
+}
+
+static pjsip_uri *create_uri8(pj_pool_t *pool)
+{
+    /* "  Power Administrator <sips:localhost>" */
+    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
+    pjsip_url *url;
+
+    url = pjsip_url_create(pool, 1);
+    name_addr->uri = (pjsip_uri*) url;
+
+    pj_strdup2(pool, &name_addr->display, "Power Administrator");
+    pj_strdup2(pool, &url->host, "localhost");
+    return (pjsip_uri*)name_addr;
+}
+
+static pjsip_uri *create_uri9(pj_pool_t *pool)
+{
+    /* " \"User\" <sip:user@localhost:5071>" */
+    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
+    pjsip_url *url;
+
+    url = pjsip_url_create(pool, 0);
+    name_addr->uri = (pjsip_uri*) url;
+
+    pj_strdup2(pool, &name_addr->display, "User");
+    pj_strdup2(pool, &url->user, "user");
+    pj_strdup2(pool, &url->host, "localhost");
+    url->port = 5071;
+    return (pjsip_uri*)name_addr;
+}
+
+static pjsip_uri *create_uri10(pj_pool_t *pool)
+{
+    /* " \"Strange User\\\"\\\\\\\"\" <sip:localhost>" */
+    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
+    pjsip_url *url;
+
+    url = pjsip_url_create(pool, 0);
+    name_addr->uri = (pjsip_uri*) url;
+
+    pj_strdup2(pool, &name_addr->display, "Strange User\\\"\\\\\\\"");
+    pj_strdup2(pool, &url->host, "localhost");
+    return (pjsip_uri*)name_addr;
+}
+
+static pjsip_uri *create_uri11(pj_pool_t *pool)
+{
+    /* " \"Rogue User\\\" <sip:localhost>" */
+    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
+    pjsip_url *url;
+
+    url = pjsip_url_create(pool, 0);
+    name_addr->uri = (pjsip_uri*) url;
+
+    pj_strdup2(pool, &name_addr->display, "Rogue User\\");
+    pj_strdup2(pool, &url->host, "localhost");
+    return (pjsip_uri*)name_addr;
+}
+
+static pjsip_uri *create_uri12(pj_pool_t *pool)
+{
+    /* "Strange User\" <sip:localhost>" */
+    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
+    pjsip_url *url;
+
+    url = pjsip_url_create(pool, 0);
+    name_addr->uri = (pjsip_uri*) url;
+
+    pj_strdup2(pool, &name_addr->display, "Strange User\"");
+    pj_strdup2(pool, &url->host, "localhost");
+    return (pjsip_uri*)name_addr;
+}
+
+static pjsip_uri *create_uri13(pj_pool_t *pool)
+{
+    /* "sip:localhost;pvalue=\"hello world\"" */
+    pjsip_url *url;
+    url = pjsip_url_create(pool, 0);
+    pj_strdup2(pool, &url->host, "localhost");
+    //pj_strdup2(pool, &url->other_param, ";pvalue=\"hello world\"");
+    param_add(url->other_param, "pvalue", "hello world");
+    return (pjsip_uri*)url;
+}
+
+static pjsip_uri *create_uri14(pj_pool_t *pool)
+{
+    /* "This is -. !% *_+`'~ me <sip:a19A&=+$,;?/%2c:%40a&Zz=+$,@my_proxy09.my-domain.com:9801>" */
+    pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
+    pjsip_url *url;
+
+    url = pjsip_url_create(pool, 0);
+    name_addr->uri = (pjsip_uri*) url;
+
+    pj_strdup2(pool, &name_addr->display, "This is -. !% *_+`'~ me");
+    pj_strdup2(pool, &url->user, "a19A&=+$,;?/,");
+    pj_strdup2(pool, &url->passwd, "@a&Zz=+$,");
+    pj_strdup2(pool, &url->host, "my_proxy09.MY-domain.com");
+    url->port = 9801;
+    return (pjsip_uri*)name_addr;
+}
+
+static pjsip_uri *create_uri15(pj_pool_t *pool)
+{
+    /* "sip:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.com" */
+    pjsip_url *url;
+    url = pjsip_url_create(pool, 0);
+    pj_strdup2(pool, &url->host, ALPHANUM "-_.com");
+    return (pjsip_uri*)url;
+}
+
+static pjsip_uri *create_uri16(pj_pool_t *pool)
+{
+    /* "sip:" USER_CHAR ":" PASS_CHAR "@host" */
+    pjsip_url *url;
+    url = pjsip_url_create(pool, 0);
+    pj_strdup2(pool, &url->user, USER_CHAR);
+    pj_strdup2(pool, &url->passwd, PASS_CHAR);
+    pj_strdup2(pool, &url->host, "host");
+    return (pjsip_uri*)url;
+}
+
+static pjsip_uri *create_uri17(pj_pool_t *pool)
+{
+    /* "sip:host;user=ip;" PARAM_CHAR "%21=" PARAM_CHAR "%21;lr;other=1;transport=sctp;other2" */
+    pjsip_url *url;
+    url = pjsip_url_create(pool, 0);
+    pj_strdup2(pool, &url->host, "host");
+    pj_strdup2(pool, &url->user_param, "ip");
+    pj_strdup2(pool, &url->transport_param, "sctp");
+    param_add(url->other_param, PARAM_CHAR "!", PARAM_CHAR "!");
+    param_add(url->other_param, "other", "1");
+    param_add(url->other_param, "other2", "");
+    url->lr_param = 1;
+    return (pjsip_uri*)url;
+}
+
+
+static pjsip_uri *create_uri25(pj_pool_t *pool)
+{
+    /* "tel:+1-201-555-0123" */
+    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
+
+    uri->number = pj_str("+1-201-555-0123");
+    return (pjsip_uri*)uri;
+}
+
+static pjsip_uri *create_uri26(pj_pool_t *pool)
+{
+    /* tel:7042;phone-context=example.com */
+    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
+
+    uri->number = pj_str("7042");
+    uri->context = pj_str("example.com");
+    return (pjsip_uri*)uri;
+}
+
+static pjsip_uri *create_uri27(pj_pool_t *pool)
+{
+    /* "tel:863-1234;phone-context=+1-914-555" */
+    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
+
+    uri->number = pj_str("863-1234");
+    uri->context = pj_str("+1-914-555");
+    return (pjsip_uri*)uri;
+}
+
+/* "tel:1" */
+static pjsip_uri *create_uri28(pj_pool_t *pool)
+{
+    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
+
+    uri->number = pj_str("1");
+    return (pjsip_uri*)uri;
+}
+
+/* "tel:(44).1234-*#+Deaf" */
+static pjsip_uri *create_uri29(pj_pool_t *pool)
+{
+    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
+
+    uri->number = pj_str("(44).1234-*#+Deaf");
+    return (pjsip_uri*)uri;    
+}
+
+/* "tel:+1;isub=/:@&$,-_.!~*'()[]/:&$aA1%21+=" */
+static pjsip_uri *create_uri30(pj_pool_t *pool)
+{
+    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
+
+    uri->number = pj_str("+1");
+    uri->isub_param = pj_str("/:@&$,-_.!~*'()[]/:&$aA1%21+=");
+    return (pjsip_uri*)uri;    
+}
+
+/* "tel:+1;ext=+123" */
+static pjsip_uri *create_uri31(pj_pool_t *pool)
+{
+    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
+
+    uri->number = pj_str("+1");
+    uri->ext_param = pj_str("+123");
+    return (pjsip_uri*)uri;    
+}
+
+/* "tel:911;phone-context=+1-911" */
+static pjsip_uri *create_uri32(pj_pool_t *pool)
+{
+    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
+
+    uri->number = pj_str("911");
+    uri->context = pj_str("+1-911");
+    return (pjsip_uri*)uri;    
+}
+
+/* "tel:911;phone-context=emergency.example.com" */
+static pjsip_uri *create_uri33(pj_pool_t *pool)
+{
+    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
+
+    uri->number = pj_str("911");
+    uri->context = pj_str("EMERGENCY.EXAMPLE.COM");
+    return (pjsip_uri*)uri;    
+}
+
+/* "tel:911;p1=p1;p2=p2" */
+static pjsip_uri *create_uri34(pj_pool_t *pool)
+{
+    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);
+    pjsip_param *p;
+
+    uri->number = pj_str("911");
+    
+    p = pj_pool_alloc(pool, sizeof(*p));
+    p->name = p->value = pj_str("p1");
+    pj_list_insert_before(&uri->other_param, p);
+
+    return (pjsip_uri*)uri;    
+}
+
+
+static pjsip_uri *create_dummy(pj_pool_t *pool)
+{
+    PJ_UNUSED_ARG(pool);
+    return NULL;
+}
+
+/*****************************************************************************/
+
+/*
+ * Test one test entry.
+ */
+static pj_status_t do_uri_test(pj_pool_t *pool, struct uri_test *entry)
+{
+    pj_status_t status;
+    int len;
+    pjsip_uri *parsed_uri, *ref_uri;
+    pj_str_t s1 = {NULL, 0}, s2 = {NULL, 0};
+    pj_timestamp t1, t2;
+
+    entry->len = pj_native_strlen(entry->str);
+
+    /* Parse URI text. */
+    pj_get_timestamp(&t1);
+    parse_len = parse_len + entry->len;
+    parsed_uri = pjsip_parse_uri(pool, entry->str, entry->len, 0);
+    if (!parsed_uri) {
+	/* Parsing failed. If the entry says that this is expected, then
+	 * return OK.
+	 */
+	status = entry->status==ERR_SYNTAX_ERR ? PJ_SUCCESS : -10;
+	if (status != 0) {
+	    PJ_LOG(3,("", "   uri parse error!\n"
+			  "   uri='%s'\n",
+			  entry->str));
+	}
+	goto on_return;
+    }
+    pj_get_timestamp(&t2);
+    pj_sub_timestamp(&t2, &t1);
+    pj_add_timestamp(&parse_time, &t2);
+
+    /* Create the reference URI. */
+    ref_uri = entry->creator(pool);
+
+    /* Print both URI. */
+    s1.ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
+    s2.ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
+
+    pj_get_timestamp(&t1);
+    len = pjsip_uri_print( PJSIP_URI_IN_OTHER, parsed_uri, s1.ptr, PJSIP_MAX_URL_SIZE);
+    if (len < 1) {
+	status = -20;
+	goto on_return;
+    }
+    s1.ptr[len] = '\0';
+    s1.slen = len;
+
+    print_len = print_len + len;
+    pj_get_timestamp(&t2);
+    pj_sub_timestamp(&t2, &t1);
+    pj_add_timestamp(&print_time, &t2);
+
+    len = pjsip_uri_print( PJSIP_URI_IN_OTHER, ref_uri, s2.ptr, PJSIP_MAX_URL_SIZE);
+    if (len < 1) {
+	status = -30;
+	goto on_return;
+    }
+    s2.ptr[len] = '\0';
+    s2.slen = len;
+
+    /* Full comparison of parsed URI with reference URI. */
+    pj_get_timestamp(&t1);
+    status = pjsip_uri_cmp(PJSIP_URI_IN_OTHER, parsed_uri, ref_uri);
+    if (status != 0) {
+	/* Not equal. See if this is the expected status. */
+	status = entry->status==ERR_NOT_EQUAL ? PJ_SUCCESS : -40;
+	if (status != 0) {
+	    PJ_LOG(3,("", "   uri comparison mismatch, status=%d:\n"
+			  "    uri1='%s'\n"
+			  "    uri2='%s'",
+			  status, s1.ptr, s2.ptr));
+	}
+	goto on_return;
+
+    } else {
+	/* Equal. See if this is the expected status. */
+	status = entry->status==PJ_SUCCESS ? PJ_SUCCESS : -50;
+	if (status != PJ_SUCCESS) {
+	    goto on_return;
+	}
+    }
+
+    cmp_len = cmp_len + len;
+    pj_get_timestamp(&t2);
+    pj_sub_timestamp(&t2, &t1);
+    pj_add_timestamp(&cmp_time, &t2);
+
+    /* Compare text. */
+    if (entry->printed) {
+	if (pj_strcmp2(&s1, entry->printed) != 0) {
+	    /* Not equal. */
+	    PJ_LOG(3,("", "   uri print mismatch:\n"
+			  "    printed='%s'\n"
+			  "    expectd='%s'",
+			  s1.ptr, entry->printed));
+	    status = -60;
+	}
+    } else {
+	if (pj_strcmp(&s1, &s2) != 0) {
+	    /* Not equal. */
+	    PJ_LOG(3,("", "   uri print mismatch:\n"
+			  "    uri1='%s'\n"
+			  "    uri2='%s'",
+			  s1.ptr, s2.ptr));
+	    status = -70;
+	}
+    }
+
+on_return:
+    return status;
+}
+
+pj_status_t uri_test()
+{
+    unsigned i, loop;
+    pj_pool_t *pool;
+    pj_status_t status;
+    pj_timestamp zero;
+    pj_time_val elapsed;
+    pj_highprec_t avg_parse, avg_print, avg_cmp, kbytes;
+
+    zero.u32.hi = zero.u32.lo = 0;
+
+    PJ_LOG(3,("", "  simple test"));
+    pool = pjsip_endpt_create_pool(endpt, "", POOL_SIZE, POOL_SIZE);
+    for (i=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) {
+	status = do_uri_test(pool, &uri_test_array[i]);
+	if (status != PJ_SUCCESS) {
+	    PJ_LOG(3,("uri_test", "  error %d when testing entry %d",
+		      status, i));
+	    goto on_return;
+	}
+    }
+    pjsip_endpt_destroy_pool(endpt, pool);
+
+    PJ_LOG(3,("", "  benchmarking..."));
+    parse_len = print_len = cmp_len = 0;
+    parse_time.u32.hi = parse_time.u32.lo = 0;
+    print_time.u32.hi = print_time.u32.lo = 0;
+    cmp_time.u32.hi = cmp_time.u32.lo = 0;
+    for (loop=0; loop<LOOP_COUNT; ++loop) {
+	pool = pjsip_endpt_create_pool(endpt, "", POOL_SIZE, POOL_SIZE);
+	for (i=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) {
+	    status = do_uri_test(pool, &uri_test_array[i]);
+	    if (status != PJ_SUCCESS) {
+		PJ_LOG(3,("uri_test", "  error %d when testing entry %d",
+			  status, i));
+		pjsip_endpt_destroy_pool(endpt, pool);
+		goto on_return;
+	    }
+	}
+	pjsip_endpt_destroy_pool(endpt, pool);
+    }
+
+    kbytes = parse_len;
+    pj_highprec_mod(kbytes, 1000000);
+    pj_highprec_div(kbytes, 100000);
+    elapsed = pj_elapsed_time(&zero, &parse_time);
+    avg_parse = pj_elapsed_usec(&zero, &parse_time);
+    pj_highprec_mul(avg_parse, AVERAGE_URL_LEN);
+    pj_highprec_div(avg_parse, parse_len);
+    avg_parse = 1000000 / avg_parse;
+
+    PJ_LOG(3,("", "    %u.%u MB of urls parsed in %d.%03ds (avg=%d urls/sec)", 
+		  (unsigned)(parse_len/1000000), (unsigned)kbytes,
+		  elapsed.sec, elapsed.msec,
+		  (unsigned)avg_parse));
+
+    kbytes = print_len;
+    pj_highprec_mod(kbytes, 1000000);
+    pj_highprec_div(kbytes, 100000);
+    elapsed = pj_elapsed_time(&zero, &print_time);
+    avg_print = pj_elapsed_usec(&zero, &print_time);
+    pj_highprec_mul(avg_print, AVERAGE_URL_LEN);
+    pj_highprec_div(avg_print, parse_len);
+    avg_print = 1000000 / avg_print;
+
+    PJ_LOG(3,("", "    %u.%u MB of urls printed in %d.%03ds (avg=%d urls/sec)", 
+		  (unsigned)(print_len/1000000), (unsigned)kbytes,
+		  elapsed.sec, elapsed.msec,
+		  (unsigned)avg_print));
+
+    kbytes = cmp_len;
+    pj_highprec_mod(kbytes, 1000000);
+    pj_highprec_div(kbytes, 100000);
+    elapsed = pj_elapsed_time(&zero, &cmp_time);
+    avg_cmp = pj_elapsed_usec(&zero, &cmp_time);
+    pj_highprec_mul(avg_cmp, AVERAGE_URL_LEN);
+    pj_highprec_div(avg_cmp, cmp_len);
+    avg_cmp = 1000000 / avg_cmp;
+
+    PJ_LOG(3,("", "    %u.%u MB of urls compared in %d.%03ds (avg=%d urls/sec)", 
+		  (unsigned)(cmp_len/1000000), (unsigned)kbytes,
+		  elapsed.sec, elapsed.msec,
+		  (unsigned)avg_cmp));
+
+    PJ_LOG(3,("", "  multithreaded test"));
+
+
+on_return:
+    return status;
+}
+
