mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 10:47:18 +00:00 
			
		
		
		
	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
This commit is contained in:
		
							
								
								
									
										7
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								CHANGES
									
									
									
									
									
								
							| @@ -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); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user