2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
21 * @author Martin Schanzenbach
22 * @file namestore/plugin_rest_namestore.c
23 * @brief GNUnet Namestore REST plugin
28 #include "gnunet_rest_plugin.h"
29 #include "gnunet_namestore_service.h"
30 #include "gnunet_identity_service.h"
31 #include "gnunet_rest_lib.h"
32 #include "microhttpd.h"
35 #define GNUNET_REST_API_NS_NAMESTORE "/names"
37 #define GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO "record"
39 #define GNUNET_REST_JSONAPI_NAMESTORE_RECORD GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO
41 #define GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE "record_type"
43 #define GNUNET_REST_JSONAPI_NAMESTORE_VALUE "value"
45 #define GNUNET_REST_JSONAPI_NAMESTORE_PUBLIC "public"
47 #define GNUNET_REST_JSONAPI_NAMESTORE_SHADOW "shadow"
49 #define GNUNET_REST_JSONAPI_NAMESTORE_PKEY "pkey"
51 #define GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION "expiration"
53 #define GNUNET_REST_JSONAPI_NAMESTORE_EGO "ego"
56 * @brief struct returned by the initialization function of the plugin
60 const struct GNUNET_CONFIGURATION_Handle *cfg;
63 const struct GNUNET_CONFIGURATION_Handle *cfg;
70 struct RecordEntry *next;
75 struct RecordEntry *prev;
84 struct RecordEntry *record_head;
89 struct record_entry *record_tail;
92 * JSON response object
94 struct JsonApiObject *resp_object;
99 struct RestConnectionDataHandle *conndata_handle;
102 * Handle to GNS service.
104 struct GNUNET_IDENTITY_Handle *identity_handle;
107 * Handle to NAMESTORE
109 struct GNUNET_NAMESTORE_Handle *ns_handle;
112 * Handle to NAMESTORE it
114 struct GNUNET_NAMESTORE_ZoneIterator *list_it;
117 * Private key for the zone
119 struct GNUNET_CRYPTO_EcdsaPrivateKey zone_pkey;
122 * Handle to identity lookup
124 struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
127 * Default Ego operation
129 struct GNUNET_IDENTITY_Operation *get_default;
147 * Name of the record to modify
152 * Value of the record
164 struct GNUNET_GNSRECORD_Data *rd;
169 unsigned int rd_count;
172 * NAMESTORE Operation
174 struct GNUNET_NAMESTORE_QueueEntry *add_qe;
177 * Desired timeout for the lookup (default is no timeout).
179 struct GNUNET_TIME_Relative timeout;
182 * ID of a task associated with the resolution process.
184 struct GNUNET_SCHEDULER_Task * timeout_task;
187 * The plugin result processor
189 GNUNET_REST_ResultProcessor proc;
192 * The closure of the result processor
202 * The data from the REST request
207 * the length of the REST data
214 const struct GNUNET_CONFIGURATION_Handle *cfg;
220 * Cleanup lookup handle
221 * @param handle Handle to clean up
224 cleanup_handle (struct RequestHandle *handle)
226 struct RecordEntry *record_entry;
227 struct RecordEntry *record_tmp;
229 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
231 if (NULL != handle->name)
232 GNUNET_free (handle->name);
233 if (NULL != handle->timeout_task)
234 GNUNET_SCHEDULER_cancel (handle->timeout_task);
235 if (NULL != handle->ego_lookup)
236 GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup);
237 if (NULL != handle->get_default)
238 GNUNET_IDENTITY_cancel (handle->get_default);
239 if (NULL != handle->list_it)
240 GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it);
241 if (NULL != handle->add_qe)
242 GNUNET_NAMESTORE_cancel (handle->add_qe);
243 if (NULL != handle->identity_handle)
244 GNUNET_IDENTITY_disconnect (handle->identity_handle);
245 if (NULL != handle->ns_handle)
246 GNUNET_NAMESTORE_disconnect (handle->ns_handle);
247 if (NULL != handle->url)
248 GNUNET_free (handle->url);
249 if (NULL != handle->value)
250 GNUNET_free (handle->value);
251 if (NULL != handle->rd)
253 for (i = 0; i < handle->rd_count; i++)
255 if (NULL != handle->rd[i].data)
256 GNUNET_free ((void*)handle->rd[i].data);
258 GNUNET_free (handle->rd);
260 if (NULL != handle->ego_name)
261 GNUNET_free (handle->ego_name);
262 for (record_entry = handle->record_head;
263 NULL != record_entry;)
265 record_tmp = record_entry;
266 record_entry = record_entry->next;
267 GNUNET_free (record_tmp);
269 GNUNET_free (handle);
273 * Create json representation of a GNSRECORD
275 * @param rd the GNSRECORD_Data
278 gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd)
280 const char *typename;
285 typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type);
286 string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type,
290 if (NULL == string_val)
292 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
293 "Record of type %d malformed, skipping\n",
294 (int) rd->record_type);
297 record_obj = json_object();
298 json_object_set_new (record_obj,
299 GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE,
300 json_string (typename));
301 json_object_set_new (record_obj,
302 GNUNET_REST_JSONAPI_NAMESTORE_VALUE,
303 json_string (string_val));
304 GNUNET_free (string_val);
306 if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags)
308 struct GNUNET_TIME_Relative time_rel;
309 time_rel.rel_value_us = rd->expiration_time;
310 exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1);
314 struct GNUNET_TIME_Absolute time_abs;
315 time_abs.abs_value_us = rd->expiration_time;
316 exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs);
318 json_object_set_new (record_obj, GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION, json_string (exp_str));
320 json_object_set_new (record_obj, "expired",
321 json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd)));
327 * Task run on shutdown. Cleans up everything.
330 * @param tc scheduler context
334 const struct GNUNET_SCHEDULER_TaskContext *tc)
336 struct RequestHandle *handle = cls;
337 struct MHD_Response *resp = GNUNET_REST_create_json_response (NULL);
338 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
339 cleanup_handle (handle);
343 cleanup_handle_delayed (void *cls,
344 const struct GNUNET_SCHEDULER_TaskContext *tc)
346 cleanup_handle (cls);
350 * Create a response with requested records
352 * @param handle the RequestHandle
355 namestore_list_response (void *cls,
356 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
359 const struct GNUNET_GNSRECORD_Data *rd)
361 struct RequestHandle *handle = cls;
362 struct JsonApiResource *json_resource;
363 struct MHD_Response *resp;
364 json_t *result_array;
369 if (NULL == handle->resp_object)
370 handle->resp_object = GNUNET_REST_jsonapi_object_new ();
375 if (GNUNET_SYSERR == GNUNET_REST_jsonapi_data_serialize (handle->resp_object, &result))
377 GNUNET_SCHEDULER_add_now (&do_error, handle);
380 GNUNET_REST_jsonapi_object_delete (handle->resp_object);
381 resp = GNUNET_REST_create_json_response (result);
382 handle->list_it = NULL;
383 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
384 GNUNET_free (result);
385 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
389 if ( (NULL != handle->name) &&
390 (0 != strcmp (handle->name, rname)) )
392 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
393 "%s does not match %s\n", rname, handle->name);
394 GNUNET_NAMESTORE_zone_iterator_next (handle->list_it);
398 json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO,
400 result_array = json_array ();
401 for (i=0; i<rd_len; i++)
403 if ( (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
404 (0 != strcmp (rname, "+")) )
407 if ( (rd[i].record_type != handle->type) &&
408 (GNUNET_GNSRECORD_TYPE_ANY != handle->type) )
410 record_obj = gnsrecord_to_json (&(rd[i]));
411 json_array_append (result_array, record_obj);
412 json_decref (record_obj);
414 GNUNET_REST_jsonapi_resource_add_attr (json_resource,
415 GNUNET_REST_JSONAPI_NAMESTORE_RECORD,
417 GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource);
418 json_decref (result_array);
419 GNUNET_NAMESTORE_zone_iterator_next (handle->list_it);
423 create_finished (void *cls, int32_t success, const char *emsg)
425 struct RequestHandle *handle = cls;
426 struct MHD_Response *resp;
428 handle->add_qe = NULL;
429 if (GNUNET_YES != success)
431 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
432 "Error storing records%s%s\n",
433 (NULL == emsg) ? "" : ": ",
434 (NULL == emsg) ? "" : emsg);
435 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
438 resp = GNUNET_REST_create_json_response (NULL);
439 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
440 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
445 * We're storing a new record; this requires
446 * that no record already exists
448 * @param cls closure, unused
449 * @param zone_key private key of the zone
450 * @param rec_name name that is being mapped (at most 255 characters long)
451 * @param rd_count number of entries in @a rd array
452 * @param rd array of records with data to store
455 create_new_record_cont (void *cls,
456 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
457 const char *rec_name,
458 unsigned int rd_count,
459 const struct GNUNET_GNSRECORD_Data *rd)
461 struct RequestHandle *handle = cls;
463 handle->add_qe = NULL;
464 if ( (NULL != zone_key) &&
465 (0 != strcmp (rec_name, handle->name)) )
468 GNUNET_SCHEDULER_add_now (&do_error, handle);
472 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
473 "Received %u records for name `%s'\n",
477 handle->proc (handle->proc_cls,
478 GNUNET_REST_create_json_response (NULL),
480 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
484 GNUNET_assert (NULL != handle->name);
485 handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
495 del_finished (void *cls,
499 struct RequestHandle *handle = cls;
501 handle->add_qe = NULL;
502 if (GNUNET_NO == success)
504 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
505 _("Deleting record failed, record does not exist%s%s\n"),
506 (NULL != emsg) ? ": " : "",
507 (NULL != emsg) ? emsg : "");
508 GNUNET_SCHEDULER_add_now (&do_error, handle); //do_not_found TODO
511 if (GNUNET_SYSERR == success)
513 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
514 _("Deleting record failed%s%s\n"),
515 (NULL != emsg) ? ": " : "",
516 (NULL != emsg) ? emsg : "");
517 GNUNET_SCHEDULER_add_now (&do_error, handle);
520 handle->proc (handle->proc_cls,
521 GNUNET_REST_create_json_response (NULL),
522 MHD_HTTP_NO_CONTENT);
523 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
528 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
530 unsigned int rd_count,
531 const struct GNUNET_GNSRECORD_Data *rd)
533 struct RequestHandle *handle = cls;
537 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
538 _("There are no records under label `%s' that could be deleted.\n"),
540 GNUNET_SCHEDULER_add_now (&do_error, handle);
544 handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
553 namestore_delete_cont (struct RestConnectionDataHandle *con,
557 struct RequestHandle *handle = cls;
559 if (NULL == handle->name)
561 GNUNET_SCHEDULER_add_now (&do_error, handle);
565 handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle,
573 json_to_gnsrecord (const json_t *records_json,
574 struct GNUNET_GNSRECORD_Data **rd,
575 unsigned int *rd_count)
577 struct GNUNET_TIME_Relative etime_rel;
578 struct GNUNET_TIME_Absolute etime_abs;
582 const char *typestring;
583 const char *expirationstring;
590 *rd_count = json_array_size (records_json);
591 *rd = GNUNET_malloc (sizeof (struct GNUNET_GNSRECORD_Data) * *rd_count);
592 for (i = 0; i < *rd_count; i++)
594 memset (&((*rd)[i]), 0, sizeof (struct GNUNET_GNSRECORD_Data));
595 record_json = json_array_get (records_json, i);
596 type_json = json_object_get (record_json,
597 GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE);
598 if (!json_is_string (type_json))
600 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
601 "Type property is no string\n");
602 return GNUNET_SYSERR;
604 typestring = json_string_value (type_json);
605 (*rd)[i].record_type = GNUNET_GNSRECORD_typename_to_number (typestring);
606 if (UINT32_MAX == (*rd)[i].record_type)
608 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unsupported type `%s'\n"),
609 json_string_value (type_json));
610 return GNUNET_SYSERR;
612 value_json = json_object_get (record_json,
613 GNUNET_REST_JSONAPI_NAMESTORE_VALUE);
614 if (!json_is_string (value_json))
616 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
617 "Value property is no string\n");
618 return GNUNET_SYSERR;
620 GNUNET_asprintf (&value, "%s", json_string_value (value_json));
621 if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value ((*rd)[i].record_type,
626 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Value `%s' invalid for record type `%s'\n"),
628 return GNUNET_SYSERR;
630 (*rd)[i].data = rdata;
631 (*rd)[i].data_size = rdata_size;
633 * if (1 == handle->is_shadow)
634 rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
635 if (1 != handle->is_public)
636 rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE;
638 exp_json = json_object_get (record_json,
639 GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION);
640 if (!json_is_string (exp_json))
642 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
643 "Expiration property is no string\n");
644 return GNUNET_SYSERR;
646 expirationstring = json_string_value (exp_json);
647 if (0 == strcmp (expirationstring, "never"))
649 (*rd)[i].expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
651 else if (GNUNET_OK ==
652 GNUNET_STRINGS_fancy_time_to_relative (expirationstring,
655 (*rd)[i].expiration_time = etime_rel.rel_value_us;
656 (*rd)[i].flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
658 else if (GNUNET_OK ==
659 GNUNET_STRINGS_fancy_time_to_absolute (expirationstring,
662 (*rd)[i].expiration_time = etime_abs.abs_value_us;
666 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Value `%s' invalid for record type `%s'\n"),
668 return GNUNET_SYSERR;
675 namestore_create_cont (struct RestConnectionDataHandle *con,
679 struct RequestHandle *handle = cls;
680 struct MHD_Response *resp;
681 struct JsonApiObject *json_obj;
682 struct JsonApiResource *json_res;
684 json_t *records_json;
685 char term_data[handle->data_size+1];
687 if (strlen (GNUNET_REST_API_NS_NAMESTORE) != strlen (handle->url))
689 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
690 "Cannot create under %s\n", handle->url);
691 GNUNET_SCHEDULER_add_now (&do_error, handle);
694 if (0 >= handle->data_size)
696 GNUNET_SCHEDULER_add_now (&do_error, handle);
699 term_data[handle->data_size] = '\0';
700 memcpy (term_data, handle->data, handle->data_size);
701 json_obj = GNUNET_REST_jsonapi_object_parse (term_data);
702 if (NULL == json_obj)
704 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
705 "Unable to parse JSONAPI Object from %s\n",
707 GNUNET_SCHEDULER_add_now (&do_error, handle);
710 if (1 != GNUNET_REST_jsonapi_object_resource_count (json_obj))
712 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
713 "Cannot create more than 1 resource! (Got %d)\n",
714 GNUNET_REST_jsonapi_object_resource_count (json_obj));
715 GNUNET_REST_jsonapi_object_delete (json_obj);
716 GNUNET_SCHEDULER_add_now (&do_error, handle);
719 json_res = GNUNET_REST_jsonapi_object_get_resource (json_obj, 0);
720 if (GNUNET_NO == GNUNET_REST_jsonapi_resource_check_type (json_res,
721 GNUNET_REST_JSONAPI_NAMESTORE_RECORD))
723 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
724 "Unsupported JSON data type\n");
725 GNUNET_REST_jsonapi_object_delete (json_obj);
726 resp = GNUNET_REST_create_json_response (NULL);
727 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
728 cleanup_handle (handle);
731 name_json = GNUNET_REST_jsonapi_resource_read_attr (json_res, GNUNET_REST_JSONAPI_KEY_ID);
732 if (!json_is_string (name_json))
734 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
735 "Name property is no string\n");
736 GNUNET_REST_jsonapi_object_delete (json_obj);
737 GNUNET_SCHEDULER_add_now (&do_error, handle);
740 GNUNET_asprintf (&handle->name, "%s", json_string_value (name_json));
741 records_json = GNUNET_REST_jsonapi_resource_read_attr (json_res,
742 GNUNET_REST_JSONAPI_NAMESTORE_RECORD);
743 if (NULL == records_json)
745 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
746 "No records given\n");
747 GNUNET_REST_jsonapi_object_delete (json_obj);
748 GNUNET_SCHEDULER_add_now (&do_error, handle);
751 if (GNUNET_SYSERR == json_to_gnsrecord (records_json, &handle->rd, &handle->rd_count))
753 GNUNET_REST_jsonapi_object_delete (json_obj);
754 GNUNET_SCHEDULER_add_now (&do_error, handle);
757 GNUNET_REST_jsonapi_object_delete (json_obj);
759 handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle,
762 &create_new_record_cont, handle );
770 namestore_info_cont (struct RestConnectionDataHandle *con,
774 struct RequestHandle *handle = cls;
775 handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
777 &namestore_list_response,
782 get_name_from_url (const char* url)
784 if (strlen (url) <= strlen (GNUNET_REST_API_NS_NAMESTORE))
786 return (char*)url + strlen (GNUNET_REST_API_NS_NAMESTORE) + 1;
790 * Function called with the result from the check if the namestore
791 * service is actually running. If it is, we start the actual
794 * @param cls closure with our configuration
795 * @param result #GNUNET_YES if the namestore service is running
798 testservice_task (void *cls,
801 struct RequestHandle *handle = cls;
802 static const struct GNUNET_REST_RestConnectionHandler handlers[] = {
803 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_info_cont}, //list
804 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_create_cont}, //create
805 // {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_edit_cont}, //update. TODO this shoul be PATCH
806 {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete_cont}, //delete
807 GNUNET_REST_HANDLER_END
810 if (GNUNET_YES != result)
812 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Service `%s' is not running\n"),
814 GNUNET_SCHEDULER_add_now (&do_error, handle);
817 handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
818 if (NULL == handle->ns_handle)
820 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
821 _("Failed to connect to namestore\n"));
822 GNUNET_SCHEDULER_add_now (&do_error, handle);
826 if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, handlers, handle))
827 GNUNET_SCHEDULER_add_now (&do_error, (void*) handle);
832 * Callback invoked from identity service with ego information.
833 * An @a ego of NULL means the ego was not found.
835 * @param cls closure with the configuration
836 * @param ego an ego known to identity service, or NULL
839 identity_cb (void *cls,
840 const struct GNUNET_IDENTITY_Ego *ego)
842 struct RequestHandle *handle = cls;
843 struct MHD_Response *resp;
845 handle->ego_lookup = NULL;
848 if (NULL != handle->ego_name)
850 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
851 _("Ego `%s' not known to identity service\n"),
854 resp = GNUNET_REST_create_json_response (NULL);
855 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
856 cleanup_handle (handle);
859 handle->zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego);
860 GNUNET_CLIENT_service_test ("namestore", handle->cfg,
861 GNUNET_TIME_UNIT_SECONDS,
867 default_ego_cb (void *cls,
868 struct GNUNET_IDENTITY_Ego *ego,
872 struct RequestHandle *handle = cls;
873 struct MHD_Response *resp;
874 handle->get_default = NULL;
877 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
878 _("No default ego configured in identity service\n"));
879 resp = GNUNET_REST_create_json_response (NULL);
880 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
881 cleanup_handle (handle);
886 identity_cb (cls, ego);
891 id_connect_cb (void *cls,
892 struct GNUNET_IDENTITY_Ego *ego,
896 struct RequestHandle *handle = cls;
899 handle->get_default = GNUNET_IDENTITY_get (handle->identity_handle,
901 &default_ego_cb, handle);
906 testservice_id_task (void *cls, int result)
908 struct RequestHandle *handle = cls;
909 struct MHD_Response *resp;
910 struct GNUNET_HashCode key;
914 if (result != GNUNET_YES)
916 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
917 _("Identity service is not running\n"));
918 resp = GNUNET_REST_create_json_response (NULL);
919 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
920 cleanup_handle (handle);
924 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_EGO,
925 strlen (GNUNET_REST_JSONAPI_NAMESTORE_EGO),
928 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
931 ego = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
934 name = get_name_from_url (handle->url);
936 GNUNET_asprintf (&handle->ego_name, "%s", ego);
938 GNUNET_asprintf (&handle->name, "%s", name);
939 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", handle->ego_name);
940 if (NULL == handle->ego_name)
942 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", handle->ego_name);
943 handle->identity_handle = GNUNET_IDENTITY_connect (handle->cfg, &id_connect_cb, handle);
944 if (NULL == handle->identity_handle)
946 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Cannot connect to identity service\n"));
947 resp = GNUNET_REST_create_json_response (NULL);
948 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
949 cleanup_handle (handle);
953 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
960 * Function processing the REST call
962 * @param method HTTP method
963 * @param url URL of the HTTP request
964 * @param data body of the HTTP request (optional)
965 * @param data_size length of the body
966 * @param proc callback function for the result
967 * @param proc_cls closure for callback function
968 * @return GNUNET_OK if request accepted
971 rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
972 GNUNET_REST_ResultProcessor proc,
975 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
977 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
978 handle->proc_cls = proc_cls;
980 handle->conndata_handle = conndata_handle;
981 handle->data = conndata_handle->data;
982 handle->data_size = conndata_handle->data_size;
983 GNUNET_asprintf (&handle->url, "%s", conndata_handle->url);
984 if (handle->url[strlen (handle->url)-1] == '/')
985 handle->url[strlen (handle->url)-1] = '\0';
986 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
989 GNUNET_CLIENT_service_test ("identity",
991 GNUNET_TIME_UNIT_SECONDS,
992 &testservice_id_task,
994 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1002 * Entry point for the plugin.
1004 * @param cls Config info
1005 * @return NULL on error, otherwise the plugin context
1008 libgnunet_plugin_rest_namestore_init (void *cls)
1010 static struct Plugin plugin;
1012 struct GNUNET_REST_Plugin *api;
1014 if (NULL != plugin.cfg)
1015 return NULL; /* can only initialize once! */
1016 memset (&plugin, 0, sizeof (struct Plugin));
1018 api = GNUNET_new (struct GNUNET_REST_Plugin);
1020 api->name = GNUNET_REST_API_NS_NAMESTORE;
1021 api->process_request = &rest_identity_process_request;
1022 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1023 _("Namestore REST API initialized\n"));
1029 * Exit point from the plugin.
1031 * @param cls the plugin context (as returned by "init")
1032 * @return always NULL
1035 libgnunet_plugin_rest_namestore_done (void *cls)
1037 struct GNUNET_REST_Plugin *api = cls;
1038 struct Plugin *plugin = api->cls;
1042 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1043 "Namestore REST plugin is finished\n");
1047 /* end of plugin_rest_namestore.c */