diff --git a/src/include/switch_xml.h b/src/include/switch_xml.h index 2d3f994878..cf8da02870 100644 --- a/src/include/switch_xml.h +++ b/src/include/switch_xml.h @@ -378,7 +378,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_locate_user_in_domain(_In_z_ const ch SWITCH_DECLARE(switch_status_t) switch_xml_locate_user_merged(const char *key, const char *user_name, const char *domain_name, const char *ip, switch_xml_t *user, switch_event_t *params); - +SWITCH_DECLARE(uint32_t) switch_xml_clear_user_cache(const char *key, const char *user_name, const char *domain_name); SWITCH_DECLARE(void) switch_xml_merge_user(switch_xml_t user, switch_xml_t domain, switch_xml_t group); SWITCH_DECLARE(switch_xml_t) switch_xml_dup(switch_xml_t xml); diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index d7d67223e4..86d1e46d65 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -4720,6 +4720,30 @@ SWITCH_STANDARD_API(hupall_api_function) return SWITCH_STATUS_SUCCESS; } + +SWITCH_STANDARD_API(xml_flush_function) +{ + char *mycmd = NULL, *argv[3] = { 0 }; + int argc = 0; + int r = 0; + + if (!zstr(cmd) && (mycmd = strdup(cmd))) { + argc = switch_split(mycmd, ' ', argv); + } + + if (argc == 3) { + r = switch_xml_clear_user_cache(argv[0], argv[1], argv[2]); + } else { + r = switch_xml_clear_user_cache(NULL, NULL, NULL); + } + + + stream->write_function(stream, "+OK cleared %u entr%s\n", r, r == 1 ? "y" : "ies"); + + switch_safe_free(mycmd); + return SWITCH_STATUS_SUCCESS; +} + SWITCH_STANDARD_API(escape_function) { int len; @@ -5233,8 +5257,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "uuid_simplify", "Try to cut out of a call path / attended xfer", uuid_simplify_function, SIMPLIFY_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_jitterbuffer", "Try to cut out of a call path / attended xfer", uuid_jitterbuffer_function, JITTERBUFFER_SYNTAX); + SWITCH_ADD_API(commands_api_interface, "xml_flush_cache", "clear xml cache", xml_flush_function, " "); SWITCH_ADD_API(commands_api_interface, "xml_locate", "find some xml", xml_locate_function, "[root |
]"); SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, " "); + + switch_console_set_complete("add alias add"); switch_console_set_complete("add alias del"); switch_console_set_complete("add complete add"); diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 9130ceb569..c757a9e43e 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -2002,7 +2002,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, const char *call_id = NULL; char *sql; char *number_alias = NULL; - switch_xml_t domain, xml = NULL, user, param, uparams, dparams, group = NULL, gparams = NULL; + switch_xml_t user = NULL, param, uparams; char hexdigest[2 * SU_MD5_DIGEST_SIZE + 1] = ""; char *domain_name = NULL; switch_event_t *params = NULL; @@ -2179,7 +2179,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, domain_name = realm; } - if (switch_xml_locate_user("id", zstr(username) ? "nobody" : username, domain_name, ip, &xml, &domain, &user, &group, params) != SWITCH_STATUS_SUCCESS) { + if (switch_xml_locate_user_merged("id", zstr(username) ? "nobody" : username, domain_name, ip, &user, params) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n" "You must define a domain called '%s' in your directory and add a user with the id=\"%s\" attribute\n" "and you must configure your device to use the proper domain in it's authentication credentials.\n", username, domain_name, @@ -2200,90 +2200,10 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, number_alias = zstr(username) ? "nobody" : username; } - dparams = switch_xml_child(domain, "params"); - uparams = switch_xml_child(user, "params"); - if (group) { - gparams = switch_xml_child(group, "params"); - } - - if (!(dparams || uparams)) { + if (!(uparams = switch_xml_child(user, "params"))) { ret = AUTH_OK; goto skip_auth; - } - - if (dparams) { - for (param = switch_xml_child(dparams, "param"); param; param = param->next) { - const char *var = switch_xml_attr_soft(param, "name"); - const char *val = switch_xml_attr_soft(param, "value"); - - if (!strcasecmp(var, "sip-forbid-register") && switch_true(val)) { - ret = AUTH_FORBIDDEN; - goto end; - } - - if (!strcasecmp(var, "password")) { - passwd = val; - } - - if (!strcasecmp(var, "auth-acl")) { - auth_acl = val; - } - - if (!strcasecmp(var, "a1-hash")) { - a1_hash = val; - } - if (!strcasecmp(var, "mwi-account")) { - mwi_account = val; - } - if (!strcasecmp(var, "allow-empty-password")) { - allow_empty_password = switch_true(val); - } - if (!strcasecmp(var, "user-agent-filter")) { - user_agent_filter = val; - } - if (!strcasecmp(var, "max-registrations-per-extension")) { - max_registrations_perext = atoi(val); - } - } - } - - if (gparams) { - for (param = switch_xml_child(gparams, "param"); param; param = param->next) { - const char *var = switch_xml_attr_soft(param, "name"); - const char *val = switch_xml_attr_soft(param, "value"); - - if (!strcasecmp(var, "sip-forbid-register") && switch_true(val)) { - ret = AUTH_FORBIDDEN; - goto end; - } - - if (!strcasecmp(var, "password")) { - passwd = val; - } - - if (!strcasecmp(var, "auth-acl")) { - auth_acl = val; - } - - if (!strcasecmp(var, "a1-hash")) { - a1_hash = val; - } - if (!strcasecmp(var, "mwi-account")) { - mwi_account = val; - } - if (!strcasecmp(var, "allow-empty-password")) { - allow_empty_password = switch_true(val); - } - if (!strcasecmp(var, "user-agent-filter")) { - user_agent_filter = val; - } - if (!strcasecmp(var, "max-registrations-per-extension")) { - max_registrations_perext = atoi(val); - } - } - } - - if (uparams) { + } else { for (param = switch_xml_child(uparams, "param"); param; param = param->next) { const char *var = switch_xml_attr_soft(param, "name"); const char *val = switch_xml_attr_soft(param, "value"); @@ -2504,31 +2424,11 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "mwi-account", mwi_account); } - if ((dparams = switch_xml_child(domain, "params"))) { - xparams_type[i] = 0; - xparams[i++] = dparams; - } - - if (group && (gparams = switch_xml_child(group, "params"))) { - xparams_type[i] = 0; - xparams[i++] = gparams; - } - if ((uparams = switch_xml_child(user, "params"))) { xparams_type[i] = 0; xparams[i++] = uparams; } - if ((dparams = switch_xml_child(domain, "variables"))) { - xparams_type[i] = 1; - xparams[i++] = dparams; - } - - if (group && (gparams = switch_xml_child(group, "variables"))) { - xparams_type[i] = 1; - xparams[i++] = gparams; - } - if ((uparams = switch_xml_child(user, "variables"))) { xparams_type[i] = 1; xparams[i++] = uparams; @@ -2632,8 +2532,8 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, switch_event_destroy(¶ms); - if (xml) { - switch_xml_free(xml); + if (user) { + switch_xml_free(user); } switch_safe_free(input); diff --git a/src/switch_xml.c b/src/switch_xml.c index 243494aa7c..2d2ba4d240 100644 --- a/src/switch_xml.c +++ b/src/switch_xml.c @@ -136,10 +136,12 @@ static switch_memory_pool_t *XML_MEMORY_POOL = NULL; static switch_thread_rwlock_t *B_RWLOCK = NULL; static switch_mutex_t *XML_LOCK = NULL; +static switch_mutex_t *CACHE_MUTEX = NULL; static switch_mutex_t *REFLOCK = NULL; static switch_mutex_t *FILE_LOCK = NULL; static switch_mutex_t *XML_GEN_LOCK = NULL; +static switch_hash_t *CACHE_HASH = NULL; struct xml_section_t { const char *name; @@ -1826,15 +1828,92 @@ SWITCH_DECLARE(void) switch_xml_merge_user(switch_xml_t user, switch_xml_t domai do_merge(user, domain, "variables", "variable"); } +SWITCH_DECLARE(uint32_t) switch_xml_clear_user_cache(const char *key, const char *user_name, const char *domain_name) +{ + switch_hash_index_t *hi; + void *val; + const void *var; + char mega_key[1024]; + int r = 0; + switch_xml_t lookup; + + switch_mutex_lock(CACHE_MUTEX); + + if (key && user_name && domain_name) { + switch_snprintf(mega_key, sizeof(mega_key), "%s%s%s", key, user_name, domain_name); + + if ((lookup = switch_core_hash_find(CACHE_HASH, mega_key))) { + switch_core_hash_delete(CACHE_HASH, mega_key); + switch_xml_free(lookup); + r++; + } + + } else { + + top: + for (hi = switch_hash_first(NULL, CACHE_HASH); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &var, NULL, &val); + switch_xml_free(val); + switch_core_hash_delete(CACHE_HASH, var); + r++; + goto top; + } + } + + switch_mutex_unlock(CACHE_MUTEX); + + return r; + +} + +static switch_status_t switch_xml_locate_user_cache(const char *key, const char *user_name, const char *domain_name, switch_xml_t *user) +{ + char mega_key[1024]; + switch_xml_t lookup; + switch_status_t status = SWITCH_STATUS_FALSE; + + switch_snprintf(mega_key, sizeof(mega_key), "%s%s%s", key, user_name, domain_name); + + switch_mutex_lock(CACHE_MUTEX); + if ((lookup = switch_core_hash_find(CACHE_HASH, mega_key))) { + *user = switch_xml_dup(lookup); + status = SWITCH_STATUS_SUCCESS; + } + switch_mutex_unlock(CACHE_MUTEX); + + return status; +} + +static void switch_xml_user_cache(const char *key, const char *user_name, const char *domain_name, switch_xml_t user) +{ + char mega_key[1024]; + switch_xml_t lookup; + + switch_snprintf(mega_key, sizeof(mega_key), "%s%s%s", key, user_name, domain_name); + switch_mutex_lock(CACHE_MUTEX); + if ((lookup = switch_core_hash_find(CACHE_HASH, mega_key))) { + switch_core_hash_delete(CACHE_HASH, mega_key); + switch_xml_free(lookup); + } + + switch_core_hash_insert(CACHE_HASH, mega_key, switch_xml_dup(user)); + switch_mutex_unlock(CACHE_MUTEX); +} + SWITCH_DECLARE(switch_status_t) switch_xml_locate_user_merged(const char *key, const char *user_name, const char *domain_name, const char *ip, switch_xml_t *user, switch_event_t *params) { switch_xml_t xml, domain, group, x_user, x_user_dup; switch_status_t status = SWITCH_STATUS_FALSE; - if ((status = switch_xml_locate_user(key, user_name, domain_name, ip, &xml, &domain, &x_user, &group, params)) == SWITCH_STATUS_SUCCESS) { + if ((status = switch_xml_locate_user_cache(key, user_name, domain_name, &x_user)) == SWITCH_STATUS_SUCCESS) { + *user = x_user; + } else if ((status = switch_xml_locate_user(key, user_name, domain_name, ip, &xml, &domain, &x_user, &group, params)) == SWITCH_STATUS_SUCCESS) { x_user_dup = switch_xml_dup(x_user); switch_xml_merge_user(x_user_dup, domain, group); + if (switch_true(switch_xml_attr(x_user_dup, "cacheable"))) { + switch_xml_user_cache(key, user_name, domain_name, x_user_dup); + } *user = x_user_dup; switch_xml_free(xml); } @@ -2057,10 +2136,12 @@ SWITCH_DECLARE(switch_status_t) switch_xml_init(switch_memory_pool_t *pool, cons XML_MEMORY_POOL = pool; *err = "Success"; + switch_mutex_init(&CACHE_MUTEX, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL); switch_mutex_init(&XML_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL); switch_mutex_init(&REFLOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL); switch_mutex_init(&FILE_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL); switch_mutex_init(&XML_GEN_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL); + switch_core_hash_init(&CACHE_HASH, XML_MEMORY_POOL); switch_thread_rwlock_create(&B_RWLOCK, XML_MEMORY_POOL); @@ -2078,6 +2159,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_destroy(void) { switch_status_t status = SWITCH_STATUS_FALSE; + switch_mutex_lock(XML_LOCK); switch_mutex_lock(REFLOCK); @@ -2091,6 +2173,10 @@ SWITCH_DECLARE(switch_status_t) switch_xml_destroy(void) switch_mutex_unlock(XML_LOCK); switch_mutex_unlock(REFLOCK); + switch_xml_clear_user_cache(NULL, NULL, NULL); + + switch_core_hash_destroy(&CACHE_HASH); + return status; }