diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index aff86a6331..931e6768ef 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -2418,6 +2418,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" @@ -2425,9 +2426,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; } @@ -2459,6 +2460,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])); @@ -2682,19 +2684,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]) { @@ -2721,7 +2723,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); @@ -2965,21 +2967,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]) { @@ -3006,7 +3008,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 ee03f235ce..1030cf01d6 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; @@ -1124,6 +1134,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 6cf16e5912..2039be9986 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); @@ -5545,6 +5579,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, @@ -5608,18 +5680,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 99caba5c2e..a4e766ad17 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -1984,6 +1984,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" @@ -2116,6 +2118,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)", @@ -2194,6 +2197,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 053ddd9a9e..32af4901f3 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',"