diff --git a/conf/xml_curl.conf.xml b/conf/xml_curl.conf.xml index 398226ddb7..d70d8bc3e1 100644 --- a/conf/xml_curl.conf.xml +++ b/conf/xml_curl.conf.xml @@ -1,11 +1,13 @@ - - - - - - - + + + + + + + + + diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 0215a53ba7..569b168d8e 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -900,7 +900,7 @@ typedef struct switch_media_bug switch_media_bug_t; typedef void (*switch_media_bug_callback_t)(switch_media_bug_t *, void *, switch_abc_type_t); typedef void (*switch_application_function_t)(switch_core_session_t *, char *); typedef void (*switch_event_callback_t)(switch_event_t *); -typedef switch_caller_extension_t *(*switch_dialplan_hunt_function_t)(switch_core_session_t *); +typedef switch_caller_extension_t *(*switch_dialplan_hunt_function_t)(switch_core_session_t *, void *); typedef switch_status_t (*switch_state_handler_t)(switch_core_session_t *); typedef switch_status_t (*switch_outgoing_channel_hook_t)(switch_core_session_t *, switch_caller_profile_t *, switch_core_session_t *); typedef switch_status_t (*switch_answer_channel_hook_t)(switch_core_session_t *); @@ -945,7 +945,8 @@ typedef switch_xml_t (*switch_xml_search_function_t)(char *section, char *tag_name, char *key_name, char *key_value, - char *params); + char *params, + void *user_data); /* things we don't deserve to know about */ /*! \brief A channel */ diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index d359fdbdc4..569ba1a023 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -182,7 +182,7 @@ switch_mutex_unlock(obj->flag_mutex); \param s the string to test \return true value if the string is NULL or zero length */ -#define switch_strlen_zero(s) (s && *s != '\0') ? 0 : 1 +#define switch_strlen_zero(s) (!s || *s == '\0') /*! \brief Wait a desired number of microseconds and yield the CPU diff --git a/src/include/switch_xml.h b/src/include/switch_xml.h index 0a453daa63..909eefe1e9 100644 --- a/src/include/switch_xml.h +++ b/src/include/switch_xml.h @@ -324,9 +324,10 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_cfg(char *file_path, switch_xml_t * ///\brief bind a search function to an external gateway ///\param function the search function to bind ///\param sections a bitmask of sections you wil service +///\param user_data a pointer to private data to be used during the callback ///\return SWITCH_STATUS_SUCCESS if successful ///\note gateway functions will be executed in the order they were binded until a success is found else the root registry will be used -SWITCH_DECLARE(switch_status_t) switch_xml_bind_search_function(switch_xml_search_function_t function, switch_xml_section_t sections); +SWITCH_DECLARE(switch_status_t) switch_xml_bind_search_function(switch_xml_search_function_t function, switch_xml_section_t sections, void *user_data); ///\brief parse a string for a list of sections ///\param str a | delimited list of section names diff --git a/src/mod/applications/mod_enum/mod_enum.c b/src/mod/applications/mod_enum/mod_enum.c index 9b20625166..6c4d926c48 100644 --- a/src/mod/applications/mod_enum/mod_enum.c +++ b/src/mod/applications/mod_enum/mod_enum.c @@ -514,7 +514,7 @@ static switch_status_t enum_lookup(char *root, char *in, enum_record_t **results } -static switch_caller_extension_t *enum_dialplan_hunt(switch_core_session_t *session) +static switch_caller_extension_t *enum_dialplan_hunt(switch_core_session_t *session, void *arg) { switch_caller_extension_t *extension = NULL; switch_caller_profile_t *caller_profile; diff --git a/src/mod/dialplans/mod_dialplan_directory/mod_dialplan_directory.c b/src/mod/dialplans/mod_dialplan_directory/mod_dialplan_directory.c index c8bb93ee3f..4f9a03176c 100644 --- a/src/mod/dialplans/mod_dialplan_directory/mod_dialplan_directory.c +++ b/src/mod/dialplans/mod_dialplan_directory/mod_dialplan_directory.c @@ -83,7 +83,7 @@ static void load_config(void) switch_xml_free(xml); } -static switch_caller_extension_t *directory_dialplan_hunt(switch_core_session_t *session) +static switch_caller_extension_t *directory_dialplan_hunt(switch_core_session_t *session, void *arg) { switch_caller_profile_t *caller_profile; switch_caller_extension_t *extension = NULL; diff --git a/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c b/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c index 25808dc22e..77c065bac5 100644 --- a/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c +++ b/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c @@ -193,12 +193,12 @@ static int parse_exten(switch_core_session_t *session, switch_xml_t xexten, swit return proceed; } -static switch_caller_extension_t *dialplan_hunt(switch_core_session_t *session) +static switch_caller_extension_t *dialplan_hunt(switch_core_session_t *session, void *arg) { switch_caller_profile_t *caller_profile; switch_caller_extension_t *extension = NULL; switch_channel_t *channel; - switch_xml_t cfg, xml, xcontext, xexten; + switch_xml_t alt_root = NULL, cfg, xml, xcontext, xexten; char *context = NULL; switch_stream_handle_t stream = {0}; switch_size_t encode_len = 1024, new_len = 0; @@ -206,6 +206,7 @@ static switch_caller_extension_t *dialplan_hunt(switch_core_session_t *session) char *prof[11] = {0}, *prof_names[11] = {0}, *e = NULL; switch_hash_index_t *hi; uint32_t x = 0; + char *alt_path = (char *) arg; channel = switch_core_session_get_channel(session); if ((caller_profile = switch_channel_get_caller_profile(channel))) { @@ -296,11 +297,28 @@ static switch_caller_extension_t *dialplan_hunt(switch_core_session_t *session) if (e && *e == '&') { *e = '\0'; } + + if (!switch_strlen_zero(alt_path)) { + switch_xml_t conf = NULL, tag = NULL; + if (!(alt_root = switch_xml_parse_file(alt_path))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of [%s] failed\n", alt_path); + return NULL; + } - if (switch_xml_locate("dialplan", NULL, NULL, NULL, &xml, &cfg, stream.data) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of dialplan failed\n"); - return NULL; - } + if ((conf = switch_xml_find_child(alt_root, "section", "name", "dialplan")) && + (tag = switch_xml_find_child(conf, "dialplan", NULL, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Getting dialplan from alternate path: %s\n", alt_path); + xml = alt_root; + cfg = tag; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of dialplan failed\n"); + return NULL; + } + } else if (switch_xml_locate("dialplan", NULL, NULL, NULL, &xml, &cfg, stream.data) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of dialplan failed\n"); + return NULL; + } + switch_safe_free(stream.data); switch_safe_free(encode_buf); diff --git a/src/mod/xml_int/mod_xml_curl/mod_xml_curl.c b/src/mod/xml_int/mod_xml_curl/mod_xml_curl.c index dbed6c8f4e..7d6c357c04 100644 --- a/src/mod/xml_int/mod_xml_curl/mod_xml_curl.c +++ b/src/mod/xml_int/mod_xml_curl/mod_xml_curl.c @@ -33,15 +33,13 @@ static const char modname[] = "mod_xml_curl"; -static struct { +struct xml_binding { char *url; char *bindings; char *cred; -} globals; +}; -SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_url, globals.url); -SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_bindings, globals.bindings); -SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cred, globals.cred); +typedef struct xml_binding xml_binding_t; struct config_data { char *name; @@ -62,7 +60,8 @@ static switch_xml_t xml_url_fetch(char *section, char *tag_name, char *key_name, char *key_value, - char *params) + char *params, + void *user_data) { char filename[512] = ""; CURL *curl_handle = NULL; @@ -71,6 +70,22 @@ static switch_xml_t xml_url_fetch(char *section, char *data = NULL; switch_uuid_t uuid; char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; + xml_binding_t *binding = (xml_binding_t *) user_data; + char *file_url; + + if (!binding) { + return NULL; + } + + if (file_url = strstr(binding->url, "file:")) { + file_url += 5; + + if (!(xml = switch_xml_parse_file(file_url))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Parsing Result!\n"); + } + + return xml; + } if (!(data = switch_mprintf("section=%s&tag_name=%s&key_name=%s&key_value=%s%s%s", section, @@ -88,20 +103,20 @@ static switch_xml_t xml_url_fetch(char *section, snprintf(filename, sizeof(filename), "%s%s.tmp.xml", SWITCH_GLOBAL_dirs.temp_dir, uuid_str); curl_handle = curl_easy_init(); - if (!strncasecmp(globals.url, "https", 5)) { + if (!strncasecmp(binding->url, "https", 5)) { curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0); } config_data.name = filename; if ((config_data.fd = open(filename, O_CREAT | O_RDWR | O_TRUNC)) > -1) { - if (!switch_strlen_zero(globals.cred)) { + if (!switch_strlen_zero(binding->cred)) { curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY); - curl_easy_setopt(curl_handle, CURLOPT_USERPWD, globals.cred); + curl_easy_setopt(curl_handle, CURLOPT_USERPWD, binding->cred); } curl_easy_setopt(curl_handle, CURLOPT_POST, 1); curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, data); - curl_easy_setopt(curl_handle, CURLOPT_URL, globals.url); + curl_easy_setopt(curl_handle, CURLOPT_URL, binding->url); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, file_callback); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&config_data); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-xml/1.0"); @@ -140,31 +155,71 @@ static switch_loadable_module_interface_t xml_curl_module_interface = { static switch_status_t do_config(void) { char *cf = "xml_curl.conf"; - switch_xml_t cfg, xml, settings, param; + switch_xml_t cfg, xml, bindings_tag, binding_tag, param; + xml_binding_t *binding = NULL; + int x = 0; if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf); return SWITCH_STATUS_TERM; } - if ((settings = switch_xml_child(cfg, "settings"))) { - for (param = switch_xml_child(settings, "param"); param; param = param->next) { + if (!(bindings_tag = switch_xml_child(cfg, "bindings"))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing tag!\n"); + return SWITCH_STATUS_FALSE; + } + + for (binding_tag = switch_xml_child(bindings_tag, "binding"); binding_tag; binding_tag = binding_tag->next) { + char *bname = (char *) switch_xml_attr_soft(binding_tag, "name"); + char *url = NULL; + char *bind_cred = NULL; + char *bind_mask = NULL; + + for (param = switch_xml_child(binding_tag, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); - if (!strcasecmp(var, "gateway-url")) { - char *bindings = (char *) switch_xml_attr_soft(param, "bindings"); - set_global_bindings(bindings); - set_global_url(val); + bind_mask = (char *) switch_xml_attr_soft(param, "bindings"); + if (val) { + url = val; + } } else if (!strcasecmp(var, "gateway-credentials")) { - set_global_cred(val); + bind_cred = var; } } + + if (!url) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Binding has no url!\n"); + continue; + } + + if (!(binding = malloc(sizeof(*binding)))) { + return SWITCH_STATUS_FALSE; + } + memset(binding, 0, sizeof(*binding)); + + binding->url = strdup(url); + + if (bind_mask) { + binding->bindings = strdup(bind_mask); + } + + if (bind_cred) { + binding->cred = strdup(bind_cred); + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Binding [%s] XML Fetch Function [%s] [%s]\n", + switch_strlen_zero(bname) ? "N/A" : bname, + binding->url, + binding->bindings ? binding->bindings : "all"); + switch_xml_bind_search_function(xml_url_fetch, switch_xml_parse_section_string(binding->bindings), binding); + x++; + binding = NULL; } switch_xml_free(xml); - return globals.url ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; + return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; } @@ -175,10 +230,7 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_mod if (do_config() == SWITCH_STATUS_SUCCESS) { curl_global_init(CURL_GLOBAL_ALL); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Binding XML Fetch Function [%s] [%s]\n", - globals.url, globals.bindings ? globals.bindings : "all"); - switch_xml_bind_search_function(xml_url_fetch, switch_xml_parse_section_string(globals.bindings)); - } else { + } else { return SWITCH_STATUS_FALSE; } diff --git a/src/switch_core.c b/src/switch_core.c index dd379f0b7b..39148abe25 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2701,13 +2701,21 @@ static void switch_core_standard_on_ring(switch_core_session_t *session) if ((dpstr = switch_core_session_strdup(session, caller_profile->dialplan))) { argc = switch_separate_string(dpstr, ',', dp, (sizeof(dp) / sizeof(dp[0]))); for (x = 0; x < argc; x++) { - if (!(dialplan_interface = switch_loadable_module_get_dialplan_interface(dp[x]))) { + char *dpname = dp[x]; + char *dparg = NULL; + + if (dpname) { + if ((dparg = strchr(dpname, ':'))) { + *dparg++ = '\0'; + } + } + if (!(dialplan_interface = switch_loadable_module_get_dialplan_interface(dpname))) { continue; } count++; - if ((extension = dialplan_interface->hunt_function(session)) != 0) { + if ((extension = dialplan_interface->hunt_function(session, dparg)) != 0) { switch_channel_set_caller_extension(session->channel, extension); return; } diff --git a/src/switch_xml.c b/src/switch_xml.c index a424b21e01..45d2594dcd 100644 --- a/src/switch_xml.c +++ b/src/switch_xml.c @@ -93,6 +93,7 @@ char *SWITCH_XML_NIL[] = { NULL }; // empty, null terminated array of strings struct switch_xml_binding { switch_xml_search_function_t function; switch_xml_section_t sections; + void *user_data; struct switch_xml_binding *next; }; @@ -141,7 +142,7 @@ SWITCH_DECLARE(switch_xml_section_t) switch_xml_parse_section_string(char *str) return sections; } -SWITCH_DECLARE(switch_status_t) switch_xml_bind_search_function(switch_xml_search_function_t function, switch_xml_section_t sections) +SWITCH_DECLARE(switch_status_t) switch_xml_bind_search_function(switch_xml_search_function_t function, switch_xml_section_t sections, void *user_data) { switch_xml_binding_t *binding = NULL, *ptr = NULL; assert(function != NULL); @@ -152,6 +153,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_bind_search_function(switch_xml_searc binding->function = function; binding->sections = sections; + binding->user_data = user_data; switch_mutex_lock(XML_LOCK); for (ptr = BINDINGS; ptr && ptr->next; ptr = ptr->next); @@ -1020,7 +1022,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_locate(char *section, continue; } - if ((xml = binding->function(section, tag_name, key_name, key_value, params))) { + if ((xml = binding->function(section, tag_name, key_name, key_value, params, binding->user_data))) { const char *err = NULL; err = switch_xml_error(xml);