XML-22
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16997 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
e8d2949267
commit
3518ef213b
|
@ -57,6 +57,10 @@ struct xml_binding {
|
||||||
int use_dynamic_url;
|
int use_dynamic_url;
|
||||||
int auth_scheme;
|
int auth_scheme;
|
||||||
int timeout;
|
int timeout;
|
||||||
|
int timeout_ms;
|
||||||
|
int weight;
|
||||||
|
struct xml_binding* next;
|
||||||
|
int chosen;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int keep_files_around = 0;
|
static int keep_files_around = 0;
|
||||||
|
@ -132,9 +136,6 @@ static size_t file_callback(void *ptr, size_t size, size_t nmemb, void *data)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static switch_xml_t xml_url_fetch(const char *section, const char *tag_name, const char *key_name, const char *key_value, switch_event_t *params,
|
static switch_xml_t xml_url_fetch(const char *section, const char *tag_name, const char *key_name, const char *key_value, switch_event_t *params,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
|
@ -240,6 +241,11 @@ static switch_xml_t xml_url_fetch(const char *section, const char *tag_name, con
|
||||||
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
|
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (binding->timeout_ms) {
|
||||||
|
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, binding->timeout_ms);
|
||||||
|
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (binding->disable100continue) {
|
if (binding->disable100continue) {
|
||||||
slist = curl_slist_append(slist, "Expect:");
|
slist = curl_slist_append(slist, "Expect:");
|
||||||
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist);
|
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist);
|
||||||
|
@ -324,12 +330,128 @@ static switch_xml_t xml_url_fetch(const char *section, const char *tag_name, con
|
||||||
return xml;
|
return xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static switch_xml_t xml_curl_fetch(const char *section, const char *tag_name, const char *key_name, const char *key_value, switch_event_t *params,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
xml_binding_t *root = (xml_binding_t*) user_data;
|
||||||
|
xml_binding_t *binding = root;
|
||||||
|
int running_weight = 0, total_weight = 0, rand_weight = 0, count = 0, pos = 0;
|
||||||
|
xml_binding_t *bindings_copy = NULL;
|
||||||
|
xml_binding_t *tmp = NULL;
|
||||||
|
xml_binding_t **first_order = NULL;
|
||||||
|
xml_binding_t **second_order = NULL;
|
||||||
|
switch_xml_t result = NULL;
|
||||||
|
|
||||||
|
// Count how many elements we have
|
||||||
|
for( ; binding != NULL; binding = binding->next) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found [%s]\n", binding->url);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "XML_CURL Fetch on %d bindings\n", count);
|
||||||
|
|
||||||
|
// Make a local copy of the bindings
|
||||||
|
bindings_copy = malloc(count*sizeof(xml_binding_t));
|
||||||
|
tmp = bindings_copy;
|
||||||
|
binding = root;
|
||||||
|
pos = 0;
|
||||||
|
for( ; binding != NULL; binding = binding->next) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Copying [%s] to 0x%0X\n", root->url, (unsigned)(intptr_t)&bindings_copy[pos]);
|
||||||
|
memcpy(&bindings_copy[pos], binding, sizeof(xml_binding_t));
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// And two ordering arrays
|
||||||
|
first_order = malloc(count*sizeof(xml_binding_t*));
|
||||||
|
memset(first_order, 0, count*sizeof(xml_binding_t*));
|
||||||
|
second_order = malloc(count*sizeof(xml_binding_t*));
|
||||||
|
memset(second_order, 0, count*sizeof(xml_binding_t*));
|
||||||
|
|
||||||
|
// Update root to point to local copy of binding data
|
||||||
|
root = bindings_copy;
|
||||||
|
|
||||||
|
// Put all weight=0 at beginning of first ordering array
|
||||||
|
binding = root; pos = 0;
|
||||||
|
for(int i = 0; i < count; i++) {
|
||||||
|
binding = &bindings_copy[i];
|
||||||
|
if(binding->weight == 0) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Copying [%s] to first_order[%d]\n", binding->url, pos);
|
||||||
|
first_order[pos] = binding;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then dump everything else into the first ordering array
|
||||||
|
binding = root;
|
||||||
|
for(int i = 0; i < count; i++) {
|
||||||
|
binding = &bindings_copy[i];
|
||||||
|
if(binding->weight != 0) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Copying [%s] to first_order[%d]\n", binding->url, pos);
|
||||||
|
first_order[pos] = binding;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
srand((unsigned)((unsigned)(intptr_t)switch_thread_self() + switch_micro_time_now()));
|
||||||
|
|
||||||
|
// We need to pick every element in the array, so loop once for every one of them
|
||||||
|
pos = 0;
|
||||||
|
for(int i = 0; i < count; i++) {
|
||||||
|
// Calculate the total remaining unchosen weight
|
||||||
|
total_weight = 0; running_weight = 0;
|
||||||
|
for(int b = 0; b < count; b++) {
|
||||||
|
binding = &bindings_copy[b];
|
||||||
|
if(!binding->chosen) total_weight += binding->weight;
|
||||||
|
}
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Remaining total weight [%d]\n", total_weight);
|
||||||
|
|
||||||
|
// Pick a random number between [0, total_weight]
|
||||||
|
// Note: Don't use rand() % M as it is not as random as this more complex
|
||||||
|
// method which achieves the same intent with more random results
|
||||||
|
rand_weight = (int)( ((double)rand()) / (((double)(RAND_MAX) + (double)(1)) / ((double)total_weight + (double)(1))) );
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Random weight [%d]\n", rand_weight);
|
||||||
|
|
||||||
|
// Then grab the first unchosen element whose running_weight >= rand_weight
|
||||||
|
// and move it into our 'picked' list
|
||||||
|
binding = root;
|
||||||
|
for(int b = 0; b < count; b++) {
|
||||||
|
binding = &bindings_copy[b];
|
||||||
|
if(binding->chosen) continue; // skip already picked elements
|
||||||
|
|
||||||
|
running_weight += binding->weight;
|
||||||
|
if(running_weight >= rand_weight) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Chose binding %d as [%s] with weight [%d] based on running weight [%d]\n", pos, binding->url, binding->weight, running_weight);
|
||||||
|
second_order[pos] = binding;
|
||||||
|
pos++;
|
||||||
|
binding->chosen = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then call our XML url fetch function for each binding based on our
|
||||||
|
* chosen order until we get a valid result or run out of bindings */
|
||||||
|
pos = 0;
|
||||||
|
for( ; pos < count && result == NULL; pos++) {
|
||||||
|
binding = second_order[pos];
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Querying binding [%s]\n", binding->url);
|
||||||
|
result = xml_url_fetch(section, tag_name, key_name, key_value, params, (void*)binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(first_order);
|
||||||
|
free(second_order);
|
||||||
|
free(bindings_copy);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define ENABLE_PARAM_VALUE "enabled"
|
#define ENABLE_PARAM_VALUE "enabled"
|
||||||
static switch_status_t do_config(void)
|
static switch_status_t do_config(void)
|
||||||
{
|
{
|
||||||
char *cf = "xml_curl.conf";
|
char *cf = "xml_curl.conf";
|
||||||
switch_xml_t cfg, xml, bindings_tag, binding_tag, param;
|
switch_xml_t cfg, xml, bindings_tag, binding_tag, param;
|
||||||
xml_binding_t *binding = NULL;
|
xml_binding_t *binding = NULL;
|
||||||
|
xml_binding_t *prev_binding = NULL;
|
||||||
|
xml_binding_t *root = NULL;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int need_vars_map = 0;
|
int need_vars_map = 0;
|
||||||
switch_hash_t *vars_map = NULL;
|
switch_hash_t *vars_map = NULL;
|
||||||
|
@ -344,14 +466,16 @@ static switch_status_t do_config(void)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (binding_tag = switch_xml_child(bindings_tag, "binding"); binding_tag; binding_tag = binding_tag->next) {
|
// Only 32768 bindings allowed or weight sum could exceed signed int max
|
||||||
|
// value breaking load balancing algorithm
|
||||||
|
for (binding_tag = switch_xml_child(bindings_tag, "binding"); binding_tag && x < 32768; binding_tag = binding_tag->next) {
|
||||||
char *bname = (char *) switch_xml_attr_soft(binding_tag, "name");
|
char *bname = (char *) switch_xml_attr_soft(binding_tag, "name");
|
||||||
char *url = NULL;
|
char *url = NULL;
|
||||||
char *bind_cred = NULL;
|
char *bind_cred = NULL;
|
||||||
char *bind_mask = NULL;
|
char *bind_mask = NULL;
|
||||||
char *method = NULL;
|
char *method = NULL;
|
||||||
int disable100continue = 0;
|
int disable100continue = 0;
|
||||||
int use_dynamic_url = 0, timeout = 0;
|
int use_dynamic_url = 0, timeout = 0, timeout_ms = 0, weight = 0;
|
||||||
uint32_t enable_cacert_check = 0;
|
uint32_t enable_cacert_check = 0;
|
||||||
char *ssl_cert_file = NULL;
|
char *ssl_cert_file = NULL;
|
||||||
char *ssl_key_file = NULL;
|
char *ssl_key_file = NULL;
|
||||||
|
@ -398,6 +522,17 @@ static switch_status_t do_config(void)
|
||||||
disable100continue = 1;
|
disable100continue = 1;
|
||||||
} else if (!strcasecmp(var, "method")) {
|
} else if (!strcasecmp(var, "method")) {
|
||||||
method = val;
|
method = val;
|
||||||
|
} else if (!strcasecmp(var, "weight")) {
|
||||||
|
int tmp = atoi(val);
|
||||||
|
if (tmp >= 0) {
|
||||||
|
if(tmp > 65535) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set weight > 65535!\n");
|
||||||
|
} else {
|
||||||
|
weight = tmp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set a negative weight!\n");
|
||||||
|
}
|
||||||
} else if (!strcasecmp(var, "timeout")) {
|
} else if (!strcasecmp(var, "timeout")) {
|
||||||
int tmp = atoi(val);
|
int tmp = atoi(val);
|
||||||
if (tmp >= 0) {
|
if (tmp >= 0) {
|
||||||
|
@ -405,6 +540,13 @@ static switch_status_t do_config(void)
|
||||||
} else {
|
} else {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set a negative timeout!\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set a negative timeout!\n");
|
||||||
}
|
}
|
||||||
|
} else if (!strcasecmp(var, "timeout-ms")) {
|
||||||
|
int tmp = atoi(val);
|
||||||
|
if (tmp >= 0) {
|
||||||
|
timeout_ms = tmp;
|
||||||
|
} else {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set a negative timeout!\n");
|
||||||
|
}
|
||||||
} else if (!strcasecmp(var, "enable-cacert-check") && switch_true(val)) {
|
} else if (!strcasecmp(var, "enable-cacert-check") && switch_true(val)) {
|
||||||
enable_cacert_check = 1;
|
enable_cacert_check = 1;
|
||||||
} else if (!strcasecmp(var, "ssl-cert-path")) {
|
} else if (!strcasecmp(var, "ssl-cert-path")) {
|
||||||
|
@ -455,7 +597,9 @@ static switch_status_t do_config(void)
|
||||||
memset(binding, 0, sizeof(*binding));
|
memset(binding, 0, sizeof(*binding));
|
||||||
|
|
||||||
binding->auth_scheme = auth_scheme;
|
binding->auth_scheme = auth_scheme;
|
||||||
|
binding->weight = weight;
|
||||||
binding->timeout = timeout;
|
binding->timeout = timeout;
|
||||||
|
binding->timeout_ms = timeout_ms;
|
||||||
binding->url = strdup(url);
|
binding->url = strdup(url);
|
||||||
switch_assert(binding->url);
|
switch_assert(binding->url);
|
||||||
|
|
||||||
|
@ -522,12 +666,24 @@ static switch_status_t do_config(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(root == NULL) {
|
||||||
|
root = binding;
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Root binding [%s] [%s] [%s]\n",
|
||||||
|
zstr(bname) ? "N/A" : bname, binding->url, binding->bindings ? binding->bindings : "all");
|
||||||
|
}
|
||||||
|
if(prev_binding != NULL) {
|
||||||
|
prev_binding->next = binding;
|
||||||
|
}
|
||||||
|
prev_binding = binding;
|
||||||
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Binding [%s] XML Fetch Function [%s] [%s]\n",
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Binding [%s] XML Fetch Function [%s] [%s]\n",
|
||||||
zstr(bname) ? "N/A" : bname, binding->url, binding->bindings ? binding->bindings : "all");
|
zstr(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++;
|
x++;
|
||||||
binding = NULL;
|
binding = NULL;
|
||||||
}
|
}
|
||||||
|
if(root != NULL) {
|
||||||
|
switch_xml_bind_search_function(xml_curl_fetch, switch_xml_parse_section_string(root->bindings), root);
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
switch_xml_free(xml);
|
switch_xml_free(xml);
|
||||||
|
|
Loading…
Reference in New Issue