diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index f2fff44b99..68f62ba4a4 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1346,6 +1346,41 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t return SWITCH_STATUS_SUCCESS; } + if (!strcasecmp(argv[1], "killgw")) { + sofia_gateway_t *gateway_ptr; + if (argc < 2) { + stream->write_function(stream, "-ERR missing gw name\n"); + goto done; + } + + if ((gateway_ptr = sofia_reg_find_gateway(argv[2]))) { + sofia_glue_del_gateway(gateway_ptr); + sofia_reg_release_gateway(gateway_ptr); + stream->write_function(stream, "+OK gateway marked for deletion.\n"); + } else { + stream->write_function(stream, "-ERR no such gateway.\n"); + } + + goto done; + } + + if (!strcasecmp(argv[1], "rescan")) { + + if (argc > 2 && !strcasecmp(argv[2], "reloadxml")) { + if ((xml_root = switch_xml_open_root(1, &err))) { + switch_xml_free(xml_root); + } + stream->write_function(stream, "Reload XML [%s]\n", err); + } + + if (reconfig_sofia(profile) == SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "+OK scan complete\n"); + } else { + stream->write_function(stream, "-ERR cannot find config for profile %s\n", profile->name); + } + goto done; + } + if (!strcasecmp(argv[1], "flush_inbound_reg")) { if (argc > 2) { sofia_reg_expire_call_id(profile, argv[2]); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 5227fd4015..e1c86c74e8 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -278,6 +278,7 @@ struct sofia_gateway { int32_t retry_seconds; reg_state_t state; switch_memory_pool_t *pool; + int deleted; struct sofia_gateway *next; }; @@ -654,4 +655,5 @@ void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id); switch_status_t sofia_glue_tech_choose_video_port(private_object_t *tech_pvt, int force); switch_status_t sofia_glue_tech_set_video_codec(private_object_t *tech_pvt, int force); const char *sofia_glue_strip_proto(const char *uri); - +switch_status_t reconfig_sofia(sofia_profile_t *profile); +void sofia_glue_del_gateway(sofia_gateway_t *gp); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 1488c48548..462b4edfdf 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -952,6 +952,78 @@ static void parse_domain_tag(sofia_profile_t *profile, switch_xml_t x_domain_tag } +switch_status_t reconfig_sofia(sofia_profile_t *profile) +{ + switch_xml_t cfg, xml = NULL, xprofile, profiles, gateways_tag, domain_tag, domains_tag; + char *cf = "sofia.conf"; + switch_event_t *params = NULL;; + switch_status_t status = SWITCH_STATUS_FALSE; + + switch_event_create(¶ms, SWITCH_EVENT_MESSAGE); + switch_assert(params); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "profile", profile->name); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "reconfig", "true"); + + if (!(xml = switch_xml_open_cfg(cf, &cfg, params))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf); + status = SWITCH_STATUS_FALSE; + goto done; + } + + 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 (strcasecmp(profile->name, xprofilename)) { + continue; + } + + if ((gateways_tag = switch_xml_child(xprofile, "gateways"))) { + parse_gateways(profile, gateways_tag); + } + + status = SWITCH_STATUS_SUCCESS; + + if ((domains_tag = switch_xml_child(xprofile, "domains"))) { + for (domain_tag = switch_xml_child(domains_tag, "domain"); domain_tag; domain_tag = domain_tag->next) { + switch_xml_t droot, x_domain_tag; + const char *dname = switch_xml_attr_soft(domain_tag, "name"); + const char *parse = switch_xml_attr_soft(domain_tag, "parse"); + const char *alias = switch_xml_attr_soft(domain_tag, "alias"); + + if (!switch_strlen_zero(dname)) { + if (!strcasecmp(dname, "all")) { + switch_xml_t xml_root, x_domains; + if (switch_xml_locate("directory", NULL, NULL, NULL, &xml_root, &x_domains, NULL) == SWITCH_STATUS_SUCCESS) { + for (x_domain_tag = switch_xml_child(x_domains, "domain"); x_domain_tag; x_domain_tag = x_domain_tag->next) { + dname = switch_xml_attr_soft(x_domain_tag, "name"); + parse_domain_tag(profile, x_domain_tag, dname, parse, alias); + } + switch_xml_free(xml_root); + } + } else if (switch_xml_locate_domain(dname, NULL, &droot, &x_domain_tag) == SWITCH_STATUS_SUCCESS) { + parse_domain_tag(profile, x_domain_tag, dname, parse, alias); + switch_xml_free(droot); + } + } + } + } + + } + } + + done: + + if (xml) { + switch_xml_free(xml); + } + + switch_event_destroy(¶ms); + + return status; + +} + switch_status_t config_sofia(int reload, char *profile_name) { char *cf = "sofia.conf"; diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 61bcafaa2c..e1c895f6a7 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -2517,6 +2517,18 @@ switch_status_t sofia_glue_add_profile(char *key, sofia_profile_t *profile) return status; } +void sofia_glue_del_gateway(sofia_gateway_t *gp) +{ + if (!gp->deleted) { + if (gp->state != REG_STATE_NOREG) { + gp->retry = 0; + gp->state = REG_STATE_UNREGISTER; + } + + gp->deleted = 1; + } +} + void sofia_glue_del_profile(sofia_profile_t *profile) { sofia_gateway_t *gp; @@ -2545,9 +2557,7 @@ void sofia_glue_del_profile(sofia_profile_t *profile) } for (gp = profile->gateways; gp; gp = gp->next) { - switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->name); - switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->register_from); - switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->register_contact); + sofia_glue_del_gateway(gp); } } switch_mutex_unlock(mod_sofia_globals.hash_mutex); diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 31bbea8162..b88f80e114 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -70,7 +70,25 @@ void sofia_reg_unregister(sofia_profile_t *profile) void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) { - sofia_gateway_t *gateway_ptr; + sofia_gateway_t *gateway_ptr, *last = NULL; + + for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) { + if (gateway_ptr->deleted && gateway_ptr->state == REG_STATE_NOREG) { + if (last) { + last->next = gateway_ptr->next; + } else { + profile->gateways = gateway_ptr->next; + } + + switch_core_hash_delete(mod_sofia_globals.gateway_hash, gateway_ptr->name); + switch_core_hash_delete(mod_sofia_globals.gateway_hash, gateway_ptr->register_from); + switch_core_hash_delete(mod_sofia_globals.gateway_hash, gateway_ptr->register_contact); + + last = gateway_ptr; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "deleted gateway %s\n", gateway_ptr->name); + } + } + for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) { int ss_state = nua_callstate_authenticating; reg_state_t ostate = gateway_ptr->state; @@ -1325,7 +1343,7 @@ sofia_gateway_t *sofia_reg_find_gateway__(const char *file, const char *func, in switch_mutex_lock(mod_sofia_globals.hash_mutex); if ((gateway = (sofia_gateway_t *) switch_core_hash_find(mod_sofia_globals.gateway_hash, key))) { - if (!(gateway->profile->pflags & PFLAG_RUNNING)) { + if (!(gateway->profile->pflags & PFLAG_RUNNING) || gateway->deleted) { gateway = NULL; goto done; } @@ -1363,6 +1381,10 @@ switch_status_t sofia_reg_add_gateway(char *key, sofia_gateway_t *gateway) } switch_mutex_unlock(mod_sofia_globals.hash_mutex); + if (status == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Added gateway '%s' to profile '%s'\n", gateway->name, gateway->profile->name); + } + return status; }