From 6eacfd9acaa599266f9d143a3248b39a40e51b8a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 30 Apr 2008 22:09:54 +0000 Subject: [PATCH] add options ping to gateway git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@8223 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- conf/directory/default/brian.xml | 2 ++ src/mod/endpoints/mod_sofia/mod_sofia.c | 15 ++++++++- src/mod/endpoints/mod_sofia/mod_sofia.h | 10 ++++++ src/mod/endpoints/mod_sofia/sofia.c | 43 +++++++++++++++++++++++-- src/mod/endpoints/mod_sofia/sofia_reg.c | 16 +++++++++ 5 files changed, 83 insertions(+), 3 deletions(-) diff --git a/conf/directory/default/brian.xml b/conf/directory/default/brian.xml index e9bca85935..6e6849ebfe 100644 --- a/conf/directory/default/brian.xml +++ b/conf/directory/default/brian.xml @@ -35,6 +35,8 @@ + + diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 908b82817b..e289918905 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1161,6 +1161,8 @@ static int show_reg_callback(void *pArg, int argc, char **argv, char **columnNam return 0; } +static const char *status_names[] = { "DOWN", "UP", NULL }; + static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t *stream) { sofia_profile_t *profile = NULL; @@ -1180,7 +1182,7 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t if (!strcasecmp(argv[0], "gateway")) { if ((gp = sofia_reg_find_gateway(argv[1]))) { switch_assert(gp->state < REG_STATE_LAST); - + stream->write_function(stream, "%s\n", line); stream->write_function(stream, "Name \t%s\n", switch_str_nil(gp->name)); stream->write_function(stream, "Scheme \t%s\n", switch_str_nil(gp->register_scheme)); @@ -1194,7 +1196,10 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t stream->write_function(stream, "Context \t%s\n", switch_str_nil(gp->register_context)); stream->write_function(stream, "Expires \t%s\n", switch_str_nil(gp->expires_str)); stream->write_function(stream, "Freq \t%d\n", gp->freq); + stream->write_function(stream, "Ping \t%d\n", gp->ping); + stream->write_function(stream, "PingFreq\t%d\n", gp->ping_freq); stream->write_function(stream, "State \t%s\n", sofia_state_names[gp->state]); + stream->write_function(stream, "Status \t%s%s\n", status_names[gp->status], gp->pinging ? " (ping)" : ""); stream->write_function(stream, "%s\n", line); sofia_reg_release_gateway(gp); } else { @@ -1695,6 +1700,14 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session goto error; } + if (gateway_ptr->status != SOFIA_GATEWAY_UP) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Gateway is down!\n"); + cause = SWITCH_CAUSE_NETWORK_OUT_OF_ORDER; + sofia_reg_release_gateway(gateway_ptr); + gateway_ptr = NULL; + goto error; + } + tech_pvt->transport = gateway_ptr->register_transport; /* diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index fe9b0c393c..f672730b43 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -99,6 +99,7 @@ typedef enum { struct sofia_private { char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1]; sofia_gateway_t *gateway; + char gateway_name[512]; }; #define set_param(ptr,val) if (ptr) {free(ptr) ; ptr = NULL;} if (val) {ptr = strdup(val);} @@ -221,6 +222,11 @@ typedef enum { SOFIA_TRANSPORT_SCTP } sofia_transport_t; +typedef enum { + SOFIA_GATEWAY_DOWN, + SOFIA_GATEWAY_UP +} sofia_gateway_status_t; + struct sofia_gateway { sofia_private_t *sofia_private; nua_handle_t *nh; @@ -241,6 +247,10 @@ struct sofia_gateway { uint32_t freq; time_t expires; time_t retry; + time_t ping; + int pinging; + sofia_gateway_status_t status; + uint32_t ping_freq; uint32_t flags; int32_t retry_seconds; reg_state_t state; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 088b458871..1a4570783f 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -782,12 +782,16 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) *params = NULL, *register_transport = NULL; + uint32_t ping_freq = 0; + gateway->register_transport = SOFIA_TRANSPORT_UDP; gateway->pool = profile->pool; gateway->profile = profile; gateway->name = switch_core_strdup(gateway->pool, name); gateway->freq = 0; gateway->next = NULL; + gateway->ping = 0; + gateway->ping_freq = 0; for (param = switch_xml_child(gateway_tag, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); @@ -807,6 +811,8 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) caller_id_in_from = val; } else if (!strcmp(var, "extension")) { extension = val; + } else if (!strcmp(var, "ping")) { + ping_freq = atoi(val); } else if (!strcmp(var, "proxy")) { proxy = val; } else if (!strcmp(var, "context")) { @@ -835,6 +841,15 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) } } + if (ping_freq) { + if (ping_freq >= 5) { + gateway->ping_freq = ping_freq; + gateway->ping = switch_timestamp(NULL) + ping_freq; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: invalid ping!\n"); + } + } + if (switch_strlen_zero(realm)) { realm = name; } @@ -1497,10 +1512,33 @@ switch_status_t config_sofia(int reload, char *profile_name) } static void sofia_handle_sip_r_options(switch_core_session_t *session, int status, - char const *phrase, + char const *phrase, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, tagi_t tags[]) { - if ((profile->pflags & PFLAG_UNREG_OPTIONS_FAIL) && status != 200 && sip && sip->sip_to) { + sofia_gateway_t *gateway = NULL; + + if (sofia_private->gateway_name) { + gateway = sofia_reg_find_gateway(sofia_private->gateway_name); + } + + if (gateway) { + if (status == 200 || status == 404) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ping success %s\n", gateway->name); + gateway->status = SOFIA_GATEWAY_UP; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "ping failed %s\n", gateway->name); + gateway->status = SOFIA_GATEWAY_DOWN; + if (gateway->state == REG_STATE_REGED) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "unregister %s\n", gateway->name); + gateway->state = REG_STATE_UNREGISTER; + } + } + gateway->ping = switch_timestamp(NULL) + gateway->ping_freq; + sofia_reg_release_gateway(gateway); + nua_handle_bind(nh, NULL); + free(sofia_private); + gateway->pinging = 0; + } else if ((profile->pflags & PFLAG_UNREG_OPTIONS_FAIL) && status != 200 && sip && sip->sip_to) { char *sql; time_t now = switch_timestamp(NULL); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Expire registration '%s@%s' due to options failure\n", @@ -1515,6 +1553,7 @@ static void sofia_handle_sip_r_options(switch_core_session_t *session, int statu ); sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); } + nua_handle_destroy(nh); } diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index ff667b3ec5..fed8b1b1c4 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -80,6 +80,21 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) gateway_ptr->expires_str = "0"; } + if (gateway_ptr->ping && !gateway_ptr->pinging && (now >= gateway_ptr->ping && (ostate == REG_STATE_NOREG || ostate == REG_STATE_REGED))) { + nua_handle_t *nh = nua_handle(profile->nua, NULL, NUTAG_URL(gateway_ptr->register_url), SIPTAG_CONTACT_STR(profile->url), TAG_END()); + sofia_private_t *pvt; + + pvt = malloc(sizeof(*pvt)); + switch_assert(pvt); + memset(pvt, 0, sizeof(*pvt)); + + switch_copy_string(pvt->gateway_name, gateway_ptr->name, sizeof(pvt->gateway_name)); + nua_handle_bind(nh, pvt); + + gateway_ptr->pinging = 1; + nua_options(nh, TAG_END()); + } + switch (ostate) { case REG_STATE_NOREG: break; @@ -87,6 +102,7 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "registered %s\n", gateway_ptr->name); gateway_ptr->expires = now + gateway_ptr->freq; gateway_ptr->state = REG_STATE_REGED; + gateway_ptr->status = SOFIA_GATEWAY_UP; break; case REG_STATE_UNREGISTER: