<p>Richard Mudgett has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/6200">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_pjsip: PJSIP Transport state monitor refactor.<br><br>The fix for the issue is broken up into three parts.<br><br>This is part one which refactors the transport state monitor code to allow<br>more modules to be able to monitor transports.<br><br>* Pull the management of PJPROJECT's transport state callback code from<br>res_pjsip_transport_management.c into res_pjsip. Now other modules can<br>dynamically add and remove themselves from transport monitoring without<br>worrying about breaking PJPROJECT's callback chain.<br><br>* Add the ability for other modules to get a callback whenever a specific<br>transport is shutdown.<br><br>ASTERISK-27147<br><br>Change-Id: I7d9a31371eb1487c9b7050cf82a9af5180a57912<br>---<br>M include/asterisk/res_pjsip.h<br>M res/res_pjsip.c<br>M res/res_pjsip/include/res_pjsip_private.h<br>A res/res_pjsip/pjsip_transport_events.c<br>M res/res_pjsip_transport_management.c<br>5 files changed, 493 insertions(+), 30 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/00/6200/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h<br>index 890ce59..31db367 100644<br>--- a/include/asterisk/res_pjsip.h<br>+++ b/include/asterisk/res_pjsip.h<br>@@ -2926,4 +2926,91 @@<br> */<br> int ast_sip_str_to_dtmf(const char *dtmf_mode);<br> <br>+/*!<br>+ * \brief Transport shutdown monitor callback.<br>+ * \since 13.18.0<br>+ *<br>+ * \param data User data to know what to do when transport shuts down.<br>+ *<br>+ * \note The callback does not need to care that data is an ao2 object.<br>+ *<br>+ * \return Nothing<br>+ */<br>+typedef void (*ast_transport_monitor_shutdown_cb)(void *data);<br>+<br>+enum ast_transport_monitor_reg {<br>+ /*! \brief Successfully registered the transport monitor */<br>+ AST_TRANSPORT_MONITOR_REG_SUCCESS,<br>+ /*! \brief Replaced the already existing transport monitor with new one. */<br>+ AST_TRANSPORT_MONITOR_REG_REPLACED,<br>+ /*!<br>+ * \brief Transport not found to monitor.<br>+ * \note Transport is either already shutdown or is not reliable.<br>+ */<br>+ AST_TRANSPORT_MONITOR_REG_NOT_FOUND,<br>+ /*! \brief Error while registering transport monitor. */<br>+ AST_TRANSPORT_MONITOR_REG_FAILED,<br>+};<br>+<br>+/*!<br>+ * \brief Register a reliable transport shutdown monitor callback.<br>+ * \since 13.18.0<br>+ *<br>+ * \param transport Transport to monitor for shutdown.<br>+ * \param cb Who to call when transport is shutdown.<br>+ * \param ao2_data Data to pass with the callback.<br>+ *<br>+ * \return enum ast_transport_monitor_reg<br>+ */<br>+enum ast_transport_monitor_reg ast_sip_transport_monitor_register(pjsip_transport *transport,<br>+ ast_transport_monitor_shutdown_cb cb, void *ao2_data);<br>+<br>+/*!<br>+ * \brief Unregister a reliable transport shutdown monitor callback.<br>+ * \since 13.18.0<br>+ *<br>+ * \param transport Transport to monitor for shutdown.<br>+ * \param cb Who to call when transport is shutdown.<br>+ *<br>+ * \return Nothing<br>+ */<br>+void ast_sip_transport_monitor_unregister(pjsip_transport *transport, ast_transport_monitor_shutdown_cb cb);<br>+<br>+/*!<br>+ * \brief Unregister monitor callback from all reliable transports.<br>+ * \since 13.18.0<br>+ *<br>+ * \param cb Who to call when a transport is shutdown.<br>+ *<br>+ * \return Nothing<br>+ */<br>+void ast_sip_transport_monitor_unregister_all(ast_transport_monitor_shutdown_cb cb);<br>+<br>+/*! Transport state notification registration element. */<br>+struct ast_sip_tpmgr_state_callback {<br>+ /*! PJPROJECT transport state notification callback */<br>+ pjsip_tp_state_callback cb;<br>+ AST_LIST_ENTRY(ast_sip_tpmgr_state_callback) node;<br>+};<br>+<br>+/*!<br>+ * \brief Register a transport state notification callback element.<br>+ * \since 13.18.0<br>+ *<br>+ * \param element What we are registering.<br>+ *<br>+ * \return Nothing<br>+ */<br>+void ast_sip_transport_state_register(struct ast_sip_tpmgr_state_callback *element);<br>+<br>+/*!<br>+ * \brief Unregister a transport state notification callback element.<br>+ * \since 13.18.0<br>+ *<br>+ * \param element What we are unregistering.<br>+ *<br>+ * \return Nothing<br>+ */<br>+void ast_sip_transport_state_unregister(struct ast_sip_tpmgr_state_callback *element);<br>+<br> #endif /* _RES_PJSIP_H */<br>diff --git a/res/res_pjsip.c b/res/res_pjsip.c<br>index f3648ac..2917df3 100644<br>--- a/res/res_pjsip.c<br>+++ b/res/res_pjsip.c<br>@@ -4662,6 +4662,7 @@<br> ast_sip_destroy_system();<br> ast_sip_destroy_global_headers();<br> internal_sip_unregister_service(&supplement_module);<br>+ ast_sip_destroy_transport_events();<br> }<br> <br> if (monitor_thread) {<br>@@ -4740,7 +4741,6 @@<br> return AST_MODULE_LOAD_SUCCESS;<br> <br> error:<br>- unload_pjsip(NULL);<br> return AST_MODULE_LOAD_DECLINE;<br> }<br> <br>@@ -4806,6 +4806,11 @@<br> goto error;<br> }<br> <br>+ if (ast_sip_initialize_transport_events()) {<br>+ ast_log(LOG_ERROR, "Failed to initialize SIP transport monitor. Aborting load\n");<br>+ goto error;<br>+ }<br>+<br> ast_sip_initialize_dns();<br> <br> ast_sip_initialize_global_headers();<br>diff --git a/res/res_pjsip/include/res_pjsip_private.h b/res/res_pjsip/include/res_pjsip_private.h<br>index 0bdb633..2969f0e 100644<br>--- a/res/res_pjsip/include/res_pjsip_private.h<br>+++ b/res/res_pjsip/include/res_pjsip_private.h<br>@@ -135,6 +135,29 @@<br> <br> /*!<br> * \internal<br>+ * \brief Initialize the transport events notify module<br>+ * \since 13.18.0<br>+ *<br>+ * The transport events notify module is responsible for monitoring<br>+ * when transports die and calling any registered callbacks when that<br>+ * happens. It also manages any PJPROJECT transport state callbacks<br>+ * registered to it so the callbacks be more dynamic allowing module<br>+ * loading/unloading.<br>+ *<br>+ * \retval -1 Failure<br>+ * \retval 0 Success<br>+ */<br>+int ast_sip_initialize_transport_events(void);<br>+<br>+/*!<br>+ * \internal<br>+ * \brief Destruct the transport events notify module.<br>+ * \since 13.18.0<br>+ */<br>+void ast_sip_destroy_transport_events(void);<br>+<br>+/*!<br>+ * \internal<br> * \brief Initialize global type on a sorcery instance<br> *<br> * \retval -1 failure<br>diff --git a/res/res_pjsip/pjsip_transport_events.c b/res/res_pjsip/pjsip_transport_events.c<br>new file mode 100644<br>index 0000000..0f57303<br>--- /dev/null<br>+++ b/res/res_pjsip/pjsip_transport_events.c<br>@@ -0,0 +1,366 @@<br>+/*<br>+ * Asterisk -- An open source telephony toolkit.<br>+ *<br>+ * Copyright (C) 2017, Digium Inc.<br>+ *<br>+ * Richard Mudgett <rmudgett@digium.com><br>+ *<br>+ * See http://www.asterisk.org for more information about<br>+ * the Asterisk project. Please do not directly contact<br>+ * any of the maintainers of this project for assistance;<br>+ * the project provides a web site, mailing lists and IRC<br>+ * channels for your use.<br>+ *<br>+ * This program is free software, distributed under the terms of<br>+ * the GNU General Public License Version 2. See the LICENSE file<br>+ * at the top of the source tree.<br>+ */<br>+<br>+/*!<br>+ * \file<br>+ * \brief Manages the global transport event notification callbacks.<br>+ *<br>+ * \author Richard Mudgett <rmudgett@digium.com><br>+ * See Also:<br>+ *<br>+ * \arg \ref AstCREDITS<br>+ */<br>+<br>+<br>+#include "asterisk.h"<br>+<br>+#include "asterisk/res_pjsip.h"<br>+#include "include/res_pjsip_private.h"<br>+#include "asterisk/linkedlists.h"<br>+#include "asterisk/vector.h"<br>+<br>+/* ------------------------------------------------------------------- */<br>+<br>+/*! \brief Number of buckets for monitored active transports */<br>+#define ACTIVE_TRANSPORTS_BUCKETS 127<br>+<br>+/*! Who to notify when transport shuts down. */<br>+struct transport_monitor_notifier {<br>+ /*! Who to call when transport shuts down. */<br>+ ast_transport_monitor_shutdown_cb cb;<br>+ /*! ao2 data object to pass to callback. */<br>+ void *data;<br>+};<br>+<br>+/*! \brief Structure for transport to be monitored */<br>+struct transport_monitor {<br>+ /*! \brief The underlying PJSIP transport */<br>+ pjsip_transport *transport;<br>+ /*! Who is interested in when this transport shuts down. */<br>+ AST_VECTOR(, struct transport_monitor_notifier) monitors;<br>+};<br>+<br>+/*! \brief Global container of active reliable transports */<br>+static AO2_GLOBAL_OBJ_STATIC(active_transports);<br>+<br>+/*! \brief Existing transport events callback that we need to invoke */<br>+static pjsip_tp_state_callback tpmgr_state_callback;<br>+<br>+/*! List of registered transport state callbacks. */<br>+static AST_RWLIST_HEAD(, ast_sip_tpmgr_state_callback) transport_state_list;<br>+<br>+<br>+/*! \brief Hashing function for struct transport_monitor */<br>+AO2_STRING_FIELD_HASH_FN(transport_monitor, transport->obj_name);<br>+<br>+/*! \brief Comparison function for struct transport_monitor */<br>+AO2_STRING_FIELD_CMP_FN(transport_monitor, transport->obj_name);<br>+<br>+static const char *transport_state2str(pjsip_transport_state state)<br>+{<br>+ const char *name;<br>+<br>+ switch (state) {<br>+ case PJSIP_TP_STATE_CONNECTED:<br>+ name = "CONNECTED";<br>+ break;<br>+ case PJSIP_TP_STATE_DISCONNECTED:<br>+ name = "DISCONNECTED";<br>+ break;<br>+ case PJSIP_TP_STATE_SHUTDOWN:<br>+ name = "SHUTDOWN";<br>+ break;<br>+ case PJSIP_TP_STATE_DESTROY:<br>+ name = "DESTROY";<br>+ break;<br>+ default:<br>+ /*<br>+ * We have to have a default case because the enum is<br>+ * defined by a third-party library.<br>+ */<br>+ ast_assert(0);<br>+ name = "<unknown>";<br>+ break;<br>+ }<br>+ return name;<br>+}<br>+<br>+static void transport_monitor_dtor(void *vdoomed)<br>+{<br>+ struct transport_monitor *monitored = vdoomed;<br>+ int idx;<br>+<br>+ for (idx = AST_VECTOR_SIZE(&monitored->monitors); idx--;) {<br>+ struct transport_monitor_notifier *notifier;<br>+<br>+ notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);<br>+ ao2_cleanup(notifier->data);<br>+ }<br>+ AST_VECTOR_FREE(&monitored->monitors);<br>+}<br>+<br>+/*! \brief Callback invoked when transport state changes occur */<br>+static void transport_state_callback(pjsip_transport *transport,<br>+ pjsip_transport_state state, const pjsip_transport_state_info *info)<br>+{<br>+ struct ao2_container *transports;<br>+<br>+ /* We only care about monitoring reliable transports */<br>+ if (PJSIP_TRANSPORT_IS_RELIABLE(transport)<br>+ && (transports = ao2_global_obj_ref(active_transports))) {<br>+ struct transport_monitor *monitored;<br>+<br>+ ast_debug(3, "Reliable transport '%s' state:%s\n",<br>+ transport->obj_name, transport_state2str(state));<br>+ switch (state) {<br>+ case PJSIP_TP_STATE_CONNECTED:<br>+ monitored = ao2_alloc_options(sizeof(*monitored),<br>+ transport_monitor_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);<br>+ if (!monitored) {<br>+ break;<br>+ }<br>+ monitored->transport = transport;<br>+ if (AST_VECTOR_INIT(&monitored->monitors, 2)) {<br>+ ao2_ref(monitored, -1);<br>+ break;<br>+ }<br>+<br>+ ao2_link(transports, monitored);<br>+ ao2_ref(monitored, -1);<br>+ break;<br>+ case PJSIP_TP_STATE_DISCONNECTED:<br>+ if (!transport->is_shutdown) {<br>+ pjsip_transport_shutdown(transport);<br>+ }<br>+ break;<br>+ case PJSIP_TP_STATE_SHUTDOWN:<br>+ /*<br>+ * Set shutdown flag early so we can force a new transport to be<br>+ * created if a monitor callback needs to reestablish a link.<br>+ * PJPROJECT sets the flag after this routine returns even though<br>+ * it has already called the transport's shutdown routine.<br>+ */<br>+ transport->is_shutdown = PJ_TRUE;<br>+<br>+ monitored = ao2_find(transports, transport->obj_name,<br>+ OBJ_SEARCH_KEY | OBJ_UNLINK);<br>+ if (monitored) {<br>+ int idx;<br>+<br>+ for (idx = AST_VECTOR_SIZE(&monitored->monitors); idx--;) {<br>+ struct transport_monitor_notifier *notifier;<br>+<br>+ notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);<br>+ notifier->cb(notifier->data);<br>+ }<br>+ ao2_ref(monitored, -1);<br>+ }<br>+ break;<br>+ default:<br>+ break;<br>+ }<br>+<br>+ ao2_ref(transports, -1);<br>+ }<br>+<br>+ /* Loop over other transport state callbacks registered with us. */<br>+ if (!AST_LIST_EMPTY(&transport_state_list)) {<br>+ struct ast_sip_tpmgr_state_callback *tpmgr_notifier;<br>+<br>+ AST_RWLIST_RDLOCK(&transport_state_list);<br>+ AST_LIST_TRAVERSE(&transport_state_list, tpmgr_notifier, node) {<br>+ tpmgr_notifier->cb(transport, state, info);<br>+ }<br>+ AST_RWLIST_UNLOCK(&transport_state_list);<br>+ }<br>+<br>+ /* Forward to the old state callback if present */<br>+ if (tpmgr_state_callback) {<br>+ tpmgr_state_callback(transport, state, info);<br>+ }<br>+}<br>+<br>+static int transport_monitor_unregister_all(void *obj, void *arg, int flags)<br>+{<br>+ struct transport_monitor *monitored = obj;<br>+ ast_transport_monitor_shutdown_cb cb = arg;<br>+ int idx;<br>+<br>+ for (idx = AST_VECTOR_SIZE(&monitored->monitors); idx--;) {<br>+ struct transport_monitor_notifier *notifier;<br>+<br>+ notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);<br>+ if (notifier->cb == cb) {<br>+ ao2_cleanup(notifier->data);<br>+ AST_VECTOR_REMOVE_UNORDERED(&monitored->monitors, idx);<br>+ break;<br>+ }<br>+ }<br>+ return 0;<br>+}<br>+<br>+void ast_sip_transport_monitor_unregister_all(ast_transport_monitor_shutdown_cb cb)<br>+{<br>+ struct ao2_container *transports;<br>+<br>+ transports = ao2_global_obj_ref(active_transports);<br>+ if (!transports) {<br>+ return;<br>+ }<br>+ ao2_callback(transports, OBJ_MULTIPLE | OBJ_NODATA, transport_monitor_unregister_all,<br>+ cb);<br>+ ao2_ref(transports, -1);<br>+}<br>+<br>+void ast_sip_transport_monitor_unregister(pjsip_transport *transport, ast_transport_monitor_shutdown_cb cb)<br>+{<br>+ struct ao2_container *transports;<br>+ struct transport_monitor *monitored;<br>+<br>+ transports = ao2_global_obj_ref(active_transports);<br>+ if (!transports) {<br>+ return;<br>+ }<br>+<br>+ ao2_lock(transports);<br>+ monitored = ao2_find(transports, transport->obj_name, OBJ_SEARCH_KEY | OBJ_NOLOCK);<br>+ if (monitored) {<br>+ int idx;<br>+<br>+ for (idx = AST_VECTOR_SIZE(&monitored->monitors); idx--;) {<br>+ struct transport_monitor_notifier *notifier;<br>+<br>+ notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);<br>+ if (notifier->cb == cb) {<br>+ ao2_cleanup(notifier->data);<br>+ AST_VECTOR_REMOVE_UNORDERED(&monitored->monitors, idx);<br>+ break;<br>+ }<br>+ }<br>+ ao2_ref(monitored, -1);<br>+ }<br>+ ao2_unlock(transports);<br>+ ao2_ref(transports, -1);<br>+}<br>+<br>+enum ast_transport_monitor_reg ast_sip_transport_monitor_register(pjsip_transport *transport,<br>+ ast_transport_monitor_shutdown_cb cb, void *ao2_data)<br>+{<br>+ struct ao2_container *transports;<br>+ struct transport_monitor *monitored;<br>+ enum ast_transport_monitor_reg res = AST_TRANSPORT_MONITOR_REG_NOT_FOUND;<br>+<br>+ transports = ao2_global_obj_ref(active_transports);<br>+ if (!transports) {<br>+ return res;<br>+ }<br>+<br>+ ao2_lock(transports);<br>+ monitored = ao2_find(transports, transport->obj_name, OBJ_SEARCH_KEY | OBJ_NOLOCK);<br>+ if (monitored) {<br>+ int idx;<br>+ struct transport_monitor_notifier new_monitor;<br>+<br>+ /* Check if the callback monitor already exists */<br>+ for (idx = AST_VECTOR_SIZE(&monitored->monitors); idx--;) {<br>+ struct transport_monitor_notifier *notifier;<br>+<br>+ notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);<br>+ if (notifier->cb == cb) {<br>+ /* The monitor is already in the vector replace with new ao2_data. */<br>+ ao2_replace(notifier->data, ao2_data);<br>+ res = AST_TRANSPORT_MONITOR_REG_REPLACED;<br>+ goto register_done;<br>+ }<br>+ }<br>+<br>+ /* Add new monitor to vector */<br>+ new_monitor.cb = cb;<br>+ new_monitor.data = ao2_bump(ao2_data);<br>+ if (AST_VECTOR_APPEND(&monitored->monitors, new_monitor)) {<br>+ ao2_cleanup(ao2_data);<br>+ res = AST_TRANSPORT_MONITOR_REG_FAILED;<br>+ }<br>+<br>+register_done:<br>+ ao2_ref(monitored, -1);<br>+ }<br>+ ao2_unlock(transports);<br>+ ao2_ref(transports, -1);<br>+ return res;<br>+}<br>+<br>+void ast_sip_transport_state_unregister(struct ast_sip_tpmgr_state_callback *element)<br>+{<br>+ AST_RWLIST_WRLOCK(&transport_state_list);<br>+ AST_LIST_REMOVE(&transport_state_list, element, node);<br>+ AST_RWLIST_UNLOCK(&transport_state_list);<br>+}<br>+<br>+void ast_sip_transport_state_register(struct ast_sip_tpmgr_state_callback *element)<br>+{<br>+ struct ast_sip_tpmgr_state_callback *tpmgr_notifier;<br>+<br>+ AST_RWLIST_WRLOCK(&transport_state_list);<br>+ AST_LIST_TRAVERSE(&transport_state_list, tpmgr_notifier, node) {<br>+ if (element == tpmgr_notifier) {<br>+ /* Already registered. */<br>+ AST_RWLIST_UNLOCK(&transport_state_list);<br>+ return;<br>+ }<br>+ }<br>+ AST_LIST_INSERT_HEAD(&transport_state_list, element, node);<br>+ AST_RWLIST_UNLOCK(&transport_state_list);<br>+}<br>+<br>+void ast_sip_destroy_transport_events(void)<br>+{<br>+ pjsip_tpmgr *tpmgr;<br>+<br>+ tpmgr = pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint());<br>+ if (tpmgr) {<br>+ pjsip_tpmgr_set_state_cb(tpmgr, tpmgr_state_callback);<br>+ }<br>+<br>+ ao2_global_obj_release(active_transports);<br>+}<br>+<br>+int ast_sip_initialize_transport_events(void)<br>+{<br>+ pjsip_tpmgr *tpmgr;<br>+ struct ao2_container *transports;<br>+<br>+ tpmgr = pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint());<br>+ if (!tpmgr) {<br>+ return -1;<br>+ }<br>+<br>+ transports = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,<br>+ ACTIVE_TRANSPORTS_BUCKETS, transport_monitor_hash_fn, NULL,<br>+ transport_monitor_cmp_fn);<br>+ if (!transports) {<br>+ return -1;<br>+ }<br>+ ao2_global_obj_replace_unref(active_transports, transports);<br>+ ao2_ref(transports, -1);<br>+<br>+ tpmgr_state_callback = pjsip_tpmgr_get_state_cb(tpmgr);<br>+ pjsip_tpmgr_set_state_cb(tpmgr, &transport_state_callback);<br>+<br>+ return 0;<br>+}<br>diff --git a/res/res_pjsip_transport_management.c b/res/res_pjsip_transport_management.c<br>index 86c53ca..eb92eb7 100644<br>--- a/res/res_pjsip_transport_management.c<br>+++ b/res/res_pjsip_transport_management.c<br>@@ -34,7 +34,7 @@<br> #include "asterisk/astobj2.h"<br> <br> /*! \brief Number of buckets for monitored transports */<br>-#define TRANSPORTS_BUCKETS 53<br>+#define TRANSPORTS_BUCKETS 127<br> <br> #define IDLE_TIMEOUT (pjsip_cfg()->tsx.td)<br> <br>@@ -52,9 +52,6 @@<br> <br> /*! \brief The global interval at which to send keepalives */<br> static unsigned int keepalive_interval;<br>-<br>-/*! \brief Existing transport manager callback that we need to invoke */<br>-static pjsip_tp_state_callback tpmgr_state_callback;<br> <br> /*! \brief Structure for transport to be monitored */<br> struct monitored_transport {<br>@@ -178,14 +175,13 @@<br> /* Let the scheduler inherit the reference from allocation */<br> if (ast_sched_add_variable(sched, IDLE_TIMEOUT, idle_sched_cb, monitored, 1) < 0) {<br> /* Uh Oh. Could not schedule the idle check. Kill the transport. */<br>- ao2_unlink(transports, monitored);<br>- ao2_ref(monitored, -1);<br> pjsip_transport_shutdown(transport);<br>+ } else {<br>+ /* monitored ref successfully passed to idle_sched_cb() */<br>+ break;<br> }<br>- } else {<br>- /* No scheduled task, so get rid of the allocation reference */<br>- ao2_ref(monitored, -1);<br> }<br>+ ao2_ref(monitored, -1);<br> break;<br> case PJSIP_TP_STATE_SHUTDOWN:<br> case PJSIP_TP_STATE_DISCONNECTED:<br>@@ -197,12 +193,11 @@<br> <br> ao2_ref(transports, -1);<br> }<br>-<br>- /* Forward to the old state callback if present */<br>- if (tpmgr_state_callback) {<br>- tpmgr_state_callback(transport, state, info);<br>- }<br> }<br>+<br>+struct ast_sip_tpmgr_state_callback monitored_transport_reg = {<br>+ monitored_transport_state_callback,<br>+};<br> <br> /*! \brief Hashing function for monitored transport */<br> static int monitored_transport_hash_fn(const void *obj, int flags)<br>@@ -327,15 +322,8 @@<br> static int load_module(void)<br> {<br> struct ao2_container *transports;<br>- pjsip_tpmgr *tpmgr;<br> <br> CHECK_PJSIP_MODULE_LOADED();<br>-<br>- tpmgr = pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint());<br>- if (!tpmgr) {<br>- ast_log(LOG_ERROR, "No transport manager to attach keepalive functionality to.\n");<br>- return AST_MODULE_LOAD_DECLINE;<br>- }<br> <br> transports = ao2_container_alloc(TRANSPORTS_BUCKETS, monitored_transport_hash_fn,<br> monitored_transport_cmp_fn);<br>@@ -363,8 +351,7 @@<br> <br> ast_sip_register_service(&idle_monitor_module);<br> <br>- tpmgr_state_callback = pjsip_tpmgr_get_state_cb(tpmgr);<br>- pjsip_tpmgr_set_state_cb(tpmgr, &monitored_transport_state_callback);<br>+ ast_sip_transport_state_register(&monitored_transport_reg);<br> <br> ast_sorcery_observer_add(ast_sip_get_sorcery(), "global", &keepalive_global_observer);<br> ast_sorcery_reload_object(ast_sip_get_sorcery(), "global");<br>@@ -375,8 +362,6 @@<br> <br> static int unload_module(void)<br> {<br>- pjsip_tpmgr *tpmgr;<br>-<br> if (keepalive_interval) {<br> keepalive_interval = 0;<br> if (keepalive_thread != AST_PTHREADT_NULL) {<br>@@ -388,10 +373,7 @@<br> <br> ast_sorcery_observer_remove(ast_sip_get_sorcery(), "global", &keepalive_global_observer);<br> <br>- tpmgr = pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint());<br>- if (tpmgr) {<br>- pjsip_tpmgr_set_state_cb(tpmgr, tpmgr_state_callback);<br>- }<br>+ ast_sip_transport_state_unregister(&monitored_transport_reg);<br> <br> ast_sip_unregister_service(&idle_monitor_module);<br> <br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/6200">change 6200</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/6200"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 15 </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I7d9a31371eb1487c9b7050cf82a9af5180a57912 </div>
<div style="display:none"> Gerrit-Change-Number: 6200 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Richard Mudgett <rmudgett@digium.com> </div>