<p>Richard Mudgett has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/6202">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_pjsip_outbound_registration.c: Re-REGISTER on transport shutdown.<br><br>The fix for the issue is broken up into three parts.<br><br>This is part three which handles the client side of REGISTER requests.<br>The registered contact may no longer be valid on the server when the<br>transport used is reliable and the connection is broken.<br><br>* Re-REGISTER our contact if the reliable transport is broken after<br>registration completes. We attempt to re-REGISTER immediately to minimize<br>the time we are unreachable. Time may have already passed between the<br>connection being broken and the loss being detected.<br><br>* Reorder sip_outbound_registration_state_alloc() so the STATSD_GUAGE's<br>are still correct if an allocation failure happens.<br><br>ASTERISK-27147<br><br>Change-Id: I3668405b1ee75dfefb07c0d637826176f741ce83<br>---<br>M res/res_pjsip_outbound_registration.c<br>1 file changed, 105 insertions(+), 9 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/02/6202/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c<br>index 7b605b9..bbb286a 100644<br>--- a/res/res_pjsip_outbound_registration.c<br>+++ b/res/res_pjsip_outbound_registration.c<br>@@ -358,6 +358,8 @@<br> unsigned int auth_attempted:1;<br> /*! \brief The name of the transport to be used for the registration */<br> char *transport_name;<br>+ /*! \brief The name of the registration sorcery object */<br>+ char *registration_name;<br> };<br> <br> /*! \brief Outbound registration state information (persists for lifetime that registration should exist) */<br>@@ -795,6 +797,82 @@<br> }<br> }<br> <br>+static int reregister_immediately_cb(void *obj)<br>+{<br>+ struct sip_outbound_registration_state *state = obj;<br>+<br>+ if (state->client_state->status != SIP_REGISTRATION_REGISTERED) {<br>+ ao2_ref(state, -1);<br>+ return 0;<br>+ }<br>+<br>+ if (DEBUG_ATLEAST(1)) {<br>+ pjsip_regc_info info;<br>+<br>+ pjsip_regc_get_info(state->client_state->client, &info);<br>+ ast_log(LOG_DEBUG,<br>+ "Outbound registration transport to server '%.*s' from client '%.*s' shutdown\n",<br>+ (int) info.server_uri.slen, info.server_uri.ptr,<br>+ (int) info.client_uri.slen, info.client_uri.ptr);<br>+ }<br>+<br>+ cancel_registration(state->client_state);<br>+<br>+ ao2_ref(state->client_state, +1);<br>+ handle_client_registration(state->client_state);<br>+<br>+ ao2_ref(state, -1);<br>+ return 0;<br>+}<br>+<br>+/*!<br>+ * \internal<br>+ * \brief The reliable transport we registered using has shutdown.<br>+ * \since 13.18.0<br>+ *<br>+ * \param obj What is needed to initiate a reregister attempt.<br>+ *<br>+ * \return Nothing<br>+ */<br>+static void registration_transport_shutdown_cb(void *obj)<br>+{<br>+ const char *registration_name = obj;<br>+ struct sip_outbound_registration_state *state;<br>+<br>+ state = get_state(registration_name);<br>+ if (!state) {<br>+ /* Registration no longer exists or shutting down. */<br>+ return;<br>+ }<br>+ if (ast_sip_push_task(state->client_state->serializer, reregister_immediately_cb, state)) {<br>+ ao2_ref(state, -1);<br>+ }<br>+}<br>+<br>+static void registration_transport_monitor_setup(pjsip_transport *transport, const char *registration_name)<br>+{<br>+ char *monitor;<br>+<br>+ if (!PJSIP_TRANSPORT_IS_RELIABLE(transport)) {<br>+ return;<br>+ }<br>+ monitor = ao2_alloc_options(strlen(registration_name) + 1, NULL,<br>+ AO2_ALLOC_OPT_LOCK_NOLOCK);<br>+ if (!monitor) {<br>+ return;<br>+ }<br>+ strcpy(monitor, registration_name);/* Safe */<br>+<br>+ /*<br>+ * We'll ignore if the transport has already been shutdown before we<br>+ * register the monitor. We might get into a message spamming infinite<br>+ * loop of registration, shutdown, reregistration...<br>+ */<br>+ ast_sip_transport_monitor_register(transport, registration_transport_shutdown_cb,<br>+ monitor);<br>+ ao2_ref(monitor, -1);<br>+}<br>+<br> /*! \brief Callback function for handling a response to a registration attempt */<br> static int handle_registration_response(void *data)<br> {<br>@@ -863,9 +941,15 @@<br> next_registration_round = 0;<br> }<br> schedule_registration(response->client_state, next_registration_round);<br>+<br>+ /* See if we should monitor for transport shutdown */<br>+ registration_transport_monitor_setup(response->rdata->tp_info.transport,<br>+ response->client_state->registration_name);<br> } else {<br> ast_debug(1, "Outbound unregistration to '%s' with client '%s' successful\n", server_uri, client_uri);<br> update_client_state_status(response->client_state, SIP_REGISTRATION_UNREGISTERED);<br>+ ast_sip_transport_monitor_unregister(response->rdata->tp_info.transport,<br>+ registration_transport_shutdown_cb);<br> }<br> } else if (response->client_state->destroy) {<br> /* We need to deal with the pending destruction instead. */<br>@@ -1008,12 +1092,13 @@<br> {<br> struct sip_outbound_registration_client_state *client_state = obj;<br> <br>- ast_free(client_state->transport_name);<br> ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GAUGE, "-1", 1.0);<br> ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "-1", 1.0,<br> sip_outbound_registration_status_str(client_state->status));<br> <br> ast_taskprocessor_unreference(client_state->serializer);<br>+ ast_free(client_state->transport_name);<br>+ ast_free(client_state->registration_name);<br> }<br> <br> /*! \brief Allocator function for registration state */<br>@@ -1033,6 +1118,23 @@<br> return NULL;<br> }<br> <br>+ state->client_state->status = SIP_REGISTRATION_UNREGISTERED;<br>+ state->client_state->timer.user_data = state->client_state;<br>+ state->client_state->timer.cb = sip_outbound_registration_timer_cb;<br>+ state->client_state->transport_name = ast_strdup(registration->transport);<br>+ state->client_state->registration_name =<br>+ ast_strdup(ast_sorcery_object_get_id(registration));<br>+<br>+ ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GAUGE, "+1", 1.0);<br>+ ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "+1", 1.0,<br>+ sip_outbound_registration_status_str(state->client_state->status));<br>+<br>+ if (!state->client_state->transport_name<br>+ || !state->client_state->registration_name) {<br>+ ao2_cleanup(state);<br>+ return NULL;<br>+ }<br>+<br> /* Create name with seq number appended. */<br> ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/outreg/%s",<br> ast_sorcery_object_get_id(registration));<br>@@ -1043,14 +1145,6 @@<br> ao2_cleanup(state);<br> return NULL;<br> }<br>- state->client_state->status = SIP_REGISTRATION_UNREGISTERED;<br>- state->client_state->timer.user_data = state->client_state;<br>- state->client_state->timer.cb = sip_outbound_registration_timer_cb;<br>- state->client_state->transport_name = ast_strdup(registration->transport);<br>-<br>- ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GAUGE, "+1", 1.0);<br>- ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "+1", 1.0,<br>- sip_outbound_registration_status_str(state->client_state->status));<br> <br> state->registration = ao2_bump(registration);<br> return state;<br>@@ -2054,6 +2148,8 @@<br> <br> ao2_global_obj_release(current_states);<br> <br>+ ast_sip_transport_monitor_unregister_all(registration_transport_shutdown_cb);<br>+<br> /* Wait for registration serializers to get destroyed. */<br> ast_debug(2, "Waiting for registration transactions to complete for unload.\n");<br> remaining = ast_serializer_shutdown_group_join(shutdown_group, MAX_UNLOAD_TIMEOUT_TIME);<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/6202">change 6202</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/6202"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 15 </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I3668405b1ee75dfefb07c0d637826176f741ce83 </div>
<div style="display:none"> Gerrit-Change-Number: 6202 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Richard Mudgett <rmudgett@digium.com> </div>