Merge branch 'collectd-5.4' into collectd-5.5
[collectd.git] / src / curl_json.c
index e99500a..448db15 100644 (file)
@@ -78,6 +78,7 @@ struct cj_s /* {{{ */
   struct curl_slist *headers;
   char *post_body;
   cdtime_t interval;
+  int timeout;
 
   CURL *curl;
   char curl_errbuf[CURL_ERROR_SIZE];
@@ -131,17 +132,11 @@ static size_t cj_curl_callback (void *buf, /* {{{ */
     return (len);
 #endif
 
-  if (status != yajl_status_ok)
-  {
-    unsigned char *msg =
-      yajl_get_error(db->yajl, /* verbose = */ 1,
-          /* jsonText = */ (unsigned char *) buf, (unsigned int) len);
-    ERROR ("curl_json plugin: yajl_parse failed: %s", msg);
-    yajl_free_error(db->yajl, msg);
-    return (0); /* abort write callback */
-  }
-
-  return (len);
+  unsigned char *msg = yajl_get_error(db->yajl, /* verbose = */ 1,
+        /* jsonText = */ (unsigned char *) buf, (unsigned int) len);
+  ERROR ("curl_json plugin: yajl_parse failed: %s", msg);
+  yajl_free_error(db->yajl, msg);
+  return (0); /* abort write callback */
 } /* }}} size_t cj_curl_callback */
 
 static int cj_get_type (cj_key_t *key)
@@ -231,7 +226,7 @@ static int cj_cb_number (void *ctx,
   buffer[sizeof (buffer) - 1] = 0;
 
   if ((key == NULL) || !CJ_IS_KEY (key)) {
-    if (key != NULL)
+    if (key != NULL && !db->state[db->depth].in_array/*can be inhomogeneous*/)
       NOTICE ("curl_json plugin: Found \"%s\", but the configuration expects"
               " a map.", buffer);
     cj_cb_inc_array_index (ctx, /* update_key = */ 1);
@@ -502,6 +497,7 @@ static int cj_config_add_key (cj_t *db, /* {{{ */
   {
     ERROR ("curl_json plugin: cj_config: "
            "Invalid key: %s", ci->key);
+    cj_key_free (key);
     return (-1);
   }
 
@@ -524,72 +520,68 @@ static int cj_config_add_key (cj_t *db, /* {{{ */
       break;
   } /* for (i = 0; i < ci->children_num; i++) */
 
-  while (status == 0)
+  if (status != 0)
   {
-    if (key->type == NULL)
-    {
-      WARNING ("curl_json plugin: `Type' missing in `Key' block.");
-      status = -1;
-    }
+    cj_key_free (key);
+    return (-1);
+  }
 
-    break;
-  } /* while (status == 0) */
+  if (key->type == NULL)
+  {
+    WARNING ("curl_json plugin: `Type' missing in `Key' block.");
+    cj_key_free (key);
+    return (-1);
+  }
 
   /* store path in a tree that will match the json map structure, example:
    * "httpd/requests/count",
    * "httpd/requests/current" ->
    * { "httpd": { "requests": { "count": $key, "current": $key } } }
    */
-  if (status == 0)
+  char *ptr;
+  char *name;
+  c_avl_tree_t *tree;
+
+  if (db->tree == NULL)
+    db->tree = cj_avl_create();
+
+  tree = db->tree;
+  ptr = key->path;
+  if (*ptr == '/')
+    ++ptr;
+
+  name = ptr;
+  while ((ptr = strchr (name, '/')) != NULL)
   {
-    char *ptr;
-    char *name;
     char ent[PATH_MAX];
-    c_avl_tree_t *tree;
+    c_avl_tree_t *value;
+    size_t len;
 
-    if (db->tree == NULL)
-      db->tree = cj_avl_create();
+    len = ptr - name;
+    if (len == 0)
+      break;
 
-    tree = db->tree;
-    name = key->path;
-    ptr = key->path;
-    if (*ptr == '/')
-      ++ptr;
+    len = COUCH_MIN(len, sizeof (ent)-1);
+    sstrncpy (ent, name, len+1);
 
-    name = ptr;
-    while (*ptr)
+    if (c_avl_get (tree, ent, (void *) &value) != 0)
     {
-      if (*ptr == '/')
-      {
-        c_avl_tree_t *value;
-        int len;
-
-        len = ptr-name;
-        if (len == 0)
-          break;
-        len = COUCH_MIN(len, sizeof (ent)-1);
-        sstrncpy (ent, name, len+1);
-
-        if (c_avl_get (tree, ent, (void *) &value) != 0)
-        {
-          value = cj_avl_create ();
-          c_avl_insert (tree, strdup (ent), value);
-        }
-
-        tree = value;
-        name = ptr+1;
-      }
-      ++ptr;
-    }
-    if (*name)
-      c_avl_insert (tree, strdup(name), key);
-    else
-    {
-      ERROR ("curl_json plugin: invalid key: %s", key->path);
-      status = -1;
+      value = cj_avl_create ();
+      c_avl_insert (tree, strdup (ent), value);
     }
+
+    tree = value;
+    name = ptr + 1;
   }
 
+  if (strlen (name) == 0)
+  {
+    ERROR ("curl_json plugin: invalid key: %s", key->path);
+    cj_key_free (key);
+    return (-1);
+  }
+
+  c_avl_insert (tree, strdup (name), key);
   return (status);
 } /* }}} int cj_config_add_key */
 
@@ -608,6 +600,8 @@ static int cj_init_curl (cj_t *db) /* {{{ */
   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)
   {
@@ -648,6 +642,17 @@ static int cj_init_curl (cj_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 if (db->interval > 0)
+    curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
+        CDTIME_T_TO_MS(db->timeout));
+  else
+    curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
+        CDTIME_T_TO_MS(plugin_get_interval()));
+#endif
+
   return (0);
 } /* }}} int cj_init_curl */
 
@@ -673,6 +678,8 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
   }
   memset (db, 0, sizeof (*db));
 
+  db->timeout = -1;
+
   if (strcasecmp ("URL", ci->key) == 0)
     status = cf_util_get_string (ci, &db->url);
   else if (strcasecmp ("Sock", ci->key) == 0)
@@ -681,6 +688,7 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
   {
     ERROR ("curl_json plugin: cj_config: "
            "Invalid key: %s", ci->key);
+    cj_free (db);
     return (-1);
   }
   if (status != 0)
@@ -718,6 +726,8 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
       status = cj_config_add_key (db, child);
     else if (strcasecmp ("Interval", child->key) == 0)
       status = cf_util_get_cdtime(child, &db->interval);
+    else if (strcasecmp ("Timeout", child->key) == 0)
+      status = cf_util_get_int (child, &db->timeout);
     else
     {
       WARNING ("curl_json plugin: Option `%s' not allowed here.", child->key);