diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-11-25 17:33:56 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-11-25 17:34:10 +0000 |
commit | 83ba6762cc43d9db581b979bb5e3445669e46cc2 (patch) | |
tree | 2e69833b43f791ed253a7a20318b767ebe56cdb8 /src/libnetdata/json | |
parent | Releasing debian version 1.47.5-1. (diff) | |
download | netdata-83ba6762cc43d9db581b979bb5e3445669e46cc2.tar.xz netdata-83ba6762cc43d9db581b979bb5e3445669e46cc2.zip |
Merging upstream version 2.0.3+dfsg (Closes: #923993, #1042533, #1045145).
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/libnetdata/json')
-rw-r--r-- | src/libnetdata/json/README.md | 9 | ||||
-rw-r--r-- | src/libnetdata/json/json-c-parser-inline.c | 52 | ||||
-rw-r--r-- | src/libnetdata/json/json-c-parser-inline.h | 69 |
3 files changed, 117 insertions, 13 deletions
diff --git a/src/libnetdata/json/README.md b/src/libnetdata/json/README.md index 9ae5ff382..21cd42a79 100644 --- a/src/libnetdata/json/README.md +++ b/src/libnetdata/json/README.md @@ -1,12 +1,3 @@ -<!-- -title: "json" -custom_edit_url: https://github.com/netdata/netdata/edit/master/src/libnetdata/json/README.md -sidebar_label: "json" -learn_status: "Published" -learn_topic_type: "Tasks" -learn_rel_path: "Developers/libnetdata" ---> - # json `json` contains a parser for json strings, based on `jsmn` (<https://github.com/zserge/jsmn>), but case you have installed the JSON-C library, the installation script will prefer it, you can also force its use with `--enable-jsonc` in the compilation time. diff --git a/src/libnetdata/json/json-c-parser-inline.c b/src/libnetdata/json/json-c-parser-inline.c new file mode 100644 index 000000000..a17847a3e --- /dev/null +++ b/src/libnetdata/json/json-c-parser-inline.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +int rrd_call_function_error(BUFFER *wb, const char *msg, int code) { + buffer_reset(wb); + buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_MINIFY); + buffer_json_member_add_int64(wb, "status", code); + buffer_json_member_add_string(wb, "error_message", msg); + buffer_json_finalize(wb); + wb->date = now_realtime_sec(); + wb->expires = wb->date + 1; + wb->response_code = code; + return code; +} + +struct json_object *json_parse_function_payload_or_error(BUFFER *output, BUFFER *payload, int *code, json_parse_function_payload_t cb, void *cb_data) { + if(!payload || !buffer_strlen(payload)) { + *code = rrd_call_function_error(output, "No payload given, but a payload is required for this feature.", HTTP_RESP_BAD_REQUEST); + return NULL; + } + + struct json_tokener *tokener = json_tokener_new(); + if (!tokener) { + *code = rrd_call_function_error(output, "Failed to initialize json parser.", HTTP_RESP_INTERNAL_SERVER_ERROR); + return NULL; + } + + struct json_object *jobj = json_tokener_parse_ex(tokener, buffer_tostring(payload), (int)buffer_strlen(payload)); + if (json_tokener_get_error(tokener) != json_tokener_success) { + const char *error_msg = json_tokener_error_desc(json_tokener_get_error(tokener)); + char tmp[strlen(error_msg) + 100]; + snprintf(tmp, sizeof(tmp), "JSON parser failed: %s", error_msg); + json_tokener_free(tokener); + *code = rrd_call_function_error(output, tmp, HTTP_RESP_INTERNAL_SERVER_ERROR); + return NULL; + } + json_tokener_free(tokener); + + CLEAN_BUFFER *error = buffer_create(0, NULL); + if(!cb(jobj, "", cb_data, error)) { + char tmp[buffer_strlen(error) + 100]; + snprintfz(tmp, sizeof(tmp), "JSON parser failed: %s", buffer_tostring(error)); + *code = rrd_call_function_error(output, tmp, HTTP_RESP_BAD_REQUEST); + json_object_put(jobj); + return NULL; + } + + *code = HTTP_RESP_OK; + + return jobj; +} diff --git a/src/libnetdata/json/json-c-parser-inline.h b/src/libnetdata/json/json-c-parser-inline.h index c1d60ca45..e51cb232e 100644 --- a/src/libnetdata/json/json-c-parser-inline.h +++ b/src/libnetdata/json/json-c-parser-inline.h @@ -25,6 +25,45 @@ } \ } while(0) +#define JSONC_PARSE_TXT2STRDUPZ_OR_ERROR_AND_RETURN(jobj, path, member, dst, error, required) do { \ + json_object *_j; \ + if (json_object_object_get_ex(jobj, member, &_j) && json_object_is_type(_j, json_type_string)) { \ + freez((void *)dst); \ + dst = strdupz(json_object_get_string(_j)); \ + } \ + else if(required) { \ + buffer_sprintf(error, "missing or invalid type for '%s.%s' string", path, member); \ + return false; \ + } \ +} while(0) + +#define JSONC_PARSE_TXT2UUID_OR_ERROR_AND_RETURN(jobj, path, member, dst, error, required) do { \ + json_object *_j; \ + if (json_object_object_get_ex(jobj, member, &_j)) { \ + if (json_object_is_type(_j, json_type_string)) { \ + if (uuid_parse(json_object_get_string(_j), dst) != 0) { \ + if(required) { \ + buffer_sprintf(error, "invalid UUID '%s.%s'", path, member); \ + return false; \ + } \ + else \ + uuid_clear(dst); \ + } \ + } \ + else if (json_object_is_type(_j, json_type_null)) { \ + uuid_clear(dst); \ + } \ + else if (required) { \ + buffer_sprintf(error, "expected UUID or null '%s.%s'", path, member); \ + return false; \ + } \ + } \ + else if (required) { \ + buffer_sprintf(error, "missing UUID '%s.%s'", path, member); \ + return false; \ + } \ +} while(0) + #define JSONC_PARSE_TXT2BUFFER_OR_ERROR_AND_RETURN(jobj, path, member, dst, error, required) do { \ json_object *_j; \ if (json_object_object_get_ex(jobj, member, &_j) && json_object_is_type(_j, json_type_string)) { \ @@ -111,7 +150,6 @@ } \ } while(0) - #define JSONC_PARSE_TXT2ENUM_OR_ERROR_AND_RETURN(jobj, path, member, converter, dst, error, required) do { \ json_object *_j; \ if (json_object_object_get_ex(jobj, member, &_j) && json_object_is_type(_j, json_type_string)) \ @@ -122,11 +160,11 @@ } \ } while(0) -#define JSONC_PARSE_INT_OR_ERROR_AND_RETURN(jobj, path, member, dst, error, required) do { \ +#define JSONC_PARSE_INT64_OR_ERROR_AND_RETURN(jobj, path, member, dst, error, required) do { \ json_object *_j; \ if (json_object_object_get_ex(jobj, member, &_j)) { \ if (_j != NULL && json_object_is_type(_j, json_type_int)) \ - dst = json_object_get_int(_j); \ + dst = json_object_get_int64(_j); \ else if (_j != NULL && json_object_is_type(_j, json_type_double)) \ dst = (typeof(dst))json_object_get_double(_j); \ else if (_j == NULL) \ @@ -136,7 +174,26 @@ return false; \ } \ } else if(required) { \ - buffer_sprintf(error, "missing or invalid type (expected int value or null) for '%s.%s'", path, member); \ + buffer_sprintf(error, "missing or invalid type (expected int value or null) for '%s.%s'", path, member);\ + return false; \ + } \ +} while(0) + +#define JSONC_PARSE_UINT64_OR_ERROR_AND_RETURN(jobj, path, member, dst, error, required) do { \ + json_object *_j; \ + if (json_object_object_get_ex(jobj, member, &_j)) { \ + if (_j != NULL && json_object_is_type(_j, json_type_int)) \ + dst = json_object_get_uint64(_j); \ + else if (_j != NULL && json_object_is_type(_j, json_type_double)) \ + dst = (typeof(dst))json_object_get_double(_j); \ + else if (_j == NULL) \ + dst = 0; \ + else { \ + buffer_sprintf(error, "not supported type (expected int) for '%s.%s'", path, member); \ + return false; \ + } \ + } else if(required) { \ + buffer_sprintf(error, "missing or invalid type (expected int value or null) for '%s.%s'", path, member);\ return false; \ } \ } while(0) @@ -174,4 +231,8 @@ } \ } while(0) +typedef bool (*json_parse_function_payload_t)(json_object *jobj, const char *path, void *data, BUFFER *error); +int rrd_call_function_error(BUFFER *wb, const char *msg, int code); +struct json_object *json_parse_function_payload_or_error(BUFFER *output, BUFFER *payload, int *code, json_parse_function_payload_t cb, void *cb_data); + #endif //NETDATA_JSON_C_PARSER_INLINE_H |