From cc577a227d6a5ae8ef75e0fa91ef98ced2d2b743 Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 25 Jul 2018 21:57:49 +0200 Subject: [PATCH] -wip namestore api, changed adding gnsrecord --- src/gnsrecord/Makefile.am | 1 + src/gnsrecord/gnsrecord.c | 127 +++++++++++++++++++ src/include/gnunet_gnsrecord_lib.h | 8 ++ src/include/gnunet_json_lib.h | 65 ---------- src/json/Makefile.am | 3 +- src/json/json_parser.c | 169 -------------------------- src/namestore/plugin_rest_namestore.c | 124 ++++++++----------- 7 files changed, 190 insertions(+), 307 deletions(-) delete mode 100644 src/json/json_parser.c diff --git a/src/gnsrecord/Makefile.am b/src/gnsrecord/Makefile.am index f840a31a4..47d83169f 100644 --- a/src/gnsrecord/Makefile.am +++ b/src/gnsrecord/Makefile.am @@ -39,6 +39,7 @@ libgnunetgnsrecord_la_SOURCES = \ gnsrecord_misc.c libgnunetgnsrecord_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ + -ljansson \ $(GN_LIBINTL) libgnunetgnsrecord_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ diff --git a/src/gnsrecord/gnsrecord.c b/src/gnsrecord/gnsrecord.c index da34846e7..30a0ffa83 100644 --- a/src/gnsrecord/gnsrecord.c +++ b/src/gnsrecord/gnsrecord.c @@ -28,7 +28,9 @@ #include "gnunet_constants.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_gnsrecord_plugin.h" +#include "gnunet_json_lib.h" #include "gnunet_tun_lib.h" +#include #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) @@ -245,5 +247,130 @@ GNUNET_GNSRECORD_number_to_typename (uint32_t type) return NULL; } +/** + * Parse given JSON object to gns record + * + * @param cls closure, NULL + * @param root the json object representing data + * @param spec where to write the data + * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error + */ +static int +parse_gnsrecordobject (void *cls, + json_t *root, + struct GNUNET_JSON_Specification *spec) +{ + struct GNUNET_GNSRECORD_Data *gnsrecord_object; + struct GNUNET_TIME_Absolute abs_expiration_time; + int unpack_state=0; + const char *data; + const char *expiration_date; + const char *record_type; + const char *dummy_value; + int flag; + void *rdata; + size_t rdata_size; + + if(!json_is_object(root)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Error json is not array nor object!\n"); + return GNUNET_SYSERR; + } + //interpret single gns record + unpack_state = json_unpack(root, + "{s:s, s:s, s:s, s?:i, s:s!}", + "value", &data, + "type", &record_type, + "expiration_time", &expiration_date, + "flag", &flag, + "label", &dummy_value); + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "{value:%s, type:%s, expire:%s, flag:%i}", + data, + record_type, + expiration_date, + flag); + if (GNUNET_SYSERR == unpack_state) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "Error json object has a wrong format!\n"); + return GNUNET_SYSERR; + } + //TODO test + gnsrecord_object = GNUNET_new (struct GNUNET_GNSRECORD_Data); + gnsrecord_object->record_type = GNUNET_GNSRECORD_typename_to_number(record_type); + if (GNUNET_OK + != GNUNET_GNSRECORD_string_to_value (gnsrecord_object->record_type, + data, &rdata, + &rdata_size)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR,"Value invalid for record type"); + return GNUNET_SYSERR; + } + gnsrecord_object->data = rdata; + gnsrecord_object->data_size = rdata_size; + + if (0 == strcmp (expiration_date, "never")) + { + gnsrecord_object->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; + } + else if (GNUNET_OK + == GNUNET_STRINGS_fancy_time_to_absolute (expiration_date, + &abs_expiration_time)) + { + gnsrecord_object->expiration_time = abs_expiration_time.abs_value_us; + } + else + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Value invalid for record type"); + return GNUNET_SYSERR; + } + gnsrecord_object->flags = (enum GNUNET_GNSRECORD_Flags)flag; + *(struct GNUNET_GNSRECORD_Data **) spec->ptr = gnsrecord_object; + return GNUNET_OK; +} + +/** + * Cleanup data left from parsing RSA public key. + * + * @param cls closure, NULL + * @param[out] spec where to free the data + */ +static void +clean_gnsrecordobject (void *cls, struct GNUNET_JSON_Specification *spec) +{ + struct GNUNET_GNSRECORD_Data **gnsrecord_object; + gnsrecord_object = (struct GNUNET_GNSRECORD_Data **) spec->ptr; + if (NULL != *gnsrecord_object) + { + if (NULL != (*gnsrecord_object)->data) + GNUNET_free((char*)(*gnsrecord_object)->data); + GNUNET_free(*gnsrecord_object); + *gnsrecord_object = NULL; + } +} + +/** + * JSON Specification for GNS Records. + * + * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill + * @return JSON Specification + */ +struct GNUNET_JSON_Specification +GNUNET_JSON_spec_gnsrecord_data (struct GNUNET_GNSRECORD_Data **gnsrecord_object) +{ + struct GNUNET_JSON_Specification ret = { + .parser = &parse_gnsrecordobject, + .cleaner = &clean_gnsrecordobject, + .cls = NULL, + .field = NULL, + .ptr = gnsrecord_object, + .ptr_size = 0, + .size_ptr = NULL + }; + *gnsrecord_object = NULL; + return ret; +} /* end of gnsrecord.c */ diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h index 20846238b..2eaa304de 100644 --- a/src/include/gnunet_gnsrecord_lib.h +++ b/src/include/gnunet_gnsrecord_lib.h @@ -447,6 +447,14 @@ GNUNET_GNSRECORD_records_deserialize (size_t len, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *dest); +/** + * JSON Specification for GNS Records. + * + * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill + * @return JSON Specification + */ +struct GNUNET_JSON_Specification +GNUNET_JSON_spec_gnsrecord_data (struct GNUNET_GNSRECORD_Data **gnsrecord_object); /* ******* general APIs relating to blocks, records and labels ******** */ diff --git a/src/include/gnunet_json_lib.h b/src/include/gnunet_json_lib.h index 6340d1f41..4855f21b4 100644 --- a/src/include/gnunet_json_lib.h +++ b/src/include/gnunet_json_lib.h @@ -479,71 +479,6 @@ GNUNET_JSON_getopt (char shortName, const char *description, json_t **json); -/* ****************** GETOPT JSON parser ******************* */ - -struct GNUNET_REST_JSON_Data -{ - /** - * Public key of an identity - */ - char *pubkey; - - /** - * Name - */ - char *name; - - /** - * Nickname - */ - char *nickname; - - /** - * New name - */ - char *new_name; - - /** - * Name of subsystem - */ - char *subsystem; - - /** - * Should data be handled as public (GNUNET_YES or GNUNET_NO) - */ - int is_public; - - /** - * Expiration date of data - */ - char *expiration_time; - - /** - * Type of data - */ - char *type; - - /** - * Value of data - */ - char *value; - - /** - * Zone - */ - char *zone; -}; -/* - * Test - */ -int -GNUNET_REST_JSON_parse (struct GNUNET_REST_JSON_Data** rest_json_data, - json_t *json_data); - -int -GNUNET_REST_JSON_free (struct GNUNET_REST_JSON_Data* rest_json_data); - - #endif /* end of gnunet_json_lib.h */ diff --git a/src/json/Makefile.am b/src/json/Makefile.am index 5aac23654..16c0450d9 100644 --- a/src/json/Makefile.am +++ b/src/json/Makefile.am @@ -16,8 +16,7 @@ libgnunetjson_la_SOURCES = \ json.c \ json_mhd.c \ json_generator.c \ - json_helper.c \ - json_parser.c + json_helper.c libgnunetjson_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ -ljansson \ diff --git a/src/json/json_parser.c b/src/json/json_parser.c deleted file mode 100644 index cfe553b34..000000000 --- a/src/json/json_parser.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2014, 2015, 2016 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - or (at your option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -/** - * @file json/json_helper.c - * @brief functions for REST JSON parsing - * @author Philippe Buschmann - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_json_lib.h" - -#define GNUNET_REST_JSON_PUBKEY_ENTRY "pubkey" -#define GNUNET_REST_JSON_NAME_ENTRY "name" -#define GNUNET_REST_JSON_NICKNAME_ENTRY "nickname" -#define GNUNET_REST_JSON_NEWNAME_ENTRY "newname" -#define GNUNET_REST_JSON_SUBSYSTEM_ENTRY "subsystem" -#define GNUNET_REST_JSON_IS_PUBLIC_ENTRY "is_public" -#define GNUNET_REST_JSON_EXPIRATION_DATE_ENTRY "expiration_time" -#define GNUNET_REST_JSON_TYPE_ENTRY "type" -#define GNUNET_REST_JSON_VALUE_ENTRY "value" -#define GNUNET_REST_JSON_ZONE_ENTRY "zone" - - -int -GNUNET_REST_JSON_parse (struct GNUNET_REST_JSON_Data** output_data ,json_t *json_data) -{ - struct GNUNET_REST_JSON_Data *rest_json_data; - json_t *cache; - - rest_json_data = GNUNET_malloc(sizeof(struct GNUNET_REST_JSON_Data)); - - cache = json_object_get (json_data, GNUNET_REST_JSON_EXPIRATION_DATE_ENTRY); - rest_json_data->expiration_time = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->expiration_time = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_NAME_ENTRY); - rest_json_data->name = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->name = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_NEWNAME_ENTRY); - rest_json_data->new_name = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->new_name = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_NICKNAME_ENTRY); - rest_json_data->nickname = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->nickname = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_PUBKEY_ENTRY); - rest_json_data->pubkey = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->pubkey = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_SUBSYSTEM_ENTRY); - rest_json_data->subsystem = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->subsystem = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_TYPE_ENTRY); - rest_json_data->type = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->type = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_VALUE_ENTRY); - rest_json_data->value = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->value = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_ZONE_ENTRY); - rest_json_data->zone = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->zone = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_IS_PUBLIC_ENTRY); - if (NULL != cache) - { - if (json_is_integer(cache)) - { - rest_json_data->is_public = json_integer_value(cache); - } - } - *output_data = rest_json_data; - return GNUNET_OK; -} - - - -int -GNUNET_REST_JSON_free (struct GNUNET_REST_JSON_Data* rest_json_data) -{ - if (rest_json_data != NULL) - { - GNUNET_free_non_null(rest_json_data->expiration_time); - GNUNET_free_non_null(rest_json_data->name); - GNUNET_free_non_null(rest_json_data->new_name); - GNUNET_free_non_null(rest_json_data->nickname); - GNUNET_free_non_null(rest_json_data->pubkey); - GNUNET_free_non_null(rest_json_data->subsystem); - GNUNET_free_non_null(rest_json_data->type); - GNUNET_free_non_null(rest_json_data->value); - GNUNET_free_non_null(rest_json_data->zone); - } - GNUNET_free_non_null(rest_json_data); - return GNUNET_OK; -} - - - - - - - - - diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c index ab490c04f..afe010b79 100644 --- a/src/namestore/plugin_rest_namestore.c +++ b/src/namestore/plugin_rest_namestore.c @@ -2,20 +2,18 @@ This file is part of GNUnet. Copyright (C) 2012-2015 GNUnet e.V. - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Affero General Public License for more details. - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ /** * @author Martin Schanzenbach @@ -42,6 +40,7 @@ #define GNUNET_REST_JSON_NAMESTORE_VALUE "value" #define GNUNET_REST_JSON_NAMESTORE_EXPIRATION "expiration" #define GNUNET_REST_JSON_NAMESTORE_EXPIRED "expired" +#define GNUNET_REST_ERROR_UNKNOWN "Unknown Error" #define GNUNET_REST_NAMESTORE_RD_COUNT 1 @@ -96,17 +95,17 @@ struct RequestHandle /** * Records to store */ - struct GNUNET_GNSRECORD_Data *rd; + char *label_name; /** - * NAMESTORE Operation + * Records to store */ - struct GNUNET_NAMESTORE_QueueEntry *add_qe; + struct GNUNET_GNSRECORD_Data *rd; /** - * JSON data parser + * NAMESTORE Operation */ - struct GNUNET_REST_JSON_Data *json_data; + struct GNUNET_NAMESTORE_QueueEntry *add_qe; /** * Response object @@ -192,8 +191,9 @@ struct RequestHandle * @param handle Handle to clean up */ static void -cleanup_handle (struct RequestHandle *handle) +cleanup_handle (void *cls) { + struct RequestHandle *handle = cls; size_t index; json_t *json_ego; @@ -204,6 +204,8 @@ cleanup_handle (struct RequestHandle *handle) GNUNET_SCHEDULER_cancel (handle->timeout_task); handle->timeout_task = NULL; } + if (NULL != handle->label_name) + GNUNET_free(handle->label_name); if (NULL != handle->url) GNUNET_free(handle->url); if (NULL != handle->emsg) @@ -243,9 +245,6 @@ cleanup_handle (struct RequestHandle *handle) } json_decref(handle->resp_object); } - - if (NULL != handle->json_data) - GNUNET_REST_JSON_free(handle->json_data); GNUNET_free (handle); } @@ -261,20 +260,22 @@ do_error (void *cls) { struct RequestHandle *handle = cls; struct MHD_Response *resp; - char *json_error; + json_t *json_error = json_object(); + char *response; if (NULL == handle->emsg) - handle->emsg = GNUNET_strdup("Unknown Error"); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN); + + json_object_set_new(json_error,"error", json_string(handle->emsg)); - GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); - if (0 == handle->response_code) handle->response_code = MHD_HTTP_OK; - - resp = GNUNET_REST_create_response (json_error); + response = json_dumps (json_error, 0); + resp = GNUNET_REST_create_response (response); handle->proc (handle->proc_cls, resp, handle->response_code); - cleanup_handle (handle); - GNUNET_free(json_error); + json_decref(json_error); + GNUNET_free(response); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } /** @@ -287,7 +288,7 @@ namestore_iteration_error (void *cls) struct MHD_Response *resp = GNUNET_REST_create_response (NULL); handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; handle->proc (handle->proc_cls, resp, handle->response_code); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } /** @@ -360,7 +361,7 @@ create_finished (void *cls, int32_t success, const char *emsg) } resp = GNUNET_REST_create_response (NULL); handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); - cleanup_handle(handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } /** @@ -391,7 +392,7 @@ namestore_list_finished (void *cls) resp = GNUNET_REST_create_response (result_str); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); GNUNET_free_non_null (result_str); - cleanup_handle(handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } @@ -476,34 +477,7 @@ namestore_get (struct GNUNET_REST_RequestHandle *con_handle, &namestore_list_finished, handle); } - -int -check_needed_data(struct RequestHandle *handle){ - if(NULL == handle->json_data->name) - { - handle->emsg = GNUNET_strdup("Missing JSON parameter: name"); - return GNUNET_SYSERR; - } - - if(NULL == handle->json_data->type) - { - handle->emsg = GNUNET_strdup("Missing JSON parameter: type"); - return GNUNET_SYSERR; - } - - if(NULL == handle->json_data->value) - { - handle->emsg = GNUNET_strdup("Missing JSON parameter: value"); - return GNUNET_SYSERR; - } - - if(NULL == handle->json_data->expiration_time) - { - handle->emsg = GNUNET_strdup("Missing JSON parameter: expiration time"); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} +/* //TODO filter input static int @@ -544,7 +518,7 @@ json_to_gnsrecord (struct RequestHandle *handle) rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; if (1 != handle->is_public) rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; - */ + * if (0 == strcmp (handle->json_data->expiration_time, "never")) { (*handle->rd).expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; @@ -569,7 +543,7 @@ json_to_gnsrecord (struct RequestHandle *handle) } return GNUNET_OK; } - +*/ /** * We're storing a new record; this requires @@ -590,8 +564,9 @@ create_new_record_cont (void *cls, { struct RequestHandle *handle = cls; + handle->add_qe = NULL; - if (0 != strcmp (rec_name, handle->json_data->name)) + if (0 != strcmp (rec_name, handle->label_name)) { GNUNET_break (0); do_error (handle); @@ -603,19 +578,18 @@ create_new_record_cont (void *cls, handle->proc (handle->proc_cls, GNUNET_REST_create_response (NULL), MHD_HTTP_CONFLICT); - cleanup_handle(handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); return; } handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, &handle->zone_pkey, - handle->json_data->name, + handle->label_name, GNUNET_REST_NAMESTORE_RD_COUNT, handle->rd, &create_finished, handle); } - /** * Handle namestore POST request * @@ -629,9 +603,15 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle, void *cls) { struct RequestHandle *handle = cls; + struct GNUNET_GNSRECORD_Data *gns_record; json_t *data_js; + json_t *name_json; json_error_t err; char term_data[handle->rest_handle->data_size + 1]; + struct GNUNET_JSON_Specification gnsspec[] = { + GNUNET_JSON_spec_gnsrecord_data(&gns_record), + GNUNET_JSON_spec_end () + }; if (strlen (GNUNET_REST_API_NS_NAMESTORE) != strlen (handle->url)) { @@ -649,24 +629,26 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_memcpy(term_data, handle->rest_handle->data, handle->rest_handle->data_size); data_js = json_loads (term_data, JSON_DECODE_ANY, &err); - GNUNET_REST_JSON_parse(&handle->json_data, data_js); - if(NULL == handle->json_data) + GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL)); + name_json = json_object_get(data_js, "label"); + if (!json_is_string(name_json)) { - handle->emsg = GNUNET_strdup("Wrong data"); + handle->emsg = GNUNET_strdup("Missing name"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - if(GNUNET_SYSERR == check_needed_data(handle)) + handle->label_name = GNUNET_strdup(json_string_value(name_json)); + if(NULL == handle->label_name) { - json_decref (data_js); + handle->emsg = GNUNET_strdup("Missing name"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } json_decref (data_js); - json_to_gnsrecord (handle); + handle->rd = gns_record; handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, &handle->zone_pkey, - handle->json_data->name, + handle->label_name, &do_error, handle, &create_new_record_cont, @@ -718,7 +700,7 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, "Access-Control-Allow-Methods", allow_methods); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); return; } -- 2.25.1