[mod_sofia] Randomize OPTIONS Ping interval

In FS-6400, the attempt was made to randomize OPTIONS
packets to be sent at a random interval.  The same random
interval is applied to all endpoints so this doesn't work.
Furthermore, rounding within the code, as well as
reseeding with srand() on each run will ultimately
make the ping times converge over time.  Once the
times converge, they will not separate since the reseeding
will cause the same random number to apply to each
registration.

This commmit will apply the random interval only during
initial registration and update of registration.
All subsequent pings will be incremented with the
actual value of ping-mean-interval. (This parameter
name is no longer accurate, and would be better named
ping-max-interval).

srand() has been moved to the start of the worker
thread, and all repeat calls have been removed,
so that each call of rand(), even during the
same second, generates a different random number.

Fixes #1132, Fixes #1133
This commit is contained in:
Joseph Nadiv 2021-10-30 21:14:00 -04:00 committed by yois615
parent bb682fc5b4
commit 7afeceb47e
3 changed files with 14 additions and 13 deletions

View File

@ -2949,6 +2949,9 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread
sofia_set_pflag_locked(profile, PFLAG_WORKER_RUNNING);
/* Seed PRNG for functions within worker thread */
srand((unsigned)((intptr_t) switch_thread_self() + switch_micro_time_now()));
while ((mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING))) {
if (tick) {

View File

@ -3755,7 +3755,6 @@ void sofia_presence_handle_sip_i_subscribe(int status,
if ((sub_max_deviation_var = profile->sip_subscription_max_deviation)) {
int sub_deviation;
srand( (unsigned) ( (unsigned)(intptr_t)switch_thread_self() + switch_micro_time_now() ) );
/* random negative number between 0 and negative sub_max_deviation_var: */
sub_deviation = ( rand() % sub_max_deviation_var ) - sub_max_deviation_var;
if ( (exp_delta + sub_deviation) > 45 ) {

View File

@ -884,7 +884,6 @@ long sofia_reg_uniform_distribution(int max)
int result;
int range = max + 1;
srand((unsigned)((intptr_t) switch_thread_self() + switch_micro_time_now()));
result = (int)((double)rand() / (((double)RAND_MAX + (double)1) / range));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Generated random %ld, max is %d\n", (long) result, max);
@ -894,8 +893,7 @@ long sofia_reg_uniform_distribution(int max)
void sofia_reg_check_ping_expire(sofia_profile_t *profile, time_t now, int interval)
{
char *sql;
int mean = interval / 2;
long next, irand;
long next;
char buf[32] = "";
int count;
@ -952,8 +950,7 @@ void sofia_reg_check_ping_expire(sofia_profile_t *profile, time_t now, int inter
/* only update if needed */
if (count) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Updating ping expires for profile %s\n", profile->name);
irand = mean + sofia_reg_uniform_distribution(interval);
next = (long) now + irand;
next = (long) now + interval;
sql = switch_mprintf("update sip_registrations set ping_expires = %ld where hostname='%q' and profile_name='%q' and ping_expires <= %ld ",
next, mod_sofia_globals.hostname, profile->name, (long) now);
@ -1765,7 +1762,6 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu
(( exp_max_deviation_var = profile->sip_expires_max_deviation )) ) {
if (exp_max_deviation_var > 0) {
int exp_deviation;
srand( (unsigned) ( (unsigned)(intptr_t)switch_thread_self() + switch_micro_time_now() ) );
/* random number between negative exp_max_deviation_var and positive exp_max_deviation_var: */
exp_deviation = ( rand() % ( exp_max_deviation_var * 2 ) ) - exp_max_deviation_var;
exptime += exp_deviation;
@ -2013,23 +2009,26 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu
sql = switch_mprintf("insert into sip_registrations "
"(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
"user_agent,server_user,server_host,profile_name,hostname,network_ip,network_port,sip_username,sip_realm,"
"mwi_user,mwi_host, orig_server_host, orig_hostname, sub_host, ping_status, ping_count, force_ping) "
"values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%q', '%q', '%q', '%q', '%q', '%q', '%q','%q','%q','%q','%q','%q','%q','%q', '%q', %d, %d)",
"mwi_user,mwi_host, orig_server_host, orig_hostname, sub_host, ping_status, ping_count, ping_expires, force_ping) "
"values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%q', '%q', '%q', '%q', '%q', '%q', '%q','%q','%q','%q','%q','%q','%q','%q', '%q', %d, %ld, %d)",
call_id, to_user, reg_host, profile->presence_hosts ? profile->presence_hosts : "",
contact_str, reg_desc, rpid, (long) reg_time + (long) exptime + profile->sip_expires_late_margin,
agent, from_user, guess_ip4, profile->name, mod_sofia_globals.hostname, network_ip, network_port_c, username, realm,
mwi_user, mwi_host, guess_ip4, mod_sofia_globals.hostname, sub_host, "Reachable", 0, force_ping);
mwi_user, mwi_host, guess_ip4, mod_sofia_globals.hostname, sub_host, "Reachable", 0,
(long) switch_epoch_time_now(NULL) + sofia_reg_uniform_distribution(profile->iping_seconds), force_ping);
} else {
sql = switch_mprintf("update sip_registrations set call_id='%q',"
"sub_host='%q', network_ip='%q',network_port='%q',"
"presence_hosts='%q', server_host='%q', orig_server_host='%q',"
"hostname='%q', orig_hostname='%q',"
"expires = %ld, force_ping=%d where sip_user='%q' and sip_username='%q' and sip_host='%q' and contact='%q'",
"expires = %ld, ping_expires=%ld, force_ping=%d "
"where sip_user='%q' and sip_username='%q' and sip_host='%q' and contact='%q'",
call_id, sub_host, network_ip, network_port_c,
profile->presence_hosts ? profile->presence_hosts : "", guess_ip4, guess_ip4,
mod_sofia_globals.hostname, mod_sofia_globals.hostname,
(long) reg_time + (long) exptime + profile->sip_expires_late_margin, force_ping,
to_user, username, reg_host, contact_str);
(long) reg_time + (long) exptime + profile->sip_expires_late_margin,
(long) switch_epoch_time_now(NULL) + sofia_reg_uniform_distribution(profile->iping_seconds),
force_ping, to_user, username, reg_host, contact_str);
}
if (sql) {