summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsip/sip_transport_tls.c
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip/src/pjsip/sip_transport_tls.c')
-rw-r--r--pjsip/src/pjsip/sip_transport_tls.c179
1 files changed, 129 insertions, 50 deletions
diff --git a/pjsip/src/pjsip/sip_transport_tls.c b/pjsip/src/pjsip/sip_transport_tls.c
index a86b398c..4e890e10 100644
--- a/pjsip/src/pjsip/sip_transport_tls.c
+++ b/pjsip/src/pjsip/sip_transport_tls.c
@@ -58,6 +58,9 @@ struct tls_listener
pj_sockaddr bound_addr;
pj_ssl_cert_t *cert;
pjsip_tls_setting tls_setting;
+
+ /* Group lock to be used by TLS transport and ioqueue key */
+ pj_grp_lock_t *grp_lock;
};
@@ -106,6 +109,9 @@ struct tls_transport
/* Pending transmission list. */
struct delayed_tdata delayed_list;
+
+ /* Group lock to be used by TLS transport and ioqueue key */
+ pj_grp_lock_t *grp_lock;
};
@@ -134,6 +140,9 @@ static pj_bool_t on_data_sent(pj_ssl_sock_t *ssock,
/* This callback is called by transport manager to destroy listener */
static pj_status_t lis_destroy(pjsip_tpfactory *factory);
+/* Clean up listener resources (group lock handler) */
+static void lis_on_destroy(void *arg);
+
/* This callback is called by transport manager to create transport */
static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
pjsip_tpmgr *mgr,
@@ -376,6 +385,18 @@ PJ_DEF(pj_status_t) pjsip_tls_transport_start2( pjsip_endpoint *endpt,
break;
}
+ /* Create group lock */
+ status = pj_grp_lock_create(pool, NULL, &listener->grp_lock);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Setup group lock handler */
+ pj_grp_lock_add_ref(listener->grp_lock);
+ pj_grp_lock_add_handler(listener->grp_lock, pool, listener,
+ &lis_on_destroy);
+
+ ssock_param.grp_lock = listener->grp_lock;
+
/* Create SSL socket */
status = pj_ssl_sock_create(pool, &ssock_param, &listener->ssock);
if (status != PJ_SUCCESS)
@@ -509,6 +530,27 @@ on_error:
}
+/* Clean up listener resources */
+static void lis_on_destroy(void *arg)
+{
+ struct tls_listener *listener = (struct tls_listener*)arg;
+
+ if (listener->factory.lock) {
+ pj_lock_destroy(listener->factory.lock);
+ listener->factory.lock = NULL;
+ }
+
+ if (listener->factory.pool) {
+ pj_pool_t *pool = listener->factory.pool;
+
+ PJ_LOG(4,(listener->factory.obj_name, "SIP TLS listener destroyed"));
+
+ listener->factory.pool = NULL;
+ pj_pool_release(pool);
+ }
+}
+
+
/* This callback is called by transport manager to destroy listener */
static pj_status_t lis_destroy(pjsip_tpfactory *factory)
{
@@ -524,18 +566,13 @@ static pj_status_t lis_destroy(pjsip_tpfactory *factory)
listener->ssock = NULL;
}
- if (listener->factory.lock) {
- pj_lock_destroy(listener->factory.lock);
- listener->factory.lock = NULL;
- }
-
- if (listener->factory.pool) {
- pj_pool_t *pool = listener->factory.pool;
-
- PJ_LOG(4,(listener->factory.obj_name, "SIP TLS listener destroyed"));
-
- listener->factory.pool = NULL;
- pj_pool_release(pool);
+ if (listener->grp_lock) {
+ pj_grp_lock_t *grp_lock = listener->grp_lock;
+ listener->grp_lock = NULL;
+ pj_grp_lock_dec_ref(grp_lock);
+ /* Listener may have been deleted at this point */
+ } else {
+ lis_on_destroy(listener);
}
return PJ_SUCCESS;
@@ -752,6 +789,50 @@ static pj_status_t tls_destroy_transport(pjsip_transport *transport)
}
+/* Clean up TLS resources */
+static void tls_on_destroy(void *arg)
+{
+ struct tls_transport *tls = (struct tls_transport*)arg;
+
+ if (tls->rdata.tp_info.pool) {
+ pj_pool_release(tls->rdata.tp_info.pool);
+ tls->rdata.tp_info.pool = NULL;
+ }
+
+ if (tls->base.lock) {
+ pj_lock_destroy(tls->base.lock);
+ tls->base.lock = NULL;
+ }
+
+ if (tls->base.ref_cnt) {
+ pj_atomic_destroy(tls->base.ref_cnt);
+ tls->base.ref_cnt = NULL;
+ }
+
+ if (tls->base.pool) {
+ pj_pool_t *pool;
+
+ if (tls->close_reason != PJ_SUCCESS) {
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(tls->close_reason, errmsg, sizeof(errmsg));
+ PJ_LOG(4,(tls->base.obj_name,
+ "TLS transport destroyed with reason %d: %s",
+ tls->close_reason, errmsg));
+
+ } else {
+
+ PJ_LOG(4,(tls->base.obj_name,
+ "TLS transport destroyed normally"));
+
+ }
+
+ pool = tls->base.pool;
+ tls->base.pool = NULL;
+ pj_pool_release(pool);
+ }
+}
+
/* Destroy TLS transport */
static pj_status_t tls_destroy(pjsip_transport *transport,
pj_status_t reason)
@@ -793,46 +874,18 @@ static pj_status_t tls_destroy(pjsip_transport *transport,
on_data_sent(tls->ssock, op_key, -reason);
}
- if (tls->rdata.tp_info.pool) {
- pj_pool_release(tls->rdata.tp_info.pool);
- tls->rdata.tp_info.pool = NULL;
- }
-
if (tls->ssock) {
pj_ssl_sock_close(tls->ssock);
tls->ssock = NULL;
}
- if (tls->base.lock) {
- pj_lock_destroy(tls->base.lock);
- tls->base.lock = NULL;
- }
-
- if (tls->base.ref_cnt) {
- pj_atomic_destroy(tls->base.ref_cnt);
- tls->base.ref_cnt = NULL;
- }
-
- if (tls->base.pool) {
- pj_pool_t *pool;
-
- if (reason != PJ_SUCCESS) {
- char errmsg[PJ_ERR_MSG_SIZE];
-
- pj_strerror(reason, errmsg, sizeof(errmsg));
- PJ_LOG(4,(tls->base.obj_name,
- "TLS transport destroyed with reason %d: %s",
- reason, errmsg));
-
- } else {
- PJ_LOG(4,(tls->base.obj_name,
- "TLS transport destroyed normally"));
-
- }
-
- pool = tls->base.pool;
- tls->base.pool = NULL;
- pj_pool_release(pool);
+ if (tls->grp_lock) {
+ pj_grp_lock_t *grp_lock = tls->grp_lock;
+ tls->grp_lock = NULL;
+ pj_grp_lock_dec_ref(grp_lock);
+ /* Transport may have been deleted at this point */
+ } else {
+ tls_on_destroy(tls);
}
return PJ_SUCCESS;
@@ -906,6 +959,7 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
struct tls_listener *listener;
struct tls_transport *tls;
pj_pool_t *pool;
+ pj_grp_lock_t *glock;
pj_ssl_sock_t *ssock;
pj_ssl_sock_param ssock_param;
pj_sockaddr local_addr;
@@ -985,15 +1039,25 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
break;
}
- status = pj_ssl_sock_create(pool, &ssock_param, &ssock);
+ /* Create group lock */
+ status = pj_grp_lock_create(pool, NULL, &glock);
if (status != PJ_SUCCESS)
return status;
+ ssock_param.grp_lock = glock;
+ status = pj_ssl_sock_create(pool, &ssock_param, &ssock);
+ if (status != PJ_SUCCESS) {
+ pj_grp_lock_destroy(glock);
+ return status;
+ }
+
/* Apply SSL certificate */
if (listener->cert) {
status = pj_ssl_sock_set_certificate(ssock, pool, listener->cert);
- if (status != PJ_SUCCESS)
+ if (status != PJ_SUCCESS) {
+ pj_grp_lock_destroy(glock);
return status;
+ }
}
/* Initially set bind address to listener's bind address */
@@ -1004,12 +1068,19 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
/* Create the transport descriptor */
status = tls_create(listener, pool, ssock, PJ_FALSE, &local_addr,
rem_addr, &remote_name, &tls);
- if (status != PJ_SUCCESS)
+ if (status != PJ_SUCCESS) {
+ pj_grp_lock_destroy(glock);
return status;
+ }
/* Set the "pending" SSL socket user data */
pj_ssl_sock_set_user_data(tls->ssock, tls);
+ /* Set up the group lock */
+ tls->grp_lock = glock;
+ pj_grp_lock_add_ref(tls->grp_lock);
+ pj_grp_lock_add_handler(tls->grp_lock, pool, tls, &tls_on_destroy);
+
/* Start asynchronous connect() operation */
tls->has_pending_connect = PJ_TRUE;
status = pj_ssl_sock_start_connect(tls->ssock, tls->base.pool,
@@ -1130,6 +1201,14 @@ 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);
+ /* Set up the group lock */
+ if (ssl_info.grp_lock) {
+ tls->grp_lock = ssl_info.grp_lock;
+ pj_grp_lock_add_ref(tls->grp_lock);
+ pj_grp_lock_add_handler(tls->grp_lock, tls->base.pool, tls,
+ &tls_on_destroy);
+ }
+
/* Prevent immediate transport destroy as application may access it
* (getting info, etc) in transport state notification callback.
*/