Skip to content
Snippets Groups Projects
Commit 06df43f6 authored by Friendly Automation's avatar Friendly Automation Committed by Gerrit Code Review
Browse files

Merge "pjsip_transport_management: Shutdown transport immediately on disconnect" into 13

parents 128b90a4 9cd61610
No related branches found
No related tags found
No related merge requests found
...@@ -139,34 +139,62 @@ static int idle_sched_init_pj_thread(void) ...@@ -139,34 +139,62 @@ static int idle_sched_init_pj_thread(void)
return 0; return 0;
} }
static struct monitored_transport *get_monitored_transport_by_name(const char *obj_name)
{
struct ao2_container *transports;
struct monitored_transport *monitored = NULL;
transports = ao2_global_obj_ref(monitored_transports);
if (transports) {
monitored = ao2_find(transports, obj_name, OBJ_SEARCH_KEY);
}
ao2_cleanup(transports);
/* Caller is responsible for cleaning up reference */
return monitored;
}
static int idle_sched_cb(const void *data) static int idle_sched_cb(const void *data)
{ {
struct monitored_transport *monitored = (struct monitored_transport *) data; char *obj_name = (char *) data;
struct monitored_transport *monitored;
if (idle_sched_init_pj_thread()) { if (idle_sched_init_pj_thread()) {
ao2_ref(monitored, -1); ast_free(obj_name);
return 0; return 0;
} }
if (!monitored->sip_received) { monitored = get_monitored_transport_by_name(obj_name);
ast_log(LOG_NOTICE, "Shutting down transport '%s' since no request was received in %d seconds\n", if (monitored) {
monitored->transport->info, IDLE_TIMEOUT / 1000); if (!monitored->sip_received) {
pjsip_transport_shutdown(monitored->transport); ast_log(LOG_NOTICE, "Shutting down transport '%s' since no request was received in %d seconds\n",
monitored->transport->info, IDLE_TIMEOUT / 1000);
pjsip_transport_shutdown(monitored->transport);
}
ao2_ref(monitored, -1);
} }
ao2_ref(monitored, -1); ast_free(obj_name);
return 0; return 0;
} }
static int idle_sched_cleanup(const void *data) static int idle_sched_cleanup(const void *data)
{ {
struct monitored_transport *monitored = (struct monitored_transport *) data; char *obj_name = (char *) data;
struct monitored_transport *monitored;
if (!idle_sched_init_pj_thread()) { if (idle_sched_init_pj_thread()) {
ast_free(obj_name);
return 0;
}
monitored = get_monitored_transport_by_name(obj_name);
if (monitored) {
pjsip_transport_shutdown(monitored->transport); pjsip_transport_shutdown(monitored->transport);
ao2_ref(monitored, -1);
} }
ao2_ref(monitored, -1);
ast_free(obj_name);
return 0; return 0;
} }
...@@ -203,13 +231,13 @@ static void monitored_transport_state_callback(pjsip_transport *transport, pjsip ...@@ -203,13 +231,13 @@ static void monitored_transport_state_callback(pjsip_transport *transport, pjsip
ao2_link(transports, monitored); ao2_link(transports, monitored);
if (transport->dir == PJSIP_TP_DIR_INCOMING) { if (transport->dir == PJSIP_TP_DIR_INCOMING) {
/* Let the scheduler inherit the reference from allocation */ char *obj_name = ast_strdup(transport->obj_name);
if (ast_sched_add_variable(sched, IDLE_TIMEOUT, idle_sched_cb, monitored, 1) < 0) {
/* Uh Oh. Could not schedule the idle check. Kill the transport. */ if (!obj_name
|| ast_sched_add_variable(sched, IDLE_TIMEOUT, idle_sched_cb, obj_name, 1) < 0) {
/* Shut down the transport if anything fails */
pjsip_transport_shutdown(transport); pjsip_transport_shutdown(transport);
} else { ast_free(obj_name);
/* monitored ref successfully passed to idle_sched_cb() */
break;
} }
} }
ao2_ref(monitored, -1); ao2_ref(monitored, -1);
...@@ -324,23 +352,14 @@ static struct ast_sorcery_observer keepalive_global_observer = { ...@@ -324,23 +352,14 @@ static struct ast_sorcery_observer keepalive_global_observer = {
*/ */
static pj_bool_t idle_monitor_on_rx_request(pjsip_rx_data *rdata) static pj_bool_t idle_monitor_on_rx_request(pjsip_rx_data *rdata)
{ {
struct ao2_container *transports;
struct monitored_transport *idle_trans; struct monitored_transport *idle_trans;
transports = ao2_global_obj_ref(monitored_transports); idle_trans = get_monitored_transport_by_name(rdata->tp_info.transport->obj_name);
if (!transports) { if (idle_trans) {
return PJ_FALSE; idle_trans->sip_received = 1;
} ao2_ref(idle_trans, -1);
idle_trans = ao2_find(transports, rdata->tp_info.transport->obj_name, OBJ_SEARCH_KEY);
ao2_ref(transports, -1);
if (!idle_trans) {
return PJ_FALSE;
} }
idle_trans->sip_received = 1;
ao2_ref(idle_trans, -1);
return PJ_FALSE; return PJ_FALSE;
} }
......
...@@ -41,6 +41,11 @@ ...@@ -41,6 +41,11 @@
static int transport_type_wss; static int transport_type_wss;
static int transport_type_wss_ipv6; static int transport_type_wss_ipv6;
/*!
* Used to ensure uniqueness among WS transport names
*/
static int ws_obj_name_serial;
/*! /*!
* \brief Wrapper for pjsip_transport, for storing the WebSocket session * \brief Wrapper for pjsip_transport, for storing the WebSocket session
*/ */
...@@ -163,8 +168,8 @@ static int transport_create(void *data) ...@@ -163,8 +168,8 @@ static int transport_create(void *data)
} }
/* Give websocket transport a unique name for its lifetime */ /* Give websocket transport a unique name for its lifetime */
snprintf(newtransport->transport.obj_name, PJ_MAX_OBJ_NAME, "ws%p", snprintf(newtransport->transport.obj_name, PJ_MAX_OBJ_NAME, "ws%p-%d",
&newtransport->transport); &newtransport->transport, ast_atomic_fetchadd_int(&ws_obj_name_serial, 1));
newtransport->transport.endpt = endpt; newtransport->transport.endpt = endpt;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment