summaryrefslogtreecommitdiff
path: root/pjsip
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2010-02-25 11:58:19 +0000
committerNanang Izzuddin <nanang@teluu.com>2010-02-25 11:58:19 +0000
commitcd0277b8c369c89206409d767d47600d3ed38786 (patch)
tree4ea90a5de7fb5a5842fff3685ac600c93246050b /pjsip
parentc80dd76f236e41c653a6e6e95c9fa44c586c6a34 (diff)
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: http://svn.pjsip.org/repos/pjproject/trunk@3110 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip')
-rw-r--r--pjsip/include/pjsip/sip_errno.h5
-rw-r--r--pjsip/include/pjsip/sip_transport.h76
-rw-r--r--pjsip/include/pjsip/sip_transport_tls.h41
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h17
-rw-r--r--pjsip/src/pjsip/sip_errno.c1
-rw-r--r--pjsip/src/pjsip/sip_transport.c43
-rw-r--r--pjsip/src/pjsip/sip_transport_loop.c1
-rw-r--r--pjsip/src/pjsip/sip_transport_tcp.c3
-rw-r--r--pjsip/src/pjsip/sip_transport_tls.c112
-rw-r--r--pjsip/src/pjsip/sip_transport_udp.c3
10 files changed, 144 insertions, 158 deletions
diff --git a/pjsip/include/pjsip/sip_errno.h b/pjsip/include/pjsip/sip_errno.h
index 802ab4a2..15f842a9 100644
--- a/pjsip/include/pjsip/sip_errno.h
+++ b/pjsip/include/pjsip/sip_errno.h
@@ -504,6 +504,11 @@ PJ_BEGIN_DECL
* 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 9f6534cd..8da4d561 100644
--- a/pjsip/include/pjsip/sip_transport.h
+++ b/pjsip/include/pjsip/sip_transport.h
@@ -693,17 +693,30 @@ typedef struct pjsip_transport_key
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 @@ struct pjsip_transport
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 @@ PJ_DECL(pj_status_t) pjsip_tpmgr_acquire_transport(pjsip_tpmgr *mgr,
* 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 @@ PJ_DECL(pj_status_t) pjsip_tpmgr_send_raw(pjsip_tpmgr *mgr,
/**
* 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 @@ typedef struct pjsip_transport_state_info {
/**
* 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 f97414b3..ddee2bc2 100644
--- a/pjsip/include/pjsip/sip_transport_tls.h
+++ b/pjsip/include/pjsip/sip_transport_tls.h
@@ -122,42 +122,36 @@ typedef struct pjsip_tls_setting
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 @@ typedef struct pjsip_tls_setting
/**
* 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 @@ typedef struct pjsip_tls_setting
/**
- * 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 45f07d90..451b8c9c 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -846,21 +846,8 @@ typedef struct pjsua_callback
/**
* 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 1225dd99..0c15206a 100644
--- a/pjsip/src/pjsip/sip_errno.c
+++ b/pjsip/src/pjsip/sip_errno.c
@@ -131,6 +131,7 @@ static const struct
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 92fbaf4d..ecfba2c9 100644
--- a/pjsip/src/pjsip/sip_transport.c
+++ b/pjsip/src/pjsip/sip_transport.c
@@ -866,7 +866,7 @@ PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
/*
* 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 @@ static pj_status_t destroy_transport( pjsip_tpmgr *mgr,
/*
* 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 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
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_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
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_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
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 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
/*
* 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 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
}
}
-
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 490a7bb3..f754f7fe 100644
--- a/pjsip/src/pjsip/sip_transport_loop.c
+++ b/pjsip/src/pjsip/sip_transport_loop.c
@@ -381,6 +381,7 @@ PJ_DEF(pj_status_t) pjsip_loop_start( pjsip_endpoint *endpt,
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 a7c7eeba..58e0ba41 100644
--- a/pjsip/src/pjsip/sip_transport_tcp.c
+++ b/pjsip/src/pjsip/sip_transport_tcp.c
@@ -584,6 +584,7 @@ static pj_status_t tcp_create( struct tcp_listener *listener,
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 @@ static pj_bool_t on_accept_complete(pj_activesock_t *asock,
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 a135c43f..0d4ef882 100644
--- a/pjsip/src/pjsip/sip_transport_tls.c
+++ b/pjsip/src/pjsip/sip_transport_tls.c
@@ -557,8 +557,6 @@ static pj_status_t tls_create( struct tls_listener *listener,
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 @@ static pj_status_t tls_create( struct tls_listener *listener,
(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 @@ static pj_bool_t on_accept_complete(pj_ssl_sock_t *ssock,
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 @@ static pj_bool_t on_accept_complete(pj_ssl_sock_t *ssock,
/* 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));
+ tls_info.ssl_sock_info = &ssl_info;
+ state_info.ext_info = &tls_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;
+ 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_ACCEPTED;
+ tp_state = PJSIP_TP_STATE_CONNECTED;
+ state_info.status = PJ_SUCCESS;
}
- tls_info.ssl_sock_info = &ssl_info;
- state_info.ext_info = &tls_info;
-
- tls_verif_ignored = (*state_cb)(&tls->base, tp_state, &state_info);
+ (*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 @@ static pj_bool_t on_connect_complete(pj_ssl_sock_t *ssock,
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 @@ static pj_bool_t on_connect_complete(pj_ssl_sock_t *ssock,
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 @@ static pj_bool_t on_connect_complete(pj_ssl_sock_t *ssock,
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 24e22945..20b15b91 100644
--- a/pjsip/src/pjsip/sip_transport_udp.c
+++ b/pjsip/src/pjsip/sip_transport_udp.c
@@ -736,6 +736,9 @@ static pj_status_t transport_attach( pjsip_endpoint *endpt,
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;