summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsip/sip_transport_tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip/src/pjsip/sip_transport_tcp.c')
-rw-r--r--pjsip/src/pjsip/sip_transport_tcp.c108
1 files changed, 85 insertions, 23 deletions
diff --git a/pjsip/src/pjsip/sip_transport_tcp.c b/pjsip/src/pjsip/sip_transport_tcp.c
index 70ae300e..1b55cdb0 100644
--- a/pjsip/src/pjsip/sip_transport_tcp.c
+++ b/pjsip/src/pjsip/sip_transport_tcp.c
@@ -61,6 +61,9 @@ struct tcp_listener
pj_qos_type qos_type;
pj_qos_params qos_params;
pj_sockopt_params sockopt_params;
+
+ /* Group lock to be used by TCP listener and ioqueue key */
+ pj_grp_lock_t *grp_lock;
};
@@ -115,6 +118,9 @@ struct tcp_transport
/* Pending transmission list. */
struct delayed_tdata delayed_list;
+
+ /* Group lock to be used by TCP transport and ioqueue key */
+ pj_grp_lock_t *grp_lock;
};
@@ -131,6 +137,9 @@ static pj_bool_t on_accept_complete(pj_activesock_t *asock,
/* 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,
@@ -399,6 +408,17 @@ PJ_DEF(pj_status_t) pjsip_tcp_transport_start3(
else
asock_cfg.async_cnt = cfg->async_cnt;
+ /* Create group lock */
+ status = pj_grp_lock_create(pool, NULL, &listener->grp_lock);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ pj_grp_lock_add_ref(listener->grp_lock);
+ pj_grp_lock_add_handler(listener->grp_lock, pool, listener,
+ &lis_on_destroy);
+
+ asock_cfg.grp_lock = listener->grp_lock;
+
pj_bzero(&listener_cb, sizeof(listener_cb));
listener_cb.on_accept_complete = &on_accept_complete;
status = pj_activesock_create(pool, sock, pj_SOCK_STREAM(), &asock_cfg,
@@ -485,6 +505,27 @@ PJ_DEF(pj_status_t) pjsip_tcp_transport_start( pjsip_endpoint *endpt,
}
+/* Clean up listener resources */
+static void lis_on_destroy(void *arg)
+{
+ struct tcp_listener *listener = (struct tcp_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 TCP 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)
{
@@ -500,18 +541,13 @@ static pj_status_t lis_destroy(pjsip_tpfactory *factory)
listener->asock = 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 TCP 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;
@@ -563,6 +599,9 @@ static pj_bool_t on_connect_complete(pj_activesock_t *asock,
/* TCP keep-alive timer callback */
static void tcp_keep_alive_timer(pj_timer_heap_t *th, pj_timer_entry *e);
+/* Clean up TCP resources */
+static void tcp_on_destroy(void *arg);
+
/*
* Common function to create TCP transport, called when pending accept() and
* pending connect() complete.
@@ -640,9 +679,18 @@ static pj_status_t tcp_create( struct tcp_listener *listener,
tcp->base.do_shutdown = &tcp_shutdown;
tcp->base.destroy = &tcp_destroy_transport;
+ /* Create group lock */
+ status = pj_grp_lock_create(pool, NULL, &tcp->grp_lock);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ pj_grp_lock_add_ref(tcp->grp_lock);
+ pj_grp_lock_add_handler(tcp->grp_lock, pool, tcp, &tcp_on_destroy);
+
/* Create active socket */
pj_activesock_cfg_default(&asock_cfg);
asock_cfg.async_cnt = 1;
+ asock_cfg.grp_lock = tcp->grp_lock;
pj_bzero(&tcp_callback, sizeof(tcp_callback));
tcp_callback.on_data_read = &on_data_read;
@@ -780,11 +828,6 @@ static pj_status_t tcp_destroy(pjsip_transport *transport,
on_data_sent(tcp->asock, op_key, -reason);
}
- if (tcp->rdata.tp_info.pool) {
- pj_pool_release(tcp->rdata.tp_info.pool);
- tcp->rdata.tp_info.pool = NULL;
- }
-
if (tcp->asock) {
pj_activesock_close(tcp->asock);
tcp->asock = NULL;
@@ -794,6 +837,23 @@ static pj_status_t tcp_destroy(pjsip_transport *transport,
tcp->sock = PJ_INVALID_SOCKET;
}
+ if (tcp->grp_lock) {
+ pj_grp_lock_t *grp_lock = tcp->grp_lock;
+ tcp->grp_lock = NULL;
+ pj_grp_lock_dec_ref(grp_lock);
+ /* Transport may have been deleted at this point */
+ } else {
+ tcp_on_destroy(tcp);
+ }
+
+ return PJ_SUCCESS;
+}
+
+/* Clean up TCP resources */
+static void tcp_on_destroy(void *arg)
+{
+ struct tcp_transport *tcp = (struct tcp_transport*)arg;
+
if (tcp->base.lock) {
pj_lock_destroy(tcp->base.lock);
tcp->base.lock = NULL;
@@ -804,16 +864,21 @@ static pj_status_t tcp_destroy(pjsip_transport *transport,
tcp->base.ref_cnt = NULL;
}
+ if (tcp->rdata.tp_info.pool) {
+ pj_pool_release(tcp->rdata.tp_info.pool);
+ tcp->rdata.tp_info.pool = NULL;
+ }
+
if (tcp->base.pool) {
pj_pool_t *pool;
- if (reason != PJ_SUCCESS) {
+ if (tcp->close_reason != PJ_SUCCESS) {
char errmsg[PJ_ERR_MSG_SIZE];
- pj_strerror(reason, errmsg, sizeof(errmsg));
+ pj_strerror(tcp->close_reason, errmsg, sizeof(errmsg));
PJ_LOG(4,(tcp->base.obj_name,
"TCP transport destroyed with reason %d: %s",
- reason, errmsg));
+ tcp->close_reason, errmsg));
} else {
@@ -826,11 +891,8 @@ static pj_status_t tcp_destroy(pjsip_transport *transport,
tcp->base.pool = NULL;
pj_pool_release(pool);
}
-
- return PJ_SUCCESS;
}
-
/*
* This utility function creates receive data buffers and start
* asynchronous recv() operations from the socket. It is called after