diff options
author | Costa Tsaousis <costa@netdata.cloud> | 2023-04-20 20:49:06 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-20 20:49:06 +0300 |
commit | c3d70ffcb43b62c95d71334ed49ad345ddf4360d (patch) | |
tree | 1f6645b504eae7801c8867d3af4d614135aa7602 /libnetdata | |
parent | 5b676d5f912fc27a126ff4ff6ba5b35da9cf930c (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.h | 22 | ||||
-rw-r--r-- | libnetdata/config/appconfig.c | 15 | ||||
-rw-r--r-- | libnetdata/config/appconfig.h | 1 | ||||
-rw-r--r-- | libnetdata/inlined.h | 58 | ||||
-rw-r--r-- | libnetdata/libnetdata.c | 165 | ||||
-rw-r--r-- | libnetdata/libnetdata.h | 10 | ||||
-rw-r--r-- | libnetdata/socket/socket.c | 4 | ||||
-rw-r--r-- | libnetdata/socket/socket.h | 3 | ||||
-rw-r--r-- | libnetdata/threads/threads.c | 59 | ||||
-rw-r--r-- | libnetdata/threads/threads.h | 2 | ||||
-rw-r--r-- | libnetdata/url/url.c | 180 | ||||
-rw-r--r-- | libnetdata/url/url.h | 8 |
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 */ |