<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/19641">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span></span><br></pre><div style="white-space:pre-wrap">Approvals:
Friendly Automation: Looks good to me, approved; Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">pjsip_transport_events: Fix possible use after free on transport<br><br>It was possible for a module that registered for transport monitor<br>events to pass in a pjsip_transport that had already been freed.<br>This caused pjsip_transport_events to crash when looking up the<br>monitor for the transport. The fix is a two pronged approach.<br><br>1. We now increment the reference count on pjsip_transports when we<br>create monitors for them, then decrement the count when the<br>transport is going to be destroyed.<br><br>2. There are now APIs to register and unregister monitor callbacks<br>by "transport key" which is a string concatenation of the remote ip<br>address and port. This way the module needing to monitor the<br>transport doesn't have to hold on to the transport object itself to<br>unregister. It just has to save the transport_key.<br><br>* Added the pjsip_transport reference increment and decrement.<br><br>* Changed the internal transport monitor container key from the<br> transport->obj_name (which may not be unique anyway) to the<br> transport_key.<br><br>* Added a helper macro AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR() that<br> fills a buffer with the transport_key using a passed-in<br> pjsip_transport.<br><br>* Added the following functions:<br> ast_sip_transport_monitor_register_key<br> ast_sip_transport_monitor_register_replace_key<br> ast_sip_transport_monitor_unregister_key<br> and marked their non-key counterparts as deprecated.<br><br>* Updated res_pjsip_pubsub and res_pjsip_outbound_register to use<br> the new "key" monitor functions.<br><br>NOTE: res_pjsip_registrar also uses the transport monitor<br>functionality but doesn't have a persistent object other than<br>contact to store a transport key. At this time, it continues to<br>use the non-key monitor functions.<br><br>ASTERISK-30244<br><br>Change-Id: I1a20baf2a8643c272dcf819871d6c395f148f00b<br>---<br>M include/asterisk/res_pjsip.h<br>M res/res_pjsip/pjsip_transport_events.c<br>M res/res_pjsip_outbound_registration.c<br>M res/res_pjsip_pubsub.c<br>4 files changed, 357 insertions(+), 43 deletions(-)<br><br></pre>
<pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h</span><br><span>index d207297..f31cd10 100644</span><br><span>--- a/include/asterisk/res_pjsip.h</span><br><span>+++ b/include/asterisk/res_pjsip.h</span><br><span>@@ -87,6 +87,26 @@</span><br><span> #define AST_STIR_SHAKEN_RESPONSE_STR_UNSUPPORTED_CREDENTIAL "Unsupported Credential"</span><br><span> #define AST_STIR_SHAKEN_RESPONSE_STR_INVALID_IDENTITY_HEADER "Invalid Identity Header"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* ":12345" */</span><br><span style="color: hsl(120, 100%, 40%);">+#define COLON_PORT_STRLEN 6</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * "<ipaddr>:<port>"</span><br><span style="color: hsl(120, 100%, 40%);">+ * PJ_INET6_ADDRSTRLEN includes the NULL terminator</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define IP6ADDR_COLON_PORT_BUFLEN (PJ_INET6_ADDRSTRLEN + COLON_PORT_STRLEN)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Fill a buffer with a pjsip transport's remote ip address and port</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param transport The pjsip_transport to use</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param dest The destination buffer of at least IP6ADDR_COLON_PORT_BUFLEN bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(_transport, _dest) \</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(_dest, IP6ADDR_COLON_PORT_BUFLEN, \</span><br><span style="color: hsl(120, 100%, 40%);">+ PJSTR_PRINTF_SPEC ":%d", \</span><br><span style="color: hsl(120, 100%, 40%);">+ PJSTR_PRINTF_VAR(_transport->remote_name.host), \</span><br><span style="color: hsl(120, 100%, 40%);">+ _transport->remote_name.port);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Forward declarations of PJSIP stuff */</span><br><span> struct pjsip_rx_data;</span><br><span> struct pjsip_module;</span><br><span>@@ -3745,6 +3765,7 @@</span><br><span> </span><br><span> /*!</span><br><span> * \brief Register a reliable transport shutdown monitor callback.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \deprecated Replaced with ast_sip_transport_monitor_register_key().</span><br><span> * \since 13.20.0</span><br><span> *</span><br><span> * \param transport Transport to monitor for shutdown.</span><br><span>@@ -3763,7 +3784,28 @@</span><br><span> ast_transport_monitor_shutdown_cb cb, void *ao2_data);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Register a reliable transport shutdown monitor callback.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param transport_key Key for the transport to monitor for shutdown.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Create the key with AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param cb Who to call when transport is shutdown.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ao2_data Data to pass with the callback.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note The data object passed will have its reference count automatically</span><br><span style="color: hsl(120, 100%, 40%);">+ * incremented by this call and automatically decremented after the callback</span><br><span style="color: hsl(120, 100%, 40%);">+ * runs or when the callback is unregistered.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * There is no checking for duplicate registrations.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return enum ast_transport_monitor_reg</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+enum ast_transport_monitor_reg ast_sip_transport_monitor_register_key(</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *transport_key, ast_transport_monitor_shutdown_cb cb,</span><br><span style="color: hsl(120, 100%, 40%);">+ void *ao2_data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span> * \brief Register a reliable transport shutdown monitor callback replacing any duplicate.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \deprecated Replaced with ast_sip_transport_monitor_register_replace_key().</span><br><span> * \since 13.26.0</span><br><span> * \since 16.3.0</span><br><span> *</span><br><span>@@ -3786,7 +3828,31 @@</span><br><span> ast_transport_monitor_shutdown_cb cb, void *ao2_data, ast_transport_monitor_data_matcher matches);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Register a reliable transport shutdown monitor callback replacing any duplicate.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param transport_key Key for the transport to monitor for shutdown.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Create the key with AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param cb Who to call when transport is shutdown.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ao2_data Data to pass with the callback.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param matches Matcher function that returns true if data matches a previously</span><br><span style="color: hsl(120, 100%, 40%);">+ * registered data object</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note The data object passed will have its reference count automatically</span><br><span style="color: hsl(120, 100%, 40%);">+ * incremented by this call and automatically decremented after the callback</span><br><span style="color: hsl(120, 100%, 40%);">+ * runs or when the callback is unregistered.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function checks for duplicates, and overwrites/replaces the old monitor</span><br><span style="color: hsl(120, 100%, 40%);">+ * with the given one.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return enum ast_transport_monitor_reg</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+enum ast_transport_monitor_reg ast_sip_transport_monitor_register_replace_key(</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *transport_key, ast_transport_monitor_shutdown_cb cb,</span><br><span style="color: hsl(120, 100%, 40%);">+ void *ao2_data, ast_transport_monitor_data_matcher matches);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span> * \brief Unregister a reliable transport shutdown monitor</span><br><span style="color: hsl(120, 100%, 40%);">+ * \deprecated Replaced with ast_sip_transport_monitor_unregister_key().</span><br><span> * \since 13.20.0</span><br><span> *</span><br><span> * \param transport Transport to monitor for shutdown.</span><br><span>@@ -3803,6 +3869,23 @@</span><br><span> ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Unregister a reliable transport shutdown monitor</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param transport_key Key for the transport to monitor for shutdown.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Create the key with AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param cb The callback that was used for the original register.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param data Data to pass to the matcher. May be NULL and does NOT need to be an ao2 object.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If NULL, all monitors with the provided callback are unregistered.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param matches Matcher function that returns true if data matches the previously</span><br><span style="color: hsl(120, 100%, 40%);">+ * registered data object. If NULL, a simple pointer comparison is done.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note The data object passed into the original register will have its reference count</span><br><span style="color: hsl(120, 100%, 40%);">+ * automatically decremented.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_sip_transport_monitor_unregister_key(const char *transport_key,</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span> * \brief Unregister a transport shutdown monitor from all reliable transports</span><br><span> * \since 13.20.0</span><br><span> *</span><br><span>diff --git a/res/res_pjsip/pjsip_transport_events.c b/res/res_pjsip/pjsip_transport_events.c</span><br><span>index a816f46..0e4705d 100644</span><br><span>--- a/res/res_pjsip/pjsip_transport_events.c</span><br><span>+++ b/res/res_pjsip/pjsip_transport_events.c</span><br><span>@@ -30,6 +30,7 @@</span><br><span> #include "asterisk.h"</span><br><span> </span><br><span> #include "asterisk/res_pjsip.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/res_pjsip_cli.h"</span><br><span> #include "include/res_pjsip_private.h"</span><br><span> #include "asterisk/linkedlists.h"</span><br><span> #include "asterisk/vector.h"</span><br><span>@@ -49,8 +50,14 @@</span><br><span> </span><br><span> /*! \brief Structure for transport to be monitored */</span><br><span> struct transport_monitor {</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! \brief Key <ipaddr>:<port> */</span><br><span style="color: hsl(120, 100%, 40%);">+ char key[IP6ADDR_COLON_PORT_BUFLEN];</span><br><span> /*! \brief The underlying PJSIP transport */</span><br><span> pjsip_transport *transport;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! For debugging purposes, we save the obj_name</span><br><span style="color: hsl(120, 100%, 40%);">+ * in case the transport goes away.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ char *transport_obj_name;</span><br><span> /*! Who is interested in when this transport shuts down. */</span><br><span> AST_VECTOR(, struct transport_monitor_notifier) monitors;</span><br><span> };</span><br><span>@@ -64,12 +71,14 @@</span><br><span> /*! List of registered transport state callbacks. */</span><br><span> static AST_RWLIST_HEAD(, ast_sip_tpmgr_state_callback) transport_state_list;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /*! \brief Hashing function for struct transport_monitor */</span><br><span style="color: hsl(0, 100%, 40%);">-AO2_STRING_FIELD_HASH_FN(transport_monitor, transport->obj_name);</span><br><span style="color: hsl(120, 100%, 40%);">+AO2_STRING_FIELD_HASH_FN(transport_monitor, key);</span><br><span> </span><br><span> /*! \brief Comparison function for struct transport_monitor */</span><br><span style="color: hsl(0, 100%, 40%);">-AO2_STRING_FIELD_CMP_FN(transport_monitor, transport->obj_name);</span><br><span style="color: hsl(120, 100%, 40%);">+AO2_STRING_FIELD_CMP_FN(transport_monitor, key);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Sort function for struct transport_monitor */</span><br><span style="color: hsl(120, 100%, 40%);">+AO2_STRING_FIELD_SORT_FN(transport_monitor, key);</span><br><span> </span><br><span> static const char *transport_state2str(pjsip_transport_state state)</span><br><span> {</span><br><span>@@ -112,6 +121,11 @@</span><br><span> ao2_cleanup(notifier->data);</span><br><span> }</span><br><span> AST_VECTOR_FREE(&monitored->monitors);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Transport %s(%s,%s) RefCnt: %ld : state:MONITOR_DESTROYED\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->key, monitored->transport->obj_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->transport->type_name,pj_atomic_get(monitored->transport->ref_cnt));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(monitored->transport_obj_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ pjsip_transport_dec_ref(monitored->transport);</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -125,8 +139,11 @@</span><br><span> static void transport_state_do_reg_callbacks(struct ao2_container *transports, pjsip_transport *transport)</span><br><span> {</span><br><span> struct transport_monitor *monitored;</span><br><span style="color: hsl(120, 100%, 40%);">+ char key[IP6ADDR_COLON_PORT_BUFLEN];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- monitored = ao2_find(transports, transport->obj_name, OBJ_SEARCH_KEY | OBJ_UNLINK);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(transport, key);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored = ao2_find(transports, key, OBJ_SEARCH_KEY | OBJ_UNLINK);</span><br><span> if (monitored) {</span><br><span> int idx;</span><br><span> </span><br><span>@@ -134,8 +151,10 @@</span><br><span> struct transport_monitor_notifier *notifier;</span><br><span> </span><br><span> notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(3, "running callback %p(%p) for transport %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- notifier->cb, notifier->data, transport->obj_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Transport %s(%s,%s) RefCnt: %ld : running callback %p(%p)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->key, monitored->transport->obj_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->transport->type_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ pj_atomic_get(monitored->transport->ref_cnt), notifier->cb, notifier->data);</span><br><span> notifier->cb(notifier->data);</span><br><span> }</span><br><span> ao2_ref(monitored, -1);</span><br><span>@@ -269,8 +288,11 @@</span><br><span> && (transports = ao2_global_obj_ref(active_transports))) {</span><br><span> struct transport_monitor *monitored;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(3, "Reliable transport '%s' state:%s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- transport->obj_name, transport_state2str(state));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Transport " PJSTR_PRINTF_SPEC ":%d(%s,%s): RefCnt: %ld state:%s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ PJSTR_PRINTF_VAR(transport->remote_name.host),</span><br><span style="color: hsl(120, 100%, 40%);">+ transport->remote_name.port, transport->obj_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ transport->type_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ pj_atomic_get(transport->ref_cnt), transport_state2str(state));</span><br><span> switch (state) {</span><br><span> case PJSIP_TP_STATE_CONNECTED:</span><br><span> if (PJSIP_TRANSPORT_IS_SECURE(transport) &&</span><br><span>@@ -285,10 +307,18 @@</span><br><span> break;</span><br><span> }</span><br><span> monitored->transport = transport;</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(transport, monitored->key);</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->transport_obj_name = ast_strdup(transport->obj_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> if (AST_VECTOR_INIT(&monitored->monitors, 5)) {</span><br><span> ao2_ref(monitored, -1);</span><br><span> break;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+ pjsip_transport_add_ref(monitored->transport);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Transport %s(%s,%s): RefCnt: %ld state:MONITOR_CREATED\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->key, monitored->transport_obj_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->transport->type_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ pj_atomic_get(monitored->transport->ref_cnt));</span><br><span> </span><br><span> ao2_link(transports, monitored);</span><br><span> ao2_ref(monitored, -1);</span><br><span>@@ -362,8 +392,10 @@</span><br><span> || cb_data->matches(cb_data->data, notifier->data))) {</span><br><span> ao2_cleanup(notifier->data);</span><br><span> AST_VECTOR_REMOVE_UNORDERED(&monitored->monitors, idx);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(3, "Unregistered monitor %p(%p) from transport %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- notifier->cb, notifier->data, monitored->transport->obj_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Transport %s(%s,%s) RefCnt: %ld : Unregistered monitor %p(%p)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->key, monitored->transport_obj_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->transport->type_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ pj_atomic_get(monitored->transport->ref_cnt), notifier->cb, notifier->data);</span><br><span> }</span><br><span> }</span><br><span> return 0;</span><br><span>@@ -397,10 +429,18 @@</span><br><span> void ast_sip_transport_monitor_unregister(pjsip_transport *transport,</span><br><span> ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ char key[IP6ADDR_COLON_PORT_BUFLEN];</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(transport, key);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sip_transport_monitor_unregister_key(key, cb, data, matches);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_sip_transport_monitor_unregister_key(const char *transport_key,</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span> struct ao2_container *transports;</span><br><span> struct transport_monitor *monitored;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ast_assert(transport != NULL && cb != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_assert(transport_key != NULL && cb != NULL);</span><br><span> </span><br><span> transports = ao2_global_obj_ref(active_transports);</span><br><span> if (!transports) {</span><br><span>@@ -408,7 +448,7 @@</span><br><span> }</span><br><span> </span><br><span> ao2_lock(transports);</span><br><span style="color: hsl(0, 100%, 40%);">- monitored = ao2_find(transports, transport->obj_name, OBJ_SEARCH_KEY | OBJ_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored = ao2_find(transports, transport_key, OBJ_SEARCH_KEY | OBJ_NOLOCK);</span><br><span> if (monitored) {</span><br><span> struct callback_data cb_data = {</span><br><span> .cb = cb,</span><br><span>@@ -426,17 +466,35 @@</span><br><span> enum ast_transport_monitor_reg ast_sip_transport_monitor_register(pjsip_transport *transport,</span><br><span> ast_transport_monitor_shutdown_cb cb, void *ao2_data)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return ast_sip_transport_monitor_register_replace(transport, cb, ao2_data, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ char key[IP6ADDR_COLON_PORT_BUFLEN];</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(transport, key);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return ast_sip_transport_monitor_register_replace_key(key, cb, ao2_data, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum ast_transport_monitor_reg ast_sip_transport_monitor_register_key(const char *transport_key,</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_transport_monitor_shutdown_cb cb, void *ao2_data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return ast_sip_transport_monitor_register_replace_key(transport_key, cb, ao2_data, NULL);</span><br><span> }</span><br><span> </span><br><span> enum ast_transport_monitor_reg ast_sip_transport_monitor_register_replace(pjsip_transport *transport,</span><br><span> ast_transport_monitor_shutdown_cb cb, void *ao2_data, ast_transport_monitor_data_matcher matches)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ char key[IP6ADDR_COLON_PORT_BUFLEN];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(transport, key);</span><br><span style="color: hsl(120, 100%, 40%);">+ return ast_sip_transport_monitor_register_replace_key(key, cb, ao2_data, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum ast_transport_monitor_reg ast_sip_transport_monitor_register_replace_key(const char *transport_key,</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_transport_monitor_shutdown_cb cb, void *ao2_data, ast_transport_monitor_data_matcher matches)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span> struct ao2_container *transports;</span><br><span> struct transport_monitor *monitored;</span><br><span> enum ast_transport_monitor_reg res = AST_TRANSPORT_MONITOR_REG_NOT_FOUND;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ast_assert(transport != NULL && cb != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_assert(transport_key != NULL && cb != NULL);</span><br><span> </span><br><span> transports = ao2_global_obj_ref(active_transports);</span><br><span> if (!transports) {</span><br><span>@@ -444,7 +502,7 @@</span><br><span> }</span><br><span> </span><br><span> ao2_lock(transports);</span><br><span style="color: hsl(0, 100%, 40%);">- monitored = ao2_find(transports, transport->obj_name, OBJ_SEARCH_KEY | OBJ_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored = ao2_find(transports, transport_key, OBJ_SEARCH_KEY | OBJ_NOLOCK);</span><br><span> if (monitored) {</span><br><span> struct transport_monitor_notifier new_monitor;</span><br><span> struct callback_data cb_data = {</span><br><span>@@ -461,12 +519,15 @@</span><br><span> if (AST_VECTOR_APPEND(&monitored->monitors, new_monitor)) {</span><br><span> ao2_cleanup(ao2_data);</span><br><span> res = AST_TRANSPORT_MONITOR_REG_FAILED;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(3, "Register monitor %p(%p) to transport %s FAILED\n",</span><br><span style="color: hsl(0, 100%, 40%);">- cb, ao2_data, transport->obj_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Transport %s(%s) RefCnt: %ld : Monitor registration failed %p(%p)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->key, monitored->transport_obj_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ pj_atomic_get(monitored->transport->ref_cnt), cb, ao2_data);</span><br><span> } else {</span><br><span> res = AST_TRANSPORT_MONITOR_REG_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(3, "Registered monitor %p(%p) to transport %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- cb, ao2_data, transport->obj_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Transport %s(%s,%s) RefCnt: %ld : Registered monitor %p(%p)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->key, monitored->transport_obj_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->transport->type_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ pj_atomic_get(monitored->transport->ref_cnt), cb, ao2_data);</span><br><span> }</span><br><span> </span><br><span> ao2_ref(monitored, -1);</span><br><span>@@ -499,10 +560,120 @@</span><br><span> AST_RWLIST_UNLOCK(&transport_state_list);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static char *cli_show_monitors(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *cli_rc = CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int using_regex = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ regex_t regex = { 0, };</span><br><span style="color: hsl(120, 100%, 40%);">+ int container_count;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ao2_iterator iter;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ao2_container *sorted_monitors = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ao2_container *transports;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct transport_monitor *monitored;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ e->command = "pjsip show transport-monitors";</span><br><span style="color: hsl(120, 100%, 40%);">+ e->usage = "Usage: pjsip show transport-monitors [ like <pattern> ]\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " Show pjsip transport monitors\n";</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_GENERATE:</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (a->argc != 3 && a->argc != 5) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (a->argc == 5) {</span><br><span style="color: hsl(120, 100%, 40%);">+ int regrc;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strcasecmp(a->argv[3], "like")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ regrc = regcomp(®ex, a->argv[4], REG_EXTENDED | REG_ICASE | REG_NOSUB);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (regrc) {</span><br><span style="color: hsl(120, 100%, 40%);">+ char err[256];</span><br><span style="color: hsl(120, 100%, 40%);">+ regerror(regrc, ®ex, err, 256);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "PJSIP Transport Monitor: Error: %s\n", err);</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ using_regex = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Get a sorted snapshot of the scheduled tasks */</span><br><span style="color: hsl(120, 100%, 40%);">+ sorted_monitors = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ transport_monitor_sort_fn, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!sorted_monitors) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "PJSIP Transport Monitor: Unable to allocate temporary container\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto error;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ transports = ao2_global_obj_ref(active_transports);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!transports) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "PJSIP Transport Monitor: Unable to get transports\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto error;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_lock(transports);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = ao2_container_dup(sorted_monitors, transports, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_unlock(transports);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(transports, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "PJSIP Transport Monitors: Unable to sort temporary container\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto error;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ container_count = ao2_container_count(sorted_monitors);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "PJSIP Transport Monitors:\n\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd,</span><br><span style="color: hsl(120, 100%, 40%);">+ "<Remote Host...................................> <State.....> <Direction> <RefCnt> <Monitors> <ObjName............>\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ iter = ao2_iterator_init(sorted_monitors, AO2_ITERATOR_UNLINK);</span><br><span style="color: hsl(120, 100%, 40%);">+ for (; (monitored = ao2_iterator_next(&iter)); ao2_ref(monitored, -1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ char *state;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (using_regex && regexec(®ex, monitored->key, 0, NULL, 0) == REG_NOMATCH) {</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (monitored->transport->is_destroying) {</span><br><span style="color: hsl(120, 100%, 40%);">+ state = "DESTROYING";</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (monitored->transport->is_shutdown) {</span><br><span style="color: hsl(120, 100%, 40%);">+ state = "SHUTDOWN";</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ state = "ACTIVE";</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, " %-46.46s %-10s %-9s %6ld %8" PRIu64 " %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->key, state,</span><br><span style="color: hsl(120, 100%, 40%);">+ monitored->transport->dir == PJSIP_TP_DIR_OUTGOING ? "Outgoing" : "Incoming",</span><br><span style="color: hsl(120, 100%, 40%);">+ pj_atomic_get(monitored->transport->ref_cnt),</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_VECTOR_SIZE(&monitored->monitors), monitored->transport->obj_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_iterator_destroy(&iter);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "\nTotal Transport Monitors: %d\n\n", container_count);</span><br><span style="color: hsl(120, 100%, 40%);">+ cli_rc = CLI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+error:</span><br><span style="color: hsl(120, 100%, 40%);">+ if (using_regex) {</span><br><span style="color: hsl(120, 100%, 40%);">+ regfree(®ex);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(sorted_monitors);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return cli_rc;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_cli_entry cli_commands[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_CLI_DEFINE(cli_show_monitors, "Show pjsip transport monitors"),</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void ast_sip_destroy_transport_events(void)</span><br><span> {</span><br><span> pjsip_tpmgr *tpmgr;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> tpmgr = pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint());</span><br><span> if (tpmgr) {</span><br><span> pjsip_tpmgr_set_state_cb(tpmgr, tpmgr_state_callback);</span><br><span>@@ -522,7 +693,7 @@</span><br><span> }</span><br><span> </span><br><span> transports = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,</span><br><span style="color: hsl(0, 100%, 40%);">- ACTIVE_TRANSPORTS_BUCKETS, transport_monitor_hash_fn, NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+ ACTIVE_TRANSPORTS_BUCKETS, transport_monitor_hash_fn, transport_monitor_sort_fn,</span><br><span> transport_monitor_cmp_fn);</span><br><span> if (!transports) {</span><br><span> return -1;</span><br><span>@@ -533,5 +704,8 @@</span><br><span> tpmgr_state_callback = pjsip_tpmgr_get_state_cb(tpmgr);</span><br><span> pjsip_tpmgr_set_state_cb(tpmgr, &transport_state_callback);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return 0;</span><br><span> }</span><br><span>diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c</span><br><span>index 79cba6a..fc1dcad 100644</span><br><span>--- a/res/res_pjsip_outbound_registration.c</span><br><span>+++ b/res/res_pjsip_outbound_registration.c</span><br><span>@@ -993,6 +993,8 @@</span><br><span> pjsip_rx_data *rdata;</span><br><span> /*! \brief Request for which the response was received */</span><br><span> pjsip_tx_data *old_request;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! \brief Key for the reliable transport in use */</span><br><span style="color: hsl(120, 100%, 40%);">+ char transport_key[IP6ADDR_COLON_PORT_BUFLEN];</span><br><span> };</span><br><span> </span><br><span> /*! \brief Registration response structure destructor */</span><br><span>@@ -1108,13 +1110,10 @@</span><br><span> return strcmp(ma, mb) == 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void registration_transport_monitor_setup(pjsip_transport *transport, const char *registration_name)</span><br><span style="color: hsl(120, 100%, 40%);">+static void registration_transport_monitor_setup(const char *transport_key, const char *registration_name)</span><br><span> {</span><br><span> char *monitor;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!PJSIP_TRANSPORT_IS_RELIABLE(transport)) {</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span> monitor = ao2_alloc_options(strlen(registration_name) + 1, NULL,</span><br><span> AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span> if (!monitor) {</span><br><span>@@ -1127,8 +1126,8 @@</span><br><span> * register the monitor. We might get into a message spamming infinite</span><br><span> * loop of registration, shutdown, reregistration...</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">- ast_sip_transport_monitor_register(transport, registration_transport_shutdown_cb,</span><br><span style="color: hsl(0, 100%, 40%);">- monitor);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sip_transport_monitor_register_replace_key(transport_key, registration_transport_shutdown_cb,</span><br><span style="color: hsl(120, 100%, 40%);">+ monitor, monitor_matcher);</span><br><span> ao2_ref(monitor, -1);</span><br><span> }</span><br><span> </span><br><span>@@ -1322,14 +1321,18 @@</span><br><span> schedule_registration(response->client_state, next_registration_round);</span><br><span> </span><br><span> /* See if we should monitor for transport shutdown */</span><br><span style="color: hsl(0, 100%, 40%);">- registration_transport_monitor_setup(response->rdata->tp_info.transport,</span><br><span style="color: hsl(0, 100%, 40%);">- response->client_state->registration_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (PJSIP_TRANSPORT_IS_RELIABLE(response->rdata->tp_info.transport)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ registration_transport_monitor_setup(response->transport_key,</span><br><span style="color: hsl(120, 100%, 40%);">+ response->client_state->registration_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> } else {</span><br><span> ast_debug(1, "Outbound unregistration to '%s' with client '%s' successful\n", server_uri, client_uri);</span><br><span> update_client_state_status(response->client_state, SIP_REGISTRATION_UNREGISTERED);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_sip_transport_monitor_unregister(response->rdata->tp_info.transport,</span><br><span style="color: hsl(0, 100%, 40%);">- registration_transport_shutdown_cb, response->client_state->registration_name,</span><br><span style="color: hsl(0, 100%, 40%);">- monitor_matcher);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (PJSIP_TRANSPORT_IS_RELIABLE(response->rdata->tp_info.transport)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sip_transport_monitor_unregister_key(response->transport_key,</span><br><span style="color: hsl(120, 100%, 40%);">+ registration_transport_shutdown_cb, response->client_state->registration_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ monitor_matcher);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> }</span><br><span> </span><br><span> save_response_fields_to_transport(response);</span><br><span>@@ -1445,6 +1448,9 @@</span><br><span> response->old_request = tsx->last_tx;</span><br><span> pjsip_tx_data_add_ref(response->old_request);</span><br><span> pjsip_rx_data_clone(param->rdata, 0, &response->rdata);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(param->rdata->tp_info.transport,</span><br><span style="color: hsl(120, 100%, 40%);">+ response->transport_key);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> } else {</span><br><span> /* old_request steals the reference */</span><br><span> response->old_request = client_state->last_tdata;</span><br><span>diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c</span><br><span>index d767269..26b86cc 100644</span><br><span>--- a/res/res_pjsip_pubsub.c</span><br><span>+++ b/res/res_pjsip_pubsub.c</span><br><span>@@ -389,8 +389,8 @@</span><br><span> char src_name[PJ_INET6_ADDRSTRLEN];</span><br><span> /*! Source port of the message */</span><br><span> int src_port;</span><br><span style="color: hsl(0, 100%, 40%);">- /*! Local transport key type */</span><br><span style="color: hsl(0, 100%, 40%);">- char transport_key[32];</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Local transport type (UDP,TCP,TLS)*/</span><br><span style="color: hsl(120, 100%, 40%);">+ char transport_type[32];</span><br><span> /*! Local transport address */</span><br><span> char local_name[PJ_INET6_ADDRSTRLEN];</span><br><span> /*! Local transport port */</span><br><span>@@ -474,7 +474,7 @@</span><br><span> /*! The transport the subscription was received on.</span><br><span> * Only used for reliable transports.</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">- pjsip_transport *transport;</span><br><span style="color: hsl(120, 100%, 40%);">+ char transport_key[IP6ADDR_COLON_PORT_BUFLEN];</span><br><span> /*! Indicator if initial notify should be generated.</span><br><span> * Used to refresh modified RLS.</span><br><span> */</span><br><span>@@ -711,8 +711,9 @@</span><br><span> rdata->tp_info.transport->obj_name,</span><br><span> sub_tree->persistence->endpoint, sub_tree->root->resource,</span><br><span> sub_tree->persistence->prune_on_boot);</span><br><span style="color: hsl(0, 100%, 40%);">- sub_tree->transport = rdata->tp_info.transport;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_sip_transport_monitor_register(rdata->tp_info.transport,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(rdata->tp_info.transport,</span><br><span style="color: hsl(120, 100%, 40%);">+ sub_tree->transport_key);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sip_transport_monitor_register_key(sub_tree->transport_key,</span><br><span> sub_tree_transport_cb, sub_tree);</span><br><span> /*</span><br><span> * FYI: ast_sip_transport_monitor_register holds a reference to the sub_tree</span><br><span>@@ -746,8 +747,8 @@</span><br><span> ast_copy_string(sub_tree->persistence->src_name, rdata->pkt_info.src_name,</span><br><span> sizeof(sub_tree->persistence->src_name));</span><br><span> sub_tree->persistence->src_port = rdata->pkt_info.src_port;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_copy_string(sub_tree->persistence->transport_key, rdata->tp_info.transport->type_name,</span><br><span style="color: hsl(0, 100%, 40%);">- sizeof(sub_tree->persistence->transport_key));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_copy_string(sub_tree->persistence->transport_type, rdata->tp_info.transport->type_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ sizeof(sub_tree->persistence->transport_type));</span><br><span> ast_copy_pj_str(sub_tree->persistence->local_name, &rdata->tp_info.transport->local_name.host,</span><br><span> sizeof(sub_tree->persistence->local_name));</span><br><span> sub_tree->persistence->local_port = rdata->tp_info.transport->local_name.port;</span><br><span>@@ -763,12 +764,12 @@</span><br><span> return;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (sub_tree->persistence->prune_on_boot && sub_tree->transport) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (sub_tree->persistence->prune_on_boot && !ast_strlen_zero(sub_tree->transport_key)) {</span><br><span> ast_debug(3, "Unregistering transport monitor on %s '%s->%s'\n",</span><br><span style="color: hsl(0, 100%, 40%);">- sub_tree->transport->obj_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ sub_tree->transport_key,</span><br><span> sub_tree->endpoint ? ast_sorcery_object_get_id(sub_tree->endpoint) : "Unknown",</span><br><span> sub_tree->root ? sub_tree->root->resource : "Unknown");</span><br><span style="color: hsl(0, 100%, 40%);">- ast_sip_transport_monitor_unregister(sub_tree->transport,</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sip_transport_monitor_unregister_key(sub_tree->transport_key,</span><br><span> sub_tree_transport_cb, sub_tree, NULL);</span><br><span> }</span><br><span> </span><br><span>@@ -1743,7 +1744,7 @@</span><br><span> rdata.tp_info.pool = pool;</span><br><span> </span><br><span> if (ast_sip_create_rdata_with_contact(&rdata, persistence->packet, persistence->src_name,</span><br><span style="color: hsl(0, 100%, 40%);">- persistence->src_port, persistence->transport_key, persistence->local_name,</span><br><span style="color: hsl(120, 100%, 40%);">+ persistence->src_port, persistence->transport_type, persistence->local_name,</span><br><span> persistence->local_port, persistence->contact_uri)) {</span><br><span> ast_log(LOG_WARNING, "Failed recreating '%s' subscription: The message could not be parsed\n",</span><br><span> persistence->endpoint);</span><br><span>@@ -5759,7 +5760,7 @@</span><br><span> ast_sorcery_object_field_register(sorcery, "subscription_persistence", "src_port", "0", OPT_UINT_T, 0,</span><br><span> FLDSET(struct subscription_persistence, src_port));</span><br><span> ast_sorcery_object_field_register(sorcery, "subscription_persistence", "transport_key", "0", OPT_CHAR_ARRAY_T, 0,</span><br><span style="color: hsl(0, 100%, 40%);">- CHARFLDSET(struct subscription_persistence, transport_key));</span><br><span style="color: hsl(120, 100%, 40%);">+ CHARFLDSET(struct subscription_persistence, transport_type));</span><br><span> ast_sorcery_object_field_register(sorcery, "subscription_persistence", "local_name", "", OPT_CHAR_ARRAY_T, 0,</span><br><span> CHARFLDSET(struct subscription_persistence, local_name));</span><br><span> ast_sorcery_object_field_register(sorcery, "subscription_persistence", "local_port", "0", OPT_UINT_T, 0,</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/19641">change 19641</a>. To unsubscribe, or for help writing mail filters, 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/c/asterisk/+/19641"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 19 </div>
<div style="display:none"> Gerrit-Change-Id: I1a20baf2a8643c272dcf819871d6c395f148f00b </div>
<div style="display:none"> Gerrit-Change-Number: 19641 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-CC: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>