<p>Benjamin Keith Ford <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/19632">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:
  Benjamin Keith Ford: 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 e168c4b..f0418f3 100644</span><br><span>--- a/include/asterisk/res_pjsip.h</span><br><span>+++ b/include/asterisk/res_pjsip.h</span><br><span>@@ -86,6 +86,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>@@ -3421,6 +3441,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>@@ -3439,7 +3460,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>@@ -3462,7 +3504,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>@@ -3479,6 +3545,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(&regex, 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, &regex, 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(&regex, 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(&regex);</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 da4fff2..6a1c71c 100644</span><br><span>--- a/res/res_pjsip_outbound_registration.c</span><br><span>+++ b/res/res_pjsip_outbound_registration.c</span><br><span>@@ -798,6 +798,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>@@ -913,13 +915,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>@@ -932,8 +931,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>@@ -1017,14 +1016,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>    } else if (response->client_state->destroy) {</span><br><span>          /* We need to deal with the pending destruction instead. */</span><br><span>@@ -1138,6 +1141,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/+/19632">change 19632</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/+/19632"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 16.29 </div>
<div style="display:none"> Gerrit-Change-Id: I1a20baf2a8643c272dcf819871d6c395f148f00b </div>
<div style="display:none"> Gerrit-Change-Number: 19632 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Benjamin Keith Ford <bford@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Benjamin Keith Ford <bford@digium.com> </div>
<div style="display:none"> Gerrit-CC: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>