diff --git a/res/res_pjsip/pjsip_transport_management.c b/res/res_pjsip/pjsip_transport_management.c index a3cfde9920f77c07a28e58b1e56e6a053e9db935..af572d3b6fd1e30e3deb932bbfc5b464f70904af 100644 --- a/res/res_pjsip/pjsip_transport_management.c +++ b/res/res_pjsip/pjsip_transport_management.c @@ -139,34 +139,62 @@ static int idle_sched_init_pj_thread(void) 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) { - struct monitored_transport *monitored = (struct monitored_transport *) data; + char *obj_name = (char *) data; + struct monitored_transport *monitored; if (idle_sched_init_pj_thread()) { - ao2_ref(monitored, -1); + ast_free(obj_name); return 0; } - if (!monitored->sip_received) { - 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); + monitored = get_monitored_transport_by_name(obj_name); + if (monitored) { + if (!monitored->sip_received) { + 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; } 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); + ao2_ref(monitored, -1); } - ao2_ref(monitored, -1); + ast_free(obj_name); return 0; } @@ -203,13 +231,13 @@ static void monitored_transport_state_callback(pjsip_transport *transport, pjsip ao2_link(transports, monitored); if (transport->dir == PJSIP_TP_DIR_INCOMING) { - /* Let the scheduler inherit the reference from allocation */ - 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. */ + char *obj_name = ast_strdup(transport->obj_name); + + 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); - } else { - /* monitored ref successfully passed to idle_sched_cb() */ - break; + ast_free(obj_name); } } ao2_ref(monitored, -1); @@ -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) { - struct ao2_container *transports; struct monitored_transport *idle_trans; - transports = ao2_global_obj_ref(monitored_transports); - if (!transports) { - return PJ_FALSE; - } - - 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 = get_monitored_transport_by_name(rdata->tp_info.transport->obj_name); + if (idle_trans) { + idle_trans->sip_received = 1; + ao2_ref(idle_trans, -1); } - idle_trans->sip_received = 1; - ao2_ref(idle_trans, -1); - return PJ_FALSE; } diff --git a/res/res_pjsip_transport_websocket.c b/res/res_pjsip_transport_websocket.c index 73268eac9117cac1726593b235bc33d37a39bd0f..8bc078b02ea3ee56bfa1324c2c8be87f6a5503b7 100644 --- a/res/res_pjsip_transport_websocket.c +++ b/res/res_pjsip_transport_websocket.c @@ -41,6 +41,11 @@ static int transport_type_wss; 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 */ @@ -163,8 +168,8 @@ static int transport_create(void *data) } /* Give websocket transport a unique name for its lifetime */ - snprintf(newtransport->transport.obj_name, PJ_MAX_OBJ_NAME, "ws%p", - &newtransport->transport); + snprintf(newtransport->transport.obj_name, PJ_MAX_OBJ_NAME, "ws%p-%d", + &newtransport->transport, ast_atomic_fetchadd_int(&ws_obj_name_serial, 1)); newtransport->transport.endpt = endpt;