Merge pull request #493 in FS/freeswitch from feature/FS-8042-store-sip-endpoint-ping-response to master

* commit '5509a627061a07d7db18967449c3e6f8f216c4a2':
  FS-8042, FS-8182: add ping time (in ms) to sip_registrations table, displays as part of the show commands that show registration details, add force_ping=true user var to force options ping on individual registered endpoints
This commit is contained in:
Mike Jerris 2015-09-21 14:43:58 -05:00
commit 47864eac86
5 changed files with 96 additions and 58 deletions

View File

@ -2498,6 +2498,7 @@ static int show_reg_callback(void *pArg, int argc, char **argv, char **columnNam
"Agent: \t%s\n"
"Status: \t%s(%s) EXP(%s) EXPSECS(%d)\n"
"Ping-Status:\t%s\n"
"Ping-Time:\t%0.2f\n"
"Host: \t%s\n"
"IP: \t%s\n"
"Port: \t%s\n"
@ -2506,7 +2507,8 @@ static int show_reg_callback(void *pArg, int argc, char **argv, char **columnNam
"MWI-Account:\t%s@%s\n\n",
switch_str_nil(argv[0]), switch_str_nil(argv[1]), switch_str_nil(argv[2]), switch_str_nil(argv[3]),
switch_str_nil(argv[7]), switch_str_nil(argv[4]), switch_str_nil(argv[5]), exp_buf, exp_secs, switch_str_nil(argv[18]),
switch_str_nil(argv[11]), switch_str_nil(argv[12]), switch_str_nil(argv[13]), switch_str_nil(argv[14]),
(float)atoll(switch_str_nil(argv[19]))/1000, switch_str_nil(argv[11]), switch_str_nil(argv[12]),
switch_str_nil(argv[13]), switch_str_nil(argv[14]),
switch_str_nil(argv[15]), switch_str_nil(argv[16]), switch_str_nil(argv[17]));
return 0;
}
@ -2540,6 +2542,7 @@ static int show_reg_callback_xml(void *pArg, int argc, char **argv, char **colum
cb->stream->write_function(cb->stream, " <status>%s(%s) exp(%s) expsecs(%d)</status>\n", switch_str_nil(argv[4]), switch_str_nil(argv[5]),
exp_buf, exp_secs);
cb->stream->write_function(cb->stream, " <ping-status>%s</ping-status>\n", switch_str_nil(argv[18]));
cb->stream->write_function(cb->stream, " <ping-time>%0.2f</ping-time>\n", (float)atoll(switch_str_nil(argv[19]))/1000);
cb->stream->write_function(cb->stream, " <host>%s</host>\n", switch_str_nil(argv[11]));
cb->stream->write_function(cb->stream, " <network-ip>%s</network-ip>\n", switch_str_nil(argv[12]));
cb->stream->write_function(cb->stream, " <network-port>%s</network-port>\n", switch_str_nil(argv[13]));
@ -2770,19 +2773,19 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
if (!sql && argv[2] && !strcasecmp(argv[2], "pres") && argv[3]) {
sql = switch_mprintf("select call_id,sip_user,sip_host,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,ping_status"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
" from sip_registrations where profile_name='%q' and presence_hosts like '%%%q%%'", profile->name, argv[3]);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "reg") && argv[3]) {
sql = switch_mprintf("select call_id,sip_user,sip_host,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, ping_status"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host, ping_status,ping_time"
" from sip_registrations where profile_name='%q' and contact like '%%%q%%'", profile->name, argv[3]);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "reg")) {
sql = switch_mprintf("select call_id,sip_user,sip_host,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,ping_status"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
" from sip_registrations where profile_name='%q'", profile->name);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "user") && argv[3]) {
@ -2809,7 +2812,7 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
sql = switch_mprintf("select call_id,sip_user,sip_host,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,ping_status"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
" from sip_registrations where profile_name='%q' and %s", profile->name, sqlextra);
switch_safe_free(dup);
switch_safe_free(sqlextra);
@ -3077,21 +3080,21 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
sql = switch_mprintf("select call_id,sip_user,sip_host,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,ping_status"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
" from sip_registrations where profile_name='%q' and presence_hosts like '%%%q%%'", profile->name, argv[3]);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "reg") && argv[3]) {
sql = switch_mprintf("select call_id,sip_user,sip_host,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,ping_status"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
" from sip_registrations where profile_name='%q' and contact like '%%%q%%'", profile->name, argv[3]);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "reg")) {
sql = switch_mprintf("select call_id,sip_user,sip_host,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,ping_status"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
" from sip_registrations where profile_name='%q'", profile->name);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "user") && argv[3]) {
@ -3118,7 +3121,7 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
sql = switch_mprintf("select call_id,sip_user,sip_host,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,ping_status"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
" from sip_registrations where profile_name='%q' and %s", profile->name, sqlextra);
switch_safe_free(dup);
switch_safe_free(sqlextra);

View File

@ -181,6 +181,7 @@ struct sofia_private {
int destroy_me;
int is_call;
int is_static;
switch_time_t ping_sent;
};
#define set_param(ptr,val) if (ptr) {free(ptr) ; ptr = NULL;} if (val) {ptr = strdup(val);}

View File

@ -5847,6 +5847,11 @@ static void sofia_handle_sip_r_options(switch_core_session_t *session, int statu
int sip_user_ping_max = profile->sip_user_ping_max;
char *sip_user = switch_mprintf("%s@%s", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host);
int ping_time = 0;
if (sofia_private && sofia_private->ping_sent) {
ping_time = switch_time_now() - sofia_private->ping_sent;
}
sip_user_status.status = ping_status;
sip_user_status.status_len = sizeof(ping_status);
@ -5862,8 +5867,8 @@ static void sofia_handle_sip_r_options(switch_core_session_t *session, int statu
if (sip_user_status.count >= 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ping to sip user '%s@%s' failed with code %d - count %d, state %s\n",
sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, status, sip_user_status.count, sip_user_status.status);
sql = switch_mprintf("update sip_registrations set ping_count=%d where sip_user='%s' and sip_host='%s' and call_id='%q'", sip_user_status.count,
sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
sql = switch_mprintf("update sip_registrations set ping_count=%d, ping_time=%d where sip_user='%s' and sip_host='%s' and call_id='%q'",
sip_user_status.count, ping_time, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
switch_safe_free(sql);
}
@ -5871,8 +5876,8 @@ static void sofia_handle_sip_r_options(switch_core_session_t *session, int statu
if (strcmp(sip_user_status.status, "Unreachable")) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Sip user '%s@%s' is now Unreachable\n",
sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host);
sql = switch_mprintf("update sip_registrations set ping_status='Unreachable' where sip_user='%s' and sip_host='%s' and call_id='%q'",
sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
sql = switch_mprintf("update sip_registrations set ping_status='Unreachable', ping_time=%d where sip_user='%s' and sip_host='%s' and call_id='%q'",
ping_time, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
switch_safe_free(sql);
sofia_reg_fire_custom_sip_user_state_event(profile, sip_user, sip_user_status.contact, sip->sip_to->a_url->url_user,
@ -5883,8 +5888,8 @@ static void sofia_handle_sip_r_options(switch_core_session_t *session, int statu
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Expire sip user '%s@%s' due to options failure\n",
sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host);
sql = switch_mprintf("update sip_registrations set expires=%ld where sip_user='%s' and sip_host='%s' and call_id='%q'",
(long) now, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
sql = switch_mprintf("update sip_registrations set expires=%ld, ping_time=%d where sip_user='%s' and sip_host='%s' and call_id='%q'",
(long) now, ping_time, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
switch_safe_free(sql);
}
@ -5895,8 +5900,8 @@ static void sofia_handle_sip_r_options(switch_core_session_t *session, int statu
if (sip_user_status.count <= sip_user_ping_max) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ping to sip user '%s@%s' succeeded with code %d - count %d, state %s\n",
sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, status, sip_user_status.count, sip_user_status.status);
sql = switch_mprintf("update sip_registrations set ping_count=%d where sip_user='%s' and sip_host='%s' and call_id='%q'", sip_user_status.count,
sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
sql = switch_mprintf("update sip_registrations set ping_count=%d, ping_time=%d where sip_user='%s' and sip_host='%s' and call_id='%q'",
sip_user_status.count, ping_time, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
switch_safe_free(sql);
}

View File

@ -2024,6 +2024,8 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
" status VARCHAR(255),\n"
" ping_status VARCHAR(255),\n"
" ping_count INTEGER,\n"
" ping_time BIGINT,\n"
" force_ping INTEGER,\n"
" rpid VARCHAR(255),\n"
" expires BIGINT,\n"
" ping_expires INTEGER not null default 0,\n"
@ -2241,6 +2243,8 @@ 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");
switch_cache_db_test_reactive(dbh, "select ping_time from sip_registrations", NULL, "alter table sip_registrations add column ping_time BIGINT not null default 0");
switch_cache_db_test_reactive(dbh, "select force_ping from sip_registrations", NULL, "alter table sip_registrations add column force_ping INTEGER not null default 0");
test2 = switch_mprintf("%s;%s", test_sql, test_sql);

View File

@ -599,6 +599,7 @@ int sofia_reg_nat_callback(void *pArg, int argc, char **argv, char **columnNames
char to[512] = "", call_id[512] = "";
sofia_destination_t *dst = NULL;
switch_uuid_t uuid;
sofia_private_t *pvt;
switch_snprintf(to, sizeof(to), "sip:%s@%s", argv[1], argv[2]);
@ -613,7 +614,15 @@ int sofia_reg_nat_callback(void *pArg, int argc, char **argv, char **columnNames
nh = nua_handle(profile->nua, NULL, SIPTAG_FROM_STR(profile->url), SIPTAG_TO_STR(to), NUTAG_URL(dst->contact), SIPTAG_CONTACT_STR(profile->url),
SIPTAG_CALL_ID_STR(call_id), TAG_END());
nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
pvt = malloc(sizeof(*pvt));
switch_assert(pvt);
memset(pvt, 0, sizeof(*pvt));
pvt->destroy_nh = 1;
pvt->destroy_me = 1;
pvt->ping_sent = switch_time_now();
nua_handle_bind(nh, pvt);
nua_options(nh,
NTATAG_SIP_T2(5000),
NTATAG_SIP_T4(10000),
@ -869,64 +878,70 @@ void sofia_reg_check_ping_expire(sofia_profile_t *profile, time_t now, int inter
char *sql;
int mean = interval / 2;
long next, irand;
char buf[32] = "";
int count;
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' and "
"ping_expires > 0 and ping_expires <= %ld", mod_sofia_globals.hostname, profile->name, mod_sofia_globals.hostname, (long) now);
"expires,user_agent,server_user,server_host,profile_name "
"from sip_registrations where hostname='%s' 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);
} 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' and ping_expires > 0 and ping_expires <= %ld ",
mod_sofia_globals.hostname, profile->name, (long) now);
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%%' or force_ping=1)"
" 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);
} else if (sofia_test_pflag(profile, PFLAG_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 '%%NAT%%' "
"or contact like '%%fs_nat=yes%%') and hostname='%s' "
"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);
"expires,user_agent,server_user,server_host,profile_name "
"from sip_registrations where (status like '%%NAT%%' "
"or contact like '%%fs_nat=yes%%' or force_ping=1) and hostname='%s' "
"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);
} else {
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 force_ping=1 and hostname='%s' "
"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);
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);
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;
/* 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 hostname='%q' and profile_name='%q' and ping_expires <= %ld ",
next, mod_sofia_globals.hostname, profile->name, (long) now);
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
}
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);
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
}
}
}
@ -1253,6 +1268,7 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu
const char *pres_on_reg = NULL;
int send_pres = 0;
int send_message_query = 0;
int force_ping = 0;
int is_tls = 0, is_tcp = 0, is_ws = 0, is_wss = 0;
char expbuf[35] = "";
time_t reg_time = switch_epoch_time_now(NULL);
@ -1797,6 +1813,15 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu
}
}
/* per-account enable options ping on register */
if (v_event && *v_event && (var = switch_event_get_header(*v_event, "force_ping"))) {
if (switch_true(var)) {
force_ping = 1;
} else {
force_ping = 0;
}
}
if (regtype != REG_REGISTER) {
switch_goto_int(r, 0, end);
}
@ -1903,22 +1928,22 @@ 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) "
"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)",
"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)",
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);
mwi_user, mwi_host, guess_ip4, mod_sofia_globals.hostname, sub_host, "Reachable", 0, 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 where sip_user='%q' and sip_username='%q' and sip_host='%q' and contact='%q'",
"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,
(long) reg_time + (long) exptime + profile->sip_expires_late_margin, force_ping,
to_user, username, reg_host, contact_str);
}