X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fcurl_xml.c;h=f3aa2d9af432fe33345c755b74e5475ce9c2c76b;hb=141816828389e3ad98f66db29b4a702479dcb05d;hp=9483738bcf637e8178f99c739688be30c73fa954;hpb=c1219a1c9db2e8400e2ee94b87f86ccd441485d5;p=collectd.git diff --git a/src/curl_xml.c b/src/curl_xml.c index 9483738b..f3aa2d9a 100644 --- a/src/curl_xml.c +++ b/src/curl_xml.c @@ -20,9 +20,11 @@ **/ #include "collectd.h" + #include "common.h" #include "plugin.h" #include "configfile.h" +#include "utils_curl_stats.h" #include "utils_llist.h" #include @@ -50,7 +52,7 @@ struct cx_xpath_s /* {{{ */ char *path; char *type; cx_values_t *values; - int values_len; + size_t values_len; char *instance_prefix; char *instance; int is_table; @@ -76,11 +78,14 @@ struct cx_s /* {{{ */ char *user; char *pass; char *credentials; + _Bool digest; _Bool verify_peer; _Bool verify_host; char *cacert; char *post_body; + int timeout; struct curl_slist *headers; + curl_stats_t *stats; cx_namespace_t *namespaces; size_t namespaces_num; @@ -112,14 +117,14 @@ static size_t cx_curl_callback (void *buf, /* {{{ */ return (0); } - if (len <= 0) + if (len == 0) return (len); if ((db->buffer_fill + len) >= db->buffer_size) { char *temp; - temp = (char *) realloc (db->buffer, + temp = realloc (db->buffer, db->buffer_fill + len + 1); if (temp == NULL) { @@ -168,13 +173,11 @@ static void cx_list_free (llist_t *list) /* {{{ */ } llist_destroy (list); - list = NULL; } /* }}} void cx_list_free */ static void cx_free (void *arg) /* {{{ */ { cx_t *db; - size_t i; DEBUG ("curl_xml plugin: cx_free (arg = %p);", arg); @@ -201,8 +204,9 @@ static void cx_free (void *arg) /* {{{ */ sfree (db->cacert); sfree (db->post_body); curl_slist_free_all (db->headers); + curl_stats_destroy (db->stats); - for (i = 0; i < db->namespaces_num; i++) + for (size_t i = 0; i < db->namespaces_num; i++) { sfree (db->namespaces[i].prefix); sfree (db->namespaces[i].url); @@ -212,6 +216,13 @@ static void cx_free (void *arg) /* {{{ */ sfree (db); } /* }}} void cx_free */ +static const char *cx_host (cx_t *db) /* {{{ */ +{ + if (db->host == NULL) + return hostname_g; + return db->host; +} /* }}} cx_host */ + static int cx_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */ oconfig_item_t *ci) { @@ -241,7 +252,7 @@ static int cx_check_type (const data_set_t *ds, cx_xpath_t *xpath) /* {{{ */ if (ds->ds_num != xpath->values_len) { - WARNING ("curl_xml plugin: DataSet `%s' requires %i values, but config talks about %i", + WARNING ("curl_xml plugin: DataSet `%s' requires %zu values, but config talks about %zu", xpath->type, ds->ds_num, xpath->values_len); return (-1); } @@ -249,7 +260,7 @@ static int cx_check_type (const data_set_t *ds, cx_xpath_t *xpath) /* {{{ */ return (0); } /* }}} cx_check_type */ -static xmlXPathObjectPtr cx_evaluate_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */ +static xmlXPathObjectPtr cx_evaluate_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */ xmlChar *expr) { xmlXPathObjectPtr xpath_obj; @@ -316,7 +327,7 @@ static int cx_handle_single_value_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */ { WARNING ("curl_xml plugin: " "relative xpath expression \"%s\" is expected to return " - "only text/attribute node which is not the case. Skipping...", + "only text/attribute node which is not the case. Skipping...", xpath->values[index].path); xmlXPathFreeObject (values_node_obj); return (-1); @@ -337,7 +348,7 @@ static int cx_handle_single_value_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */ vl->values[index].absolute = (absolute_t) strtoull (node_value, /* endptr = */ NULL, /* base = */ 0); break; - case DS_TYPE_GAUGE: + case DS_TYPE_GAUGE: vl->values[index].gauge = (gauge_t) strtod (node_value, /* endptr = */ NULL); } @@ -357,14 +368,13 @@ static int cx_handle_all_value_xpaths (xmlXPathContextPtr xpath_ctx, /* {{{ */ { value_t values[xpath->values_len]; int status; - int i; assert (xpath->values_len > 0); assert (xpath->values_len == vl->values_len); assert (xpath->values_len == ds->ds_num); vl->values = values; - for (i = 0; i < xpath->values_len; i++) + for (size_t i = 0; i < xpath->values_len; i++) { status = cx_handle_single_value_xpath (xpath_ctx, xpath, ds, vl, i); if (status != 0) @@ -473,18 +483,17 @@ static int cx_handle_instance_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */ static int cx_handle_base_xpath (char const *plugin_instance, /* {{{ */ char const *host, - xmlXPathContextPtr xpath_ctx, const data_set_t *ds, + xmlXPathContextPtr xpath_ctx, const data_set_t *ds, char *base_xpath, cx_xpath_t *xpath) { int total_nodes; - int i; xmlXPathObjectPtr base_node_obj = NULL; xmlNodeSetPtr base_nodes = NULL; value_list_t vl = VALUE_LIST_INIT; - base_node_obj = cx_evaluate_xpath (xpath_ctx, BAD_CAST base_xpath); + base_node_obj = cx_evaluate_xpath (xpath_ctx, BAD_CAST base_xpath); if (base_node_obj == NULL) return -1; /* error is logged already */ @@ -501,7 +510,7 @@ static int cx_handle_base_xpath (char const *plugin_instance, /* {{{ */ } /* If base_xpath returned multiple results, then */ - /* Instance in the xpath block is required */ + /* Instance in the xpath block is required */ if (total_nodes > 1 && xpath->instance == NULL) { ERROR ("curl_xml plugin: " @@ -514,11 +523,11 @@ static int cx_handle_base_xpath (char const *plugin_instance, /* {{{ */ vl.values_len = ds->ds_num; sstrncpy (vl.type, xpath->type, sizeof (vl.type)); sstrncpy (vl.plugin, "curl_xml", sizeof (vl.plugin)); - sstrncpy (vl.host, (host != NULL) ? host : hostname_g, sizeof (vl.host)); + sstrncpy (vl.host, host, sizeof (vl.host)); if (plugin_instance != NULL) - sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); + sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); - for (i = 0; i < total_nodes; i++) + for (int i = 0; i < total_nodes; i++) { int status; @@ -535,19 +544,19 @@ static int cx_handle_base_xpath (char const *plugin_instance, /* {{{ */ } /* for (i = 0; i < total_nodes; i++) */ /* free up the allocated memory */ - xmlXPathFreeObject (base_node_obj); + xmlXPathFreeObject (base_node_obj); - return (0); + return (0); } /* }}} cx_handle_base_xpath */ -static int cx_handle_parsed_xml(xmlDocPtr doc, /* {{{ */ +static int cx_handle_parsed_xml(xmlDocPtr doc, /* {{{ */ xmlXPathContextPtr xpath_ctx, cx_t *db) { llentry_t *le; const data_set_t *ds; cx_xpath_t *xpath; int status=-1; - + le = llist_head (db->list); while (le != NULL) @@ -557,7 +566,7 @@ static int cx_handle_parsed_xml(xmlDocPtr doc, /* {{{ */ ds = plugin_get_ds (xpath->type); if ( (cx_check_type(ds, xpath) == 0) && - (cx_handle_base_xpath(db->instance, db->host, + (cx_handle_base_xpath(db->instance, cx_host (db), xpath_ctx, ds, le->key, xpath) == 0) ) status = 0; /* we got atleast one success */ @@ -572,7 +581,6 @@ static int cx_parse_stats_xml(xmlChar* xml, cx_t *db) /* {{{ */ int status; xmlDocPtr doc; xmlXPathContextPtr xpath_ctx; - size_t i; /* Load the XML */ doc = xmlParseDoc(xml); @@ -590,7 +598,7 @@ static int cx_parse_stats_xml(xmlChar* xml, cx_t *db) /* {{{ */ return (-1); } - for (i = 0; i < db->namespaces_num; i++) + for (size_t i = 0; i < db->namespaces_num; i++) { cx_namespace_t const *ns = db->namespaces + i; status = xmlXPathRegisterNs (xpath_ctx, @@ -621,7 +629,7 @@ static int cx_curl_perform (cx_t *db, CURL *curl) /* {{{ */ char *url; url = db->url; - db->buffer_fill = 0; + db->buffer_fill = 0; status = curl_easy_perform (curl); if (status != CURLE_OK) { @@ -629,6 +637,8 @@ static int cx_curl_perform (cx_t *db, CURL *curl) /* {{{ */ status, db->curl_errbuf, url); return (-1); } + if (db->stats != NULL) + curl_stats_dispatch (db->stats, db->curl, cx_host (db), "curl_xml", db->instance); curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rc); @@ -669,15 +679,13 @@ static int cx_read (user_data_t *ud) /* {{{ */ static int cx_config_add_values (const char *name, cx_xpath_t *xpath, /* {{{ */ oconfig_item_t *ci) { - int i; - if (ci->values_num < 1) { WARNING ("curl_xml plugin: `ValuesFrom' needs at least one argument."); return (-1); } - for (i = 0; i < ci->values_num; i++) + for (int i = 0; i < ci->values_num; i++) if (ci->values[i].type != OCONFIG_TYPE_STRING) { WARNING ("curl_xml plugin: `ValuesFrom' needs only string argument."); @@ -687,13 +695,13 @@ static int cx_config_add_values (const char *name, cx_xpath_t *xpath, /* {{{ */ sfree (xpath->values); xpath->values_len = 0; - xpath->values = (cx_values_t *) malloc (sizeof (cx_values_t) * ci->values_num); + xpath->values = malloc (sizeof (cx_values_t) * ci->values_num); if (xpath->values == NULL) return (-1); - xpath->values_len = ci->values_num; + xpath->values_len = (size_t) ci->values_num; /* populate cx_values_t structure */ - for (i = 0; i < ci->values_num; i++) + for (int i = 0; i < ci->values_num; i++) { xpath->values[i].path_len = sizeof (ci->values[i].value.string); sstrncpy (xpath->values[i].path, ci->values[i].value.string, sizeof (xpath->values[i].path)); @@ -708,15 +716,13 @@ static int cx_config_add_xpath (cx_t *db, oconfig_item_t *ci) /* {{{ */ char *name; llentry_t *le; int status; - int i; - xpath = malloc (sizeof (*xpath)); + xpath = calloc (1, sizeof (*xpath)); if (xpath == NULL) { - ERROR ("curl_xml plugin: malloc failed."); + ERROR ("curl_xml plugin: calloc failed."); return (-1); } - memset (xpath, 0, sizeof (*xpath)); status = cf_util_get_string (ci, &xpath->path); if (status != 0) @@ -735,7 +741,7 @@ static int cx_config_add_xpath (cx_t *db, oconfig_item_t *ci) /* {{{ */ } status = 0; - for (i = 0; i < ci->children_num; i++) + for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; @@ -855,20 +861,26 @@ static int cx_init_curl (cx_t *db) /* {{{ */ curl_easy_setopt (db->curl, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt (db->curl, CURLOPT_WRITEFUNCTION, cx_curl_callback); curl_easy_setopt (db->curl, CURLOPT_WRITEDATA, db); - curl_easy_setopt (db->curl, CURLOPT_USERAGENT, - PACKAGE_NAME"/"PACKAGE_VERSION); + curl_easy_setopt (db->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT); curl_easy_setopt (db->curl, CURLOPT_ERRORBUFFER, db->curl_errbuf); curl_easy_setopt (db->curl, CURLOPT_URL, db->url); + curl_easy_setopt (db->curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt (db->curl, CURLOPT_MAXREDIRS, 50L); if (db->user != NULL) { +#ifdef HAVE_CURLOPT_USERNAME + curl_easy_setopt (db->curl, CURLOPT_USERNAME, db->user); + curl_easy_setopt (db->curl, CURLOPT_PASSWORD, + (db->pass == NULL) ? "" : db->pass); +#else size_t credentials_size; credentials_size = strlen (db->user) + 2; if (db->pass != NULL) credentials_size += strlen (db->pass); - db->credentials = (char *) malloc (credentials_size); + db->credentials = malloc (credentials_size); if (db->credentials == NULL) { ERROR ("curl_xml plugin: malloc failed."); @@ -878,6 +890,10 @@ static int cx_init_curl (cx_t *db) /* {{{ */ ssnprintf (db->credentials, credentials_size, "%s:%s", db->user, (db->pass == NULL) ? "" : db->pass); curl_easy_setopt (db->curl, CURLOPT_USERPWD, db->credentials); +#endif + + if (db->digest) + curl_easy_setopt (db->curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); } curl_easy_setopt (db->curl, CURLOPT_SSL_VERIFYPEER, db->verify_peer ? 1L : 0L); @@ -890,6 +906,13 @@ static int cx_init_curl (cx_t *db) /* {{{ */ if (db->post_body != NULL) curl_easy_setopt (db->curl, CURLOPT_POSTFIELDS, db->post_body); +#ifdef HAVE_CURLOPT_TIMEOUT_MS + if (db->timeout >= 0) + curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) db->timeout); + else + curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval())); +#endif + return (0); } /* }}} int cx_init_curl */ @@ -897,7 +920,6 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */ { cx_t *db; int status = 0; - int i; if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) @@ -907,13 +929,14 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */ return (-1); } - db = (cx_t *) malloc (sizeof (*db)); + db = calloc (1, sizeof (*db)); if (db == NULL) { - ERROR ("curl_xml plugin: malloc failed."); + ERROR ("curl_xml plugin: calloc failed."); return (-1); } - memset (db, 0, sizeof (*db)); + + db->timeout = -1; if (strcasecmp ("URL", ci->key) == 0) { @@ -933,7 +956,7 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */ } /* Fill the `cx_t' structure.. */ - for (i = 0; i < ci->children_num; i++) + for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; @@ -945,6 +968,8 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */ status = cf_util_get_string (child, &db->user); else if (strcasecmp ("Password", child->key) == 0) status = cf_util_get_string (child, &db->pass); + else if (strcasecmp ("Digest", child->key) == 0) + status = cf_util_get_boolean (child, &db->digest); else if (strcasecmp ("VerifyPeer", child->key) == 0) status = cf_util_get_boolean (child, &db->verify_peer); else if (strcasecmp ("VerifyHost", child->key) == 0) @@ -959,6 +984,14 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */ status = cf_util_get_string (child, &db->post_body); else if (strcasecmp ("Namespace", child->key) == 0) status = cx_config_add_namespace (db, child); + else if (strcasecmp ("Timeout", child->key) == 0) + status = cf_util_get_int (child, &db->timeout); + else if (strcasecmp ("Statistics", child->key) == 0) + { + db->stats = curl_stats_from_config (child); + if (db->stats == NULL) + status = -1; + } else { WARNING ("curl_xml plugin: Option `%s' not allowed here.", child->key); @@ -984,7 +1017,7 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */ /* If all went well, register this database for reading */ if (status == 0) { - user_data_t ud; + user_data_t ud = { 0 }; char *cb_name; if (db->instance == NULL) @@ -993,13 +1026,12 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */ DEBUG ("curl_xml plugin: Registering new read callback: %s", db->instance); - memset (&ud, 0, sizeof (ud)); ud.data = (void *) db; ud.free_func = cx_free; cb_name = ssnprintf_alloc ("curl_xml-%s-%s", db->instance, db->url); plugin_register_complex_read (/* group = */ "curl_xml", cb_name, cx_read, - /* interval = */ NULL, &ud); + /* interval = */ 0, &ud); sfree (cb_name); } else @@ -1018,12 +1050,11 @@ static int cx_config (oconfig_item_t *ci) /* {{{ */ int success; int errors; int status; - int i; success = 0; errors = 0; - for (i = 0; i < ci->children_num; i++) + for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i;