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
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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 * @author Martin Schanzenbach
22 * @file identity/plugin_rest_identity.c
23 * @brief GNUnet Namestore REST plugin
28 #include "gnunet_rest_plugin.h"
29 #include "gnunet_identity_service.h"
30 #include "gnunet_rest_lib.h"
31 #include "microhttpd.h"
33 #include "gnunet_signatures.h"
38 #define GNUNET_REST_API_NS_IDENTITY "/identity"
41 * State while collecting all egos
43 #define ID_REST_STATE_INIT 0
46 * Done collecting egos
48 #define ID_REST_STATE_POST_INIT 1
53 #define GNUNET_REST_JSONAPI_IDENTITY_EGO "ego"
58 #define GNUNET_REST_JSONAPI_IDENTITY_NAME "name"
61 * Attribute to rename "name" TODO we changed id to the pubkey
62 * so this can be unified with "name"
64 #define GNUNET_REST_JSONAPI_IDENTITY_NEWNAME "newname"
67 * URL parameter to change the subsytem for ego
69 #define GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM "subsystem"
75 #define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
76 #define GNUNET_REST_ERROR_NO_DATA "No data"
79 * GNUid token lifetime
81 #define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000
84 * The configuration handle
86 const struct GNUNET_CONFIGURATION_Handle *cfg;
89 * HTTP methods allows for this plugin
91 static char* allow_methods;
94 * @brief struct returned by the initialization function of the plugin
98 const struct GNUNET_CONFIGURATION_Handle *cfg;
109 struct EgoEntry *next;
114 struct EgoEntry *prev;
129 struct GNUNET_IDENTITY_Ego *ego;
138 struct EgoEntry *ego_head;
143 struct EgoEntry *ego_tail;
146 * Handle to the rest connection
148 struct RestConnectionDataHandle *conndata_handle;
151 * The processing state
156 * Handle to GNS service.
158 struct GNUNET_IDENTITY_Handle *identity_handle;
163 struct GNUNET_IDENTITY_Operation *op;
166 * Desired timeout for the lookup (default is no timeout).
168 struct GNUNET_TIME_Relative timeout;
171 * ID of a task associated with the resolution process.
173 struct GNUNET_SCHEDULER_Task * timeout_task;
176 * The plugin result processor
178 GNUNET_REST_ResultProcessor proc;
181 * The closure of the result processor
186 * The name to look up
191 * The subsystem set from REST
201 * The data from the REST request
206 * the length of the REST data
216 * Error response message
224 * Cleanup lookup handle
225 * @param handle Handle to clean up
228 cleanup_handle (struct RequestHandle *handle)
230 struct EgoEntry *ego_entry;
231 struct EgoEntry *ego_tmp;
232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
234 if (NULL != handle->name)
235 GNUNET_free (handle->name);
236 if (NULL != handle->timeout_task)
237 GNUNET_SCHEDULER_cancel (handle->timeout_task);
238 if (NULL != handle->identity_handle)
239 GNUNET_IDENTITY_disconnect (handle->identity_handle);
240 if (NULL != handle->subsys)
241 GNUNET_free (handle->subsys);
242 if (NULL != handle->url)
243 GNUNET_free (handle->url);
244 if (NULL != handle->emsg)
245 GNUNET_free (handle->emsg);
246 for (ego_entry = handle->ego_head;
250 ego_entry = ego_entry->next;
251 GNUNET_free (ego_tmp->identifier);
252 GNUNET_free (ego_tmp->keystring);
253 GNUNET_free (ego_tmp);
255 GNUNET_free (handle);
260 * Task run on shutdown. Cleans up everything.
263 * @param tc scheduler context
267 const struct GNUNET_SCHEDULER_TaskContext *tc)
269 struct RequestHandle *handle = cls;
270 struct MHD_Response *resp;
273 GNUNET_asprintf (&json_error,
274 "{Error while processing request: %s}",
277 resp = GNUNET_REST_create_json_response (json_error);
278 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
279 cleanup_handle (handle);
280 GNUNET_free (json_error);
285 * Callback for IDENTITY_get()
287 * @param cls the RequestHandle
288 * @param ego the Ego found
289 * @param ctx the context
290 * @param name the id of the ego
293 get_ego_for_subsys (void *cls,
294 struct GNUNET_IDENTITY_Ego *ego,
298 struct RequestHandle *handle = cls;
299 struct JsonApiObject *json_object;
300 struct JsonApiResource *json_resource;
301 struct EgoEntry *ego_entry;
302 struct MHD_Response *resp;
306 json_object = GNUNET_REST_jsonapi_object_new ();
308 for (ego_entry = handle->ego_head;
310 ego_entry = ego_entry->next)
312 if ( (NULL != name) && (0 != strcmp (name, ego_entry->identifier)) )
316 json_resource = GNUNET_REST_jsonapi_resource_new
317 (GNUNET_REST_JSONAPI_IDENTITY_EGO, ego_entry->keystring);
318 name_json = json_string (ego_entry->identifier);
319 GNUNET_REST_jsonapi_resource_add_attr (json_resource,
320 GNUNET_REST_JSONAPI_IDENTITY_NAME,
322 json_decref (name_json);
323 GNUNET_REST_jsonapi_object_resource_add (json_object, json_resource);
326 if (0 == GNUNET_REST_jsonapi_object_resource_count (json_object))
328 GNUNET_REST_jsonapi_object_delete (json_object);
329 handle->emsg = GNUNET_strdup("No identity matches results!");
330 GNUNET_SCHEDULER_add_now (&do_error, handle);
333 GNUNET_REST_jsonapi_data_serialize (json_object, &result_str);
334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
335 resp = GNUNET_REST_create_json_response (result_str);
336 GNUNET_REST_jsonapi_object_delete (json_object);
337 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
338 GNUNET_free (result_str);
339 cleanup_handle (handle);
343 * Create a response with requested ego(s)
345 * @param con the Rest handle
346 * @param url the requested url
347 * @param cls the request handle
350 ego_info_response (struct RestConnectionDataHandle *con,
358 struct RequestHandle *handle = cls;
359 struct EgoEntry *ego_entry;
360 struct GNUNET_HashCode key;
361 struct MHD_Response *resp;
362 struct JsonApiObject *json_object;
363 struct JsonApiResource *json_resource;
366 if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url, GNUNET_REST_API_NS_IDENTITY))
368 resp = GNUNET_REST_create_json_response (NULL);
369 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
370 cleanup_handle (handle);
375 if (strlen (GNUNET_REST_API_NS_IDENTITY) < strlen (handle->url))
377 keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY)+1];
379 for (ego_entry = handle->ego_head;
381 ego_entry = ego_entry->next)
383 if ( (NULL != keystring) && (0 != strcmp (keystring, ego_entry->keystring)) )
385 egoname = ego_entry->identifier;
389 if ( NULL == egoname ) {
390 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM,
391 strlen (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM),
394 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
397 subsys_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
399 if (NULL != subsys_val)
401 GNUNET_asprintf (&handle->subsys, "%s", subsys_val);
402 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsys_val);
403 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
412 json_object = GNUNET_REST_jsonapi_object_new ();
415 for (ego_entry = handle->ego_head;
417 ego_entry = ego_entry->next)
419 if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) )
421 json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO,
422 ego_entry->keystring);
423 name_str = json_string (ego_entry->identifier);
424 GNUNET_REST_jsonapi_resource_add_attr (
426 GNUNET_REST_JSONAPI_IDENTITY_NAME,
428 json_decref (name_str);
429 GNUNET_REST_jsonapi_object_resource_add (json_object, json_resource);
431 if (0 == GNUNET_REST_jsonapi_object_resource_count (json_object))
433 GNUNET_REST_jsonapi_object_delete (json_object);
434 handle->emsg = GNUNET_strdup ("No identities found!");
435 GNUNET_SCHEDULER_add_now (&do_error, handle);
438 GNUNET_REST_jsonapi_data_serialize (json_object, &result_str);
439 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
440 resp = GNUNET_REST_create_json_response (result_str);
441 GNUNET_REST_jsonapi_object_delete (json_object);
442 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
443 GNUNET_free (result_str);
444 cleanup_handle (handle);
448 * Processing finished
450 * @param cls request handle
451 * @param emsg error message
454 do_finished (void *cls, const char *emsg)
456 struct RequestHandle *handle = cls;
457 struct MHD_Response *resp;
462 handle->emsg = GNUNET_strdup (emsg);
463 GNUNET_SCHEDULER_add_now (&do_error, handle);
466 resp = GNUNET_REST_create_json_response (NULL);
467 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
468 cleanup_handle (handle);
474 * @param con rest handle
476 * @param cls request handle
479 ego_create_cont (struct RestConnectionDataHandle *con,
483 struct RequestHandle *handle = cls;
484 struct EgoEntry *ego_entry;
485 struct MHD_Response *resp;
486 struct JsonApiObject *json_obj;
487 struct JsonApiResource *json_res;
488 json_t *egoname_json;
490 char term_data[handle->data_size+1];
492 if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
494 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID);
495 GNUNET_SCHEDULER_add_now (&do_error, handle);
498 if (0 >= handle->data_size)
500 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
501 GNUNET_SCHEDULER_add_now (&do_error, handle);
504 term_data[handle->data_size] = '\0';
505 memcpy (term_data, handle->data, handle->data_size);
506 json_obj = GNUNET_REST_jsonapi_object_parse (term_data);
507 if (NULL == json_obj)
509 GNUNET_SCHEDULER_add_now (&do_error, handle);
512 if (1 != GNUNET_REST_jsonapi_object_resource_count (json_obj))
514 GNUNET_REST_jsonapi_object_delete (json_obj);
515 handle->emsg = GNUNET_strdup ("Provided resource count invalid");
516 GNUNET_SCHEDULER_add_now (&do_error, handle);
519 json_res = GNUNET_REST_jsonapi_object_get_resource (json_obj, 0);
520 if (GNUNET_NO == GNUNET_REST_jsonapi_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO))
522 GNUNET_REST_jsonapi_object_delete (json_obj);
523 resp = GNUNET_REST_create_json_response (NULL);
524 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
525 cleanup_handle (handle);
528 egoname_json = GNUNET_REST_jsonapi_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_NAME);
529 if (!json_is_string (egoname_json))
531 GNUNET_REST_jsonapi_object_delete (json_obj);
532 handle->emsg = GNUNET_strdup ("No name provided");
533 GNUNET_SCHEDULER_add_now (&do_error, handle);
536 egoname = json_string_value (egoname_json);
537 for (ego_entry = handle->ego_head;
539 ego_entry = ego_entry->next)
541 if (0 == strcasecmp (egoname, ego_entry->identifier))
543 GNUNET_REST_jsonapi_object_delete (json_obj);
544 resp = GNUNET_REST_create_json_response (NULL);
545 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
546 cleanup_handle (handle);
550 GNUNET_asprintf (&handle->name, "%s", egoname);
551 GNUNET_REST_jsonapi_object_delete (json_obj);
552 handle->op = GNUNET_IDENTITY_create (handle->identity_handle,
560 * Handle ego edit request
562 * @param con rest connection handle
563 * @param url the url that is requested
564 * @param cls the RequestHandle
567 ego_edit_cont (struct RestConnectionDataHandle *con,
571 struct JsonApiObject *json_obj;
572 struct JsonApiResource *json_res;
573 struct RequestHandle *handle = cls;
574 struct EgoEntry *ego_entry;
575 struct MHD_Response *resp;
578 const char *keystring;
581 char term_data[handle->data_size+1];
582 int ego_exists = GNUNET_NO;
584 if (strlen (GNUNET_REST_API_NS_IDENTITY) > strlen (handle->url))
586 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID);
587 GNUNET_SCHEDULER_add_now (&do_error, handle);
591 keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1];
593 for (ego_entry = handle->ego_head;
595 ego_entry = ego_entry->next)
597 if (0 != strcasecmp (keystring, ego_entry->keystring))
599 ego_exists = GNUNET_YES;
603 if (GNUNET_NO == ego_exists)
605 resp = GNUNET_REST_create_json_response (NULL);
606 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
607 cleanup_handle (handle);
611 if (0 >= handle->data_size)
613 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
614 GNUNET_SCHEDULER_add_now (&do_error, handle);
618 term_data[handle->data_size] = '\0';
619 memcpy (term_data, handle->data, handle->data_size);
620 json_obj = GNUNET_REST_jsonapi_object_parse (term_data);
622 if (NULL == json_obj)
624 handle->emsg = GNUNET_strdup ("Data invalid");
625 GNUNET_SCHEDULER_add_now (&do_error, handle);
629 if (1 != GNUNET_REST_jsonapi_object_resource_count (json_obj))
631 GNUNET_REST_jsonapi_object_delete (json_obj);
632 handle->emsg = GNUNET_strdup ("Resource amount invalid");
633 GNUNET_SCHEDULER_add_now (&do_error, handle);
636 json_res = GNUNET_REST_jsonapi_object_get_resource (json_obj, 0);
638 if (GNUNET_NO == GNUNET_REST_jsonapi_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO))
640 GNUNET_REST_jsonapi_object_delete (json_obj);
641 handle->emsg = GNUNET_strdup ("Resource type invalid");
642 GNUNET_SCHEDULER_add_now (&do_error, handle);
647 name_json = GNUNET_REST_jsonapi_resource_read_attr (json_res,
648 GNUNET_REST_JSONAPI_IDENTITY_NEWNAME);
649 if ((NULL != name_json) && json_is_string (name_json))
651 newname = json_string_value (name_json);
652 for (ego_entry = handle->ego_head;
654 ego_entry = ego_entry->next)
656 if (0 == strcasecmp (newname, ego_entry->identifier) &&
657 0 != strcasecmp (keystring, ego_entry->keystring))
659 //Ego with same name not allowed
660 GNUNET_REST_jsonapi_object_delete (json_obj);
661 resp = GNUNET_REST_create_json_response (NULL);
662 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
663 cleanup_handle (handle);
667 handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
668 ego_entry->identifier,
672 GNUNET_REST_jsonapi_object_delete (json_obj);
677 subsys_json = GNUNET_REST_jsonapi_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM);
678 if ( (NULL != subsys_json) && json_is_string (subsys_json))
680 subsys = json_string_value (subsys_json);
681 GNUNET_asprintf (&handle->subsys, "%s", subsys);
682 GNUNET_REST_jsonapi_object_delete (json_obj);
683 handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
690 GNUNET_REST_jsonapi_object_delete (json_obj);
691 handle->emsg = GNUNET_strdup ("Subsystem not provided");
692 GNUNET_SCHEDULER_add_now (&do_error, handle);
696 ego_delete_cont (struct RestConnectionDataHandle *con_handle,
700 const char *keystring;
701 struct EgoEntry *ego_entry;
702 struct MHD_Response *resp;
703 struct RequestHandle *handle = cls;
704 int ego_exists = GNUNET_NO;
706 if (strlen (GNUNET_REST_API_NS_IDENTITY) >= strlen (handle->url))
708 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID);
709 GNUNET_SCHEDULER_add_now (&do_error, handle);
713 keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1];
714 for (ego_entry = handle->ego_head;
716 ego_entry = ego_entry->next)
718 if (0 != strcasecmp (keystring, ego_entry->keystring))
720 ego_exists = GNUNET_YES;
723 if (GNUNET_NO == ego_exists)
725 resp = GNUNET_REST_create_json_response (NULL);
726 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
727 cleanup_handle (handle);
730 handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
731 ego_entry->identifier,
739 * Respond to OPTIONS request
741 * @param con_handle the connection handle
743 * @param cls the RequestHandle
746 options_cont (struct RestConnectionDataHandle *con_handle,
750 struct MHD_Response *resp;
751 struct RequestHandle *handle = cls;
753 //For now, independent of path return all options
754 resp = GNUNET_REST_create_json_response (NULL);
755 MHD_add_response_header (resp,
756 "Access-Control-Allow-Methods",
758 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
759 cleanup_handle (handle);
764 * Handle rest request
766 * @param handle the request handle
769 init_cont (struct RequestHandle *handle)
771 static const struct GNUNET_REST_RestConnectionHandler handlers[] = {
772 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_info_response},
773 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create_cont},
774 {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY, &ego_edit_cont},
775 {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY, &ego_delete_cont},
776 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont},
777 GNUNET_REST_HANDLER_END
780 if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, handlers, handle))
782 handle->emsg = GNUNET_strdup ("Request unsupported");
783 GNUNET_SCHEDULER_add_now (&do_error, handle);
788 * If listing is enabled, prints information about the egos.
790 * This function is initially called for all egos and then again
791 * whenever a ego's identifier changes or if it is deleted. At the
792 * end of the initial pass over all egos, the function is once called
793 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
794 * be invoked in the future or that there was an error.
796 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
797 * this function is only called ONCE, and 'NULL' being passed in
798 * 'ego' does indicate an error (i.e. name is taken or no default
799 * value is known). If 'ego' is non-NULL and if '*ctx'
800 * is set in those callbacks, the value WILL be passed to a subsequent
801 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
802 * that one was not NULL).
804 * When an identity is renamed, this function is called with the
805 * (known) ego but the NEW identifier.
807 * When an identity is deleted, this function is called with the
808 * (known) ego and "NULL" for the 'identifier'. In this case,
809 * the 'ego' is henceforth invalid (and the 'ctx' should also be
813 * @param ego ego handle
814 * @param ctx context for application to store data for this ego
815 * (during the lifetime of this process, initially NULL)
816 * @param identifier identifier assigned by the user for this ego,
817 * NULL if the user just deleted the ego and it
818 * must thus no longer be used
822 struct GNUNET_IDENTITY_Ego *ego,
824 const char *identifier)
826 struct RequestHandle *handle = cls;
827 struct EgoEntry *ego_entry;
828 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
830 if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
832 handle->state = ID_REST_STATE_POST_INIT;
836 if (ID_REST_STATE_INIT == handle->state) {
837 ego_entry = GNUNET_new (struct EgoEntry);
838 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
839 ego_entry->keystring =
840 GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
841 ego_entry->ego = ego;
842 GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
843 GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
849 * Function processing the REST call
851 * @param method HTTP method
852 * @param url URL of the HTTP request
853 * @param data body of the HTTP request (optional)
854 * @param data_size length of the body
855 * @param proc callback function for the result
856 * @param proc_cls closure for callback function
857 * @return GNUNET_OK if request accepted
860 rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
861 GNUNET_REST_ResultProcessor proc,
864 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
868 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
870 handle->proc_cls = proc_cls;
872 handle->state = ID_REST_STATE_INIT;
873 handle->conndata_handle = conndata_handle;
874 handle->data = conndata_handle->data;
875 handle->data_size = conndata_handle->data_size;
876 handle->method = conndata_handle->method;
877 GNUNET_asprintf (&handle->url, "%s", conndata_handle->url);
878 if (handle->url[strlen (handle->url)-1] == '/')
879 handle->url[strlen (handle->url)-1] = '\0';
880 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
882 handle->identity_handle = GNUNET_IDENTITY_connect (cfg,
885 handle->timeout_task =
886 GNUNET_SCHEDULER_add_delayed (handle->timeout,
891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
896 * Entry point for the plugin.
898 * @param cls Config info
899 * @return NULL on error, otherwise the plugin context
902 libgnunet_plugin_rest_identity_init (void *cls)
904 static struct Plugin plugin;
905 struct GNUNET_REST_Plugin *api;
908 if (NULL != plugin.cfg)
909 return NULL; /* can only initialize once! */
910 memset (&plugin, 0, sizeof (struct Plugin));
912 api = GNUNET_new (struct GNUNET_REST_Plugin);
914 api->name = GNUNET_REST_API_NS_IDENTITY;
915 api->process_request = &rest_identity_process_request;
916 GNUNET_asprintf (&allow_methods,
917 "%s, %s, %s, %s, %s",
919 MHD_HTTP_METHOD_POST,
921 MHD_HTTP_METHOD_DELETE,
922 MHD_HTTP_METHOD_OPTIONS);
924 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
925 _("Identity REST API initialized\n"));
931 * Exit point from the plugin.
933 * @param cls the plugin context (as returned by "init")
934 * @return always NULL
937 libgnunet_plugin_rest_identity_done (void *cls)
939 struct GNUNET_REST_Plugin *api = cls;
940 struct Plugin *plugin = api->cls;
943 GNUNET_free_non_null (allow_methods);
945 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
946 "Identity REST plugin is finished\n");
950 /* end of plugin_rest_gns.c */