From e5965165e326ea666f755fac5773d377d23b9d3f Mon Sep 17 00:00:00 2001 From: Alfonso Pinto Date: Thu, 8 Feb 2024 15:34:02 +0100 Subject: [PATCH] Fix UNREGISTER flow (#253) --- src/mod/endpoints/mod_sofia/mod_sofia.c | 12 +++++++--- src/mod/endpoints/mod_sofia/mod_sofia.h | 1 + src/mod/endpoints/mod_sofia/sofia.c | 29 ++++++++++++++++++------- src/mod/endpoints/mod_sofia/sofia_reg.c | 24 +++++--------------- 4 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 6206d5bca2d..50beac8f041 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -3967,13 +3967,19 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t stream->write_function(stream, "+OK\n"); } else if ((gateway_ptr = sofia_reg_find_gateway(gname))) { if (gateway_ptr->state != REG_STATE_NOREG && gateway_ptr->state != REG_STATE_DOWN) { - gateway_ptr->retry = 0; - gateway_ptr->state = REG_STATE_UNREGISTER; + if (gateway_ptr->state == REG_STATE_FAILED && !sofia_test_flag(gateway_ptr, REG_FLAG_REGISTERED)) { + gateway_ptr->retry = 0; + gateway_ptr->state = REG_STATE_DOWN; + sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL); + } else { + gateway_ptr->retry = 0; + gateway_ptr->state = REG_STATE_UNREGISTER; + } stream->write_function(stream, "+OK\n"); - sofia_reg_release_gateway(gateway_ptr); } else { stream->write_function(stream, "-ERR NOREG gateway [%s] can't be unregistered!\n", gname); } + sofia_reg_release_gateway(gateway_ptr); } else { stream->write_function(stream, "Invalid gateway!\n"); } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 708770ce553..66d5d65d201 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -434,6 +434,7 @@ extern struct mod_sofia_globals mod_sofia_globals; typedef enum { REG_FLAG_AUTHED, REG_FLAG_CALLERID, + REG_FLAG_REGISTERED, /* No new flags below this line */ REG_FLAG_MAX diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 3adb82d6bf1..c4954ce22ee 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1625,14 +1625,6 @@ static void our_sofia_event_callback(nua_event_t event, } } - if (event == nua_r_unregister && status != 401 && status != 407 && status >= 200) { - if (gateway) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Mark gateway %s for destruction after unregister. Status %d.\n", sofia_private->gateway_name, status); - gateway->destroy = 1; - } - goto done; - } - if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip && (event < nua_r_set_params || event > nua_r_authenticate)) { sip_authorization_t const *authorization = NULL; @@ -1679,6 +1671,27 @@ static void our_sofia_event_callback(nua_event_t event, case nua_r_info: break; case nua_r_unregister: + if (gateway && status != 401 && status != 407 && status >= 200) { + reg_state_t ostate = gateway->state; + + gateway->state = REG_STATE_DOWN; + gateway->status = SOFIA_GATEWAY_DOWN; + gateway->last_inactive = switch_epoch_time_now(NULL); + + if (gateway->sofia_private) { + sofia_private_free(gateway->sofia_private); + } + + if (gateway->nh) { + nua_handle_bind(gateway->nh, NULL); + nua_handle_destroy(gateway->nh); + gateway->nh = NULL; + } + if (ostate != gateway->state) { + sofia_reg_fire_custom_gateway_state_event(gateway, status, NULL); + } + } + break; case nua_r_unsubscribe: case nua_i_terminated: case nua_r_publish: diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 3ebe41c9bd6..87f7fac5229 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -139,6 +139,8 @@ static void sofia_reg_kill_reg(sofia_gateway_t *gateway_ptr) if (gateway_ptr->state == REG_STATE_REGED || gateway_ptr->state == REG_STATE_UNREGISTER) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "UN-Registering %s\n", gateway_ptr->name); nua_unregister(gateway_ptr->nh, NUTAG_URL(gateway_ptr->register_url), NUTAG_REGISTRAR(gateway_ptr->register_proxy), TAG_END()); + + // Returning here, nua_handle and sofia_private must be clean up in event *nua_r_unregister* with proper status return; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Destroying registration handle for %s\n", gateway_ptr->name); @@ -461,22 +463,6 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) user_via = NULL; } - if(ostate == REG_STATE_DOWN && gateway_ptr->destroy) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Destroy sofia_private and nua_handler for gateway %s\n", gateway_ptr->name); - - if (gateway_ptr->sofia_private) { - sofia_private_free(gateway_ptr->sofia_private); - } - - if (gateway_ptr->nh) { - nua_handle_bind(gateway_ptr->nh, NULL); - nua_handle_destroy(gateway_ptr->nh); - gateway_ptr->nh = NULL; - } - - gateway_ptr->destroy = 0; - } - switch (ostate) { case REG_STATE_DOWN: case REG_STATE_NOREG: @@ -514,9 +500,6 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) case REG_STATE_UNREGISTER: sofia_reg_kill_reg(gateway_ptr); - gateway_ptr->state = REG_STATE_DOWN; - gateway_ptr->status = SOFIA_GATEWAY_DOWN; - gateway_ptr->last_inactive = switch_epoch_time_now(NULL); request++; // Only increment when FS sends out request break; case REG_STATE_UNREGED: @@ -2761,6 +2744,9 @@ void sofia_reg_handle_sip_r_register(int status, } } } + if (!sofia_test_flag(gateway, REG_FLAG_REGISTERED)) { + sofia_set_flag(gateway, REG_FLAG_REGISTERED); + } gateway->state = REG_STATE_REGISTER; break; case 100: