@ -35,6 +35,7 @@
# include "asterisk/stasis_system.h"
# include "asterisk/threadstorage.h"
# include "asterisk/threadpool.h"
# include "asterisk/statsd.h"
# include "res_pjsip/include/res_pjsip_private.h"
/*** DOCUMENTATION
@ -612,6 +613,19 @@ static void schedule_registration(struct sip_outbound_registration_client_state
}
}
static void update_client_state_status ( struct sip_outbound_registration_client_state * client_state , enum sip_outbound_registration_status status )
{
if ( client_state - > status = = status ) {
return ;
}
ast_statsd_log_string_va ( " PJSIP.registrations.state.%s " , AST_STATSD_GUAGE , " -1 " , 1.0 ,
sip_outbound_registration_status_str ( client_state - > status ) ) ;
ast_statsd_log_string_va ( " PJSIP.registrations.state.%s " , AST_STATSD_GUAGE , " +1 " , 1.0 ,
sip_outbound_registration_status_str ( status ) ) ;
client_state - > status = status ;
}
/*! \brief Callback function for unregistering (potentially) and destroying state */
static int handle_client_state_destruction ( void * data )
{
@ -645,7 +659,7 @@ static int handle_client_state_destruction(void *data)
( int ) info . server_uri . slen , info . server_uri . ptr ,
( int ) info . client_uri . slen , info . client_uri . ptr ) ;
client_state - > status = SIP_REGISTRATION_STOPPING ;
update_client_state_status ( client_state , SIP_REGISTRATION_STOPPING ) ;
client_state - > destroy = 1 ;
if ( pjsip_regc_unregister ( client_state - > client , & tdata ) = = PJ_SUCCESS
& & registration_client_send ( client_state , tdata ) = = PJ_SUCCESS ) {
@ -664,7 +678,7 @@ static int handle_client_state_destruction(void *data)
client_state - > client = NULL ;
}
client_state - > status = SIP_REGISTRATION_STOPPED ;
update_client_state_status ( client_state , SIP_REGISTRATION_STOPPED ) ;
ast_sip_auth_vector_destroy ( & client_state - > outbound_auths ) ;
ao2_ref ( client_state , - 1 ) ;
@ -726,7 +740,7 @@ static int sip_outbound_registration_is_temporal(unsigned int code,
static void schedule_retry ( struct registration_response * response , unsigned int interval ,
const char * server_uri , const char * client_uri )
{
response - > client_state - > status = SIP_REGISTRATION_REJECTED_TEMPORARY ;
update_client_state_status ( response - > client_state , SIP_REGISTRATION_REJECTED_TEMPORARY ) ;
schedule_registration ( response - > client_state , interval ) ;
if ( response - > rdata ) {
@ -800,7 +814,7 @@ static int handle_registration_response(void *data)
/* If the registration went fine simply reschedule registration for the future */
ast_debug ( 1 , " Outbound registration to '%s' with client '%s' successful \n " , server_uri , client_uri ) ;
response - > client_state - > status = SIP_REGISTRATION_REGISTERED ;
update_client_state_status ( response - > client_state , SIP_REGISTRATION_REGISTERED ) ;
response - > client_state - > retries = 0 ;
next_registration_round = response - > expiration - REREGISTER_BUFFER_TIME ;
if ( next_registration_round < 0 ) {
@ -810,7 +824,7 @@ static int handle_registration_response(void *data)
schedule_registration ( response - > client_state , next_registration_round ) ;
} else {
ast_debug ( 1 , " Outbound unregistration to '%s' with client '%s' successful \n " , server_uri , client_uri ) ;
response - > client_state - > status = SIP_REGISTRATION_UNREGISTERED ;
update_client_state_status ( response - > client_state , SIP_REGISTRATION_UNREGISTERED ) ;
}
} else if ( response - > client_state - > destroy ) {
/* We need to deal with the pending destruction instead. */
@ -821,7 +835,7 @@ static int handle_registration_response(void *data)
& & sip_outbound_registration_is_temporal ( response - > code , response - > client_state ) ) {
if ( response - > client_state - > retries = = response - > client_state - > max_retries ) {
/* If we received enough temporal responses to exceed our maximum give up permanently */
response - > client_state - > status = SIP_REGISTRATION_REJECTED_PERMANENT ;
update_client_state_status ( response - > client_state , SIP_REGISTRATION_REJECTED_PERMANENT ) ;
ast_log ( LOG_WARNING , " Maximum retries reached when attempting outbound registration to '%s' with client '%s', stopping registration attempt \n " ,
server_uri , client_uri ) ;
} else {
@ -834,7 +848,7 @@ static int handle_registration_response(void *data)
& & response - > client_state - > forbidden_retry_interval
& & response - > client_state - > retries < response - > client_state - > max_retries ) {
/* A forbidden response retry interval is configured and there are retries remaining */
response - > client_state - > status = SIP_REGISTRATION_REJECTED_TEMPORARY ;
update_client_state_status ( response - > client_state , SIP_REGISTRATION_REJECTED_TEMPORARY ) ;
response - > client_state - > retries + + ;
schedule_registration ( response - > client_state , response - > client_state - > forbidden_retry_interval ) ;
ast_log ( LOG_WARNING , " 403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds \n " ,
@ -842,14 +856,14 @@ static int handle_registration_response(void *data)
} else if ( response - > client_state - > fatal_retry_interval
& & response - > client_state - > retries < response - > client_state - > max_retries ) {
/* Some kind of fatal failure response received, so retry according to configured interval */
response - > client_state - > status = SIP_REGISTRATION_REJECTED_TEMPORARY ;
update_client_state_status ( response - > client_state , SIP_REGISTRATION_REJECTED_TEMPORARY ) ;
response - > client_state - > retries + + ;
schedule_registration ( response - > client_state , response - > client_state - > fatal_retry_interval ) ;
ast_log ( LOG_WARNING , " '%d' fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds \n " ,
response - > code , server_uri , client_uri , response - > client_state - > fatal_retry_interval ) ;
} else {
/* Finally if there's no hope of registering give up */
response - > client_state - > status = SIP_REGISTRATION_REJECTED_PERMANENT ;
update_client_state_status ( response - > client_state , SIP_REGISTRATION_REJECTED_PERMANENT ) ;
if ( response - > rdata ) {
ast_log ( LOG_WARNING , " Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration \n " ,
response - > code , server_uri , client_uri ) ;
@ -934,7 +948,6 @@ static void sip_outbound_registration_state_destroy(void *obj)
ast_debug ( 3 , " Destroying registration state for registration to server '%s' from client '%s' \n " ,
state - > registration - > server_uri , state - > registration - > client_uri ) ;
ao2_cleanup ( state - > registration ) ;
if ( ! state - > client_state ) {
@ -953,6 +966,10 @@ static void sip_outbound_registration_client_state_destroy(void *obj)
{
struct sip_outbound_registration_client_state * client_state = obj ;
ast_statsd_log_string ( " PJSIP.registrations.count " , AST_STATSD_GUAGE , " -1 " , 1.0 ) ;
ast_statsd_log_string_va ( " PJSIP.registrations.state.%s " , AST_STATSD_GUAGE , " -1 " , 1.0 ,
sip_outbound_registration_status_str ( client_state - > status ) ) ;
ast_taskprocessor_unreference ( client_state - > serializer ) ;
}
@ -981,6 +998,10 @@ static struct sip_outbound_registration_state *sip_outbound_registration_state_a
state - > client_state - > timer . user_data = state - > client_state ;
state - > client_state - > timer . cb = sip_outbound_registration_timer_cb ;
ast_statsd_log_string ( " PJSIP.registrations.count " , AST_STATSD_GUAGE , " +1 " , 1.0 ) ;
ast_statsd_log_string_va ( " PJSIP.registrations.state.%s " , AST_STATSD_GUAGE , " +1 " , 1.0 ,
sip_outbound_registration_status_str ( state - > client_state - > status ) ) ;
state - > registration = ao2_bump ( registration ) ;
return state ;
}
@ -2013,6 +2034,12 @@ static int load_module(void)
ast_manager_register_xml ( " PJSIPRegister " , EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING , ami_register ) ;
ast_manager_register_xml ( " PJSIPShowRegistrationsOutbound " , EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING , ami_show_outbound_registrations ) ;
/* Clear any previous statsd gauges in case we weren't shutdown cleanly */
ast_statsd_log ( " PJSIP.registrations.count " , AST_STATSD_GUAGE , 0 ) ;
ast_statsd_log ( " PJSIP.registrations.state.Registered " , AST_STATSD_GUAGE , 0 ) ;
ast_statsd_log ( " PJSIP.registrations.state.Unregistered " , AST_STATSD_GUAGE , 0 ) ;
ast_statsd_log ( " PJSIP.registrations.state.Rejected " , AST_STATSD_GUAGE , 0 ) ;
/* Load configuration objects */
ast_sorcery_load_object ( ast_sip_get_sorcery ( ) , " registration " ) ;