Merge pull request #64 in FS/freeswitch from ~MBRANCA/freeswitch:bugfix/FS-6400-improve-sip-ping-generation-by-distributing to master

* commit 'beb1d1792134f61a252538d45af909ee50771017':
  FS-6400 Improve sip ping generation by distributing them across an interval
This commit is contained in:
Mike Jerris 2014-10-14 11:59:43 -05:00
commit e898770e69
4 changed files with 83 additions and 6 deletions

View File

@ -43,6 +43,8 @@
#define SQL_CACHE_TIMEOUT 300
#define DEFAULT_NONCE_TTL 60
#define IREG_SECONDS 30
#define IPING_SECONDS 30
#define IPING_FREQUENCY 1
#define GATEWAY_SECONDS 1
#define SOFIA_QUEUE_SIZE 50000
#define HAVE_APR
@ -720,6 +722,8 @@ struct sofia_profile {
uint32_t sip_expires_late_margin;
uint32_t sip_subscription_max_deviation;
int ireg_seconds;
int iping_seconds;
int iping_freq;
sofia_paid_type_t paid_type;
uint32_t rtp_digit_delay;
switch_queue_t *event_queue;
@ -976,6 +980,7 @@ void sofia_glue_actually_execute_sql_trans(sofia_profile_t *profile, char *sql,
void sofia_glue_execute_sql_now(sofia_profile_t *profile, char **sqlp, switch_bool_t sql_already_dynamic);
void sofia_glue_execute_sql_soon(sofia_profile_t *profile, char **sqlp, switch_bool_t sql_already_dynamic);
void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot);
void sofia_reg_check_ping_expire(sofia_profile_t *profile, time_t now, int interval);
void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now);
void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now);
void sofia_reg_unregister(sofia_profile_t *profile);

View File

@ -2574,6 +2574,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread
{
sofia_profile_t *profile = (sofia_profile_t *) obj;
uint32_t ireg_loops = profile->ireg_seconds; /* Number of loop iterations done when we haven't checked for registrations */
uint32_t iping_loops = profile->iping_freq; /* Number of loop iterations done when we haven't checked for ping expires */
uint32_t gateway_loops = GATEWAY_SECONDS; /* Number of loop iterations done when we haven't checked for gateways */
sofia_set_pflag_locked(profile, PFLAG_WORKER_RUNNING);
@ -2618,6 +2619,12 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread
sofia_reg_check_expire(profile, now, 0);
ireg_loops = 0;
}
if(++iping_loops >= (uint32_t)profile->iping_freq) {
time_t now = switch_epoch_time_now(NULL);
sofia_reg_check_ping_expire(profile, now, profile->iping_seconds);
iping_loops = 0;
}
if (++gateway_loops >= GATEWAY_SECONDS) {
sofia_reg_check_gateway(profile, switch_epoch_time_now(NULL));
@ -4099,6 +4106,8 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
profile->mndlb |= SM_NDLB_ALLOW_NONDUP_SDP;
profile->te = 101;
profile->ireg_seconds = IREG_SECONDS;
profile->iping_seconds = IPING_SECONDS;
profile->iping_freq = IPING_FREQUENCY;
profile->paid_type = PAID_DEFAULT;
profile->bind_attempts = 2;
profile->bind_attempt_interval = 5;
@ -4229,6 +4238,16 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
if (profile->ireg_seconds < 0) {
profile->ireg_seconds = IREG_SECONDS;
}
} else if (!strcasecmp(var, "ping-mean-interval")) {
profile->iping_seconds = atoi(val);
if (profile->iping_seconds < 0) {
profile->iping_seconds = IPING_SECONDS;
}
} else if (!strcasecmp(var, "ping-thread-frequency")) {
profile->iping_freq = atoi(val);
if (profile->iping_freq < 0) {
profile->iping_freq = IPING_FREQUENCY;
}
} else if (!strcasecmp(var, "user-agent-string")) {
profile->user_agent = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "auto-restart")) {

View File

@ -1993,6 +1993,7 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
" ping_count INTEGER,\n"
" rpid VARCHAR(255),\n"
" expires BIGINT,\n"
" ping_expires INTEGER not null default 0,\n"
" user_agent VARCHAR(255),\n"
" server_user VARCHAR(255),\n"
" server_host VARCHAR(255),\n"
@ -2121,6 +2122,7 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
"create index sr_presence_hosts on sip_registrations (presence_hosts)",
"create index sr_contact on sip_registrations (contact)",
"create index sr_expires on sip_registrations (expires)",
"create index sr_ping_expires on sip_registrations (ping_expires)",
"create index sr_hostname on sip_registrations (hostname)",
"create index sr_status on sip_registrations (status)",
"create index sr_ping_status on sip_registrations (ping_status)",
@ -2205,6 +2207,7 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
switch_cache_db_test_reactive(dbh, "select ping_count from sip_registrations", NULL, "alter table sip_registrations add column ping_count INTEGER default 0");
switch_cache_db_test_reactive(dbh, "select ping_status from sip_registrations", NULL, "alter table sip_registrations add column ping_status VARCHAR(255) default \"Reachable\"");
switch_cache_db_test_reactive(dbh, "select ping_expires from sip_registrations", NULL, "alter table sip_registrations add column ping_expires INTEGER not null default 0");
test2 = switch_mprintf("%s;%s", test_sql, test_sql);

View File

@ -846,21 +846,45 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
}
long sofia_reg_uniform_distribution(int max)
{
/*
* Generate a random number following a uniform distribution between 0 and max
*/
int result;
int range = max + 1;
srand((unsigned) 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);
return (long) result;
}
void sofia_reg_check_ping_expire(sofia_profile_t *profile, time_t now, int interval)
{
char *sql;
int mean = interval / 2;
long next, irand;
if (now) {
if (sofia_test_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING)) {
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,"
"expires,user_agent,server_user,server_host,profile_name"
" from sip_registrations where hostname='%s' and "
"profile_name='%s' and orig_hostname='%s'", mod_sofia_globals.hostname, profile->name, mod_sofia_globals.hostname);
"profile_name='%s' and orig_hostname='%s' and "
"ping_expires > 0 and ping_expires <= %ld", mod_sofia_globals.hostname, profile->name, mod_sofia_globals.hostname, (long) now);
sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nat_callback, profile);
switch_safe_free(sql);
} else if (sofia_test_pflag(profile, PFLAG_UDP_NAT_OPTIONS_PING)) {
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,"
"expires,user_agent,server_user,server_host,profile_name"
" from sip_registrations where status like '%%UDP-NAT%%' "
"and hostname='%s' and profile_name='%s'", mod_sofia_globals.hostname, profile->name);
sql = switch_mprintf( " select call_id,sip_user,sip_host,contact,status,rpid, "
" expires,user_agent,server_user,server_host,profile_name "
" from sip_registrations where status like '%%UDP-NAT%%' "
" and hostname='%s' and profile_name='%s' and ping_expires > 0 and ping_expires <= %ld ",
mod_sofia_globals.hostname, profile->name, (long) now);
sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nat_callback, profile);
switch_safe_free(sql);
@ -869,11 +893,37 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
"expires,user_agent,server_user,server_host,profile_name"
" from sip_registrations where (status like '%%NAT%%' "
"or contact like '%%fs_nat=yes%%') and hostname='%s' "
"and profile_name='%s' and orig_hostname='%s'", mod_sofia_globals.hostname, profile->name, mod_sofia_globals.hostname);
"and profile_name='%s' and orig_hostname='%s' and "
"ping_expires > 0 and ping_expires <= %ld", mod_sofia_globals.hostname, profile->name, mod_sofia_globals.hostname, (long) now);
sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nat_callback, profile);
switch_safe_free(sql);
}
if (sofia_test_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING) ||
sofia_test_pflag(profile, PFLAG_UDP_NAT_OPTIONS_PING) ||
sofia_test_pflag(profile, PFLAG_NAT_OPTIONS_PING)) {
char buf[32] = "";
int count;
sql = switch_mprintf("select count(*) from sip_registrations where hostname='%q' and profile_name='%q' and ping_expires <= %ld",
mod_sofia_globals.hostname, profile->name, (long) now);
sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, buf, sizeof(buf));
switch_safe_free(sql);
count = atoi(buf);
/* 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;
sql = switch_mprintf(" update sip_registrations set ping_expires = %ld where ping_expires <= %ld ",
next, (long) now);
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
}
}
}
}