2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @author Martin Schanzenbach
22 * @author Philippe Buschmann
23 * @file namestore/plugin_rest_namestore.c
24 * @brief GNUnet Namestore REST plugin
28 #include "gnunet_rest_plugin.h"
29 #include "gnunet_gns_service.h"
30 #include "gnunet_namestore_service.h"
31 #include "gnunet_identity_service.h"
32 #include "gnunet_rest_lib.h"
33 #include "gnunet_json_lib.h"
34 #include "microhttpd.h"
40 #define GNUNET_REST_API_NS_NAMESTORE "/namestore"
43 * Error message Unknown Error
45 #define GNUNET_REST_NAMESTORE_ERROR_UNKNOWN "Unknown Error"
48 * Error message No identity found
50 #define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
53 * Error message No default zone specified
55 #define GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE "No default zone specified"
58 * Error message Failed request
60 #define GNUNET_REST_NAMESTORE_FAILED "Namestore action failed"
63 * Error message invalid data
65 #define GNUNET_REST_NAMESTORE_INVALID_DATA "Data invalid"
68 * Error message No data
70 #define GNUNET_REST_NAMESTORE_NO_DATA "No data"
73 * State while collecting all egos
75 #define ID_REST_STATE_INIT 0
78 * Done collecting egos
80 #define ID_REST_STATE_POST_INIT 1
82 * The configuration handle
84 const struct GNUNET_CONFIGURATION_Handle *cfg;
87 * HTTP methods allows for this plugin
89 static char* allow_methods;
92 * @brief struct returned by the initialization function of the plugin
96 const struct GNUNET_CONFIGURATION_Handle *cfg;
100 * The default namestore ego
107 struct EgoEntry *next;
112 struct EgoEntry *prev;
127 struct GNUNET_IDENTITY_Ego *ego;
143 struct GNUNET_GNSRECORD_Data *rd;
146 * NAMESTORE Operation
148 struct GNUNET_NAMESTORE_QueueEntry *add_qe;
156 * The processing state
161 * Handle to NAMESTORE
163 struct GNUNET_NAMESTORE_Handle *ns_handle;
166 * Handle to NAMESTORE it
168 struct GNUNET_NAMESTORE_ZoneIterator *list_it;
171 * Private key for the zone
173 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_pkey;
178 struct EgoEntry *ego_entry;
183 struct EgoEntry *ego_head;
188 struct EgoEntry *ego_tail;
193 struct GNUNET_IDENTITY_Operation *op;
196 * Handle to Identity service.
198 struct GNUNET_IDENTITY_Handle *identity_handle;
203 struct GNUNET_REST_RequestHandle *rest_handle;
206 * Desired timeout for the lookup (default is no timeout).
208 struct GNUNET_TIME_Relative timeout;
211 * ID of a task associated with the resolution process.
213 struct GNUNET_SCHEDULER_Task *timeout_task;
216 * The plugin result processor
218 GNUNET_REST_ResultProcessor proc;
221 * The closure of the result processor
231 * Error response message
243 * Cleanup lookup handle
244 * @param handle Handle to clean up
247 cleanup_handle (void *cls)
249 struct RequestHandle *handle = cls;
250 struct EgoEntry *ego_entry;
251 struct EgoEntry *ego_tmp;
253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
255 if (NULL != handle->timeout_task)
257 GNUNET_SCHEDULER_cancel (handle->timeout_task);
258 handle->timeout_task = NULL;
260 if (NULL != handle->record_name)
261 GNUNET_free(handle->record_name);
262 if (NULL != handle->url)
263 GNUNET_free(handle->url);
264 if (NULL != handle->emsg)
265 GNUNET_free(handle->emsg);
266 if (NULL != handle->rd)
268 if (NULL != handle->rd->data)
269 GNUNET_free((void*)handle->rd->data);
270 GNUNET_free(handle->rd);
272 if (NULL != handle->timeout_task)
273 GNUNET_SCHEDULER_cancel(handle->timeout_task);
274 if (NULL != handle->list_it)
275 GNUNET_NAMESTORE_zone_iteration_stop(handle->list_it);
276 if (NULL != handle->add_qe)
277 GNUNET_NAMESTORE_cancel(handle->add_qe);
278 if (NULL != handle->identity_handle)
279 GNUNET_IDENTITY_disconnect(handle->identity_handle);
280 if (NULL != handle->ns_handle)
282 GNUNET_NAMESTORE_disconnect(handle->ns_handle);
285 for (ego_entry = handle->ego_head;
289 ego_entry = ego_entry->next;
290 GNUNET_free(ego_tmp->identifier);
291 GNUNET_free(ego_tmp->keystring);
292 GNUNET_free(ego_tmp);
295 if(NULL != handle->resp_object)
297 json_decref(handle->resp_object);
300 GNUNET_free (handle);
305 * Task run on errors. Reports an error and cleans up everything.
307 * @param cls the `struct RequestHandle`
312 struct RequestHandle *handle = cls;
313 struct MHD_Response *resp;
314 json_t *json_error = json_object();
317 if (NULL == handle->emsg)
318 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_ERROR_UNKNOWN);
320 json_object_set_new(json_error,"error", json_string(handle->emsg));
322 if (0 == handle->response_code)
323 handle->response_code = MHD_HTTP_OK;
324 response = json_dumps (json_error, 0);
325 resp = GNUNET_REST_create_response (response);
326 handle->proc (handle->proc_cls, resp, handle->response_code);
327 json_decref(json_error);
328 GNUNET_free(response);
329 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
334 * Get EgoEntry from list with either a public key or a name
335 * If public key and name are not NULL, it returns the public key result first
337 * @param handle the RequestHandle
338 * @param pubkey the public key of an identity (only one can be NULL)
339 * @param name the name of an identity (only one can be NULL)
340 * @return EgoEntry or NULL if not found
343 get_egoentry_namestore(struct RequestHandle *handle, char *name)
345 struct EgoEntry *ego_entry;
348 for (ego_entry = handle->ego_head;
350 ego_entry = ego_entry->next)
352 if (0 != strcasecmp (name, ego_entry->identifier))
362 * Does internal server error when iteration failed.
364 * @param cls the `struct RequestHandle`
367 namestore_iteration_error (void *cls)
369 struct RequestHandle *handle = cls;
370 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
371 GNUNET_SCHEDULER_add_now (&do_error, handle);
377 * Create finished callback
379 * @param cls the `struct RequestHandle`
380 * @param success the success indicating integer, GNUNET_OK on success
381 * @param emsg the error message (can be NULL)
384 create_finished (void *cls, int32_t success, const char *emsg)
386 struct RequestHandle *handle = cls;
387 struct MHD_Response *resp;
389 handle->add_qe = NULL;
390 if (GNUNET_YES != success)
394 handle->emsg = GNUNET_strdup(emsg);
395 GNUNET_SCHEDULER_add_now (&do_error, handle);
398 handle->emsg = GNUNET_strdup("Error storing records");
399 GNUNET_SCHEDULER_add_now (&do_error, handle);
402 resp = GNUNET_REST_create_response (NULL);
403 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
404 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
409 * Delete finished callback
411 * @param cls the `struct RequestHandle`
412 * @param success the success indicating integer, GNUNET_OK on success
413 * @param emsg the error message (can be NULL)
416 del_finished (void *cls, int32_t success, const char *emsg)
418 struct RequestHandle *handle = cls;
420 handle->add_qe = NULL;
421 if (GNUNET_NO == success)
423 handle->response_code = MHD_HTTP_NOT_FOUND;
424 handle->emsg = GNUNET_strdup("No record found");
425 GNUNET_SCHEDULER_add_now (&do_error, handle);
428 if (GNUNET_SYSERR == success)
432 handle->emsg = GNUNET_strdup(emsg);
433 GNUNET_SCHEDULER_add_now (&do_error, handle);
436 handle->emsg = GNUNET_strdup("Deleting record failed");
437 GNUNET_SCHEDULER_add_now (&do_error, handle);
440 handle->proc (handle->proc_cls,
441 GNUNET_REST_create_response (NULL),
442 MHD_HTTP_NO_CONTENT);
443 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
448 * Iteration over all results finished, build final
451 * @param cls the `struct RequestHandle`
454 namestore_list_finished (void *cls)
456 struct RequestHandle *handle = cls;
458 struct MHD_Response *resp;
460 handle->list_it = NULL;
462 if (NULL == handle->resp_object)
463 handle->resp_object = json_array();
465 result_str = json_dumps (handle->resp_object, 0);
466 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
467 resp = GNUNET_REST_create_response (result_str);
468 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
469 GNUNET_free_non_null (result_str);
470 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
475 * Create a response with requested records
477 * @param handle the RequestHandle
480 namestore_list_iteration (void *cls,
481 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
484 const struct GNUNET_GNSRECORD_Data *rd)
486 struct RequestHandle *handle = cls;
489 if (NULL == handle->resp_object)
490 handle->resp_object = json_array();
492 for (unsigned int i = 0; i < rd_len; i++)
494 if ( (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
495 (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)) )
498 record_obj = GNUNET_JSON_from_gns_record (rname, &rd[i]);
500 if(NULL == record_obj)
503 json_array_append (handle->resp_object, record_obj);
504 json_decref (record_obj);
507 GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1);
512 * @param ego ego handle
513 * @param ctx context for application to store data for this ego
514 * (during the lifetime of this process, initially NULL)
515 * @param identifier identifier assigned by the user for this ego,
516 * NULL if the user just deleted the ego and it
517 * must thus no longer be used
520 default_ego_get (void *cls,
521 struct GNUNET_IDENTITY_Ego *ego,
523 const char *identifier)
525 struct RequestHandle *handle = cls;
530 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE);
531 GNUNET_SCHEDULER_add_now (&do_error, handle);
534 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
536 handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
538 &namestore_iteration_error,
540 &namestore_list_iteration,
542 &namestore_list_finished,
544 if (NULL == handle->list_it)
546 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
547 GNUNET_SCHEDULER_add_now (&do_error, handle);
554 * Handle namestore GET request
556 * @param con_handle the connection handle
558 * @param cls the RequestHandle
561 namestore_get (struct GNUNET_REST_RequestHandle *con_handle,
565 struct RequestHandle *handle = cls;
566 struct EgoEntry *ego_entry;
572 //set zone to name if given
573 if (strlen (GNUNET_REST_API_NS_NAMESTORE) < strlen (handle->url))
575 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE)+1];
576 ego_entry = get_egoentry_namestore(handle, egoname);
578 if (NULL == ego_entry)
580 handle->response_code = MHD_HTTP_NOT_FOUND;
581 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
582 GNUNET_SCHEDULER_add_now (&do_error, handle);
586 if ( NULL != ego_entry )
588 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
591 if (NULL == handle->zone_pkey)
593 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
599 handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
601 &namestore_iteration_error,
603 &namestore_list_iteration,
605 &namestore_list_finished,
607 if (NULL == handle->list_it)
609 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
610 GNUNET_SCHEDULER_add_now (&do_error, handle);
618 * @param ego ego handle
619 * @param ctx context for application to store data for this ego
620 * (during the lifetime of this process, initially NULL)
621 * @param identifier identifier assigned by the user for this ego,
622 * NULL if the user just deleted the ego and it
623 * must thus no longer be used
626 default_ego_post (void *cls,
627 struct GNUNET_IDENTITY_Ego *ego,
629 const char *identifier)
631 struct RequestHandle *handle = cls;
636 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE);
637 GNUNET_SCHEDULER_add_now (&do_error, handle);
640 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
642 handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
649 if (NULL == handle->add_qe)
651 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
652 GNUNET_SCHEDULER_add_now (&do_error, handle);
659 * Handle namestore POST request
661 * @param con_handle the connection handle
663 * @param cls the RequestHandle
666 namestore_add (struct GNUNET_REST_RequestHandle *con_handle,
670 struct RequestHandle *handle = cls;
671 struct GNUNET_GNSRECORD_Data *gns_record;
672 struct EgoEntry *ego_entry;
677 char term_data[handle->rest_handle->data_size + 1];
679 struct GNUNET_JSON_Specification gnsspec[] = {
680 GNUNET_JSON_spec_gnsrecord_data(&gns_record),
681 GNUNET_JSON_spec_end ()
684 if (0 >= handle->rest_handle->data_size)
686 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_NO_DATA);
687 GNUNET_SCHEDULER_add_now (&do_error, handle);
690 term_data[handle->rest_handle->data_size] = '\0';
691 GNUNET_memcpy(term_data, handle->rest_handle->data,
692 handle->rest_handle->data_size);
693 data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
694 if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL))
696 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
697 GNUNET_SCHEDULER_add_now (&do_error, handle);
698 GNUNET_JSON_parse_free(gnsspec);
699 json_decref (data_js);
702 handle->rd = gns_record;
704 name_json = json_object_get(data_js, "record_name");
705 if (!json_is_string(name_json))
707 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
708 GNUNET_SCHEDULER_add_now (&do_error, handle);
709 json_decref (data_js);
712 handle->record_name = GNUNET_strdup(json_string_value(name_json));
713 if(NULL == handle->record_name)
715 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
716 GNUNET_SCHEDULER_add_now (&do_error, handle);
717 json_decref (data_js);
720 if (0 >= strlen(handle->record_name))
722 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
723 GNUNET_SCHEDULER_add_now (&do_error, handle);
724 json_decref (data_js);
727 json_decref (data_js);
732 //set zone to name if given
733 if (strlen (GNUNET_REST_API_NS_NAMESTORE) < strlen (handle->url))
735 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE)+1];
736 ego_entry = get_egoentry_namestore(handle, egoname);
738 if (NULL == ego_entry)
740 handle->response_code = MHD_HTTP_NOT_FOUND;
741 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
742 GNUNET_SCHEDULER_add_now (&do_error, handle);
746 if (NULL != ego_entry)
748 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
750 if (NULL == handle->zone_pkey)
752 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
758 handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
765 if (NULL == handle->add_qe)
767 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
768 GNUNET_SCHEDULER_add_now (&do_error, handle);
776 * @param ego ego handle
777 * @param ctx context for application to store data for this ego
778 * (during the lifetime of this process, initially NULL)
779 * @param identifier identifier assigned by the user for this ego,
780 * NULL if the user just deleted the ego and it
781 * must thus no longer be used
784 default_ego_delete (void *cls,
785 struct GNUNET_IDENTITY_Ego *ego,
787 const char *identifier)
789 struct RequestHandle *handle = cls;
794 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE);
795 GNUNET_SCHEDULER_add_now (&do_error, handle);
798 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
800 handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
807 if (NULL == handle->add_qe)
809 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
810 GNUNET_SCHEDULER_add_now (&do_error, handle);
817 * Handle namestore DELETE request
819 * @param con_handle the connection handle
821 * @param cls the RequestHandle
824 namestore_delete (struct GNUNET_REST_RequestHandle *con_handle,
828 struct RequestHandle *handle = cls;
829 struct GNUNET_HashCode key;
830 struct EgoEntry *ego_entry;
836 //set zone to name if given
837 if (strlen (GNUNET_REST_API_NS_NAMESTORE) < strlen (handle->url))
839 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE)+1];
840 ego_entry = get_egoentry_namestore(handle, egoname);
842 if (NULL == ego_entry)
844 handle->response_code = MHD_HTTP_NOT_FOUND;
845 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
846 GNUNET_SCHEDULER_add_now (&do_error, handle);
850 if ( NULL != ego_entry )
852 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
855 GNUNET_CRYPTO_hash ("record_name", strlen ("record_name"), &key);
857 == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
860 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
861 GNUNET_SCHEDULER_add_now (&do_error, handle);
864 handle->record_name = GNUNET_strdup(
865 GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key));
867 if (NULL == handle->zone_pkey)
869 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
876 handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
883 if (NULL == handle->add_qe)
885 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
886 GNUNET_SCHEDULER_add_now (&do_error, handle);
894 * Respond to OPTIONS request
896 * @param con_handle the connection handle
898 * @param cls the RequestHandle
901 options_cont (struct GNUNET_REST_RequestHandle *con_handle,
905 struct MHD_Response *resp;
906 struct RequestHandle *handle = cls;
908 //independent of path return all options
909 resp = GNUNET_REST_create_response (NULL);
910 MHD_add_response_header (resp,
911 "Access-Control-Allow-Methods",
913 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
914 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
920 * Handle rest request
922 * @param handle the request handle
925 init_cont (struct RequestHandle *handle)
927 struct GNUNET_REST_RequestHandlerError err;
928 static const struct GNUNET_REST_RequestHandler handlers[] = {
929 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get},
930 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add},
931 {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete},
932 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont},
933 GNUNET_REST_HANDLER_END
936 if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
941 handle->response_code = err.error_code;
942 GNUNET_SCHEDULER_add_now (&do_error, handle);
948 * This function is initially called for all egos and then again
949 * whenever a ego's identifier changes or if it is deleted. At the
950 * end of the initial pass over all egos, the function is once called
951 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
952 * be invoked in the future or that there was an error.
954 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
955 * this function is only called ONCE, and 'NULL' being passed in
956 * 'ego' does indicate an error (i.e. name is taken or no default
957 * value is known). If 'ego' is non-NULL and if '*ctx'
958 * is set in those callbacks, the value WILL be passed to a subsequent
959 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
960 * that one was not NULL).
962 * When an identity is renamed, this function is called with the
963 * (known) ego but the NEW identifier.
965 * When an identity is deleted, this function is called with the
966 * (known) ego and "NULL" for the 'identifier'. In this case,
967 * the 'ego' is henceforth invalid (and the 'ctx' should also be
971 * @param ego ego handle
972 * @param ctx context for application to store data for this ego
973 * (during the lifetime of this process, initially NULL)
974 * @param name identifier assigned by the user for this ego,
975 * NULL if the user just deleted the ego and it
976 * must thus no longer be used
979 id_connect_cb (void *cls,
980 struct GNUNET_IDENTITY_Ego *ego,
984 struct RequestHandle *handle = cls;
985 struct EgoEntry *ego_entry;
986 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
988 if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
990 handle->state = ID_REST_STATE_POST_INIT;
994 if (ID_REST_STATE_INIT == handle->state)
996 ego_entry = GNUNET_new(struct EgoEntry);
997 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
998 ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
999 ego_entry->ego = ego;
1000 GNUNET_asprintf (&ego_entry->identifier, "%s", name);
1001 GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail,
1009 * Function processing the REST call
1011 * @param method HTTP method
1012 * @param url URL of the HTTP request
1013 * @param data body of the HTTP request (optional)
1014 * @param data_size length of the body
1015 * @param proc callback function for the result
1016 * @param proc_cls closure for callback function
1017 * @return GNUNET_OK if request accepted
1020 rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
1021 GNUNET_REST_ResultProcessor proc,
1024 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1026 handle->response_code = 0;
1027 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1028 handle->proc_cls = proc_cls;
1029 handle->proc = proc;
1030 handle->rest_handle = rest_handle;
1031 handle->zone_pkey = NULL;
1033 handle->url = GNUNET_strdup (rest_handle->url);
1034 if (handle->url[strlen (handle->url)-1] == '/')
1035 handle->url[strlen (handle->url)-1] = '\0';
1036 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1038 handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
1039 handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, handle);
1040 handle->timeout_task =
1041 GNUNET_SCHEDULER_add_delayed (handle->timeout,
1045 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1050 * Entry point for the plugin.
1052 * @param cls Config info
1053 * @return NULL on error, otherwise the plugin context
1056 libgnunet_plugin_rest_namestore_init (void *cls)
1058 static struct Plugin plugin;
1059 struct GNUNET_REST_Plugin *api;
1062 if (NULL != plugin.cfg)
1063 return NULL; /* can only initialize once! */
1064 memset (&plugin, 0, sizeof (struct Plugin));
1066 api = GNUNET_new (struct GNUNET_REST_Plugin);
1068 api->name = GNUNET_REST_API_NS_NAMESTORE;
1069 api->process_request = &rest_process_request;
1070 GNUNET_asprintf (&allow_methods,
1071 "%s, %s, %s, %s, %s",
1072 MHD_HTTP_METHOD_GET,
1073 MHD_HTTP_METHOD_POST,
1074 MHD_HTTP_METHOD_PUT,
1075 MHD_HTTP_METHOD_DELETE,
1076 MHD_HTTP_METHOD_OPTIONS);
1078 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1079 _("Namestore REST API initialized\n"));
1085 * Exit point from the plugin.
1087 * @param cls the plugin context (as returned by "init")
1088 * @return always NULL
1091 libgnunet_plugin_rest_namestore_done (void *cls)
1093 struct GNUNET_REST_Plugin *api = cls;
1094 struct Plugin *plugin = api->cls;
1097 GNUNET_free_non_null (allow_methods);
1099 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1100 "Namestore REST plugin is finished\n");
1104 /* end of plugin_rest_namestore.c */