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);