diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
index 7ae8002805..dde3c88e1a 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
@@ -2422,6 +2422,7 @@ static int show_reg_callback(void *pArg, int argc, char **argv, char **columnNam
"Contact: \t%s\n"
"Agent: \t%s\n"
"Status: \t%s(%s) EXP(%s) EXPSECS(%d)\n"
+ "Ping-Status:\t%s\n"
"Host: \t%s\n"
"IP: \t%s\n"
"Port: \t%s\n"
@@ -2429,9 +2430,9 @@ static int show_reg_callback(void *pArg, int argc, char **argv, char **columnNam
"Auth-Realm: \t%s\n"
"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[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]));
+ 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]),
+ switch_str_nil(argv[15]), switch_str_nil(argv[16]), switch_str_nil(argv[17]));
return 0;
}
@@ -2463,6 +2464,7 @@ static int show_reg_callback_xml(void *pArg, int argc, char **argv, char **colum
cb->stream->write_function(cb->stream, " %s\n", switch_amp_encode(switch_str_nil(argv[7]), xmlbuf, buflen));
cb->stream->write_function(cb->stream, " %s(%s) exp(%s) expsecs(%d)\n", switch_str_nil(argv[4]), switch_str_nil(argv[5]),
exp_buf, exp_secs);
+ cb->stream->write_function(cb->stream, " %s\n", switch_str_nil(argv[18]));
cb->stream->write_function(cb->stream, " %s\n", switch_str_nil(argv[11]));
cb->stream->write_function(cb->stream, " %s\n", switch_str_nil(argv[12]));
cb->stream->write_function(cb->stream, " %s\n", switch_str_nil(argv[13]));
@@ -2686,19 +2688,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"
+ "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status"
" 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"
+ "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host, ping_status"
" 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"
+ "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status"
" from sip_registrations where profile_name='%q'", profile->name);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "user") && argv[3]) {
@@ -2725,7 +2727,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"
+ "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status"
" from sip_registrations where profile_name='%q' and %s", profile->name, sqlextra);
switch_safe_free(dup);
switch_safe_free(sqlextra);
@@ -2969,21 +2971,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"
+ "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status"
" 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"
+ "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status"
" 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"
+ "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status"
" from sip_registrations where profile_name='%q'", profile->name);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "user") && argv[3]) {
@@ -3010,7 +3012,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"
+ "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status"
" from sip_registrations where profile_name='%q' and %s", profile->name, sqlextra);
switch_safe_free(dup);
switch_safe_free(sqlextra);
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h
index ba8143de4f..2aab666248 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.h
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.h
@@ -84,6 +84,7 @@ typedef struct private_object private_object_t;
#define MY_EVENT_UNREGISTER "sofia::unregister"
#define MY_EVENT_EXPIRE "sofia::expire"
#define MY_EVENT_GATEWAY_STATE "sofia::gateway_state"
+#define MY_EVENT_SIP_USER_STATE "sofia::sip_user_state"
#define MY_EVENT_NOTIFY_REFER "sofia::notify_refer"
#define MY_EVENT_REINVITE "sofia::reinvite"
#define MY_EVENT_GATEWAY_ADD "sofia::gateway_add"
@@ -426,6 +427,13 @@ typedef enum {
SOFIA_GATEWAY_INVALID
} sofia_gateway_status_t;
+typedef enum {
+ SOFIA_REG_REACHABLE,
+ SOFIA_REG_UNREACHABLE,
+
+ SOFIA_REG_INVALID
+} sofia_sip_user_status_t;
+
typedef enum {
SUB_STATE_UNSUBED,
SUB_STATE_TRYING,
@@ -603,6 +611,8 @@ struct sofia_profile {
char *challenge_realm;
char *pnp_prov_url;
char *pnp_notify_profile;
+ int sip_user_ping_max;
+ int sip_user_ping_min;
sofia_cid_type_t cid_type;
switch_core_media_dtmf_t dtmf_type;
int auto_restart;
@@ -1125,6 +1135,9 @@ void sofia_profile_destroy(sofia_profile_t *profile);
switch_status_t sip_dig_function(_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream);
const char *sofia_gateway_status_name(sofia_gateway_status_t status);
void sofia_reg_fire_custom_gateway_state_event(sofia_gateway_t *gateway, int status, const char *phrase);
+const char *sofia_sip_user_status_name(sofia_sip_user_status_t status);
+void sofia_reg_fire_custom_sip_user_state_event(sofia_profile_t *profile, const char *sip_user, const char *contact,
+ const char* from_user, const char* from_host, const char *call_id, sofia_sip_user_status_t status, int options_res, const char *phrase);
uint32_t sofia_reg_reg_count(sofia_profile_t *profile, const char *user, const char *host);
char *sofia_media_get_multipart(switch_core_session_t *session, const char *prefix, const char *sdp, char **mp_type);
int sofia_glue_tech_simplify(private_object_t *tech_pvt);
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index 11a8b560d0..af7d4b9857 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -2477,11 +2477,11 @@ void event_handler(switch_event_t *event)
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) "
- "values ('%q','%q','%q','%q','%q','Registered','%q',%ld, '%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q')",
+ "mwi_user, mwi_host, orig_server_host, orig_hostname, ping_status, ping_count) "
+ "values ('%q','%q','%q','%q','%q','Registered','%q',%ld, '%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q', '%q', %d)",
call_id, from_user, from_host, presence_hosts, contact_str, rpid, expires, user_agent, to_user, guess_ip4,
profile_name, mod_sofia_globals.hostname, network_ip, network_port, username, realm, mwi_user, mwi_host,
- orig_server_host, orig_hostname);
+ orig_server_host, orig_hostname, "Reachable", 0);
if (sql) {
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
@@ -2495,6 +2495,33 @@ void event_handler(switch_event_t *event)
end:
switch_safe_free(fixed_contact_str);
switch_safe_free(dup_mwi_account);
+ } else if ((subclass = switch_event_get_header_nil(event, "orig-event-subclass")) && !strcasecmp(subclass, MY_EVENT_SIP_USER_STATE)) {
+ char *profile_name = switch_event_get_header_nil(event, "orig-profile-name");
+ char *from_user = switch_event_get_header_nil(event, "orig-from-user");
+ char *from_host = switch_event_get_header_nil(event, "orig-from-host");
+ const char *call_id = switch_event_get_header_nil(event, "orig-call-id");
+ char *ping_status = switch_event_get_header_nil(event, "orig-Ping-Status");
+ sofia_profile_t *profile = NULL;
+
+ if (!profile_name || !(profile = sofia_glue_find_profile(profile_name))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile\n");
+ } else {
+ if (!strcmp(ping_status, "REACHABLE")) {
+ sql = switch_mprintf("update sip_registrations set ping_status='%s' where sip_user='%s' and sip_host='%s' and call_id='%q'",
+ "Reachable", from_user, from_host, call_id);
+ } else {
+ sql = switch_mprintf("update sip_registrations set ping_status='%s' where sip_user='%s' and sip_host='%s' and call_id='%q'",
+ "Unreachable", from_user, from_host, call_id);
+ }
+ if (sql) {
+ sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Propagating sip_user_state for %s@%s. Ping-Status: %s\n", from_user, from_host, ping_status);
+ }
+
+ if (profile) {
+ sofia_glue_release_profile(profile);
+ }
+ }
}
}
@@ -4014,6 +4041,9 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
profile->user_agent = switch_core_sprintf(profile->pool, "FreeSWITCH-mod_sofia/%s", switch_version_full());
+ profile->sip_user_ping_max = 3;
+ profile->sip_user_ping_min = 1;
+
profile->name = switch_core_strdup(profile->pool, xprofilename);
switch_snprintf(url, sizeof(url), "sofia_reg_%s", xprofilename);
@@ -4772,6 +4802,10 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_UNREG_OPTIONS_FAIL);
}
+ } else if (!strcasecmp(var, "sip-user-ping-max")) {
+ profile->sip_user_ping_max = atoi(val);
+ } else if (!strcasecmp(var, "sip-user-ping-min")) {
+ profile->sip_user_ping_min = atoi(val);
} else if (!strcasecmp(var, "require-secure-rtp")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_SECURE);
@@ -5544,6 +5578,44 @@ const char *sofia_gateway_status_name(sofia_gateway_status_t status)
}
}
+const char *sofia_sip_user_status_name(sofia_sip_user_status_t status)
+{
+ static const char *status_names[] = { "UNREACHABLE", "REACHABLE", NULL };
+
+ if (status < SOFIA_REG_INVALID) {
+ return status_names[status];
+ } else {
+ return "INVALID";
+ }
+}
+
+struct cb_helper_sip_user_status {
+ char *status;
+ size_t status_len;
+
+ char *contact;
+ size_t contact_len;
+
+ int count;
+};
+
+int sofia_sip_user_status_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+ struct cb_helper_sip_user_status *cbt = (struct cb_helper_sip_user_status *) pArg;
+
+ if (argc != 3) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "expected 3 arguments from query, instead got %d\n", argc);
+ return 0;
+ }
+
+ switch_copy_string(cbt->status, argv[0], cbt->status_len);
+ cbt->count = (argv[1] && switch_is_number(argv[1])) ? atoi(argv[1]) : 0;
+
+ switch_copy_string(cbt->contact, argv[2], cbt->contact_len);
+
+ return 1;
+}
+
static void sofia_handle_sip_r_options(switch_core_session_t *session, int status,
char const *phrase,
nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
@@ -5607,18 +5679,85 @@ static void sofia_handle_sip_r_options(switch_core_session_t *session, int statu
gateway->ping = switch_epoch_time_now(NULL) + gateway->ping_freq;
sofia_reg_release_gateway(gateway);
gateway->pinging = 0;
- } else if (sofia_test_pflag(profile, PFLAG_UNREG_OPTIONS_FAIL) && (status != 200 && status != 486) &&
- sip && sip->sip_to && sip->sip_call_id && sip->sip_call_id->i_id && strchr(sip->sip_call_id->i_id, '_')) {
- char *sql;
- time_t now = switch_epoch_time_now(NULL);
+ } else if (sip && sip->sip_to && sip->sip_call_id && sip->sip_call_id->i_id && strchr(sip->sip_call_id->i_id, '_')) {
const char *call_id = strchr(sip->sip_call_id->i_id, '_') + 1;
+ char *sql;
+ struct cb_helper_sip_user_status sip_user_status;
+ char ping_status[255] = "";
+ char sip_contact[1024] = "";
+ int sip_user_ping_min = profile->sip_user_ping_min;
+ int sip_user_ping_max = profile->sip_user_ping_max;
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Expire registration '%s@%s' due to options failure\n",
- sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host);
+ char *sip_user = switch_mprintf("%s@%s", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host);
+
+ sip_user_status.status = ping_status;
+ sip_user_status.status_len = sizeof(ping_status);
+ sip_user_status.contact = sip_contact;
+ sip_user_status.contact_len = sizeof(sip_contact);
+ sql = switch_mprintf("select ping_status, ping_count, contact from sip_registrations 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);
+ sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_sip_user_status_callback, &sip_user_status);
+ switch_safe_free(sql);
+
+ if (status != 200 && status != 486) {
+ sip_user_status.count--;
+ 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);
+ sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
+ switch_safe_free(sql);
+ }
+ if (sip_user_status.count < sip_user_ping_min) {
+ 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);
+ 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,
+ sip->sip_to->a_url->url_host, call_id, SOFIA_REG_REACHABLE, status, phrase);
+
+ if (sofia_test_pflag(profile, PFLAG_UNREG_OPTIONS_FAIL)) {
+ time_t now = switch_epoch_time_now(NULL);
+ 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);
+ sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
+ switch_safe_free(sql);
+ }
+ }
+ }
+ } else {
+ sip_user_status.count++;
+ 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);
+ sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
+ switch_safe_free(sql);
+ }
+ if (sip_user_status.count >= sip_user_ping_min) {
+ if (strcmp(sip_user_status.status, "Reachable")) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Sip user '%s@%s' is now Reachable\n",
+ sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host);
+ sql = switch_mprintf("update sip_registrations set ping_status='Reachable' 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);
+ 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,
+ sip->sip_to->a_url->url_host, call_id, SOFIA_REG_UNREACHABLE, status, phrase);
+ }
+ }
+ }
+
+ switch_safe_free(sip_user);
- 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);
- sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
}
}
diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c
index 3a9fdf800f..a52ba0473d 100644
--- a/src/mod/endpoints/mod_sofia/sofia_glue.c
+++ b/src/mod/endpoints/mod_sofia/sofia_glue.c
@@ -1989,6 +1989,8 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
" presence_hosts VARCHAR(255),\n"
" contact VARCHAR(1024),\n"
" status VARCHAR(255),\n"
+ " ping_status VARCHAR(255),\n"
+ " ping_count INTEGER,\n"
" rpid VARCHAR(255),\n"
" expires BIGINT,\n"
" user_agent VARCHAR(255),\n"
@@ -2121,6 +2123,7 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
"create index sr_expires on sip_registrations (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)",
"create index sr_network_ip on sip_registrations (network_ip)",
"create index sr_network_port on sip_registrations (network_port)",
"create index sr_sip_username on sip_registrations (sip_username)",
@@ -2199,6 +2202,9 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
switch_cache_db_test_reactive(dbh, test_sql, "drop table sip_registrations", reg_sql);
+
+ 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\"");
test2 = switch_mprintf("%s;%s", test_sql, test_sql);
diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c
index c796d0ad7e..8b3373ce9a 100644
--- a/src/mod/endpoints/mod_sofia/sofia_reg.c
+++ b/src/mod/endpoints/mod_sofia/sofia_reg.c
@@ -161,6 +161,26 @@ void sofia_reg_fire_custom_gateway_state_event(sofia_gateway_t *gateway, int sta
}
}
+void sofia_reg_fire_custom_sip_user_state_event(sofia_profile_t *profile, const char *sip_user, const char *contact,
+ const char* from_user, const char* from_host, const char *call_id, sofia_sip_user_status_t status, int options_res, const char *phrase)
+{
+ switch_event_t *s_event;
+ if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_SIP_USER_STATE) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "sip_contact", contact);
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "sip_user", sip_user);
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", from_user);
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", from_host);
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id);
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Ping-Status", sofia_sip_user_status_name(status));
+ switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "Status", "%d", options_res);
+ if (!zstr(phrase)) {
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Phrase", phrase);
+ }
+ switch_event_fire(&s_event);
+ }
+}
+
void sofia_reg_unregister(sofia_profile_t *profile)
{
sofia_gateway_t *gateway_ptr;
@@ -830,7 +850,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
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'", mod_sofia_globals.hostname, profile->name);
+ "profile_name='%s' and orig_hostname='%s'", mod_sofia_globals.hostname, profile->name, mod_sofia_globals.hostname);
sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nat_callback, profile);
switch_safe_free(sql);
@@ -847,7 +867,7 @@ 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'", mod_sofia_globals.hostname, profile->name);
+ "and profile_name='%s' and orig_hostname='%s'", mod_sofia_globals.hostname, profile->name, mod_sofia_globals.hostname);
sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nat_callback, profile);
switch_safe_free(sql);
@@ -1805,12 +1825,12 @@ 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) "
- "values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%q', '%q', '%q', '%q', '%q', '%q', '%q','%q','%q','%q','%q','%q','%q','%q')",
+ "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)",
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);
+ mwi_user, mwi_host, guess_ip4, mod_sofia_globals.hostname, sub_host, "Reachable", 0);
} else {
sql = switch_mprintf("update sip_registrations set call_id='%q',"
"sub_host='%q', network_ip='%q',network_port='%q',"