summaryrefslogtreecommitdiffstats
path: root/libnetdata
diff options
context:
space:
mode:
authorCosta Tsaousis <costa@netdata.cloud>2023-04-20 20:49:06 +0300
committerGitHub <noreply@github.com>2023-04-20 20:49:06 +0300
commitc3d70ffcb43b62c95d71334ed49ad345ddf4360d (patch)
tree1f6645b504eae7801c8867d3af4d614135aa7602 /libnetdata
parent5b676d5f912fc27a126ff4ff6ba5b35da9cf930c (diff)
WEBRTC for communication between agents and browsers (#14874)
* initial webrtc setup * missing files * rewrite of webrtc integration * initialization and cleanup of webrtc connections * make it compile without libdatachannel * add missing webrtc_initialize() function when webrtc is not enabled * make c++17 optional * add build/m4/ax_compiler_vendor.m4 * add ax_cxx_compile_stdcxx.m4 * added new m4 files to makefile.am * id all webrtc connections * show warning when webrtc is disabled * fixed message * moved all webrtc error checking inside webrtc.cpp * working webrtc connection establishment and cleanup * remove obsolete code * rewrote webrtc code in C to remove dependency for c++17 * fixed left-over reference * detect binary and text messages * minor fix * naming of webrtc threads * added webrtc configuration * fix for thread_get_name_np() * smaller web_client memory footprint * universal web clients cache * free web clients every 100 uses * webrtc is now enabled by default only when compiled with internal checks * webrtc responses to /api/ requests, including LZ4 compression * fix for binary and text messages * web_client_cache is now global * unification of the internal web server API, for web requests, aclk request, webrtc requests * more cleanup and unification of web client timings * fixed compiler warnings * update sent and received bytes * eliminated of almost all big buffers in web client * registry now uses the new json generation * cookies are now an array; fixed redirects * fix redirects, again * write cookies directly to the header buffer, eliminating the need for cookie structures in web client * reset the has_cookies flag * gathered all web client cleanup to one function * fixes redirects * added summary.globals in /api/v2/data response * ars to arc in /api/v2/data * properly handle host impersonation * set the context of mem.numa_nodes
Diffstat (limited to 'libnetdata')
-rw-r--r--libnetdata/buffer/buffer.h22
-rw-r--r--libnetdata/config/appconfig.c15
-rw-r--r--libnetdata/config/appconfig.h1
-rw-r--r--libnetdata/inlined.h58
-rw-r--r--libnetdata/libnetdata.c165
-rw-r--r--libnetdata/libnetdata.h10
-rw-r--r--libnetdata/socket/socket.c4
-rw-r--r--libnetdata/socket/socket.h3
-rw-r--r--libnetdata/threads/threads.c59
-rw-r--r--libnetdata/threads/threads.h2
-rw-r--r--libnetdata/url/url.c180
-rw-r--r--libnetdata/url/url.h8
12 files changed, 202 insertions, 325 deletions
diff --git a/libnetdata/buffer/buffer.h b/libnetdata/buffer/buffer.h
index 73aa428bd9..83c2a38dd0 100644
--- a/libnetdata/buffer/buffer.h
+++ b/libnetdata/buffer/buffer.h
@@ -201,6 +201,28 @@ static inline void buffer_strcat(BUFFER *wb, const char *txt) {
buffer_overflow_check(wb);
}
+static inline void buffer_strncat(BUFFER *wb, const char *txt, size_t len) {
+ if(unlikely(!txt || !*txt)) return;
+
+ const char *t = txt;
+ while(*t) {
+ buffer_need_bytes(wb, len);
+ char *s = &wb->buffer[wb->len];
+ char *d = s;
+ const char *e = &wb->buffer[wb->len + len];
+
+ while(*t && d < e)
+ *d++ = *t++;
+
+ wb->len += d - s;
+ }
+
+ buffer_need_bytes(wb, 1);
+ wb->buffer[wb->len] = '\0';
+
+ buffer_overflow_check(wb);
+}
+
static inline void buffer_json_strcat(BUFFER *wb, const char *txt) {
if(unlikely(!txt || !*txt)) return;
diff --git a/libnetdata/config/appconfig.c b/libnetdata/config/appconfig.c
index 938c7dde27..f5d0bd3c29 100644
--- a/libnetdata/config/appconfig.c
+++ b/libnetdata/config/appconfig.c
@@ -845,13 +845,14 @@ void appconfig_generate(struct config *root, BUFFER *wb, int only_changed)
else if(!strcmp(co->name, CONFIG_SECTION_ML)) pri = 8;
else if(!strcmp(co->name, CONFIG_SECTION_HEALTH)) pri = 9;
else if(!strcmp(co->name, CONFIG_SECTION_WEB)) pri = 10;
- // by default, new sections will get pri = 11 (set at the end, below)
- else if(!strcmp(co->name, CONFIG_SECTION_REGISTRY)) pri = 12;
- else if(!strcmp(co->name, CONFIG_SECTION_GLOBAL_STATISTICS)) pri = 13;
- else if(!strcmp(co->name, CONFIG_SECTION_PLUGINS)) pri = 14;
- else if(!strcmp(co->name, CONFIG_SECTION_STATSD)) pri = 15;
- else if(!strncmp(co->name, "plugin:", 7)) pri = 16; // << change the loop too if you change this
- else pri = 11; // this is used for any new (currently unknown) sections
+ else if(!strcmp(co->name, CONFIG_SECTION_WEBRTC)) pri = 11;
+ // by default, new sections will get pri = 12 (set at the end, below)
+ else if(!strcmp(co->name, CONFIG_SECTION_REGISTRY)) pri = 13;
+ else if(!strcmp(co->name, CONFIG_SECTION_GLOBAL_STATISTICS)) pri = 14;
+ else if(!strcmp(co->name, CONFIG_SECTION_PLUGINS)) pri = 15;
+ else if(!strcmp(co->name, CONFIG_SECTION_STATSD)) pri = 16;
+ else if(!strncmp(co->name, "plugin:", 7)) pri = 17; // << change the loop too if you change this
+ else pri = 12; // this is used for any new (currently unknown) sections
if(i == pri) {
int loaded = 0;
diff --git a/libnetdata/config/appconfig.h b/libnetdata/config/appconfig.h
index 2828e107a5..b3a090248e 100644
--- a/libnetdata/config/appconfig.h
+++ b/libnetdata/config/appconfig.h
@@ -88,6 +88,7 @@
#define CONFIG_SECTION_ENV_VARS "environment variables"
#define CONFIG_SECTION_SQLITE "sqlite"
#define CONFIG_SECTION_WEB "web"
+#define CONFIG_SECTION_WEBRTC "webrtc"
#define CONFIG_SECTION_STATSD "statsd"
#define CONFIG_SECTION_PLUGINS "plugins"
#define CONFIG_SECTION_CLOUD "cloud"
diff --git a/libnetdata/inlined.h b/libnetdata/inlined.h
index 6bd2089b3a..2697b9a03f 100644
--- a/libnetdata/inlined.h
+++ b/libnetdata/inlined.h
@@ -514,4 +514,62 @@ static inline int uuid_memcmp(const uuid_t *uu1, const uuid_t *uu2) {
return memcmp(uu1, uu2, sizeof(uuid_t));
}
+static inline char *strsep_skip_consecutive_separators(char **ptr, char *s) {
+ char *p = (char *)"";
+ while (p && !p[0] && *ptr) p = strsep(ptr, s);
+ return (p);
+}
+
+// remove leading and trailing spaces; may return NULL
+static inline char *trim(char *s) {
+ // skip leading spaces
+ while (*s && isspace(*s)) s++;
+ if (!*s) return NULL;
+
+ // skip tailing spaces
+ // this way is way faster. Writes only one NUL char.
+ ssize_t l = (ssize_t)strlen(s);
+ if (--l >= 0) {
+ char *p = s + l;
+ while (p > s && isspace(*p)) p--;
+ *++p = '\0';
+ }
+
+ if (!*s) return NULL;
+
+ return s;
+}
+
+// like trim(), but also remove duplicate spaces inside the string; may return NULL
+static inline char *trim_all(char *buffer) {
+ char *d = buffer, *s = buffer;
+
+ // skip spaces
+ while(isspace(*s)) s++;
+
+ while(*s) {
+ // copy the non-space part
+ while(*s && !isspace(*s)) *d++ = *s++;
+
+ // add a space if we have to
+ if(*s && isspace(*s)) {
+ *d++ = ' ';
+ s++;
+ }
+
+ // skip spaces
+ while(isspace(*s)) s++;
+ }
+
+ *d = '\0';
+
+ if(d > buffer) {
+ d--;
+ if(isspace(*d)) *d = '\0';
+ }
+
+ if(!buffer[0]) return NULL;
+ return buffer;
+}
+
#endif //NETDATA_INLINED_H
diff --git a/libnetdata/libnetdata.c b/libnetdata/libnetdata.c
index 2633eeaab4..3029b08d1c 100644
--- a/libnetdata/libnetdata.c
+++ b/libnetdata/libnetdata.c
@@ -1042,171 +1042,6 @@ void netdata_fix_chart_id(char *s) {
while ((*s = netdata_map_chart_ids[(unsigned char) *s])) s++;
}
-/*
-// http://stackoverflow.com/questions/7666509/hash-function-for-string
-uint32_t simple_hash(const char *name)
-{
- const char *s = name;
- uint32_t hash = 5381;
- int i;
-
- while((i = *s++)) hash = ((hash << 5) + hash) + i;
-
- // fprintf(stderr, "HASH: %lu %s\n", hash, name);
-
- return hash;
-}
-*/
-
-/*
-// http://isthe.com/chongo/tech/comp/fnv/#FNV-1a
-uint32_t simple_hash(const char *name) {
- unsigned char *s = (unsigned char *) name;
- uint32_t hval = 0x811c9dc5;
-
- // FNV-1a algorithm
- while (*s) {
- // multiply by the 32 bit FNV magic prime mod 2^32
- // NOTE: No need to optimize with left shifts.
- // GCC will use imul instruction anyway.
- // Tested with 'gcc -O3 -S'
- //hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
- hval *= 16777619;
-
- // xor the bottom with the current octet
- hval ^= (uint32_t) *s++;
- }
-
- // fprintf(stderr, "HASH: %u = %s\n", hval, name);
- return hval;
-}
-
-uint32_t simple_uhash(const char *name) {
- unsigned char *s = (unsigned char *) name;
- uint32_t hval = 0x811c9dc5, c;
-
- // FNV-1a algorithm
- while ((c = *s++)) {
- if (unlikely(c >= 'A' && c <= 'Z')) c += 'a' - 'A';
- hval *= 16777619;
- hval ^= c;
- }
- return hval;
-}
-*/
-
-/*
-// http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
-// one at a time hash
-uint32_t simple_hash(const char *name) {
- unsigned char *s = (unsigned char *)name;
- uint32_t h = 0;
-
- while(*s) {
- h += *s++;
- h += (h << 10);
- h ^= (h >> 6);
- }
-
- h += (h << 3);
- h ^= (h >> 11);
- h += (h << 15);
-
- // fprintf(stderr, "HASH: %u = %s\n", h, name);
-
- return h;
-}
-*/
-
-void strreverse(char *begin, char *end) {
- while (end > begin) {
- // clearer code.
- char aux = *end;
- *end-- = *begin;
- *begin++ = aux;
- }
-}
-
-char *strsep_on_1char(char **ptr, char c) {
- if(unlikely(!ptr || !*ptr))
- return NULL;
-
- // remember the position we started
- char *s = *ptr;
-
- // skip separators in front
- while(*s == c) s++;
- char *ret = s;
-
- // find the next separator
- while(*s++) {
- if(unlikely(*s == c)) {
- *s++ = '\0';
- *ptr = s;
- return ret;
- }
- }
-
- *ptr = NULL;
- return ret;
-}
-
-char *mystrsep(char **ptr, char *s) {
- char *p = "";
- while (p && !p[0] && *ptr) p = strsep(ptr, s);
- return (p);
-}
-
-char *trim(char *s) {
- // skip leading spaces
- while (*s && isspace(*s)) s++;
- if (!*s) return NULL;
-
- // skip tailing spaces
- // this way is way faster. Writes only one NUL char.
- ssize_t l = strlen(s);
- if (--l >= 0) {
- char *p = s + l;
- while (p > s && isspace(*p)) p--;
- *++p = '\0';
- }
-
- if (!*s) return NULL;
-
- return s;
-}
-
-inline char *trim_all(char *buffer) {
- char *d = buffer, *s = buffer;
-
- // skip spaces
- while(isspace(*s)) s++;
-
- while(*s) {
- // copy the non-space part
- while(*s && !isspace(*s)) *d++ = *s++;
-
- // add a space if we have to
- if(*s && isspace(*s)) {
- *d++ = ' ';
- s++;
- }
-
- // skip spaces
- while(isspace(*s)) s++;
- }
-
- *d = '\0';
-
- if(d > buffer) {
- d--;
- if(isspace(*d)) *d = '\0';
- }
-
- if(!buffer[0]) return NULL;
- return buffer;
-}
-
static int memory_file_open(const char *filename, size_t size) {
// info("memory_file_open('%s', %zu", filename, size);
diff --git a/libnetdata/libnetdata.h b/libnetdata/libnetdata.h
index c1246aafa9..1f164e3a07 100644
--- a/libnetdata/libnetdata.h
+++ b/libnetdata/libnetdata.h
@@ -491,11 +491,6 @@ typedef struct storage_point {
void netdata_fix_chart_id(char *s);
void netdata_fix_chart_name(char *s);
-void strreverse(char* begin, char* end);
-char *mystrsep(char **ptr, char *s);
-char *trim(char *s); // remove leading and trailing spaces; may return NULL
-char *trim_all(char *buffer); // like trim(), but also remove duplicate spaces inside the string; may return NULL
-
int madvise_sequential(void *mem, size_t len);
int madvise_random(void *mem, size_t len);
int madvise_dontfork(void *mem, size_t len);
@@ -673,9 +668,8 @@ extern char *netdata_configured_host_prefix;
#include "parser/parser.h"
#include "yaml.h"
-// BEWARE: Outside of the C code this also exists in alarm-notify.sh
-#define DEFAULT_CLOUD_BASE_URL "https://api.netdata.cloud"
-#define DEFAULT_CLOUD_UI_URL "https://app.netdata.cloud"
+// BEWARE: this exists in alarm-notify.sh
+#define DEFAULT_CLOUD_BASE_URL "https://app.netdata.cloud"
#define RRD_STORAGE_TIERS 5
diff --git a/libnetdata/socket/socket.c b/libnetdata/socket/socket.c
index dd36da105e..7eb212b335 100644
--- a/libnetdata/socket/socket.c
+++ b/libnetdata/socket/socket.c
@@ -1149,8 +1149,8 @@ int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags) {
* update the client_host if uninitialized - ensure the hostsize is the number
* of *writable* bytes (i.e. be aware of the strdup used to compact the pollinfo).
*/
-extern int connection_allowed(int fd, char *client_ip, char *client_host, size_t hostsize, SIMPLE_PATTERN *access_list,
- const char *patname, int allow_dns)
+int connection_allowed(int fd, char *client_ip, char *client_host, size_t hostsize, SIMPLE_PATTERN *access_list,
+ const char *patname, int allow_dns)
{
debug(D_LISTENER,"checking %s... (allow_dns=%d)", patname, allow_dns);
if (!access_list)
diff --git a/libnetdata/socket/socket.h b/libnetdata/socket/socket.h
index 3a8369fba0..1100630149 100644
--- a/libnetdata/socket/socket.h
+++ b/libnetdata/socket/socket.h
@@ -22,8 +22,11 @@ typedef enum web_client_acl {
WEB_CLIENT_ACL_SSL_FORCE = (1 << 7),
WEB_CLIENT_ACL_SSL_DEFAULT = (1 << 8),
WEB_CLIENT_ACL_ACLK = (1 << 9),
+ WEB_CLIENT_ACL_WEBRTC = (1 << 10),
} WEB_CLIENT_ACL;
+#define WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC (WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_ACLK | WEB_CLIENT_ACL_WEBRTC)
+
#define WEB_CLIENT_ACL_ALL 0xFFFF
#define web_client_can_access_dashboard(w) ((w)->acl & WEB_CLIENT_ACL_DASHBOARD)
diff --git a/libnetdata/threads/threads.c b/libnetdata/threads/threads.c
index 16de45fd14..c4026a7331 100644
--- a/libnetdata/threads/threads.c
+++ b/libnetdata/threads/threads.c
@@ -21,8 +21,63 @@ inline int netdata_thread_tag_exists(void) {
return (netdata_thread && netdata_thread->tag && *netdata_thread->tag);
}
+static const char *thread_name_get(bool recheck) {
+ static __thread char threadname[NETDATA_THREAD_NAME_MAX + 1] = "";
+
+ if(netdata_thread_tag_exists())
+ strncpyz(threadname, netdata_thread->tag, NETDATA_THREAD_NAME_MAX + 1);
+ else {
+ if(!recheck && threadname[0])
+ return threadname;
+
+#if defined(__FreeBSD__)
+ pthread_get_name_np(pthread_self(), threadname, NETDATA_THREAD_NAME_MAX + 1);
+ if(strcmp(threadname, "netdata") == 0)
+ strncpyz(threadname, "MAIN", NETDATA_THREAD_NAME_MAX + 1);
+#elif defined(__APPLE__)
+ strncpyz(threadname, "MAIN", NETDATA_THREAD_NAME_MAX + 1);
+#elif defined(HAVE_PTHREAD_GETNAME_NP)
+ pthread_getname_np(pthread_self(), threadname, NETDATA_THREAD_NAME_MAX + 1);
+ if(strcmp(threadname, "netdata") == 0)
+ strncpyz(threadname, "MAIN", NETDATA_THREAD_NAME_MAX + 1);
+#else
+ strncpyz(threadname, "MAIN", NETDATA_THREAD_NAME_MAX + 1);
+#endif
+ }
+
+ return threadname;
+}
+
const char *netdata_thread_tag(void) {
- return (netdata_thread_tag_exists() ? netdata_thread->tag : "MAIN");
+ return thread_name_get(false);
+}
+
+static size_t webrtc_id = 0;
+static __thread bool webrtc_name_set = false;
+void webrtc_set_thread_name(void) {
+ if(!netdata_thread && !webrtc_name_set) {
+ webrtc_name_set = true;
+ char threadname[NETDATA_THREAD_NAME_MAX + 1];
+
+#if defined(__FreeBSD__)
+ snprintfz(threadname, NETDATA_THREAD_NAME_MAX, "WEBRTC[%zu]", __atomic_fetch_add(&webrtc_id, 1, __ATOMIC_RELAXED));
+ pthread_set_name_np(pthread_self(), threadname);
+#elif defined(__APPLE__)
+ snprintfz(threadname, NETDATA_THREAD_NAME_MAX, "WEBRTC[%zu]", __atomic_fetch_add(&webrtc_id, 1, __ATOMIC_RELAXED));
+ pthread_setname_np(threadname);
+#elif defined(HAVE_PTHREAD_GETNAME_NP)
+ pthread_getname_np(pthread_self(), threadname, NETDATA_THREAD_NAME_MAX+1);
+ if(strcmp(threadname, "netdata") == 0) {
+ snprintfz(threadname, NETDATA_THREAD_NAME_MAX, "WEBRTC[%zu]", __atomic_fetch_add(&webrtc_id, 1, __ATOMIC_RELAXED));
+ pthread_setname_np(pthread_self(), threadname);
+ }
+#else
+ snprintfz(threadname, NETDATA_THREAD_NAME_MAX, "WEBRTC[%zu]", __atomic_fetch_add(&webrtc_id, 1, __ATOMIC_RELAXED));
+ pthread_setname_np(pthread_self(), threadname);
+#endif
+
+ thread_name_get(true);
+ }
}
// ----------------------------------------------------------------------------
@@ -173,6 +228,8 @@ void uv_thread_set_name_np(uv_thread_t ut, const char* name) {
ret = pthread_setname_np(ut, threadname);
#endif
+ thread_name_get(true);
+
if (ret)
info("cannot set libuv thread name to %s. Err: %d", threadname, ret);
}
diff --git a/libnetdata/threads/threads.h b/libnetdata/threads/threads.h
index ccc18aff0a..ad31b88161 100644
--- a/libnetdata/threads/threads.h
+++ b/libnetdata/threads/threads.h
@@ -43,6 +43,8 @@ int netdata_thread_detach(pthread_t thread);
void uv_thread_set_name_np(uv_thread_t ut, const char* name);
void os_thread_get_current_name_np(char threadname[NETDATA_THREAD_NAME_MAX + 1]);
+void webrtc_set_thread_name(void);
+
#define netdata_thread_self pthread_self
#define netdata_thread_testcancel pthread_testcancel
diff --git a/libnetdata/url/url.c b/libnetdata/url/url.c
index f90b3d5897..7a671946ab 100644
--- a/libnetdata/url/url.c
+++ b/libnetdata/url/url.c
@@ -17,7 +17,7 @@ char to_hex(char code) {
return hex[code & 15];
}
-/* Returns a url-encoded version of str */
+/* Returns an url-encoded version of str */
/* IMPORTANT: be sure to free() the returned string after use */
char *url_encode(char *str) {
char *buf, *pbuf;
@@ -33,8 +33,8 @@ char *url_encode(char *str) {
else{
*pbuf++ = '%';
- *pbuf++ = to_hex(*str >> 4);
- *pbuf++ = to_hex(*str & 15);
+ *pbuf++ = to_hex((char)(*str >> 4));
+ *pbuf++ = to_hex((char)(*str & 15));
}
str++;
@@ -55,9 +55,9 @@ char *url_encode(char *str) {
*
* @return The character decoded on success and 0 otherwise
*/
-char url_percent_escape_decode(char *s) {
+char url_percent_escape_decode(const char *s) {
if(likely(s[1] && s[2]))
- return from_hex(s[1]) << 4 | from_hex(s[2]);
+ return (char)(from_hex(s[1]) << 4 | from_hex(s[2]));
return 0;
}
@@ -98,7 +98,7 @@ char url_utf8_get_byte_length(char c) {
*
* @return count of bytes written to *d
*/
-char url_decode_multibyte_utf8(char *s, char *d, char *d_end) {
+char url_decode_multibyte_utf8(const char *s, char *d, const char *d_end) {
char first_byte = url_percent_escape_decode(s);
if(unlikely(!first_byte || !IS_UTF8_STARTBYTE(first_byte)))
@@ -189,9 +189,9 @@ unsigned char *utf8_check(unsigned char *s)
return NULL;
}
-char *url_decode_r(char *to, char *url, size_t size) {
- char *s = url, // source
- *d = to, // destination
+char *url_decode_r(char *to, const char *url, size_t size) {
+ const char *s = url; // source
+ char *d = to, // destination
*e = &to[size - 1]; // destination end
while(*s && d < e) {
@@ -236,31 +236,45 @@ fail_cleanup:
return NULL;
}
-/**
- * Is request complete?
- *
- * Check whether the request is complete.
- * This function cannot check all the requests METHODS, for example, case you are working with POST, it will fail.
- *
- * @param begin is the first character of the sequence to analyse.
- * @param end is the last character of the sequence
- * @param length is the length of the total of bytes read, it is not the difference between end and begin.
- *
- * @return It returns 1 when the request is complete and 0 otherwise.
- */
-inline int url_is_request_complete(char *begin, char *end, size_t length) {
+inline bool url_is_request_complete(char *begin, char *end, size_t length, char **post_payload, size_t *post_payload_size) {
+ if (begin == end || length < 4)
+ return false;
- if ( begin == end) {
- //Message cannot be complete when first and last address are the same
- return 0;
+ if(likely(strncmp(begin, "GET ", 4)) == 0) {
+ return strstr(end - 4, "\r\n\r\n");
}
+ else if(unlikely(strncmp(begin, "POST ", 5) == 0)) {
+ char *cl = strstr(begin, "Content-Length: ");
+ if(!cl) return false;
+ cl = &cl[16];
- //This math to verify the last is valid, because we are discarding the POST
- if (length > 4) {
- begin = end - 4;
- }
+ size_t content_length = str2ul(cl);
+
+ char *payload = strstr(cl, "\r\n\r\n");
+ if(!payload) return false;
+ payload += 4;
+
+ size_t payload_length = length - (payload - begin);
+
+ if(payload_length == content_length) {
+ if(post_payload && post_payload_size) {
+ if (*post_payload)
+ freez(*post_payload);
+
+ *post_payload = mallocz(payload_length + 1);
+ memcpy(*post_payload, payload, payload_length);
+ (*post_payload)[payload_length] = '\0';
+
+ *post_payload_size = payload_length;
+ }
+ return true;
+ }
- return (strstr(begin, "\r\n\r\n"))?1:0;
+ return false;
+ }
+ else {
+ return strstr(end - 4, "\r\n\r\n");
+ }
}
/**
@@ -283,109 +297,3 @@ inline char *url_find_protocol(char *s) {
return s;
}
-
-/**
- * Map query string
- *
- * Map the query string fields that will be decoded.
- * This functions must be called after to check the presence of query strings,
- * here we are assuming that you already tested this.
- *
- * @param out the pointer to pointers that will be used to map
- * @param url the input url that we are decoding.
- *
- * @return It returns the number of total variables in the query string.
- */
-int url_map_query_string(char **out, char *url) {
- (void)out;
- (void)url;
- int count = 0;
-
- //First we try to parse considering that there was not URL encode process
- char *moveme = url;
- char *ptr;
-
- //We always we have at least one here, so I can set this.
- out[count++] = moveme;
- while(moveme) {
- ptr = strchr((moveme+1), '&');
- if(ptr) {
- out[count++] = ptr;
- }
-
- moveme = ptr;
- }
-
- //I could not find any '&', so I am assuming now it is like '%26'
- if (count == 1) {
- moveme = url;
- while(moveme) {
- ptr = strchr((moveme+1), '%');
- if(ptr) {
- char *test = (ptr+1);
- if (!strncmp(test, "3f", 2) || !strncmp(test, "3F", 2)) {
- out[count++] = ptr;
- }
- }
- moveme = ptr;
- }
- }
-
- return count;
-}
-
-/**
- * Parse query string
- *
- * Parse the query string mapped and store it inside output.
- *
- * @param output is a vector where I will store the string.
- * @param max is the maximum length of the output
- * @param map the map done by the function url_map_query_string.
- * @param total the total number of variables inside map
- *
- * @return It returns 0 on success and -1 otherwise
- */
-int url_parse_query_string(char *output, size_t max, char **map, int total) {
- if(!total) {
- return 0;
- }
-
- int counter, next;
- size_t length;
- char *end;
- char *begin = map[0];
- char save;
- size_t copied = 0;
- for(counter = 0, next=1 ; next <= total ; ++counter, ++next) {
- if (next != total) {
- end = map[next];
- length = (size_t) (end - begin);
- save = *end;
- *end = 0x00;
- } else {
- length = strlen(begin);
- end = NULL;
- }
- length++;
-
- if (length > (max - copied)) {
- error("Parsing query string: we cannot parse a query string so big");
- break;
- }
-
- if(!url_decode_r(output, begin, length)) {
- return -1;
- }
- length = strlen(output);
- copied += length;
- output += length;
-
- begin = end;
- if (begin) {
- *begin = save;
- }
- }
-
- return 0;
-}
diff --git a/libnetdata/url/url.h b/libnetdata/url/url.h
index da0f69ac1c..9db018f0bf 100644
--- a/libnetdata/url/url.h
+++ b/libnetdata/url/url.h
@@ -23,13 +23,9 @@ char *url_encode(char *str);
/* IMPORTANT: be sure to free() the returned string after use */
char *url_decode(char *str);
-char *url_decode_r(char *to, char *url, size_t size);
+char *url_decode_r(char *to, const char *url, size_t size);
-#define WEB_FIELDS_MAX 400
-int url_map_query_string(char **out, char *url);
-int url_parse_query_string(char *output, size_t max, char **map, int total);
-
-int url_is_request_complete(char *begin,char *end,size_t length);
+bool url_is_request_complete(char *begin, char *end, size_t length, char **post_payload, size_t *post_payload_length);
char *url_find_protocol(char *s);
#endif /* NETDATA_URL_H */