diff --git a/CHANGES b/CHANGES index 7e54a2095660b89531c1e548b7d559eac2697d1e..ef78d97bf292ddf3aa137d8b4fca2d14499d42cd 100644 --- a/CHANGES +++ b/CHANGES @@ -147,6 +147,10 @@ res_pjsip unavailable. When any contact becomes available, the endpoint will status will change back to "Reachable". + * A new global option has been added: "max_initial_qualify_time", which + sets the maximum amount of time from startup that qualifies should be + attempted on all contacts. + res_ari_channels ------------------ * Two new events, 'ChannelHold' and 'ChannelUnhold', have been added to the diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample index 57b712a873a983306f86a4051a9646e92e92ed94..0f95d19e0065ed36123367508fb236a36708925d 100644 --- a/configs/samples/pjsip.conf.sample +++ b/configs/samples/pjsip.conf.sample @@ -869,7 +869,10 @@ ; The order by which endpoint identifiers are given priority. ; Identifier names are derived from res_pjsip_endpoint_identifier_* ; modules. (default: ip,username,anonymous) - +;max_initial_qualify_time=4 ; The maximum amount of time (in seconds) from + startup that qualifies should be attempted on all + contacts. If greater than the qualify_frequency + for an aor, qualify_frequency will be used instead. ; MODULE PROVIDING BELOW SECTION(S): res_pjsip_acl ;==========================ACL SECTION OPTIONS========================= diff --git a/contrib/ast-db-manage/config/versions/a541e0b5e89_add_pjsip_max_initial_qualify_time.py b/contrib/ast-db-manage/config/versions/a541e0b5e89_add_pjsip_max_initial_qualify_time.py new file mode 100644 index 0000000000000000000000000000000000000000..0ffd7848da25541c30d19695e93c435d2ef423ef --- /dev/null +++ b/contrib/ast-db-manage/config/versions/a541e0b5e89_add_pjsip_max_initial_qualify_time.py @@ -0,0 +1,20 @@ +"""add pjsip max_initial_qualify_time + +Revision ID: a541e0b5e89 +Revises: 461d7d691209 +Create Date: 2015-04-15 14:37:36.424471 + +""" + +# revision identifiers, used by Alembic. +revision = 'a541e0b5e89' +down_revision = '461d7d691209' + +from alembic import op +import sqlalchemy as sa + +def upgrade(): + op.add_column('ps_globals', sa.Column('max_initial_qualify_time', sa.Integer)) + +def downgrade(): + op.drop_column('ps_globals', 'max_initial_qualify_time') diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index 184cb57451ba09ad4e2501f31307d078f35f5a8a..99b65ab088b2810e12ceeae84db728f9467d3112 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -1995,4 +1995,12 @@ char *ast_sip_get_endpoint_identifier_order(void); */ unsigned int ast_sip_get_keep_alive_interval(void); +/*! + * \brief Retrieve the system max initial qualify time. + * + * \retval the maximum initial qualify time. + */ +unsigned int ast_sip_get_max_initial_qualify_time(void); + + #endif /* _RES_PJSIP_H */ diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 4f77b51021575bf998144beac1c78a84727147d5..e54f2c7cce52e27bee815d13771f2055e72cb014 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -1229,6 +1229,10 @@ <configOption name="keep_alive_interval" default="0"> <synopsis>The interval (in seconds) to send keepalives to active connection-oriented transports.</synopsis> </configOption> + <configOption name="max_initial_qualify_time" default="0"> + <synopsis>The maximum amount of time from startup that qualifies should be attempted on all contacts. + If greater than the qualify_frequency for an aor, qualify_frequency will be used instead.</synopsis> + </configOption> <configOption name="type"> <synopsis>Must be of type 'global'.</synopsis> </configOption> diff --git a/res/res_pjsip/config_global.c b/res/res_pjsip/config_global.c index 2aa15838f4e8f12b30676bee43d79db686dfe2a2..42ba23487c6e038905eea285c70529f8a05b25a3 100644 --- a/res/res_pjsip/config_global.c +++ b/res/res_pjsip/config_global.c @@ -33,6 +33,7 @@ #define DEFAULT_OUTBOUND_ENDPOINT "default_outbound_endpoint" #define DEFAULT_DEBUG "no" #define DEFAULT_ENDPOINT_IDENTIFIER_ORDER "ip,username,anonymous" +#define DEFAULT_MAX_INITIAL_QUALIFY_TIME 0 static char default_useragent[256]; @@ -50,6 +51,8 @@ struct global_config { unsigned int max_forwards; /* The interval at which to send keep alive messages to active connection-oriented transports */ unsigned int keep_alive_interval; + /* The maximum time for all contacts to be qualified at startup */ + unsigned int max_initial_qualify_time; }; static void global_destructor(void *obj) @@ -161,6 +164,21 @@ unsigned int ast_sip_get_keep_alive_interval(void) return interval; } +unsigned int ast_sip_get_max_initial_qualify_time(void) +{ + unsigned int time; + struct global_config *cfg; + + cfg = get_global_cfg(); + if (!cfg) { + return DEFAULT_MAX_INITIAL_QUALIFY_TIME; + } + + time = cfg->max_initial_qualify_time; + ao2_ref(cfg, -1); + return time; +} + /*! * \internal * \brief Observer to set default global object if none exist. @@ -271,6 +289,9 @@ int ast_sip_initialize_sorcery_global(void) ast_sorcery_object_field_register(sorcery, "global", "keep_alive_interval", __stringify(DEFAULT_KEEPALIVE_INTERVAL), OPT_UINT_T, 0, FLDSET(struct global_config, keep_alive_interval)); + ast_sorcery_object_field_register(sorcery, "global", "max_initial_qualify_time", + __stringify(DEFAULT_MAX_INITIAL_QUALIFY_TIME), + OPT_UINT_T, 0, FLDSET(struct global_config, max_initial_qualify_time)); if (ast_sorcery_instance_observer_add(sorcery, &observer_callbacks_global)) { return -1; diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c index dc5a70175bd05a2ef7c16736ba8fbdc6307cd002..9c0a1379d0905987fdac38c8c294a750bd44a4c1 100644 --- a/res/res_pjsip/pjsip_options.c +++ b/res/res_pjsip/pjsip_options.c @@ -994,14 +994,20 @@ static int qualify_and_schedule_cb(void *obj, void *arg, int flags) struct ast_sip_contact *contact = obj; struct ast_sip_aor *aor = arg; int initial_interval; + int max_time = ast_sip_get_max_initial_qualify_time(); contact->qualify_frequency = aor->qualify_frequency; contact->qualify_timeout = aor->qualify_timeout; contact->authenticate_qualify = aor->authenticate_qualify; /* Delay initial qualification by a random fraction of the specified interval */ - initial_interval = contact->qualify_frequency * 1000; - initial_interval = (int)(initial_interval * ast_random_double()); + if (max_time && max_time < contact->qualify_frequency) { + initial_interval = max_time; + } else { + initial_interval = contact->qualify_frequency; + } + + initial_interval = (int)((initial_interval * 1000) * ast_random_double()); if (contact->qualify_frequency) { schedule_qualify(contact, initial_interval);