diff --git a/conf/sip_profiles/external.xml b/conf/sip_profiles/external.xml index 5e49d3c6a3..5f6435f141 100644 --- a/conf/sip_profiles/external.xml +++ b/conf/sip_profiles/external.xml @@ -18,6 +18,8 @@ + + diff --git a/conf/sip_profiles/internal.xml b/conf/sip_profiles/internal.xml index 077ab654f5..6c435b04f9 100644 --- a/conf/sip_profiles/internal.xml +++ b/conf/sip_profiles/internal.xml @@ -39,6 +39,8 @@ + + diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 1f7f0db97d..4a59925ec4 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1255,7 +1255,8 @@ typedef uint32_t switch_io_flag_t; SWITCH_EVENT_NOTIFY - Notification SWITCH_EVENT_SEND_MESSAGE - Message SWITCH_EVENT_RECV_MESSAGE - Message - SWITCH_EVENT_NAT - NAT Management (new/del/status) + SWITCH_EVENT_NAT - NAT Management (new/del/status) + SWITCH_EVENT_FAILURE - A failure occurred which might impact the normal functioning of the switch SWITCH_EVENT_ALL - All events at once @@ -1332,6 +1333,7 @@ typedef enum { SWITCH_EVENT_RECORD_START, SWITCH_EVENT_RECORD_STOP, SWITCH_EVENT_CALL_UPDATE, + SWITCH_EVENT_FAILURE, SWITCH_EVENT_ALL } switch_event_types_t; diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 788cd97de5..8030a6fdc9 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -423,6 +423,7 @@ struct sofia_profile { char *dbname; char *dialplan; char *context; + char *shutdown_type; char *extrtpip; char *rtpip; char *sipip; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 4bacb8d370..7f9a275848 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -882,6 +882,40 @@ end: } } +static void sofia_perform_profile_start_failure(sofia_profile_t *profile, char *profile_name, char* file, int line) +{ + int arg = 0; + switch_event_t *s_event; + + if (profile) { + if (!strcasecmp(profile->shutdown_type, "true")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile %s could not load! Shutting down!\n", profile->name); + switch_core_session_ctl(SCSC_SHUTDOWN, &arg); + } else if (!strcasecmp(profile->shutdown_type, "elegant")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile %s could not load! Waiting for calls to finish, then shutting down!\n", profile->name); + switch_core_session_ctl(SCSC_SHUTDOWN_ELEGANT, &arg); + } else if (!strcasecmp(profile->shutdown_type, "asap")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile %s could not load! Shutting down ASAP!\n", profile->name); + switch_core_session_ctl(SCSC_SHUTDOWN_ASAP, &arg); + } + } + + if ((switch_event_create(&s_event, SWITCH_EVENT_FAILURE) == SWITCH_STATUS_SUCCESS)) { + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "module_name", "mod_sofia"); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_name", profile_name); + if (profile) { + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_uri", profile->url); + } + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "failure_message", "Profile failed to start."); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "file", file); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "line", "%d", line); + + switch_event_fire(&s_event); + } +} +#define sofia_profile_start_failure(p, xp) sofia_perform_profile_start_failure(p, xp, __FILE__, __LINE__) + + #define SQLLEN 1024 * 64 void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread, void *obj) { @@ -1039,6 +1073,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void if (!sofia_glue_init_sql(profile)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open SQL Database [%s]!\n", profile->name); + sofia_profile_start_failure(profile, profile->name); sofia_glue_del_profile(profile); goto end; } @@ -1087,6 +1122,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void if (!profile->nua) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Creating SIP UA for profile: %s\n", profile->name); + sofia_profile_start_failure(profile, profile->name); sofia_glue_del_profile(profile); goto end; } @@ -1848,6 +1884,7 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) profile->ob_calls = 0; profile->ib_failed_calls = 0; profile->ob_failed_calls = 0; + profile->shutdown_type = "false"; if (xprofiledomain) { profile->domain_name = switch_core_strdup(profile->pool, xprofiledomain); @@ -1859,6 +1896,8 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) char *val = (char *) switch_xml_attr_soft(param, "value"); if (!strcasecmp(var, "debug")) { profile->debug = atoi(val); + } else if (!strcasecmp(var, "shutdown-on-fail")) { + profile->shutdown_type = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "tracelevel")) { mod_sofia_globals.tracelevel = switch_log_str2level(val); } else if (!strcasecmp(var, "pass-callee-id")) { @@ -2373,11 +2412,12 @@ switch_status_t config_sofia(int reload, char *profile_name) if ((profiles = switch_xml_child(cfg, "profiles"))) { for (xprofile = switch_xml_child(profiles, "profile"); xprofile; xprofile = xprofile->next) { + char *xprofilename = (char *) switch_xml_attr_soft(xprofile, "name"); + char *xprofiledomain = (char *) switch_xml_attr(xprofile, "domain"); if (!(settings = switch_xml_child(xprofile, "settings"))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Settings, check the new config!\n"); + sofia_profile_start_failure(NULL, xprofilename); } else { - char *xprofilename = (char *) switch_xml_attr_soft(xprofile, "name"); - char *xprofiledomain = (char *) switch_xml_attr(xprofile, "domain"); switch_memory_pool_t *pool = NULL; if (!xprofilename) { @@ -2395,11 +2435,13 @@ switch_status_t config_sofia(int reload, char *profile_name) /* Setup the pool */ if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); + sofia_profile_start_failure(NULL, xprofilename); goto done; } if (!(profile = (sofia_profile_t *) switch_core_alloc(pool, sizeof(*profile)))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n"); + sofia_profile_start_failure(NULL, xprofilename); goto done; } @@ -2432,7 +2474,7 @@ switch_status_t config_sofia(int reload, char *profile_name) sofia_set_pflag(profile, PFLAG_PASS_CALLEE_ID); sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER); sofia_set_pflag(profile, PFLAG_SQL_IN_TRANS); - + profile->shutdown_type = "false"; profile->local_network = "localnet.auto"; for (param = switch_xml_child(settings, "param"); param; param = param->next) { @@ -2443,6 +2485,8 @@ switch_status_t config_sofia(int reload, char *profile_name) if (!strcasecmp(var, "debug")) { profile->debug = atoi(val); + } else if (!strcasecmp(var, "shutdown-on-fail")) { + profile->shutdown_type = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "sip-trace") && switch_true(val)) { sofia_set_flag(profile, TFLAG_TPORT_LOG); } else if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) { @@ -3208,6 +3252,7 @@ switch_status_t config_sofia(int reload, char *profile_name) } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Unable to start Profile %s due to no configured sip-ip\n", profile->name); + sofia_profile_start_failure(profile, profile->name); } profile = NULL; } diff --git a/src/switch_event.c b/src/switch_event.c index f9343a3f54..b957c0dc2e 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -185,6 +185,7 @@ static char *EVENT_NAMES[] = { "RECORD_START", "RECORD_STOP", "CALL_UPDATE", + "FAILURE", "ALL" };