res_pjsip_outbound_registration: registration stops due to fatal 4xx response

During outbound registration it is possible to receive a fatal (any permanent/
non-temporary 4xx, 5xx, 6xx) response from the registrar that is simply due
to a problem with the registrar itself. Upon receiving the failure response
Asterisk terminates outbound registration for the given endpoint.

This patch adds an option, 'fatal_retry_interval', that when set continues
outbound registration at the given interval up to 'max_retries' upon receiving
a fatal response.

ASTERISK-25485 #close

Change-Id: Ibc2c7b47164ac89cc803433c0bbe7063bfa143a2
changes/73/1473/5
Kevin Harwell 10 years ago
parent b9bd249a85
commit 691c0e0b31

@ -162,6 +162,13 @@ res_pjsip
will be used instead. The new SIP resolver provides NAPTR support, improved will be used instead. The new SIP resolver provides NAPTR support, improved
SRV support, and AAAA record support. SRV support, and AAAA record support.
res_pjsip_outbound_registration
-------------------------------
* A new 'fatal_retry_interval' option has been added to outbound registration.
When set (default is zero), and upon receiving a failure response to an
outbound registration, registration is retried at the given interval up to
'max_retries'.
CEL Backends CEL Backends
------------------ ------------------

@ -931,6 +931,14 @@
; registration is unsuccessful (default: "60") ; registration is unsuccessful (default: "60")
;forbidden_retry_interval=0 ; Interval used when receiving a 403 Forbidden ;forbidden_retry_interval=0 ; Interval used when receiving a 403 Forbidden
; response (default: "0") ; response (default: "0")
;fatal_retry_interval=0 ; Interval used when receiving a fatal response.
; (default: "0") A fatal response is any permanent
; failure (non-temporary 4xx, 5xx, 6xx) response
; received from the registrar. NOTE - if also set
; the 'forbidden_retry_interval' takes precedence
; over this one when a 403 is received. Also, if
; 'auth_rejection_permanent' equals 'yes' a 401 and
; 407 become subject to this retry interval.
;server_uri= ; SIP URI of the server to register against (default: "") ;server_uri= ; SIP URI of the server to register against (default: "")
;transport= ; Transport used for outbound authentication (default: "") ;transport= ; Transport used for outbound authentication (default: "")
;type= ; Must be of type registration (default: "") ;type= ; Must be of type registration (default: "")

@ -0,0 +1,22 @@
"""add fatal_response_interval
Revision ID: 28ce1e718f05
Revises: 154177371065
Create Date: 2015-10-20 17:57:45.560585
"""
# revision identifiers, used by Alembic.
revision = '28ce1e718f05'
down_revision = '154177371065'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.add_column('ps_registrations', sa.Column('fatal_retry_interval', sa.Integer))
def downgrade():
op.drop_column('ps_registrations', 'fatal_retry_interval')

@ -100,6 +100,21 @@
buggy registrars. buggy registrars.
</para></description> </para></description>
</configOption> </configOption>
<configOption name="fatal_retry_interval" default="0">
<synopsis>Interval used when receiving a Fatal response.</synopsis>
<description><para>
If a fatal response is received, chan_pjsip will wait
<replaceable>fatal_retry_interval</replaceable> seconds before
attempting registration again. If 0 is specified, chan_pjsip will not
retry after receiving a fatal (non-temporary 4xx, 5xx, 6xx) response.
Setting this to a non-zero value may go against a "SHOULD NOT" in RFC3261,
but can be used to work around buggy registrars.</para>
<note><para>if also set the <replaceable>forbidden_retry_interval</replaceable>
takes precedence over this one when a 403 is received.
Also, if <replaceable>auth_rejection_permanent</replaceable> equals 'yes' then
a 401 and 407 become subject to this retry interval.</para></note>
</description>
</configOption>
<configOption name="server_uri"> <configOption name="server_uri">
<synopsis>SIP URI of the server to register against</synopsis> <synopsis>SIP URI of the server to register against</synopsis>
<description><para> <description><para>
@ -277,6 +292,8 @@ struct sip_outbound_registration {
unsigned int retry_interval; unsigned int retry_interval;
/*! \brief Interval at which retries should occur for permanent responses */ /*! \brief Interval at which retries should occur for permanent responses */
unsigned int forbidden_retry_interval; unsigned int forbidden_retry_interval;
/*! \brief Interval at which retries should occur for all permanent responses */
unsigned int fatal_retry_interval;
/*! \brief Treat authentication challenges that we cannot handle as permanent failures */ /*! \brief Treat authentication challenges that we cannot handle as permanent failures */
unsigned int auth_rejection_permanent; unsigned int auth_rejection_permanent;
/*! \brief Maximum number of retries permitted */ /*! \brief Maximum number of retries permitted */
@ -312,6 +329,8 @@ struct sip_outbound_registration_client_state {
unsigned int retry_interval; unsigned int retry_interval;
/*! \brief Interval at which retries should occur for permanent responses */ /*! \brief Interval at which retries should occur for permanent responses */
unsigned int forbidden_retry_interval; unsigned int forbidden_retry_interval;
/*! \brief Interval at which retries should occur for all permanent responses */
unsigned int fatal_retry_interval;
/*! \brief Treat authentication challenges that we cannot handle as permanent failures */ /*! \brief Treat authentication challenges that we cannot handle as permanent failures */
unsigned int auth_rejection_permanent; unsigned int auth_rejection_permanent;
/*! \brief Determines whether SIP Path support should be advertised */ /*! \brief Determines whether SIP Path support should be advertised */
@ -799,6 +818,14 @@ static int handle_registration_response(void *data)
schedule_registration(response->client_state, response->client_state->forbidden_retry_interval); 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", ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
server_uri, client_uri, response->client_state->forbidden_retry_interval); server_uri, client_uri, response->client_state->forbidden_retry_interval);
} 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;
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 { } else {
/* Finally if there's no hope of registering give up */ /* Finally if there's no hope of registering give up */
response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT; response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
@ -1186,6 +1213,7 @@ static int sip_outbound_registration_perform(void *data)
} }
state->client_state->retry_interval = registration->retry_interval; state->client_state->retry_interval = registration->retry_interval;
state->client_state->forbidden_retry_interval = registration->forbidden_retry_interval; state->client_state->forbidden_retry_interval = registration->forbidden_retry_interval;
state->client_state->fatal_retry_interval = registration->fatal_retry_interval;
state->client_state->max_retries = registration->max_retries; state->client_state->max_retries = registration->max_retries;
state->client_state->retries = 0; state->client_state->retries = 0;
state->client_state->support_path = registration->support_path; state->client_state->support_path = registration->support_path;
@ -1909,6 +1937,7 @@ static int load_module(void)
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration)); ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval)); ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "forbidden_retry_interval", "0", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, forbidden_retry_interval)); ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "forbidden_retry_interval", "0", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, forbidden_retry_interval));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "fatal_retry_interval", "0", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, fatal_retry_interval));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "max_retries", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_retries)); ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "max_retries", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_retries));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "auth_rejection_permanent", "yes", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, auth_rejection_permanent)); ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "auth_rejection_permanent", "yes", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, auth_rejection_permanent));
ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "outbound_auth", "", outbound_auth_handler, outbound_auths_to_str, outbound_auths_to_var_list, 0, 0); ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "outbound_auth", "", outbound_auth_handler, outbound_auths_to_str, outbound_auths_to_var_list, 0, 0);

Loading…
Cancel
Save