From: Phil Date: Thu, 26 Jul 2018 00:31:30 +0000 (+0200) Subject: change namestore, json handling; fix identity, gns X-Git-Tag: v0.11.0~319^2~14 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=f7ca27a73e69a8c224d65768be3416ff1388c1d7;p=oweals%2Fgnunet.git change namestore, json handling; fix identity, gns --- diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c index 22c908275..aae14153d 100644 --- a/src/gns/plugin_rest_gns.c +++ b/src/gns/plugin_rest_gns.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 Philippe Buschmann @@ -36,6 +34,7 @@ #define GNUNET_REST_PARAMETER_GNS_NAME "name" #define GNUNET_REST_PARAMETER_GNS_RECORD_TYPE "record_type" +#define GNUNET_REST_GNS_ERROR_UNKNOWN "Unknown Error" /** * The configuration handle @@ -128,8 +127,9 @@ struct RequestHandle * @param handle Handle to clean up */ static void -cleanup_handle (struct RequestHandle *handle) +cleanup_handle (void *cls) { + struct RequestHandle *handle = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); @@ -170,20 +170,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_GNS_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); } @@ -201,6 +203,7 @@ handle_gns_response (void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd) { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "TEST4\n"); struct RequestHandle *handle = cls; struct MHD_Response *resp; json_t *result_array; @@ -216,12 +219,6 @@ handle_gns_response (void *cls, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - if (0 == rd_count) - { - handle->emsg = GNUNET_strdup("No result found"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } result_array = json_array(); for (uint32_t i=0;iproc (handle->proc_cls, resp, MHD_HTTP_OK); GNUNET_free (result); json_decref (result_array); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now(&cleanup_handle, handle); } @@ -264,7 +261,8 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, { struct RequestHandle *handle = cls; struct GNUNET_HashCode key; - int conversion_state; + char *record_type; + char *name; GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME, strlen (GNUNET_REST_PARAMETER_GNS_NAME), @@ -277,8 +275,14 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - handle->name = GNUNET_strdup( - GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,&key)); + name = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,&key); + if(0 >= strlen (name)) + { + handle->emsg = GNUNET_strdup("Length of parameter name is zero"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->name = GNUNET_strdup(name); GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE, strlen (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE), @@ -291,11 +295,13 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - conversion_state = sscanf ( - GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key),"%u", - &(handle->record_type)); - if((EOF == conversion_state) || (0 == conversion_state)) + + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "TEST1\n"); + + record_type = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key); + handle->record_type = GNUNET_GNSRECORD_typename_to_number(record_type); + if(UINT32_MAX == handle->record_type) { handle->record_type = GNUNET_GNSRECORD_TYPE_ANY; } @@ -307,6 +313,7 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "TEST2\n"); handle->gns_lookup = GNUNET_GNS_lookup_with_tld (handle->gns, handle->name, @@ -314,13 +321,7 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_NO, &handle_gns_response, handle); - - if (NULL == handle->gns_lookup) - { - handle->emsg = GNUNET_strdup("GNS lookup failed"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } + return; } @@ -346,7 +347,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; } diff --git a/src/gns/plugin_rest_gns2.c b/src/gns/plugin_rest_gns2.c deleted file mode 100644 index 82d62744c..000000000 --- a/src/gns/plugin_rest_gns2.c +++ /dev/null @@ -1,717 +0,0 @@ -/* - 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 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 . - */ -/** - * @author Martin Schanzenbach - * @author Philippe Buschmann - * @file gns/plugin_rest_gns.c - * @brief GNUnet GNS REST plugin - * - */ - -#include "platform.h" -#include "gnunet_rest_plugin.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define GNUNET_REST_API_NS_GNS "/gns" - -#define GNUNET_REST_JSONAPI_GNS_RECORD_TYPE "record_type" - -#define GNUNET_REST_PARAMETER_GNS_NAME "name" - -#define GNUNET_REST_JSONAPI_GNS_TYPEINFO "gns_name" - -#define GNUNET_REST_JSONAPI_GNS_RECORD "records" - -#define GNUNET_REST_JSONAPI_GNS_EGO "ego" - -#define GNUNET_REST_JSONAPI_GNS_PKEY "pkey" - -#define GNUNET_REST_JSONAPI_GNS_OPTIONS "options" - -/** - * @brief struct returned by the initialization function of the plugin - */ -struct Plugin -{ - const struct GNUNET_CONFIGURATION_Handle *cfg; -}; - -const struct GNUNET_CONFIGURATION_Handle *cfg; - -struct LookupHandle -{ - /** - * Handle to GNS service. - */ - struct GNUNET_GNS_Handle *gns; - - /** - * Desired timeout for the lookup (default is no timeout). - */ - struct GNUNET_TIME_Relative timeout; - - /** - * Handle to lookup request - */ - struct GNUNET_GNS_LookupRequest *lookup_request; - - /** - * Handle to rest request - */ - struct GNUNET_REST_RequestHandle *rest_handle; - - /** - * Lookup an ego with the identity service. - */ - struct GNUNET_IDENTITY_EgoLookup *el; - - /** - * Handle for identity service. - */ - struct GNUNET_IDENTITY_Handle *identity; - - /** - * Active operation on identity service. - */ - struct GNUNET_IDENTITY_Operation *id_op; - - /** - * ID of a task associated with the resolution process. - */ - struct GNUNET_SCHEDULER_Task * timeout_task; - - /** - * The root of the received JSON or NULL - */ - json_t *json_root; - - /** - * The plugin result processor - */ - GNUNET_REST_ResultProcessor proc; - - /** - * The closure of the result processor - */ - void *proc_cls; - - /** - * The name to look up - */ - char *name; - - /** - * The ego to use - * In string representation from JSON - */ - const char *ego_str; - - /** - * The Pkey to use - * In string representation from JSON - */ - const char *pkey_str; - - /** - * The record type - */ - int type; - - /** - * The public key of to use for lookup - */ - struct GNUNET_CRYPTO_EcdsaPublicKey pkey; - - /** - * The public key to use for lookup - */ - struct GNUNET_CRYPTO_EcdsaPublicKey pkeym; - - /** - * The resolver options - */ - enum GNUNET_GNS_LocalOptions options; - - /** - * the shorten key - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key; - - /** - * HTTP response code - */ - int response_code; - - /** - * HTTP response code - */ - char* emsg; - -}; - - -/** - * Cleanup lookup handle. - * - * @param handle Handle to clean up - */ -static void -cleanup_handle (struct LookupHandle *handle) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Cleaning up\n"); - if (NULL != handle->json_root) - json_decref (handle->json_root); - - if (NULL != handle->name) - GNUNET_free (handle->name); - if (NULL != handle->emsg) - GNUNET_free (handle->emsg); - if (NULL != handle->el) - { - GNUNET_IDENTITY_ego_lookup_cancel (handle->el); - handle->el = NULL; - } - if (NULL != handle->id_op) - { - GNUNET_IDENTITY_cancel (handle->id_op); - handle->id_op = NULL; - } - if (NULL != handle->lookup_request) - { - GNUNET_GNS_lookup_cancel (handle->lookup_request); - handle->lookup_request = NULL; - } - if (NULL != handle->identity) - { - GNUNET_IDENTITY_disconnect (handle->identity); - handle->identity = NULL; - } - if (NULL != handle->gns) - { - GNUNET_GNS_disconnect (handle->gns); - handle->gns = NULL; - } - - if (NULL != handle->timeout_task) - { - GNUNET_SCHEDULER_cancel (handle->timeout_task); - } - GNUNET_free (handle); -} - - -/** - * Task run on shutdown. Cleans up everything. - * - * @param cls unused - * @param tc scheduler context - */ -static void -do_error (void *cls) -{ - struct LookupHandle *handle = cls; - struct MHD_Response *resp; - char *json_error; - - if (NULL == handle->emsg) - handle->emsg = GNUNET_strdup("Unknown Error"); - - GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); - handle->response_code = MHD_HTTP_OK; - - resp = GNUNET_REST_create_response (json_error); - handle->proc (handle->proc_cls, resp, handle->response_code); - cleanup_handle (handle); - GNUNET_free(json_error); -} - - -/** - * Create json representation of a GNSRECORD - * - * @param rd the GNSRECORD_Data - */ -static json_t * -gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) -{ - const char *typename; - char *string_val; - const char *exp_str; - json_t *record_obj; - - typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type); - string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type, - rd->data, - rd->data_size); - - if (NULL == string_val) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Record of type %d malformed, skipping\n", - (int) rd->record_type); - return NULL; - } - record_obj = json_object (); - json_object_set_new (record_obj, "type", json_string (typename)); - json_object_set_new (record_obj, "value", json_string (string_val)); - GNUNET_free (string_val); - - if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags) - { - struct GNUNET_TIME_Relative time_rel; - time_rel.rel_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1); - } - else - { - struct GNUNET_TIME_Absolute time_abs; - time_abs.abs_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs); - } - json_object_set_new (record_obj, "expiration_time", json_string (exp_str)); - - json_object_set_new (record_obj, "expired", - json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd))); - return record_obj; -} - -/** - * Function called with the result of a GNS lookup. - * - * @param cls the 'const char *' name that was resolved - * @param rd_count number of records returned - * @param rd array of @a rd_count records with the results - */ -static void -process_lookup_result (void *cls, uint32_t rd_count, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct LookupHandle *handle = cls; - struct MHD_Response *resp; - uint32_t i; - char *result; - json_t *result_array; - json_t *record_obj; - - result_array = json_array(); - handle->lookup_request = NULL; - for (i=0; itype) && - (GNUNET_GNSRECORD_TYPE_ANY != handle->type) ) - continue; - record_obj = gnsrecord_to_json (&(rd[i])); - json_array_append (result_array, record_obj); - json_decref (record_obj); - } - result = json_dumps(result_array, 0); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result); - resp = GNUNET_REST_create_response (result); - handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - GNUNET_free (result); - json_decref (result_array); - cleanup_handle (handle); -} - - -/** - * Perform the actual resolution, starting with the zone - * identified by the given public key and the shorten zone. - * - * @param pkey public key to use for the zone, can be NULL - */ -static void -lookup_with_public_key (struct LookupHandle *handle) -{ - if (UINT32_MAX == handle->type) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Invalid typename specified, assuming `ANY'\n")); - handle->type = GNUNET_GNSRECORD_TYPE_ANY; - } - if (NULL != handle->name) - { - handle->lookup_request = GNUNET_GNS_lookup (handle->gns, - handle->name, - &handle->pkey, - handle->type, - handle->options, - &process_lookup_result, - handle); - } - else - { - handle->emsg = GNUNET_strdup("Parameter name is missing"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } -} - - -/** - * Method called to with the ego we are to use for the lookup, - * when the ego is determined by a name. - * - * @param cls closure (NULL, unused) - * @param ego ego handle, NULL if not found - */ -static void -identity_zone_cb (void *cls, - const struct GNUNET_IDENTITY_Ego *ego) -{ - struct LookupHandle *handle = cls; - - handle->el = NULL; - if (NULL == ego) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Ego for not found, cannot perform lookup.\n")); - handle->emsg = GNUNET_strdup ("Ego for not found, cannot perform lookup."); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - else - { - GNUNET_IDENTITY_ego_get_public_key (ego, &handle->pkey); - lookup_with_public_key (handle); - } - json_decref(handle->json_root); -} - - -/** - * Method called to with the ego we are to use for the lookup, - * when the ego is the one for the default master zone. - * - * @param cls closure (NULL, unused) - * @param ego ego handle, NULL if not found - * @param ctx context for application to store data for this ego - * (during the lifetime of this process, initially NULL) - * @param name name assigned by the user for this ego, - * NULL if the user just deleted the ego and it - * must thus no longer be used - */ -static void -identity_master_cb (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *name) -{ - const char *dot; - struct LookupHandle *handle = cls; - - handle->id_op = NULL; - if (NULL == ego) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n")); - handle->emsg = GNUNET_strdup("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - GNUNET_IDENTITY_ego_get_public_key (ego, - &handle->pkey); - /* main name is our own master zone, do no look for that in the DHT */ - handle->options = GNUNET_GNS_LO_LOCAL_MASTER; - /* if the name is of the form 'label.gnu', never go to the DHT */ - dot = NULL; - if (NULL != handle->name) - dot = strchr (handle->name, '.'); - if ( (NULL != dot) && - (0 == strcasecmp (dot, ".gnu")) ) - handle->options = GNUNET_GNS_LO_NO_DHT; - lookup_with_public_key (handle); -} - -/** - * Handle get request - * - * @param handle the lookup handle - */ -static void -get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle, - const char* url, - void *cls) -{ - struct LookupHandle *handle = cls; - struct GNUNET_HashCode key; - long int enum_test; - char *temp_val; - - //check for /gns otherwise 404 - if (strlen (GNUNET_REST_API_NS_GNS) > strlen (url)) - { - handle->emsg = GNUNET_strdup("Wrong URL"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - //connect to gns - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); - handle->gns = GNUNET_GNS_connect (cfg); - handle->identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL); - handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, - &do_error, handle); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); - if (NULL == handle->gns) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connecting to GNS failed\n"); - handle->emsg = GNUNET_strdup("Connecting to GNS failed"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - //check parameter name -> BAD_REQUEST - GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME, - strlen (GNUNET_REST_PARAMETER_GNS_NAME), - &key); - if ( GNUNET_NO - == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key)) - { - handle->emsg = GNUNET_strdup("Parameter name is missing"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->name = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - &key)); - - //check parameter record_type, optional - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE, - strlen (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE), - &key); - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key) ) - { - handle->type = GNUNET_GNSRECORD_typename_to_number( - GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - &key)); - } - else - { - handle->type = GNUNET_GNSRECORD_TYPE_ANY; - } - - //check parameter options, optional - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_OPTIONS, - strlen (GNUNET_REST_JSONAPI_GNS_OPTIONS), - &key); - handle->options = GNUNET_GNS_LO_DEFAULT; - if ( GNUNET_YES - == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key)) - { - temp_val = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, &key); - if (1 < strlen(temp_val)) - { - handle->options = GNUNET_GNS_LO_DEFAULT; - } - else - { - //atoi because no valid conversion is default local option - enum_test = atoi(temp_val); - if (2 < enum_test) - handle->options = GNUNET_GNS_LO_DEFAULT; - else - handle->options = enum_test; - } - } - else - handle->options = GNUNET_GNS_LO_DEFAULT; - - //check parameter pkey, shortcut to lookup - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_PKEY, - strlen (GNUNET_REST_JSONAPI_GNS_PKEY), - &key); - if ( GNUNET_YES - == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key)) - { - handle->pkey_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - &key); - GNUNET_assert(NULL != handle->pkey_str); - if (GNUNET_OK - != GNUNET_CRYPTO_ecdsa_public_key_from_string ( - handle->pkey_str, strlen (handle->pkey_str), &(handle->pkey))) - { - handle->emsg = GNUNET_strdup("Parameter pkey has a wrong format"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - lookup_with_public_key (handle); - return; - } - - //check parameter ego, lookup public key of ego - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_EGO, - strlen (GNUNET_REST_JSONAPI_GNS_EGO), - &key); - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key) ) - { - handle->ego_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - &key); - handle->el = GNUNET_IDENTITY_ego_lookup (cfg, - handle->ego_str, - &identity_zone_cb, - handle); - return; - } - - //if name ends with .zkey then get public key - if ( (NULL != handle->name) && - (strlen (handle->name) > 4) && - (0 == strcmp (".zkey", - &handle->name[strlen (handle->name) - 4])) ) - { - GNUNET_CRYPTO_ecdsa_key_get_public( GNUNET_CRYPTO_ecdsa_key_get_anonymous (), - &(handle->pkey)); - lookup_with_public_key (handle); - } - else //else use gns-master identity - { - handle->id_op = GNUNET_IDENTITY_get (handle->identity, - "gns-master", - &identity_master_cb, - handle); - } -} - -/** - * Handle rest request - * - * @param handle the lookup handle - */ -static void -options_cont (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) -{ - struct MHD_Response *resp; - struct LookupHandle *handle = cls; - - //For GNS, independent of path return all options - resp = GNUNET_REST_create_response (NULL); - MHD_add_response_header (resp, - "Access-Control-Allow-Methods", - MHD_HTTP_METHOD_GET); - handle->proc (handle->proc_cls, - resp, - MHD_HTTP_OK); - cleanup_handle (handle); -} - - -/** - * Function processing the REST call - * - * @param method HTTP method - * @param url URL of the HTTP request - * @param data body of the HTTP request (optional) - * @param data_size length of the body - * @param proc callback function for the result - * @param proc_cls closure for @a proc - * @return #GNUNET_OK if request accepted - */ -static void -rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle, - GNUNET_REST_ResultProcessor proc, - void *proc_cls) -{ - static const struct GNUNET_REST_RequestHandler handlers[] = { - {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont}, - {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont}, - GNUNET_REST_HANDLER_END - }; - struct LookupHandle *handle = GNUNET_new (struct LookupHandle); - struct GNUNET_REST_RequestHandlerError err; - - handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; - handle->proc_cls = proc_cls; - handle->proc = proc; - handle->rest_handle = conndata_handle; - - if (GNUNET_NO == GNUNET_REST_handle_request (conndata_handle, - handlers, - &err, - handle)) - { - handle->response_code = err.error_code; - GNUNET_SCHEDULER_add_now (&do_error, handle); - } -} - - -/** - * Entry point for the plugin. - * - * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" - * @return NULL on error, otherwise the plugin context - */ -void * -libgnunet_plugin_rest_gns_init (void *cls) -{ - static struct Plugin plugin; - cfg = cls; - struct GNUNET_REST_Plugin *api; - - if (NULL != plugin.cfg) - return NULL; /* can only initialize once! */ - memset (&plugin, 0, sizeof (struct Plugin)); - plugin.cfg = cfg; - api = GNUNET_new (struct GNUNET_REST_Plugin); - api->cls = &plugin; - api->name = GNUNET_REST_API_NS_GNS; - api->process_request = &rest_gns_process_request; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("GNS REST API initialized\n")); - return api; -} - - -/** - * Exit point from the plugin. - * - * @param cls the plugin context (as returned by "init") - * @return always NULL - */ -void * -libgnunet_plugin_rest_gns_done (void *cls) -{ - struct GNUNET_REST_Plugin *api = cls; - struct Plugin *plugin = api->cls; - - plugin->cfg = NULL; - GNUNET_free (api); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "GNS REST plugin is finished\n"); - return NULL; -} - -/* end of plugin_rest_gns.c */ diff --git a/src/gnsrecord/Makefile.am b/src/gnsrecord/Makefile.am index 47d83169f..f840a31a4 100644 --- a/src/gnsrecord/Makefile.am +++ b/src/gnsrecord/Makefile.am @@ -39,7 +39,6 @@ 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 30a0ffa83..b80d86073 100644 --- a/src/gnsrecord/gnsrecord.c +++ b/src/gnsrecord/gnsrecord.c @@ -247,130 +247,4 @@ 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/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index 59dad66c7..49fa9f0fb 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -42,7 +42,7 @@ /** * Error messages */ -#define GNUNET_REST_ERROR_UNKNOWN "Unknown Error" +#define GNUNET_REST_IDENTITY_ERROR_UNKNOWN "Unknown Error" #define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid" #define GNUNET_REST_ERROR_NO_DATA "No data" #define GNUNET_REST_ERROR_DATA_INVALID "Data invalid" @@ -251,7 +251,7 @@ do_error (void *cls) char *response; if (NULL == handle->emsg) - handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN); + handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_ERROR_UNKNOWN); json_object_set_new(json_error,"error", json_string(handle->emsg)); diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h index 2eaa304de..20846238b 100644 --- a/src/include/gnunet_gnsrecord_lib.h +++ b/src/include/gnunet_gnsrecord_lib.h @@ -447,14 +447,6 @@ 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 4855f21b4..781d5698b 100644 --- a/src/include/gnunet_json_lib.h +++ b/src/include/gnunet_json_lib.h @@ -26,6 +26,7 @@ #define GNUNET_JSON_LIB_H #include "gnunet_util_lib.h" +#include "gnunet_gnsrecord_lib.h" #include @@ -318,6 +319,17 @@ GNUNET_JSON_spec_rsa_signature (const char *name, struct GNUNET_CRYPTO_RsaSignature **sig); + +/** + * 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); + + /* ****************** Generic generator interface ******************* */ @@ -393,6 +405,16 @@ GNUNET_JSON_from_rsa_public_key (const struct GNUNET_CRYPTO_RsaPublicKey *pk); json_t * GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig); +/** + * Convert Gns record to JSON. + * + * @param rname name of record + * @param rd record data + * @return corresponding JSON encoding + */ +json_t * +GNUNET_JSON_from_gns_record (const char* rname, + const struct GNUNET_GNSRECORD_Data *rd); /* ******************* Helpers for MHD upload handling ******************* */ diff --git a/src/json/Makefile.am b/src/json/Makefile.am index 16c0450d9..04f27fec7 100644 --- a/src/json/Makefile.am +++ b/src/json/Makefile.am @@ -16,7 +16,8 @@ libgnunetjson_la_SOURCES = \ json.c \ json_mhd.c \ json_generator.c \ - json_helper.c + json_helper.c \ + json_gnsrecord.c libgnunetjson_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ -ljansson \ diff --git a/src/json/json_generator.c b/src/json/json_generator.c index dd6df4f74..7b24a3c12 100644 --- a/src/json/json_generator.c +++ b/src/json/json_generator.c @@ -157,5 +157,40 @@ GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig) return ret; } +/** + * Convert Gns record to JSON. + * + * @param rname name of record + * @param rd record data + * @return corresponding JSON encoding + */ +json_t * +GNUNET_JSON_from_gns_record (const char* rname, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct GNUNET_TIME_Absolute expiration_time; + const char *expiration_time_str; + const char *record_type_str; + char *value_str; + json_t *ret; + int flags; + + value_str = GNUNET_GNSRECORD_value_to_string(rd->record_type,rd->data,rd->data_size); + expiration_time = GNUNET_GNSRECORD_record_get_expiration_time(1, rd); + expiration_time_str = GNUNET_STRINGS_absolute_time_to_string(expiration_time); + flags = (int)rd->flags; //maybe necessary + record_type_str = GNUNET_GNSRECORD_number_to_typename(rd->record_type); + + // ? for possible NULL values + ret = json_pack("{s:s?,s:s?,s:s?,s:i,s:s?}", + "value", value_str, + "type", record_type_str, + "expiration_time", expiration_time_str, + "flag", flags, + "label", rname); + GNUNET_free_non_null(value_str); + return ret; +} + /* End of json/json_generator.c */ diff --git a/src/json/json_gnsrecord.c b/src/json/json_gnsrecord.c new file mode 100644 index 000000000..48b78f38b --- /dev/null +++ b/src/json/json_gnsrecord.c @@ -0,0 +1,163 @@ +/* + This file is part of GNUnet. + Copyright (C) 2009-2013 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_gnsrecord.c + * @brief JSON handling of GNS record data + * @author Philippe Buschmann + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_gnsrecord_lib.h" +#include "gnunet_json_lib.h" + +#define GNUNET_JSON_GNSRECORD_VALUE "value" +#define GNUNET_JSON_GNSRECORD_TYPE "type" +#define GNUNET_JSON_GNSRECORD_EXPIRATION_TIME "expiration_time" +#define GNUNET_JSON_GNSRECORD_FLAG "flag" +#define GNUNET_JSON_GNSRECORD_LABEL "label" +#define GNUNET_JSON_GNSRECORD_NEVER "never" + + +/** + * 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 *value; + const char *expiration_time; + const char *record_type; + const char *label; + int flag; + void *rdata; + size_t rdata_size; + + GNUNET_assert(NULL != root); + 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!}", + GNUNET_JSON_GNSRECORD_VALUE, &value, + GNUNET_JSON_GNSRECORD_TYPE, &record_type, + GNUNET_JSON_GNSRECORD_EXPIRATION_TIME, &expiration_time, + GNUNET_JSON_GNSRECORD_FLAG, &flag, + GNUNET_JSON_GNSRECORD_LABEL, &label); + if (GNUNET_SYSERR == unpack_state) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Error json object has a wrong format!\n"); + return GNUNET_SYSERR; + } + gnsrecord_object = GNUNET_new (struct GNUNET_GNSRECORD_Data); + gnsrecord_object->record_type = GNUNET_GNSRECORD_typename_to_number(record_type); + if (UINT32_MAX == gnsrecord_object->record_type) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Unsupported type"); + return GNUNET_SYSERR; + } + if (GNUNET_OK + != GNUNET_GNSRECORD_string_to_value (gnsrecord_object->record_type, + value, + &rdata, + &rdata_size)) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Value invalid for record type"); + return GNUNET_SYSERR; + } + + gnsrecord_object->data = rdata; + gnsrecord_object->data_size = rdata_size; + + if (0 == strcmp (expiration_time, GNUNET_JSON_GNSRECORD_NEVER)) + { + gnsrecord_object->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; + } + else if (GNUNET_OK + == GNUNET_STRINGS_fancy_time_to_absolute (expiration_time, + &abs_expiration_time)) + { + gnsrecord_object->expiration_time = abs_expiration_time.abs_value_us; + } + else + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Value invalid for expiration time"); + 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; +} diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c index afe010b79..6924c53a4 100644 --- a/src/namestore/plugin_rest_namestore.c +++ b/src/namestore/plugin_rest_namestore.c @@ -36,11 +36,7 @@ #define GNUNET_REST_SUBSYSTEM_NAMESTORE "namestore" -#define GNUNET_REST_JSON_NAMESTORE_RECORD_TYPE "record_type" -#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_ERROR_UNKNOWN "Unknown Error" #define GNUNET_REST_NAMESTORE_RD_COUNT 1 @@ -194,8 +190,6 @@ static void cleanup_handle (void *cls) { struct RequestHandle *handle = cls; - size_t index; - json_t *json_ego; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); @@ -239,10 +233,6 @@ cleanup_handle (void *cls) if(NULL != handle->resp_object) { - json_array_foreach(handle->resp_object, index, json_ego ) - { - json_decref (json_ego); - } json_decref(handle->resp_object); } @@ -264,7 +254,7 @@ do_error (void *cls) char *response; if (NULL == handle->emsg) - handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN); + handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_ERROR_UNKNOWN); json_object_set_new(json_error,"error", json_string(handle->emsg)); @@ -286,66 +276,10 @@ namestore_iteration_error (void *cls) { struct RequestHandle *handle = 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); + handle->proc (handle->proc_cls, resp, MHD_HTTP_INTERNAL_SERVER_ERROR); GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } -/** - * Create json representation of a GNSRECORD - * - * @param rd the GNSRECORD_Data - */ -static json_t * -gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) -{ - const char *typename; - char *string_val; - const char *exp_str; - json_t *record_obj; - - typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type); - string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type, - rd->data, - rd->data_size); - - if (NULL == string_val) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Record of type %d malformed, skipping\n", - (int) rd->record_type); - return NULL; - } - record_obj = json_object(); - json_object_set_new (record_obj, - GNUNET_REST_JSON_NAMESTORE_RECORD_TYPE, - json_string (typename)); - json_object_set_new (record_obj, - GNUNET_REST_JSON_NAMESTORE_VALUE, - json_string (string_val)); - //GNUNET_free (string_val); - - if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags) - { - struct GNUNET_TIME_Relative time_rel; - time_rel.rel_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1); - } - else - { - struct GNUNET_TIME_Absolute time_abs; - time_abs.abs_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs); - } - json_object_set_new (record_obj, - GNUNET_REST_JSON_NAMESTORE_EXPIRATION, - json_string (exp_str)); - json_object_set_new (record_obj, "expired", - json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd))); - return record_obj; -} - - static void create_finished (void *cls, int32_t success, const char *emsg) { @@ -364,6 +298,29 @@ create_finished (void *cls, int32_t success, const char *emsg) GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } +static void +del_finished (void *cls, int32_t success, const char *emsg) +{ + struct RequestHandle *handle = cls; + + handle->add_qe = NULL; + if (GNUNET_NO == success) + { + handle->emsg = GNUNET_strdup("Deleting record failed. Record does not exist"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + if (GNUNET_SYSERR == success) + { + handle->emsg = GNUNET_strdup("Deleting record failed"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->proc (handle->proc_cls, + GNUNET_REST_create_response (NULL), + MHD_HTTP_NO_CONTENT); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); +} /** * Iteration over all results finished, build final * response. @@ -379,10 +336,8 @@ namestore_list_finished (void *cls) handle->list_it = NULL; - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "HEY\n"); if (NULL == handle->resp_object) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "OH\n"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } @@ -415,9 +370,6 @@ namestore_list_iteration (void *cls, if (NULL == handle->resp_object) handle->resp_object = json_array(); - char *result_str = json_dumps (handle->resp_object, 0); - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", result_str); - GNUNET_free(result_str); /*if ( (NULL != handle->ego_entry->identifier) && (0 != strcmp (handle->ego_entry->identifier, rname)) ) @@ -435,13 +387,12 @@ namestore_list_iteration (void *cls, (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)) ) continue; - record_obj = gnsrecord_to_json (&rd[i]); + record_obj = GNUNET_JSON_from_gns_record(rname,rd); if(NULL == record_obj) continue; - json_array_append (handle->resp_object, - record_obj); + json_array_append (handle->resp_object, record_obj); json_decref (record_obj); } @@ -477,73 +428,7 @@ namestore_get (struct GNUNET_REST_RequestHandle *con_handle, &namestore_list_finished, handle); } -/* -//TODO filter input -static int -json_to_gnsrecord (struct RequestHandle *handle) -{ - struct GNUNET_TIME_Relative etime_rel; - struct GNUNET_TIME_Absolute etime_abs; - void *rdata; - size_t rdata_size; - - handle->rd = GNUNET_new_array(GNUNET_REST_NAMESTORE_RD_COUNT, - struct GNUNET_GNSRECORD_Data); - memset (handle->rd, 0, sizeof(struct GNUNET_GNSRECORD_Data)); - handle->rd->record_type = GNUNET_GNSRECORD_typename_to_number ( - handle->json_data->type); - if (UINT32_MAX == (*handle->rd).record_type) - { - handle->emsg = GNUNET_strdup("Unsupported type"); - return GNUNET_SYSERR; - } - if (GNUNET_OK - != GNUNET_GNSRECORD_string_to_value ((*handle->rd).record_type, - handle->json_data->value, &rdata, - &rdata_size)) - { - handle->emsg = GNUNET_strdup("Value invalid for record type"); - return GNUNET_SYSERR; - } - (*handle->rd).data = rdata; - (*handle->rd).data_size = rdata_size; - //TODO other flags - if (0 == handle->json_data->is_public) - { - handle->rd->flags |= GNUNET_GNSRECORD_RF_PRIVATE; - } - /**TODO - * if (1 == handle->is_shadow) - 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; - } - else if (GNUNET_OK - == GNUNET_STRINGS_fancy_time_to_relative ( - handle->json_data->expiration_time, &etime_rel)) - { - (*handle->rd).expiration_time = etime_rel.rel_value_us; - (*handle->rd).flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; - } - else if (GNUNET_OK - == GNUNET_STRINGS_fancy_time_to_absolute ( - handle->json_data->expiration_time, &etime_abs)) - { - (*handle->rd).expiration_time = etime_abs.abs_value_us; - } - else - { - handle->emsg = GNUNET_strdup("Value invalid for record type"); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} -*/ /** * We're storing a new record; this requires @@ -564,12 +449,11 @@ create_new_record_cont (void *cls, { struct RequestHandle *handle = cls; - handle->add_qe = NULL; if (0 != strcmp (rec_name, handle->label_name)) { GNUNET_break (0); - do_error (handle); + GNUNET_SCHEDULER_add_now (&do_error, handle); return; } @@ -656,6 +540,31 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle, } +static void +del_cont (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct RequestHandle *handle = cls; + + handle->add_qe = NULL; + if (0 == rd_count) + { + handle->emsg = GNUNET_strdup("Record not found"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, + &handle->zone_pkey, + handle->label_name, + 0, NULL, + &del_finished, + handle); +} + /** * Handle namestore DELETE request * @@ -669,12 +578,28 @@ namestore_delete (struct GNUNET_REST_RequestHandle *con_handle, void *cls) { struct RequestHandle *handle = cls; + struct GNUNET_HashCode key; + + GNUNET_CRYPTO_hash ("label", strlen ("label"), &key); + if ( GNUNET_NO + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) + { + handle->emsg = GNUNET_strdup("Missing name"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->label_name = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, + &key); - //TODO add behaviour and response - - handle->emsg = GNUNET_strdup ("Not implemented yet"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, + &handle->zone_pkey, + handle->label_name, + &do_error, + handle, + &del_cont, + handle); + } diff --git a/src/namestore/plugin_rest_namestore2.c b/src/namestore/plugin_rest_namestore2.c deleted file mode 100644 index ec44046e0..000000000 --- a/src/namestore/plugin_rest_namestore2.c +++ /dev/null @@ -1,1229 +0,0 @@ -/* - 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 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 . - */ -/** - * @author Martin Schanzenbach - * @file namestore/plugin_rest_namestore.c - * @brief GNUnet Namestore REST plugin - * - */ - -#include "platform.h" -#include "gnunet_rest_plugin.h" -#include "gnunet_gns_service.h" -#include "gnunet_namestore_service.h" -#include "gnunet_identity_service.h" -#include "gnunet_rest_lib.h" -#include "gnunet_jsonapi_lib.h" -#include "gnunet_jsonapi_util.h" -#include "microhttpd.h" -#include - -#define GNUNET_REST_API_NS_NAMESTORE "/names" - -#define GNUNET_REST_API_NS_NAMESTORE_ZKEY "/names/zkey" - -#define GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO "record" - -#define GNUNET_REST_JSONAPI_NAMESTORE_NAME "name" - -#define GNUNET_REST_JSONAPI_NAMESTORE_REVINFO "revinfo" - -#define GNUNET_REST_JSONAPI_NAMESTORE_RECORD GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO - -#define GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE "record_type" - -#define GNUNET_REST_JSONAPI_NAMESTORE_VALUE "value" - -#define GNUNET_REST_JSONAPI_NAMESTORE_PUBLIC "public" - -#define GNUNET_REST_JSONAPI_NAMESTORE_SHADOW "shadow" - -#define GNUNET_REST_JSONAPI_NAMESTORE_PKEY "pkey" - -#define GNUNET_REST_JSONAPI_NAMESTORE_ZKEY "zkey" - -#define GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION "expiration" - -#define GNUNET_REST_JSONAPI_NAMESTORE_EGO "ego" - -/** - * @brief struct returned by the initialization function of the plugin - */ -struct Plugin -{ - const struct GNUNET_CONFIGURATION_Handle *cfg; -}; - - -/** - * HTTP methods allows for this plugin - */ -static char* allow_methods; - -const struct GNUNET_CONFIGURATION_Handle *cfg; - -struct RecordEntry -{ - /** - * DLL - */ - struct RecordEntry *next; - - /** - * DLL - */ - struct RecordEntry *prev; - -}; - -struct RequestHandle -{ - /** - * Ego list - */ - struct RecordEntry *record_head; - - /** - * Ego list - */ - struct record_entry *record_tail; - - /** - * JSON response object - */ - struct GNUNET_JSONAPI_Document *resp_object; - - /** - * Rest connection - */ - struct GNUNET_REST_RequestHandle *rest_handle; - - /** - * Handle to GNS service. - */ - struct GNUNET_IDENTITY_Handle *identity_handle; - - /** - * Handle to NAMESTORE - */ - struct GNUNET_NAMESTORE_Handle *ns_handle; - - /** - * Handle to NAMESTORE it - */ - struct GNUNET_NAMESTORE_ZoneIterator *list_it; - - /** - * Private key for the zone - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey zone_pkey; - - /** - * Handle to identity lookup - */ - struct GNUNET_IDENTITY_EgoLookup *ego_lookup; - - /** - * Default Ego operation - */ - struct GNUNET_IDENTITY_Operation *get_default; - - /** - * Name of the ego - */ - char *ego_name; - - /** - * Record is public - */ - int is_public; - - /** - * Shadow record - */ - int is_shadow; - - /** - * Name of the record to modify - */ - char *name; - - /** - * Value of the record - */ - char *value; - - /** - * Zkey string - */ - const char* zkey_str; - - /** - * record type - */ - uint32_t type; - - /** - * Records to store - */ - struct GNUNET_GNSRECORD_Data *rd; - - /** - * record count - */ - unsigned int rd_count; - - /** - * NAMESTORE Operation - */ - struct GNUNET_NAMESTORE_QueueEntry *add_qe; - - /** - * NAMESTORE Operation - */ - struct GNUNET_NAMESTORE_QueueEntry *reverse_qe; - - /** - * Desired timeout for the lookup (default is no timeout). - */ - struct GNUNET_TIME_Relative timeout; - - /** - * ID of a task associated with the resolution process. - */ - struct GNUNET_SCHEDULER_Task * timeout_task; - - /** - * The plugin result processor - */ - GNUNET_REST_ResultProcessor proc; - - /** - * The closure of the result processor - */ - void *proc_cls; - - /** - * The url - */ - char *url; - - /** - * Cfg - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * HTTP response code - */ - int response_code; - -}; - - -/** - * Cleanup lookup handle - * - * @param handle Handle to clean up - */ -static void -cleanup_handle (struct RequestHandle *handle) -{ - struct RecordEntry *record_entry; - struct RecordEntry *record_tmp; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Cleaning up\n"); - if (NULL != handle->resp_object) - GNUNET_JSONAPI_document_delete (handle->resp_object); - if (NULL != handle->name) - GNUNET_free (handle->name); - if (NULL != handle->timeout_task) - GNUNET_SCHEDULER_cancel (handle->timeout_task); - if (NULL != handle->ego_lookup) - GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup); - if (NULL != handle->get_default) - GNUNET_IDENTITY_cancel (handle->get_default); - if (NULL != handle->list_it) - GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it); - if (NULL != handle->add_qe) - GNUNET_NAMESTORE_cancel (handle->add_qe); - if (NULL != handle->identity_handle) - GNUNET_IDENTITY_disconnect (handle->identity_handle); - if (NULL != handle->ns_handle) - GNUNET_NAMESTORE_disconnect (handle->ns_handle); - if (NULL != handle->url) - GNUNET_free (handle->url); - if (NULL != handle->value) - GNUNET_free (handle->value); - if (NULL != handle->rd) - { - for (unsigned int i = 0; i < handle->rd_count; i++) - { - if (NULL != handle->rd[i].data) - GNUNET_free ((void*)handle->rd[i].data); - } - GNUNET_free (handle->rd); - } - if (NULL != handle->ego_name) - GNUNET_free (handle->ego_name); - for (record_entry = handle->record_head; - NULL != record_entry;) - { - record_tmp = record_entry; - record_entry = record_entry->next; - GNUNET_free (record_tmp); - } - GNUNET_free (handle); -} - - -/** - * Create json representation of a GNSRECORD - * - * @param rd the GNSRECORD_Data - */ -static json_t * -gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) -{ - const char *typename; - char *string_val; - const char *exp_str; - json_t *record_obj; - - typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type); - string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type, - rd->data, - rd->data_size); - - if (NULL == string_val) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Record of type %d malformed, skipping\n", - (int) rd->record_type); - return NULL; - } - record_obj = json_object(); - json_object_set_new (record_obj, - GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE, - json_string (typename)); - json_object_set_new (record_obj, - GNUNET_REST_JSONAPI_NAMESTORE_VALUE, - json_string (string_val)); - GNUNET_free (string_val); - - if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags) - { - struct GNUNET_TIME_Relative time_rel; - time_rel.rel_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1); - } - else - { - struct GNUNET_TIME_Absolute time_abs; - time_abs.abs_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs); - } - json_object_set_new (record_obj, GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION, json_string (exp_str)); - - json_object_set_new (record_obj, "expired", - json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd))); - return record_obj; -} - - -/** - * Task run on error. Generates error response and cleans up. - * - * @param cls the request to generate an error response for - */ -static void -do_error (void *cls) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp = GNUNET_REST_create_response (NULL); - - handle->proc (handle->proc_cls, resp, handle->response_code); - cleanup_handle (handle); -} - - -/** - * Task run on timeout. - * - * @param cls the request to time out - */ -static void -do_timeout (void *cls) -{ - struct RequestHandle *handle = cls; - - handle->timeout_task = NULL; - do_error (handle); -} - - -static void -cleanup_handle_delayed (void *cls) -{ - cleanup_handle (cls); -} - - -/** - * Iteration over all results finished, build final - * response. - * - * @param cls the `struct RequestHandle` - */ -static void -namestore_list_finished (void *cls) -{ - struct RequestHandle *handle = cls; - char *result; - struct MHD_Response *resp; - - handle->list_it = NULL; - if (NULL == handle->resp_object) - handle->resp_object = GNUNET_JSONAPI_document_new (); - - if (GNUNET_SYSERR == - GNUNET_JSONAPI_document_serialize (handle->resp_object, - &result)) - { - handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - GNUNET_SCHEDULER_add_now (&do_error, - handle); - return; - } - resp = GNUNET_REST_create_response (result); - handle->proc (handle->proc_cls, - resp, - MHD_HTTP_OK); - GNUNET_free_non_null (result); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, - handle); -} - - - -/** - * Create a response with requested records - * - * @param handle the RequestHandle - */ -static void -namestore_list_response (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, - const char *rname, - unsigned int rd_len, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct RequestHandle *handle = cls; - struct GNUNET_JSONAPI_Resource *json_resource; - json_t *result_array; - json_t *record_obj; - - if (NULL == handle->resp_object) - handle->resp_object = GNUNET_JSONAPI_document_new (); - - if ( (NULL != handle->name) && - (0 != strcmp (handle->name, - rname)) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "%s does not match %s\n", - rname, - handle->name); - GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, - 1); - return; - } - - result_array = json_array (); - for (unsigned int i=0; itype) && - (GNUNET_GNSRECORD_TYPE_ANY != handle->type) ) - continue; - record_obj = gnsrecord_to_json (&rd[i]); - json_array_append (result_array, - record_obj); - json_decref (record_obj); - } - - if (0 < json_array_size(result_array)) - { - json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO, - rname); - GNUNET_JSONAPI_resource_add_attr (json_resource, - GNUNET_REST_JSONAPI_NAMESTORE_RECORD, - result_array); - GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); - } - - json_decref (result_array); - GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, - 1); -} - - -static void -create_finished (void *cls, int32_t success, const char *emsg) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - - handle->add_qe = NULL; - if (GNUNET_YES != success) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Error storing records%s%s\n", - (NULL == emsg) ? "" : ": ", - (NULL == emsg) ? "" : emsg); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); - return; - } - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); -} - - -/** - * We're storing a new record; this requires - * that no record already exists - * - * @param cls closure, unused - * @param zone_key private key of the zone - * @param rec_name name that is being mapped (at most 255 characters long) - * @param rd_count number of entries in @a rd array - * @param rd array of records with data to store - */ -static void -create_new_record_cont (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, - const char *rec_name, - unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct RequestHandle *handle = cls; - - handle->add_qe = NULL; - if (0 != strcmp (rec_name, handle->name)) - { - GNUNET_break (0); - do_error (handle); - return; - } - - if (0 != rd_count) - { - handle->proc (handle->proc_cls, - GNUNET_REST_create_response (NULL), - MHD_HTTP_CONFLICT); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); - return; - } - - GNUNET_assert (NULL != handle->name); - handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, - &handle->zone_pkey, - handle->name, - handle->rd_count, - handle->rd, - &create_finished, - handle); -} - - -static void -del_finished (void *cls, - int32_t success, - const char *emsg) -{ - struct RequestHandle *handle = cls; - - handle->add_qe = NULL; - if (GNUNET_NO == success) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Deleting record failed, record does not exist%s%s\n"), - (NULL != emsg) ? ": " : "", - (NULL != emsg) ? emsg : ""); - GNUNET_SCHEDULER_add_now (&do_error, handle); //do_not_found TODO - return; - } - if (GNUNET_SYSERR == success) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Deleting record failed%s%s\n"), - (NULL != emsg) ? ": " : "", - (NULL != emsg) ? emsg : ""); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->proc (handle->proc_cls, - GNUNET_REST_create_response (NULL), - MHD_HTTP_NO_CONTENT); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); -} - - -static void -del_cont (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, - const char *label, - unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct RequestHandle *handle = cls; - - handle->add_qe = NULL; - if (0 == rd_count) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("There are no records under label `%s' that could be deleted.\n"), - label); - do_error (handle); - return; - } - - handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, - &handle->zone_pkey, - handle->name, - 0, NULL, - &del_finished, - handle); -} - - -static void -namestore_delete_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) -{ - struct RequestHandle *handle = cls; - - if (NULL == handle->name) - { - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, - &handle->zone_pkey, - handle->name, - &do_error, - handle, - &del_cont, - handle); -} - - -static int -json_to_gnsrecord (const json_t *records_json, - struct GNUNET_GNSRECORD_Data **rd, - unsigned int *rd_count) -{ - struct GNUNET_TIME_Relative etime_rel; - struct GNUNET_TIME_Absolute etime_abs; - char *value; - void *rdata; - size_t rdata_size; - const char *typestring; - const char *expirationstring; - json_t *type_json; - json_t *value_json; - json_t *record_json; - json_t *exp_json; - - *rd_count = json_array_size (records_json); - *rd = GNUNET_new_array (*rd_count, - struct GNUNET_GNSRECORD_Data); - for (unsigned int i = 0; i < *rd_count; i++) - { - memset (&(*rd)[i], - 0, - sizeof (struct GNUNET_GNSRECORD_Data)); - record_json = json_array_get (records_json, - i); - type_json = json_object_get (record_json, - GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE); - if (! json_is_string (type_json)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Type property is no string\n"); - return GNUNET_SYSERR; - } - typestring = json_string_value (type_json); - (*rd)[i].record_type = GNUNET_GNSRECORD_typename_to_number (typestring); - if (UINT32_MAX == (*rd)[i].record_type) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unsupported type `%s'\n"), - json_string_value (type_json)); - return GNUNET_SYSERR; - } - value_json = json_object_get (record_json, - GNUNET_REST_JSONAPI_NAMESTORE_VALUE); - if (! json_is_string (value_json)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Value property is no string\n"); - return GNUNET_SYSERR; - } - value = GNUNET_strdup (json_string_value (value_json)); - if (GNUNET_OK != - GNUNET_GNSRECORD_string_to_value ((*rd)[i].record_type, - value, - &rdata, - &rdata_size)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Value `%s' invalid for record type `%s'\n"), - value, - typestring); - return GNUNET_SYSERR; - } - (*rd)[i].data = rdata; - (*rd)[i].data_size = rdata_size; - /**TODO - * if (1 == handle->is_shadow) - rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; - if (1 != handle->is_public) - rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; - */ - exp_json = json_object_get (record_json, - GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION); - if (! json_is_string (exp_json)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Expiration property is no string\n"); - return GNUNET_SYSERR; - } - expirationstring = json_string_value (exp_json); - if (0 == strcmp (expirationstring, "never")) - { - (*rd)[i].expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; - } - else if (GNUNET_OK == - GNUNET_STRINGS_fancy_time_to_relative (expirationstring, - &etime_rel)) - { - (*rd)[i].expiration_time = etime_rel.rel_value_us; - (*rd)[i].flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; - } - else if (GNUNET_OK == - GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, - &etime_abs)) - { - (*rd)[i].expiration_time = etime_abs.abs_value_us; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Value `%s' invalid for record type `%s'\n"), - value, - typestring); - return GNUNET_SYSERR; - } - } - return GNUNET_OK; -} - - -static void -namestore_create_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - struct GNUNET_JSONAPI_Document *json_obj; - struct GNUNET_JSONAPI_Resource *json_res; - json_t *records_json; - json_t *data_js; - json_error_t err; - char term_data[handle->rest_handle->data_size+1]; - struct GNUNET_JSON_Specification docspec[] = { - GNUNET_JSON_spec_jsonapi_document (&json_obj), - GNUNET_JSON_spec_end() - }; - - if (strlen (GNUNET_REST_API_NS_NAMESTORE) != strlen (handle->url)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Cannot create under %s\n", handle->url); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - if (0 >= handle->rest_handle->data_size) - { - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - term_data[handle->rest_handle->data_size] = '\0'; - GNUNET_memcpy (term_data, - handle->rest_handle->data, - handle->rest_handle->data_size); - data_js = json_loads (term_data, - JSON_DECODE_ANY, - &err); - GNUNET_assert (GNUNET_OK == - GNUNET_JSON_parse (data_js, docspec, - NULL, NULL)); - json_decref (data_js); - if (NULL == json_obj) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unable to parse JSONAPI Object from %s\n", - term_data); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Cannot create more than 1 resource! (Got %d)\n", - GNUNET_JSONAPI_document_resource_count (json_obj)); - GNUNET_JSONAPI_document_delete (json_obj); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0); - if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, - GNUNET_REST_JSONAPI_NAMESTORE_RECORD)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unsupported JSON data type\n"); - GNUNET_JSONAPI_document_delete (json_obj); - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); - cleanup_handle (handle); - return; - } - handle->name = GNUNET_strdup (GNUNET_JSONAPI_resource_get_id (json_res)); - records_json = GNUNET_JSONAPI_resource_read_attr (json_res, - GNUNET_REST_JSONAPI_NAMESTORE_RECORD); - if (NULL == records_json) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No records given\n"); - GNUNET_JSONAPI_document_delete (json_obj); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - if (GNUNET_SYSERR == json_to_gnsrecord (records_json, &handle->rd, &handle->rd_count)) - { - GNUNET_JSONAPI_document_delete (json_obj); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - GNUNET_JSONAPI_document_delete (json_obj); - - handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, - &handle->zone_pkey, - handle->name, - &do_error, - handle, - &create_new_record_cont, - handle); -} - - -static void -namestore_zkey_response (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, - const char *label, - unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - struct GNUNET_JSONAPI_Document *json_obj; - struct GNUNET_JSONAPI_Resource *json_res; - json_t *name_json; - char* result; - - handle->reverse_qe = NULL; - json_obj = GNUNET_JSONAPI_document_new (); - if (NULL != label) - { - name_json = json_string (label); - json_res = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_REVINFO, - handle->zkey_str); - GNUNET_JSONAPI_resource_add_attr (json_res, - GNUNET_REST_JSONAPI_NAMESTORE_NAME, - name_json); - GNUNET_JSONAPI_document_resource_add (json_obj, json_res); - json_decref (name_json); - } - //Handle response - if (GNUNET_SYSERR == GNUNET_JSONAPI_document_serialize (json_obj, &result)) - { - GNUNET_JSONAPI_document_delete (json_obj); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - resp = GNUNET_REST_create_response (result); - handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - GNUNET_JSONAPI_document_delete (json_obj); - GNUNET_free (result); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); -} - - -static void -namestore_zkey_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) -{ - struct RequestHandle *handle = cls; - struct GNUNET_HashCode key; - struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; - - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY, - strlen (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY), - &key); - if ( GNUNET_NO == - GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, - &key) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No zkey given %s\n", handle->url); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->zkey_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, - &key); - if ((NULL == handle->zkey_str) || - (GNUNET_OK != - GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str, - strlen (handle->zkey_str), - &pubkey))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Zkey invalid %s\n", handle->zkey_str); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->reverse_qe = GNUNET_NAMESTORE_zone_to_name (handle->ns_handle, - &handle->zone_pkey, - &pubkey, - &do_error, - handle, - &namestore_zkey_response, - handle); -} - - -static void -namestore_info_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) -{ - struct RequestHandle *handle = cls; - - handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, - &handle->zone_pkey, - &do_error, - handle, - &namestore_list_response, - handle, - &namestore_list_finished, - handle); -} - - -static char* -get_name_from_url (const char* url) -{ - if (strlen (url) <= strlen (GNUNET_REST_API_NS_NAMESTORE)) - return NULL; - return (char*)url + strlen (GNUNET_REST_API_NS_NAMESTORE) + 1; -} - -/** - * Respond to OPTIONS request - * - * @param con_handle the connection handle - * @param url the url - * @param cls the RequestHandle - */ -static void -options_cont (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) -{ - struct MHD_Response *resp; - struct RequestHandle *handle = cls; - - //For now, independent of path return all options - resp = GNUNET_REST_create_response (NULL); - MHD_add_response_header (resp, - "Access-Control-Allow-Methods", - allow_methods); - handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - cleanup_handle (handle); -} - - -/** - * Callback invoked from identity service with ego information. - * An @a ego of NULL means the ego was not found. - * - * @param cls closure with the configuration - * @param ego an ego known to identity service, or NULL - */ -static void -identity_cb (void *cls, - const struct GNUNET_IDENTITY_Ego *ego) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - struct GNUNET_REST_RequestHandlerError err; - static const struct GNUNET_REST_RequestHandler handlers[] = { - {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE_ZKEY, &namestore_zkey_cont}, //reverse - {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_info_cont}, //list - {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_create_cont}, //create - // {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_edit_cont}, //update. TODO this shoul be PATCH - {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete_cont}, //delete - {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont}, - GNUNET_REST_HANDLER_END - }; - - handle->ego_lookup = NULL; - if (NULL == ego) - { - if (NULL != handle->ego_name) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Ego `%s' not known to identity service\n"), - handle->ego_name); - } - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - cleanup_handle (handle); - return; - } - handle->zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); - handle->ns_handle = GNUNET_NAMESTORE_connect (cfg); - if (NULL == handle->ns_handle) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Failed to connect to namestore\n")); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - if (GNUNET_OK != - GNUNET_JSONAPI_handle_request (handle->rest_handle, - handlers, - &err, - handle)) - { - handle->response_code = err.error_code; - GNUNET_SCHEDULER_add_now (&do_error, - (void *) handle); - } -} - - -static void -default_ego_cb (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *name) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - handle->get_default = NULL; - if (NULL == ego) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("No default ego configured in identity service\n")); - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - cleanup_handle (handle); - return; - } - else - { - identity_cb (cls, ego); - } -} - -static void -id_connect_cb (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *name) -{ - struct RequestHandle *handle = cls; - if (NULL == ego) - { - handle->get_default = GNUNET_IDENTITY_get (handle->identity_handle, - "namestore", - &default_ego_cb, handle); - } -} - - -/** - * Function processing the REST call - * - * @param method HTTP method - * @param url URL of the HTTP request - * @param data body of the HTTP request (optional) - * @param data_size length of the body - * @param proc callback function for the result - * @param proc_cls closure for callback function - * @return #GNUNET_OK if request accepted - */ -static void -rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, - GNUNET_REST_ResultProcessor proc, - void *proc_cls) -{ - struct RequestHandle *handle = GNUNET_new (struct RequestHandle); - struct MHD_Response *resp; - struct GNUNET_HashCode key; - char *ego; - char *name; - char *type; - - handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; - handle->proc_cls = proc_cls; - handle->proc = proc; - handle->rest_handle = rest_handle; - handle->url = GNUNET_strdup (rest_handle->url); - if (handle->url[strlen (handle->url)-1] == '/') - handle->url[strlen (handle->url)-1] = '\0'; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connecting...\n"); - handle->cfg = cfg; - ego = NULL; - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_EGO, - strlen (GNUNET_REST_JSONAPI_NAMESTORE_EGO), - &key); - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, - &key) ) - { - ego = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, - &key); - } - - handle->type = GNUNET_GNSRECORD_TYPE_ANY; - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE, - strlen (GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE), - &key); - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, - &key) ) - { - type = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, - &key); - if (NULL != type) - handle->type = GNUNET_GNSRECORD_typename_to_number (type); - } - name = get_name_from_url (handle->url); - if (NULL != ego) - handle->ego_name = GNUNET_strdup (ego); - if (NULL != name) - handle->name = GNUNET_strdup (name); - if (NULL == handle->ego_name) - { - handle->identity_handle = GNUNET_IDENTITY_connect (handle->cfg, &id_connect_cb, handle); - if (NULL == handle->identity_handle) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Cannot connect to identity service\n")); - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - cleanup_handle (handle); - } - return; - } - handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg, - handle->ego_name, - &identity_cb, - handle); - handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, - &do_timeout, - handle); -} - -/** - * Entry point for the plugin. - * - * @param cls Config info - * @return NULL on error, otherwise the plugin context - */ -void * -libgnunet_plugin_rest_namestore_init (void *cls) -{ - static struct Plugin plugin; - cfg = cls; - struct GNUNET_REST_Plugin *api; - - if (NULL != plugin.cfg) - return NULL; /* can only initialize once! */ - memset (&plugin, 0, sizeof (struct Plugin)); - plugin.cfg = cfg; - api = GNUNET_new (struct GNUNET_REST_Plugin); - api->cls = &plugin; - api->name = GNUNET_REST_API_NS_NAMESTORE; - api->process_request = &rest_identity_process_request; - GNUNET_asprintf (&allow_methods, - "%s, %s, %s, %s, %s", - MHD_HTTP_METHOD_GET, - MHD_HTTP_METHOD_POST, - MHD_HTTP_METHOD_PUT, - MHD_HTTP_METHOD_DELETE, - MHD_HTTP_METHOD_OPTIONS); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Namestore REST API initialized\n")); - return api; -} - - -/** - * Exit point from the plugin. - * - * @param cls the plugin context (as returned by "init") - * @return always NULL - */ -void * -libgnunet_plugin_rest_namestore_done (void *cls) -{ - struct GNUNET_REST_Plugin *api = cls; - struct Plugin *plugin = api->cls; - - plugin->cfg = NULL; - GNUNET_free (api); - GNUNET_free_non_null (allow_methods); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Namestore REST plugin is finished\n"); - return NULL; -} - -/* end of plugin_rest_namestore.c */