diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample index 0303050d8f..a019708c39 100644 --- a/configs/samples/pjsip.conf.sample +++ b/configs/samples/pjsip.conf.sample @@ -1350,6 +1350,11 @@ ; (default: "") ;outbound_proxy= ; Proxy through which to send registrations, a full SIP URI ; must be provided (default: "") +;max_random_initial_delay=10 ; Maximum random delay for initial registrations (default: 10) + ; Generally it is a good idea to space out registrations + ; to not overload the system. If you have a small number + ; of registrations and need them to register more quickly, + ; you can reduce this to a lower value. ;retry_interval=60 ; Interval in seconds between retries if outbound ; registration is unsuccessful (default: "60") ;forbidden_retry_interval=0 ; Interval used when receiving a 403 Forbidden diff --git a/contrib/ast-db-manage/config/versions/18e0805d367f_max_random_initial_delay.py b/contrib/ast-db-manage/config/versions/18e0805d367f_max_random_initial_delay.py new file mode 100644 index 0000000000..343b841463 --- /dev/null +++ b/contrib/ast-db-manage/config/versions/18e0805d367f_max_random_initial_delay.py @@ -0,0 +1,21 @@ +"""max_random_initial_delay + +Revision ID: 18e0805d367f +Revises: 0bee61aa9425 +Create Date: 2022-05-18 17:07:02.626045 + +""" + +# revision identifiers, used by Alembic. +revision = '18e0805d367f' +down_revision = '0bee61aa9425' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + op.add_column('ps_registrations', sa.Column('max_random_initial_delay', sa.Integer)) + +def downgrade(): + op.drop_column('ps_registrations', 'max_random_initial_delay') diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c index 91cffcb038..20a4761b3f 100644 --- a/res/res_pjsip_outbound_registration.c +++ b/res/res_pjsip_outbound_registration.c @@ -109,6 +109,15 @@ Full SIP URI of the outbound proxy used to send registrations + + Maximum interval in seconds for which an initial registration may be randomly delayed + + By default, registrations are randomly delayed by a small amount to prevent + too many registrations from being made simultaneously. + Depending on your system usage, it may be desirable to set this to a smaller + or larger value to have fine grained control over the size of this random delay. + + Interval in seconds between retries if outbound registration is unsuccessful @@ -319,6 +328,8 @@ struct sip_outbound_registration { ); /*! \brief Requested expiration time */ unsigned int expiration; + /*! \brief Maximum random initial delay interval for initial registrations */ + unsigned int max_random_initial_delay; /*! \brief Interval at which retries should occur for temporal responses */ unsigned int retry_interval; /*! \brief Interval at which retries should occur for permanent responses */ @@ -1711,6 +1722,7 @@ static int sip_outbound_registration_perform(void *data) struct sip_outbound_registration_state *state = data; struct sip_outbound_registration *registration = ao2_bump(state->registration); size_t i; + int max_delay; /* Just in case the client state is being reused for this registration, free the auth information */ ast_sip_auth_vector_destroy(&state->client_state->outbound_auths); @@ -1731,10 +1743,12 @@ static int sip_outbound_registration_perform(void *data) state->client_state->support_path = registration->support_path; state->client_state->support_outbound = registration->support_outbound; state->client_state->auth_rejection_permanent = registration->auth_rejection_permanent; + max_delay = registration->max_random_initial_delay; pjsip_regc_update_expires(state->client_state->client, registration->expiration); - schedule_registration(state->client_state, (ast_random() % 10) + 1); + /* n mod 0 is undefined, so don't let that happen */ + schedule_registration(state->client_state, (max_delay ? ast_random() % max_delay : 0) + 1); ao2_ref(registration, -1); ao2_ref(state, -1); @@ -2546,6 +2560,7 @@ static int load_module(void) ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, transport)); ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy)); 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", "max_random_initial_delay", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_random_initial_delay)); 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", "fatal_retry_interval", "0", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, fatal_retry_interval));