@ -358,6 +358,8 @@ struct sip_outbound_registration_client_state {
unsigned int auth_attempted : 1 ;
unsigned int auth_attempted : 1 ;
/*! \brief The name of the transport to be used for the registration */
/*! \brief The name of the transport to be used for the registration */
char * transport_name ;
char * transport_name ;
/*! \brief The name of the registration sorcery object */
char * registration_name ;
} ;
} ;
/*! \brief Outbound registration state information (persists for lifetime that registration should exist) */
/*! \brief Outbound registration state information (persists for lifetime that registration should exist) */
@ -796,6 +798,82 @@ static void schedule_retry(struct registration_response *response, unsigned int
}
}
}
}
static int reregister_immediately_cb ( void * obj )
{
struct sip_outbound_registration_state * state = obj ;
if ( state - > client_state - > status ! = SIP_REGISTRATION_REGISTERED ) {
ao2_ref ( state , - 1 ) ;
return 0 ;
}
if ( DEBUG_ATLEAST ( 1 ) ) {
pjsip_regc_info info ;
pjsip_regc_get_info ( state - > client_state - > client , & info ) ;
ast_log ( LOG_DEBUG ,
" Outbound registration transport to server '%.*s' from client '%.*s' shutdown \n " ,
( int ) info . server_uri . slen , info . server_uri . ptr ,
( int ) info . client_uri . slen , info . client_uri . ptr ) ;
}
cancel_registration ( state - > client_state ) ;
ao2_ref ( state - > client_state , + 1 ) ;
handle_client_registration ( state - > client_state ) ;
ao2_ref ( state , - 1 ) ;
return 0 ;
}
/*!
* \ internal
* \ brief The reliable transport we registered using has shutdown .
* \ since 13.18 .0
*
* \ param obj What is needed to initiate a reregister attempt .
*
* \ return Nothing
*/
static void registration_transport_shutdown_cb ( void * obj )
{
const char * registration_name = obj ;
struct sip_outbound_registration_state * state ;
state = get_state ( registration_name ) ;
if ( ! state ) {
/* Registration no longer exists or shutting down. */
return ;
}
if ( ast_sip_push_task ( state - > client_state - > serializer , reregister_immediately_cb , state ) ) {
ao2_ref ( state , - 1 ) ;
}
}
static void registration_transport_monitor_setup ( pjsip_transport * transport , const char * registration_name )
{
char * monitor ;
if ( ! PJSIP_TRANSPORT_IS_RELIABLE ( transport ) ) {
return ;
}
monitor = ao2_alloc_options ( strlen ( registration_name ) + 1 , NULL ,
AO2_ALLOC_OPT_LOCK_NOLOCK ) ;
if ( ! monitor ) {
return ;
}
strcpy ( monitor , registration_name ) ; /* Safe */
/*
* We ' ll ignore if the transport has already been shutdown before we
* register the monitor . We might get into a message spamming infinite
* loop of registration , shutdown , reregistration . . .
*/
ast_sip_transport_monitor_register ( transport , registration_transport_shutdown_cb ,
monitor ) ;
ao2_ref ( monitor , - 1 ) ;
}
/*! \brief Callback function for handling a response to a registration attempt */
/*! \brief Callback function for handling a response to a registration attempt */
static int handle_registration_response ( void * data )
static int handle_registration_response ( void * data )
{
{
@ -864,9 +942,15 @@ static int handle_registration_response(void *data)
next_registration_round = 0 ;
next_registration_round = 0 ;
}
}
schedule_registration ( response - > client_state , next_registration_round ) ;
schedule_registration ( response - > client_state , next_registration_round ) ;
/* See if we should monitor for transport shutdown */
registration_transport_monitor_setup ( response - > rdata - > tp_info . transport ,
response - > client_state - > registration_name ) ;
} else {
} else {
ast_debug ( 1 , " Outbound unregistration to '%s' with client '%s' successful \n " , server_uri , client_uri ) ;
ast_debug ( 1 , " Outbound unregistration to '%s' with client '%s' successful \n " , server_uri , client_uri ) ;
update_client_state_status ( response - > client_state , SIP_REGISTRATION_UNREGISTERED ) ;
update_client_state_status ( response - > client_state , SIP_REGISTRATION_UNREGISTERED ) ;
ast_sip_transport_monitor_unregister ( response - > rdata - > tp_info . transport ,
registration_transport_shutdown_cb ) ;
}
}
} else if ( response - > client_state - > destroy ) {
} else if ( response - > client_state - > destroy ) {
/* We need to deal with the pending destruction instead. */
/* We need to deal with the pending destruction instead. */
@ -1009,12 +1093,13 @@ static void sip_outbound_registration_client_state_destroy(void *obj)
{
{
struct sip_outbound_registration_client_state * client_state = obj ;
struct sip_outbound_registration_client_state * client_state = obj ;
ast_free ( client_state - > transport_name ) ;
ast_statsd_log_string ( " PJSIP.registrations.count " , AST_STATSD_GAUGE , " -1 " , 1.0 ) ;
ast_statsd_log_string ( " PJSIP.registrations.count " , AST_STATSD_GAUGE , " -1 " , 1.0 ) ;
ast_statsd_log_string_va ( " PJSIP.registrations.state.%s " , AST_STATSD_GAUGE , " -1 " , 1.0 ,
ast_statsd_log_string_va ( " PJSIP.registrations.state.%s " , AST_STATSD_GAUGE , " -1 " , 1.0 ,
sip_outbound_registration_status_str ( client_state - > status ) ) ;
sip_outbound_registration_status_str ( client_state - > status ) ) ;
ast_taskprocessor_unreference ( client_state - > serializer ) ;
ast_taskprocessor_unreference ( client_state - > serializer ) ;
ast_free ( client_state - > transport_name ) ;
ast_free ( client_state - > registration_name ) ;
}
}
/*! \brief Allocator function for registration state */
/*! \brief Allocator function for registration state */
@ -1034,6 +1119,23 @@ static struct sip_outbound_registration_state *sip_outbound_registration_state_a
return NULL ;
return NULL ;
}
}
state - > client_state - > status = SIP_REGISTRATION_UNREGISTERED ;
state - > client_state - > timer . user_data = state - > client_state ;
state - > client_state - > timer . cb = sip_outbound_registration_timer_cb ;
state - > client_state - > transport_name = ast_strdup ( registration - > transport ) ;
state - > client_state - > registration_name =
ast_strdup ( ast_sorcery_object_get_id ( registration ) ) ;
ast_statsd_log_string ( " PJSIP.registrations.count " , AST_STATSD_GAUGE , " +1 " , 1.0 ) ;
ast_statsd_log_string_va ( " PJSIP.registrations.state.%s " , AST_STATSD_GAUGE , " +1 " , 1.0 ,
sip_outbound_registration_status_str ( state - > client_state - > status ) ) ;
if ( ! state - > client_state - > transport_name
| | ! state - > client_state - > registration_name ) {
ao2_cleanup ( state ) ;
return NULL ;
}
/* Create name with seq number appended. */
/* Create name with seq number appended. */
ast_taskprocessor_build_name ( tps_name , sizeof ( tps_name ) , " pjsip/outreg/%s " ,
ast_taskprocessor_build_name ( tps_name , sizeof ( tps_name ) , " pjsip/outreg/%s " ,
ast_sorcery_object_get_id ( registration ) ) ;
ast_sorcery_object_get_id ( registration ) ) ;
@ -1044,14 +1146,6 @@ static struct sip_outbound_registration_state *sip_outbound_registration_state_a
ao2_cleanup ( state ) ;
ao2_cleanup ( state ) ;
return NULL ;
return NULL ;
}
}
state - > client_state - > status = SIP_REGISTRATION_UNREGISTERED ;
state - > client_state - > timer . user_data = state - > client_state ;
state - > client_state - > timer . cb = sip_outbound_registration_timer_cb ;
state - > client_state - > transport_name = ast_strdup ( registration - > transport ) ;
ast_statsd_log_string ( " PJSIP.registrations.count " , AST_STATSD_GAUGE , " +1 " , 1.0 ) ;
ast_statsd_log_string_va ( " PJSIP.registrations.state.%s " , AST_STATSD_GAUGE , " +1 " , 1.0 ,
sip_outbound_registration_status_str ( state - > client_state - > status ) ) ;
state - > registration = ao2_bump ( registration ) ;
state - > registration = ao2_bump ( registration ) ;
return state ;
return state ;
@ -2055,6 +2149,8 @@ static int unload_module(void)
ao2_global_obj_release ( current_states ) ;
ao2_global_obj_release ( current_states ) ;
ast_sip_transport_monitor_unregister_all ( registration_transport_shutdown_cb ) ;
/* Wait for registration serializers to get destroyed. */
/* Wait for registration serializers to get destroyed. */
ast_debug ( 2 , " Waiting for registration transactions to complete for unload. \n " ) ;
ast_debug ( 2 , " Waiting for registration transactions to complete for unload. \n " ) ;
remaining = ast_serializer_shutdown_group_join ( shutdown_group , MAX_UNLOAD_TIMEOUT_TIME ) ;
remaining = ast_serializer_shutdown_group_join ( shutdown_group , MAX_UNLOAD_TIMEOUT_TIME ) ;