More ticket #1032:
 - Updated transport state notification callback to return void.
 - Updated transport state enum to only contain connected and disconnected, no more bitmask value.
 - Added direction field to SIP transport.
 - Removed remote hostname hash from transport key.
 - Updated cert info dump to return -1 when buffer is insufficient.
 - Added new error code PJSIP_TLS_ECERTVERIF.
 - Updated get_cert_name() in ssl_sock_symbian.c to use heap buffer instead of stack.
 - Minors, e.g: added prefix PJ in cipher types, docs.




git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@3110 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjsip/include/pjsip/sip_errno.h b/pjsip/include/pjsip/sip_errno.h
index 802ab4a..15f842a 100644
--- a/pjsip/include/pjsip/sip_errno.h
+++ b/pjsip/include/pjsip/sip_errno.h
@@ -504,6 +504,11 @@
  * SSL negotiation has exceeded the maximum configured timeout.
  */
 #define PJSIP_TLS_ETIMEDOUT	(PJSIP_ERRNO_START_PJSIP+172)	/* 171172 */
+/**
+ * @hideinitializer
+ * SSL certificate verification error.
+ */
+#define PJSIP_TLS_ECERTVERIF	(PJSIP_ERRNO_START_PJSIP+173)	/* 171173 */
 
 
 /**
diff --git a/pjsip/include/pjsip/sip_transport.h b/pjsip/include/pjsip/sip_transport.h
index 9f6534c..8da4d56 100644
--- a/pjsip/include/pjsip/sip_transport.h
+++ b/pjsip/include/pjsip/sip_transport.h
@@ -693,17 +693,30 @@
     long		    type;
 
     /**
-     * Hash of host name.
-     */
-    pj_uint32_t		    hname;
-
-    /**
      * Destination address.
      */
     pj_sockaddr		    rem_addr;
 
 } pjsip_transport_key;
 
+
+/**
+ * Enumeration of transport direction types.
+ */
+typedef enum pjsip_transport_dir
+{
+    PJSIP_TP_DIR_NONE,		    /**< Direction not set, normally used by
+				         connectionless transports such as 
+					 UDP transport.			    */
+    PJSIP_TP_DIR_OUTGOING,	    /**< Outgoing connection or client mode,
+				         this is only for connection-oriented 
+					 transports.			    */
+    PJSIP_TP_DIR_INCOMING,	    /**< Incoming connection or server mode,
+					 this is only for connection-oriented
+					 transports.			    */
+} pjsip_transport_dir;
+
+
 /**
  * This structure represent the "public" interface of a SIP transport.
  * Applications normally extend this structure to include transport
@@ -731,6 +744,7 @@
     pj_sockaddr		    local_addr;	    /**< Bound address.		    */
     pjsip_host_port	    local_name;	    /**< Published name (eg. STUN). */
     pjsip_host_port	    remote_name;    /**< Remote address name.	    */
+    pjsip_transport_dir	    dir;	    /**< Connection direction.	    */
     
     pjsip_endpoint	   *endpt;	    /**< Endpoint instance.	    */
     pjsip_tpmgr		   *tpmgr;	    /**< Transport manager.	    */
@@ -1130,7 +1144,7 @@
  * transport is found, a new one will be created.
  *
  * This is an internal function since normally application doesn't have access
- * to transport manager. Application should use pjsip_endpt_acquire_transport()
+ * to transport manager. Application should use pjsip_endpt_acquire_transport2()
  * instead.
  *
  * @param mgr	    The transport manager instance.
@@ -1244,35 +1258,26 @@
 /**
  * Enumeration of transport state types.
  */
-typedef enum pjsip_transport_state_type {
-
-    /** Transport connected.	*/
-    PJSIP_TP_STATE_CONNECTED	    = (1 << 0),
-
-    /** Transport accepted.	*/
-    PJSIP_TP_STATE_ACCEPTED	    = (1 << 1),
-
-    /** Transport disconnected.	*/
-    PJSIP_TP_STATE_DISCONNECTED	    = (1 << 2),
-
-    /** Incoming connection rejected.	*/
-    PJSIP_TP_STATE_REJECTED	    = (1 << 3),
-
-    /** TLS verification error.	*/
-    PJSIP_TP_STATE_TLS_VERIF_ERROR  = (1 << 8)
-
-} pjsip_transport_state_type;
+typedef enum pjsip_transport_state
+{
+    PJSIP_TP_STATE_CONNECTED,	    /**< Transport connected, applicable only
+					 to connection-oriented transports
+					 such as TCP and TLS.		    */
+    PJSIP_TP_STATE_DISCONNECTED	    /**< Transport disconnected, applicable
+					 only to connection-oriented 
+					 transports such as TCP and TLS.    */
+} pjsip_transport_state;
 
 
 /**
- * Structure of transport state info.
+ * Structure of transport state info passed by #pjsip_tp_state_callback.
  */
 typedef struct pjsip_transport_state_info {
     /**
      * The last error code related to the transport state.
      */
     pj_status_t		 status;
-    
+
     /**
      * Optional extended info, the content is specific for each transport type.
      */
@@ -1282,30 +1287,23 @@
 
 /**
  * Type of callback to receive transport state notifications, such as
- * transport connected, disconnected or TLS verification error.
+ * transport connected/disconnected. Application may shutdown the transport
+ * in this callback.
  *
  * @param tp		The transport instance.
- * @param state		The transport state, this may contain single or 
- *			combination of transport state types defined in
- *			#pjsip_transport_state_type.
+ * @param state		The transport state.
  * @param info		The transport state info.
- *
- * @return		When TLS verification fails and peer verification in
- *			#pjsip_tls_setting is not set, application may return
- *			PJ_TRUE to ignore the verification result and continue
- *			using the transport. On other cases, this return value
- *			is currently not used and will be ignored.
  */
-typedef pj_bool_t (*pjsip_tp_state_callback)(
+typedef void (*pjsip_tp_state_callback)(
 				    pjsip_transport *tp,
-				    pj_uint32_t state,
+				    pjsip_transport_state state,
 				    const pjsip_transport_state_info *info);
 
 
 /**
  * Setting callback of transport state notification. The caller will be
  * notified whenever the state of transport is changed. The type of
- * events are defined in #pjsip_transport_state_type.
+ * events are defined in #pjsip_transport_state.
  * 
  * @param mgr	    Transport manager.
  * @param cb	    Callback to be called to notify caller about transport 
diff --git a/pjsip/include/pjsip/sip_transport_tls.h b/pjsip/include/pjsip/sip_transport_tls.h
index f97414b..ddee2bc 100644
--- a/pjsip/include/pjsip/sip_transport_tls.h
+++ b/pjsip/include/pjsip/sip_transport_tls.h
@@ -122,42 +122,36 @@
     pj_str_t	server_name;
 
     /**
-     * Specifies the action when verification of server TLS certificate
-     * resulting errors:
+     * Specifies TLS transport behavior on the server TLS certificate 
+     * verification result:
      * - If \a verify_server is disabled (set to PJ_FALSE), TLS transport 
      *   will just notify the application via #pjsip_tp_state_callback with
-     *   state (PJSIP_TP_STATE_CONNECTED | PJSIP_TP_STATE_TLS_VERIF_ERROR)
-     *   whenever there is any TLS verification error, the return value of 
-     *   the callback will be used to decide whether transport should be 
-     *   shutdown.
+     *   state PJSIP_TP_STATE_CONNECTED regardless TLS verification result.
      * - If \a verify_server is enabled (set to PJ_TRUE), TLS transport 
      *   will be shutdown and application will be notified with state
-     *   (PJSIP_TP_STATE_DISCONNECTED | PJSIP_TP_STATE_TLS_VERIF_ERROR)
-     *   whenever there is any TLS verification error.
+     *   PJSIP_TP_STATE_DISCONNECTED whenever there is any TLS verification
+     *   error, otherwise PJSIP_TP_STATE_CONNECTED will be notified.
      *
-     * When the verification resulting success, application will be notified
-     * via #pjsip_tp_state_callback with state PJSIP_TP_STATE_CONNECTED.
+     * In any cases, application can inspect #pjsip_tls_state_info in the
+     * callback to see the verification detail.
      *
      * Default value is PJ_FALSE.
      */
     pj_bool_t	verify_server;
 
     /**
-     * Specifies the action when verification of server TLS certificate
-     * resulting errors:
+     * Specifies TLS transport behavior on the client TLS certificate 
+     * verification result:
      * - If \a verify_client is disabled (set to PJ_FALSE), TLS transport 
      *   will just notify the application via #pjsip_tp_state_callback with
-     *   state (PJSIP_TP_STATE_ACCEPTED | PJSIP_TP_STATE_TLS_VERIF_ERROR)
-     *   whenever there is any TLS verification error, the return value of 
-     *   the callback will be used to decide whether transport should be 
-     *   shutdown.
+     *   state PJSIP_TP_STATE_CONNECTED regardless TLS verification result.
      * - If \a verify_client is enabled (set to PJ_TRUE), TLS transport 
      *   will be shutdown and application will be notified with state
-     *   (PJSIP_TP_STATE_REJECTED | PJSIP_TP_STATE_TLS_VERIF_ERROR)
-     *   whenever there is any TLS verification error.
+     *   PJSIP_TP_STATE_DISCONNECTED whenever there is any TLS verification
+     *   error, otherwise PJSIP_TP_STATE_CONNECTED will be notified.
      *
-     * When the verification resulting success, application will be notified
-     * via #pjsip_tp_state_callback with state PJSIP_TP_STATE_ACCEPTED.
+     * In any cases, application can inspect #pjsip_tls_state_info in the
+     * callback to see the verification detail.
      *
      * Default value is PJ_FALSE.
      */
@@ -165,7 +159,7 @@
 
     /**
      * When acting as server (incoming TLS connections), reject inocming
-     * connection if client doesn't have a valid certificate.
+     * connection if client doesn't supply a TLS certificate.
      *
      * This setting corresponds to SSL_VERIFY_FAIL_IF_NO_PEER_CERT flag.
      * Default value is PJ_FALSE.
@@ -209,8 +203,9 @@
 
 
 /**
- * This structure defines transport state extended info specifically for
- * TLS transport.
+ * This structure defines TLS transport extended info in <tt>ext_info</tt>
+ * field of #pjsip_transport_state_info for the transport state notification
+ * callback #pjsip_tp_state_callback.
  */
 typedef struct pjsip_tls_state_info
 {
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index 45f07d9..451b8c9 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -846,21 +846,8 @@
     /**
      * This callback is called when transport state is changed. See also
      * #pjsip_tp_state_callback.
-     *
-     * @param tp	The transport instance.
-     * @param state	The transport state, this may contain single or 
-     *			combination of transport state types defined in
-     *			#pjsip_transport_state_type.
-     * @param info	The transport state info.
-     *
-     * @return		When TLS verification fails and peer verification in
-     *			#pjsip_tls_setting is not set, application may return
-     *			PJ_TRUE to ignore the verification result and continue
-     *			using the transport. On other cases, this return value
-     *			is currently not used and will be ignored.
      */
-    pj_bool_t (*on_transport_state)(pjsip_transport *tp, pj_uint32_t state,
-				    const pjsip_transport_state_info *info);
+    pjsip_tp_state_callback on_transport_state;
 
 } pjsua_callback;
 
diff --git a/pjsip/src/pjsip/sip_errno.c b/pjsip/src/pjsip/sip_errno.c
index 1225dd9..0c15206 100644
--- a/pjsip/src/pjsip/sip_errno.c
+++ b/pjsip/src/pjsip/sip_errno.c
@@ -131,6 +131,7 @@
     PJ_BUILD_ERR( PJSIP_TLS_ESEND,	"Unknown error when sending SSL data"),
     PJ_BUILD_ERR( PJSIP_TLS_EREAD,	"Unknown error when reading SSL data"),
     PJ_BUILD_ERR( PJSIP_TLS_ETIMEDOUT,	"SSL negotiation has timed out"),
+    PJ_BUILD_ERR( PJSIP_TLS_ECERTVERIF,	"SSL certificate verification error"),
 };
 
 
diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c
index 92fbaf4..ecfba2c 100644
--- a/pjsip/src/pjsip/sip_transport.c
+++ b/pjsip/src/pjsip/sip_transport.c
@@ -866,7 +866,7 @@
     /* 
      * Register to hash table (see Trac ticket #42).
      */
-    key_len = sizeof(tp->key.type) + sizeof(tp->key.hname) + tp->addr_len;
+    key_len = sizeof(tp->key.type) + tp->addr_len;
     pj_lock_acquire(mgr->lock);
 
     /* If entry already occupied, unregister previous entry */
@@ -916,7 +916,7 @@
     /*
      * Unregister from hash table (see Trac ticket #42).
      */
-    key_len = sizeof(tp->key.type) + sizeof(tp->key.hname) + tp->addr_len;
+    key_len = sizeof(tp->key.type) + tp->addr_len;
     hval = 0;
     entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval);
     if (entry == (void*)tp)
@@ -1591,34 +1591,12 @@
 	int key_len;
 	pjsip_transport *transport;
 
-	/*
-	 * Find factory that can create such transport.
-	 */
-	factory = mgr->factory_list.next;
-	while (factory != &mgr->factory_list) {
-	    if (factory->type == type)
-		break;
-	    factory = factory->next;
-	}
-	if (factory == &mgr->factory_list)
-	    factory = NULL;
-
 	pj_bzero(&key, sizeof(key));
-	key_len = sizeof(key.type) + sizeof(key.hname) + addr_len;
+	key_len = sizeof(key.type) + addr_len;
 
 	/* First try to get exact destination. */
 	key.type = type;
 	pj_memcpy(&key.rem_addr, remote, addr_len);
-	if (factory && factory->create_transport2 && 
-	    tdata && tdata->dest_info.name.slen)
-	{
-	    /* Only include hostname hash in the key when the factory support
-	     * create_transport2() and tdata is supplied.
-	     */
-	    key.hname = pj_hash_calc_tolower(0, 
-				    (char*)tdata->dest_info.name.ptr,
-				    &tdata->dest_info.name);
-	}
 
 	transport = (pjsip_transport*)
 		    pj_hash_get(mgr->table, &key, key_len, NULL);
@@ -1635,7 +1613,7 @@
 		pj_sockaddr *addr = &key.rem_addr;
 
 		pj_bzero(addr, addr_len);
-		key_len = sizeof(key.type) + sizeof(key.hname) + addr_len;
+		key_len = sizeof(key.type) + addr_len;
 		transport = (pjsip_transport*) 
 			    pj_hash_get(mgr->table, &key, key_len, NULL);
 	    }
@@ -1648,7 +1626,7 @@
 		pj_bzero(addr, addr_len);
 		addr->addr.sa_family = remote_addr->addr.sa_family;
 
-		key_len = sizeof(key.type) + sizeof(key.hname) + addr_len;
+		key_len = sizeof(key.type) + addr_len;
 		transport = (pjsip_transport*)
 			    pj_hash_get(mgr->table, &key, key_len, NULL);
 	    }
@@ -1668,8 +1646,16 @@
 
 	/*
 	 * Transport not found!
+	 * Find factory that can create such transport.
 	 */
-	if (NULL == factory) {
+	factory = mgr->factory_list.next;
+	while (factory != &mgr->factory_list) {
+	    if (factory->type == type)
+		break;
+	    factory = factory->next;
+	}
+
+	if (factory == &mgr->factory_list) {
 	    /* No factory can create the transport! */
 	    pj_lock_release(mgr->lock);
 	    TRACE_((THIS_FILE, "No suitable factory was found either"));
@@ -1677,7 +1663,6 @@
 	}
     }
 
-    
     TRACE_((THIS_FILE, "Creating new transport from factory"));
 
     /* Request factory to create transport. */
diff --git a/pjsip/src/pjsip/sip_transport_loop.c b/pjsip/src/pjsip/sip_transport_loop.c
index 490a7bb..f754f7f 100644
--- a/pjsip/src/pjsip/sip_transport_loop.c
+++ b/pjsip/src/pjsip/sip_transport_loop.c
@@ -381,6 +381,7 @@
 	pjsip_transport_get_default_port_for_type((pjsip_transport_type_e)
 						  loop->base.key.type);
     loop->base.addr_len = sizeof(pj_sockaddr_in);
+    loop->base.dir = PJSIP_TP_DIR_NONE;
     loop->base.endpt = endpt;
     loop->base.tpmgr = pjsip_endpt_get_tpmgr(endpt);
     loop->base.send_msg = &loop_send_msg;
diff --git a/pjsip/src/pjsip/sip_transport_tcp.c b/pjsip/src/pjsip/sip_transport_tcp.c
index a7c7eeb..58e0ba4 100644
--- a/pjsip/src/pjsip/sip_transport_tcp.c
+++ b/pjsip/src/pjsip/sip_transport_tcp.c
@@ -584,6 +584,7 @@
     pj_memcpy(&tcp->base.local_addr, local, sizeof(pj_sockaddr_in));
     sockaddr_to_host_port(pool, &tcp->base.local_name, local);
     sockaddr_to_host_port(pool, &tcp->base.remote_name, remote);
+    tcp->base.dir = is_server? PJSIP_TP_DIR_INCOMING : PJSIP_TP_DIR_OUTGOING;
 
     tcp->base.endpt = listener->endpt;
     tcp->base.tpmgr = listener->tpmgr;
@@ -1004,7 +1005,7 @@
 		pjsip_transport_state_info state_info;
             
 		pj_bzero(&state_info, sizeof(state_info));
-		(*state_cb)(&tcp->base, PJSIP_TP_STATE_ACCEPTED, &state_info);
+		(*state_cb)(&tcp->base, PJSIP_TP_STATE_CONNECTED, &state_info);
 	    }
 	}
     }
diff --git a/pjsip/src/pjsip/sip_transport_tls.c b/pjsip/src/pjsip/sip_transport_tls.c
index a135c43..0d4ef88 100644
--- a/pjsip/src/pjsip/sip_transport_tls.c
+++ b/pjsip/src/pjsip/sip_transport_tls.c
@@ -557,8 +557,6 @@
 
     tls->base.key.type = PJSIP_TRANSPORT_TLS;
     pj_memcpy(&tls->base.key.rem_addr, remote, sizeof(pj_sockaddr_in));
-    tls->base.key.hname = pj_hash_calc_tolower(0, (char*)tls->remote_name.ptr,
-					       &tls->remote_name);
     tls->base.type_name = "tls";
     tls->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_TLS);
 
@@ -568,6 +566,7 @@
 		     (int)pj_ntohs(remote->sin_port));
 
     tls->base.addr_len = sizeof(pj_sockaddr_in);
+    tls->base.dir = is_server? PJSIP_TP_DIR_INCOMING : PJSIP_TP_DIR_OUTGOING;
     
     /* Set initial local address */
     if (!pj_sockaddr_has_addr(local)) {
@@ -978,10 +977,9 @@
     struct tls_transport *tls;
     pj_ssl_sock_info ssl_info;
     char addr[PJ_INET6_ADDRSTRLEN+10];
-    pj_status_t status;
-
     pjsip_tp_state_callback *state_cb;
-    pj_bool_t tls_verif_ignored;
+    pj_bool_t is_shutdown;
+    pj_status_t status;
 
     PJ_UNUSED_ARG(src_addr_len);
 
@@ -1021,46 +1019,54 @@
     /* Set the "pending" SSL socket user data */
     pj_ssl_sock_set_user_data(new_ssock, tls);
 
-    tls_verif_ignored = !listener->tls_setting.verify_client;
+    /* Prevent immediate transport destroy as application may access it 
+     * (getting info, etc) in transport state notification callback.
+     */
+    pjsip_transport_add_ref(&tls->base);
+
+    /* If there is verification error and verification is mandatory, shutdown
+     * and destroy the transport.
+     */
+    if (ssl_info.verify_status && listener->tls_setting.verify_client) {
+	if (tls->close_reason == PJ_SUCCESS) 
+	    tls->close_reason = PJSIP_TLS_ECERTVERIF;
+	pjsip_transport_shutdown(&tls->base);
+    }
 
     /* Notify transport state to application */
     state_cb = pjsip_tpmgr_get_status_cb(tls->base.tpmgr);
     if (state_cb) {
 	pjsip_transport_state_info state_info;
 	pjsip_tls_state_info tls_info;
-	pj_uint32_t tp_state = 0;
+	pjsip_transport_state tp_state;
 
-	/* Init transport state notification callback */
+	/* Init transport state info */
 	pj_bzero(&tls_info, sizeof(tls_info));
 	pj_bzero(&state_info, sizeof(state_info));
-
-	/* Set transport state based on verification status */
-	if (ssl_info.verify_status) {
-	    state_info.status = PJSIP_TLS_EACCEPT;
-	    tp_state |= PJSIP_TP_STATE_TLS_VERIF_ERROR;
-	    if (listener->tls_setting.verify_client)
-		tp_state |= PJSIP_TP_STATE_REJECTED;
-	    else
-		tp_state |= PJSIP_TP_STATE_ACCEPTED;
-	} else {
-	    tp_state |= PJSIP_TP_STATE_ACCEPTED;
-	}
-
 	tls_info.ssl_sock_info = &ssl_info;
 	state_info.ext_info = &tls_info;
 
-	tls_verif_ignored = (*state_cb)(&tls->base, tp_state, &state_info);
+	/* Set transport state based on verification status */
+	if (ssl_info.verify_status && listener->tls_setting.verify_client)
+	{
+	    tp_state = PJSIP_TP_STATE_DISCONNECTED;
+	    state_info.status = PJSIP_TLS_ECERTVERIF;
+	} else {
+	    tp_state = PJSIP_TP_STATE_CONNECTED;
+	    state_info.status = PJ_SUCCESS;
+	}
+
+	(*state_cb)(&tls->base, tp_state, &state_info);
     }
 
-    /* Transport should be destroyed when there is TLS verification error
-     * and application doesn't want to ignore it.
+    /* Release transport reference. If transport is shutting down, it may
+     * get destroyed here.
      */
-    if (ssl_info.verify_status && 
-	(listener->tls_setting.verify_client || !tls_verif_ignored))
-    {
-	tls_destroy(&tls->base, PJSIP_TLS_EACCEPT);
+    is_shutdown = tls->base.is_shutdown;
+    pjsip_transport_dec_ref(&tls->base);
+    if (is_shutdown)
 	return PJ_TRUE;
-    }
+
 
     status = tls_start_read(tls);
     if (status != PJ_SUCCESS) {
@@ -1331,9 +1337,8 @@
     struct tls_transport *tls;
     pj_ssl_sock_info ssl_info;
     pj_sockaddr_in addr, *tp_addr;
-
     pjsip_tp_state_callback *state_cb;
-    pj_bool_t tls_verif_ignored;
+    pj_bool_t is_shutdown;
 
     tls = (struct tls_transport*) pj_ssl_sock_get_user_data(ssock);
 
@@ -1432,7 +1437,19 @@
 	    ssl_info.verify_status |= PJ_SSL_CERT_EIDENTITY_NOT_MATCH;
     }
 
-    tls_verif_ignored = !tls->verify_server;
+    /* Prevent immediate transport destroy as application may access it 
+     * (getting info, etc) in transport state notification callback.
+     */
+    pjsip_transport_add_ref(&tls->base);
+
+    /* If there is verification error and verification is mandatory, shutdown
+     * and destroy the transport.
+     */
+    if (ssl_info.verify_status && tls->verify_server) {
+	if (tls->close_reason == PJ_SUCCESS) 
+	    tls->close_reason = PJSIP_TLS_ECERTVERIF;
+	pjsip_transport_shutdown(&tls->base);
+    }
 
     /* Notify transport state to application */
     state_cb = pjsip_tpmgr_get_status_cb(tls->base.tpmgr);
@@ -1441,40 +1458,33 @@
 	pjsip_tls_state_info tls_info;
 	pj_uint32_t tp_state = 0;
 
-	/* Init transport state notification callback */
+	/* Init transport state info */
 	pj_bzero(&state_info, sizeof(state_info));
 	pj_bzero(&tls_info, sizeof(tls_info));
-
-	/* Set transport state info */
 	state_info.ext_info = &tls_info;
 	tls_info.ssl_sock_info = &ssl_info;
 
 	/* Set transport state based on verification status */
-	if (ssl_info.verify_status) {
-	    state_info.status = PJSIP_TLS_ECONNECT;
-	    tp_state |= PJSIP_TP_STATE_TLS_VERIF_ERROR;
-	    if (tls->verify_server)
-		tp_state |= PJSIP_TP_STATE_DISCONNECTED;
-	    else
-		tp_state |= PJSIP_TP_STATE_CONNECTED;
+	if (ssl_info.verify_status && tls->verify_server)
+	{
+	    tp_state = PJSIP_TP_STATE_DISCONNECTED;
+	    state_info.status = PJSIP_TLS_ECERTVERIF;
 	} else {
-	    tp_state |= PJSIP_TP_STATE_CONNECTED;
+	    tp_state = PJSIP_TP_STATE_CONNECTED;
+	    state_info.status = PJ_SUCCESS;
 	}
 
-	tls_verif_ignored = (*state_cb)(&tls->base, tp_state, &state_info);
+	(*state_cb)(&tls->base, tp_state, &state_info);
     }
 
-    /* Transport should be shutdown when there is TLS verification error
-     * and application doesn't want to ignore it.
+    /* Release transport reference. If transport is shutting down, it may
+     * get destroyed here.
      */
-    if (ssl_info.verify_status && 
-	(tls->verify_server || !tls_verif_ignored))
-    {
-	if (tls->close_reason == PJ_SUCCESS) 
-	    tls->close_reason = PJSIP_TLS_ECONNECT;
-	pjsip_transport_shutdown(&tls->base);
+    is_shutdown = tls->base.is_shutdown;
+    pjsip_transport_dec_ref(&tls->base);
+    if (is_shutdown)
 	return PJ_FALSE;
-    }
+
 
     /* Mark that pending connect() operation has completed. */
     tls->has_pending_connect = PJ_FALSE;
diff --git a/pjsip/src/pjsip/sip_transport_udp.c b/pjsip/src/pjsip/sip_transport_udp.c
index 24e2294..20b15b9 100644
--- a/pjsip/src/pjsip/sip_transport_udp.c
+++ b/pjsip/src/pjsip/sip_transport_udp.c
@@ -736,6 +736,9 @@
 	tp->base.remote_name.host = pj_str("::0");
     tp->base.remote_name.port = 0;
 
+    /* Init direction */
+    tp->base.dir = PJSIP_TP_DIR_NONE;
+
     /* Set endpoint. */
     tp->base.endpt = endpt;