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.
16 * @author Martin Schanzenbach
17 * @file identity/plugin_rest_identity.c
18 * @brief GNUnet Namestore REST plugin
23 #include "gnunet_rest_plugin.h"
24 #include "gnunet_identity_service.h"
25 #include "gnunet_rest_lib.h"
26 #include "gnunet_jsonapi_lib.h"
27 #include "gnunet_jsonapi_util.h"
28 #include "microhttpd.h"
30 #include "gnunet_signatures.h"
35 #define GNUNET_REST_API_NS_IDENTITY "/identity"
38 * State while collecting all egos
40 #define ID_REST_STATE_INIT 0
43 * Done collecting egos
45 #define ID_REST_STATE_POST_INIT 1
50 #define GNUNET_REST_JSONAPI_IDENTITY_EGO "ego"
55 #define GNUNET_REST_JSONAPI_IDENTITY_NAME "name"
58 * Attribute to rename "name" TODO we changed id to the pubkey
59 * so this can be unified with "name"
61 #define GNUNET_REST_JSONAPI_IDENTITY_NEWNAME "newname"
64 * URL parameter to change the subsytem for ego
66 #define GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM "subsystem"
72 #define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
73 #define GNUNET_REST_ERROR_NO_DATA "No data"
76 * GNUid token lifetime
78 #define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000
81 * The configuration handle
83 const struct GNUNET_CONFIGURATION_Handle *cfg;
86 * HTTP methods allows for this plugin
88 static char* allow_methods;
91 * @brief struct returned by the initialization function of the plugin
95 const struct GNUNET_CONFIGURATION_Handle *cfg;
106 struct EgoEntry *next;
111 struct EgoEntry *prev;
126 struct GNUNET_IDENTITY_Ego *ego;
135 struct EgoEntry *ego_head;
140 struct EgoEntry *ego_tail;
143 * Handle to the rest connection
145 struct GNUNET_REST_RequestHandle *conndata_handle;
153 * The processing state
158 * Handle to GNS service.
160 struct GNUNET_IDENTITY_Handle *identity_handle;
165 struct GNUNET_IDENTITY_Operation *op;
168 * Desired timeout for the lookup (default is no timeout).
170 struct GNUNET_TIME_Relative timeout;
173 * ID of a task associated with the resolution process.
175 struct GNUNET_SCHEDULER_Task * timeout_task;
178 * The plugin result processor
180 GNUNET_REST_ResultProcessor proc;
183 * The closure of the result processor
188 * The name to look up
193 * The subsystem set from REST
203 * The data from the REST request
208 * the length of the REST data
218 * Error response message
226 * Cleanup lookup handle
227 * @param handle Handle to clean up
230 cleanup_handle (struct RequestHandle *handle)
232 struct EgoEntry *ego_entry;
233 struct EgoEntry *ego_tmp;
234 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
236 if (NULL != handle->name)
237 GNUNET_free (handle->name);
238 if (NULL != handle->timeout_task)
240 GNUNET_SCHEDULER_cancel (handle->timeout_task);
241 handle->timeout_task = NULL;
243 if (NULL != handle->identity_handle)
244 GNUNET_IDENTITY_disconnect (handle->identity_handle);
245 if (NULL != handle->subsys)
246 GNUNET_free (handle->subsys);
247 if (NULL != handle->url)
248 GNUNET_free (handle->url);
249 if (NULL != handle->emsg)
250 GNUNET_free (handle->emsg);
251 for (ego_entry = handle->ego_head;
255 ego_entry = ego_entry->next;
256 GNUNET_free (ego_tmp->identifier);
257 GNUNET_free (ego_tmp->keystring);
258 GNUNET_free (ego_tmp);
260 GNUNET_free (handle);
265 * Task run on errors. Reports an error and cleans up everything.
267 * @param cls the `struct RequestHandle`
272 struct RequestHandle *handle = cls;
273 struct MHD_Response *resp;
276 GNUNET_asprintf (&json_error,
277 "{Error while processing request: %s}",
280 resp = GNUNET_REST_create_response (json_error);
281 handle->proc (handle->proc_cls,
283 handle->response_code);
284 cleanup_handle (handle);
285 GNUNET_free (json_error);
290 * Callback for IDENTITY_get()
292 * @param cls the RequestHandle
293 * @param ego the Ego found
294 * @param ctx the context
295 * @param name the id of the ego
298 get_ego_for_subsys (void *cls,
299 struct GNUNET_IDENTITY_Ego *ego,
303 struct RequestHandle *handle = cls;
304 struct GNUNET_JSONAPI_Document *json_document;
305 struct GNUNET_JSONAPI_Resource *json_resource;
306 struct EgoEntry *ego_entry;
307 struct MHD_Response *resp;
311 json_document = GNUNET_JSONAPI_document_new ();
313 for (ego_entry = handle->ego_head;
315 ego_entry = ego_entry->next)
317 if ( (NULL != name) && (0 != strcmp (name, ego_entry->identifier)) )
321 json_resource = GNUNET_JSONAPI_resource_new
322 (GNUNET_REST_JSONAPI_IDENTITY_EGO, ego_entry->keystring);
323 name_json = json_string (ego_entry->identifier);
324 GNUNET_JSONAPI_resource_add_attr (json_resource,
325 GNUNET_REST_JSONAPI_IDENTITY_NAME,
327 json_decref (name_json);
328 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
331 if (0 == GNUNET_JSONAPI_document_resource_count (json_document))
333 GNUNET_JSONAPI_document_delete (json_document);
334 handle->emsg = GNUNET_strdup("No identity matches results!");
335 GNUNET_SCHEDULER_add_now (&do_error, handle);
338 GNUNET_JSONAPI_document_serialize (json_document, &result_str);
339 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
340 resp = GNUNET_REST_create_response (result_str);
341 GNUNET_JSONAPI_document_delete (json_document);
342 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
343 GNUNET_free (result_str);
344 cleanup_handle (handle);
348 * Create a response with requested ego(s)
350 * @param con the Rest handle
351 * @param url the requested url
352 * @param cls the request handle
355 ego_info_response (struct GNUNET_REST_RequestHandle *con,
363 struct RequestHandle *handle = cls;
364 struct EgoEntry *ego_entry;
365 struct GNUNET_HashCode key;
366 struct MHD_Response *resp;
367 struct GNUNET_JSONAPI_Document *json_document;
368 struct GNUNET_JSONAPI_Resource *json_resource;
371 if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url, GNUNET_REST_API_NS_IDENTITY))
373 resp = GNUNET_REST_create_response (NULL);
374 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
375 cleanup_handle (handle);
380 if (strlen (GNUNET_REST_API_NS_IDENTITY) < strlen (handle->url))
382 keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY)+1];
384 for (ego_entry = handle->ego_head;
386 ego_entry = ego_entry->next)
388 if ( (NULL != keystring) && (0 != strcmp (keystring, ego_entry->keystring)) )
390 egoname = ego_entry->identifier;
394 if ( NULL == egoname ) {
395 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM,
396 strlen (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM),
399 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
402 subsys_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
404 if (NULL != subsys_val)
406 GNUNET_asprintf (&handle->subsys, "%s", subsys_val);
407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsys_val);
408 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
417 json_document = GNUNET_JSONAPI_document_new ();
420 for (ego_entry = handle->ego_head;
422 ego_entry = ego_entry->next)
424 if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) )
426 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO,
427 ego_entry->keystring);
428 name_str = json_string (ego_entry->identifier);
429 GNUNET_JSONAPI_resource_add_attr (
431 GNUNET_REST_JSONAPI_IDENTITY_NAME,
433 json_decref (name_str);
434 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
436 if (0 == GNUNET_JSONAPI_document_resource_count (json_document))
438 GNUNET_JSONAPI_document_delete (json_document);
439 handle->emsg = GNUNET_strdup ("No identities found!");
440 GNUNET_SCHEDULER_add_now (&do_error, handle);
443 GNUNET_JSONAPI_document_serialize (json_document, &result_str);
444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
445 resp = GNUNET_REST_create_response (result_str);
446 GNUNET_JSONAPI_document_delete (json_document);
447 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
448 GNUNET_free (result_str);
449 cleanup_handle (handle);
453 * Processing finished
455 * @param cls request handle
456 * @param emsg error message
459 do_finished (void *cls, const char *emsg)
461 struct RequestHandle *handle = cls;
462 struct MHD_Response *resp;
467 handle->emsg = GNUNET_strdup (emsg);
468 GNUNET_SCHEDULER_add_now (&do_error, handle);
471 resp = GNUNET_REST_create_response (NULL);
472 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
473 cleanup_handle (handle);
479 * @param con rest handle
481 * @param cls request handle
484 ego_create_cont (struct GNUNET_REST_RequestHandle *con,
488 struct RequestHandle *handle = cls;
489 struct EgoEntry *ego_entry;
490 struct MHD_Response *resp;
491 struct GNUNET_JSONAPI_Document *json_obj;
492 struct GNUNET_JSONAPI_Resource *json_res;
493 json_t *egoname_json;
497 char term_data[handle->data_size+1];
498 struct GNUNET_JSON_Specification docspec[] = {
499 GNUNET_JSON_spec_jsonapi_document (&json_obj),
500 GNUNET_JSON_spec_end()
502 if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
504 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID);
505 GNUNET_SCHEDULER_add_now (&do_error, handle);
508 if (0 >= handle->data_size)
510 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
511 GNUNET_SCHEDULER_add_now (&do_error, handle);
514 term_data[handle->data_size] = '\0';
515 GNUNET_memcpy (term_data, handle->data, handle->data_size);
516 data_js = json_loads (term_data,
519 GNUNET_assert (NULL != data_js);
520 GNUNET_assert (GNUNET_OK ==
521 GNUNET_JSON_parse (data_js, docspec,
524 json_decref (data_js);
526 if (NULL == json_obj)
528 GNUNET_SCHEDULER_add_now (&do_error, handle);
531 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
533 GNUNET_JSONAPI_document_delete (json_obj);
534 handle->emsg = GNUNET_strdup ("Provided resource count invalid");
535 GNUNET_SCHEDULER_add_now (&do_error, handle);
538 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
539 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO))
541 GNUNET_JSONAPI_document_delete (json_obj);
542 resp = GNUNET_REST_create_response (NULL);
543 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
544 cleanup_handle (handle);
547 egoname_json = GNUNET_JSONAPI_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_NAME);
548 if (!json_is_string (egoname_json))
550 GNUNET_JSONAPI_document_delete (json_obj);
551 handle->emsg = GNUNET_strdup ("No name provided");
552 GNUNET_SCHEDULER_add_now (&do_error, handle);
555 egoname = json_string_value (egoname_json);
556 for (ego_entry = handle->ego_head;
558 ego_entry = ego_entry->next)
560 if (0 == strcasecmp (egoname, ego_entry->identifier))
562 GNUNET_JSONAPI_document_delete (json_obj);
563 resp = GNUNET_REST_create_response (NULL);
564 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
565 cleanup_handle (handle);
569 GNUNET_asprintf (&handle->name, "%s", egoname);
570 GNUNET_JSONAPI_document_delete (json_obj);
571 handle->op = GNUNET_IDENTITY_create (handle->identity_handle,
579 * Handle ego edit request
581 * @param con rest connection handle
582 * @param url the url that is requested
583 * @param cls the RequestHandle
586 ego_edit_cont (struct GNUNET_REST_RequestHandle *con,
590 struct GNUNET_JSONAPI_Document *json_obj;
591 struct GNUNET_JSONAPI_Resource *json_res;
592 struct RequestHandle *handle = cls;
593 struct EgoEntry *ego_entry;
594 struct EgoEntry *ego_entry_tmp;
595 struct MHD_Response *resp;
600 const char *keystring;
603 char term_data[handle->data_size+1];
604 int ego_exists = GNUNET_NO;
605 struct GNUNET_JSON_Specification docspec[] = {
606 GNUNET_JSON_spec_jsonapi_document (&json_obj),
607 GNUNET_JSON_spec_end()
610 if (strlen (GNUNET_REST_API_NS_IDENTITY) > strlen (handle->url))
612 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID);
613 GNUNET_SCHEDULER_add_now (&do_error, handle);
617 keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1];
619 for (ego_entry = handle->ego_head;
621 ego_entry = ego_entry->next)
623 if (0 != strcasecmp (keystring, ego_entry->keystring))
625 ego_exists = GNUNET_YES;
629 if (GNUNET_NO == ego_exists)
631 resp = GNUNET_REST_create_response (NULL);
632 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
633 cleanup_handle (handle);
637 if (0 >= handle->data_size)
639 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
640 GNUNET_SCHEDULER_add_now (&do_error, handle);
644 term_data[handle->data_size] = '\0';
645 GNUNET_memcpy (term_data, handle->data, handle->data_size);
646 data_js = json_loads (term_data,
649 GNUNET_assert (NULL != data_js);
650 GNUNET_assert (GNUNET_OK ==
651 GNUNET_JSON_parse (data_js, docspec,
654 json_decref (data_js);
656 if (NULL == json_obj)
658 handle->emsg = GNUNET_strdup ("Data invalid");
659 GNUNET_SCHEDULER_add_now (&do_error, handle);
663 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
665 GNUNET_JSONAPI_document_delete (json_obj);
666 handle->emsg = GNUNET_strdup ("Resource amount invalid");
667 GNUNET_SCHEDULER_add_now (&do_error, handle);
670 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
672 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO))
674 GNUNET_JSONAPI_document_delete (json_obj);
675 handle->emsg = GNUNET_strdup ("Resource type invalid");
676 GNUNET_SCHEDULER_add_now (&do_error, handle);
681 name_json = GNUNET_JSONAPI_resource_read_attr (json_res,
682 GNUNET_REST_JSONAPI_IDENTITY_NEWNAME);
683 if ((NULL != name_json) && json_is_string (name_json))
685 newname = json_string_value (name_json);
686 for (ego_entry_tmp = handle->ego_head;
687 NULL != ego_entry_tmp;
688 ego_entry_tmp = ego_entry_tmp->next)
690 if (0 == strcasecmp (newname, ego_entry_tmp->identifier) &&
691 0 != strcasecmp (keystring, ego_entry_tmp->keystring))
693 //Ego with same name not allowed
694 GNUNET_JSONAPI_document_delete (json_obj);
695 resp = GNUNET_REST_create_response (NULL);
696 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
697 cleanup_handle (handle);
701 handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
702 ego_entry->identifier,
706 GNUNET_JSONAPI_document_delete (json_obj);
711 subsys_json = GNUNET_JSONAPI_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM);
712 if ( (NULL != subsys_json) && json_is_string (subsys_json))
714 subsys = json_string_value (subsys_json);
715 GNUNET_asprintf (&handle->subsys, "%s", subsys);
716 GNUNET_JSONAPI_document_delete (json_obj);
717 handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
724 GNUNET_JSONAPI_document_delete (json_obj);
725 handle->emsg = GNUNET_strdup ("Subsystem not provided");
726 GNUNET_SCHEDULER_add_now (&do_error, handle);
730 ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle,
734 const char *keystring;
735 struct EgoEntry *ego_entry;
736 struct MHD_Response *resp;
737 struct RequestHandle *handle = cls;
738 int ego_exists = GNUNET_NO;
740 if (strlen (GNUNET_REST_API_NS_IDENTITY) >= strlen (handle->url))
742 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID);
743 GNUNET_SCHEDULER_add_now (&do_error, handle);
747 keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1];
748 for (ego_entry = handle->ego_head;
750 ego_entry = ego_entry->next)
752 if (0 != strcasecmp (keystring, ego_entry->keystring))
754 ego_exists = GNUNET_YES;
757 if (GNUNET_NO == ego_exists)
759 resp = GNUNET_REST_create_response (NULL);
760 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
761 cleanup_handle (handle);
764 handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
765 ego_entry->identifier,
773 * Respond to OPTIONS request
775 * @param con_handle the connection handle
777 * @param cls the RequestHandle
780 options_cont (struct GNUNET_REST_RequestHandle *con_handle,
784 struct MHD_Response *resp;
785 struct RequestHandle *handle = cls;
787 //For now, independent of path return all options
788 resp = GNUNET_REST_create_response (NULL);
789 MHD_add_response_header (resp,
790 "Access-Control-Allow-Methods",
792 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
793 cleanup_handle (handle);
798 * Handle rest request
800 * @param handle the request handle
803 init_cont (struct RequestHandle *handle)
805 struct GNUNET_REST_RequestHandlerError err;
806 static const struct GNUNET_REST_RequestHandler handlers[] = {
807 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_info_response},
808 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create_cont},
809 {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY, &ego_edit_cont},
810 {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY, &ego_delete_cont},
811 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont},
812 GNUNET_REST_HANDLER_END
815 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (handle->conndata_handle,
820 handle->response_code = err.error_code;
821 GNUNET_SCHEDULER_add_now (&do_error, handle);
826 * If listing is enabled, prints information about the egos.
828 * This function is initially called for all egos and then again
829 * whenever a ego's identifier changes or if it is deleted. At the
830 * end of the initial pass over all egos, the function is once called
831 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
832 * be invoked in the future or that there was an error.
834 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
835 * this function is only called ONCE, and 'NULL' being passed in
836 * 'ego' does indicate an error (i.e. name is taken or no default
837 * value is known). If 'ego' is non-NULL and if '*ctx'
838 * is set in those callbacks, the value WILL be passed to a subsequent
839 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
840 * that one was not NULL).
842 * When an identity is renamed, this function is called with the
843 * (known) ego but the NEW identifier.
845 * When an identity is deleted, this function is called with the
846 * (known) ego and "NULL" for the 'identifier'. In this case,
847 * the 'ego' is henceforth invalid (and the 'ctx' should also be
851 * @param ego ego handle
852 * @param ctx context for application to store data for this ego
853 * (during the lifetime of this process, initially NULL)
854 * @param identifier identifier assigned by the user for this ego,
855 * NULL if the user just deleted the ego and it
856 * must thus no longer be used
860 struct GNUNET_IDENTITY_Ego *ego,
862 const char *identifier)
864 struct RequestHandle *handle = cls;
865 struct EgoEntry *ego_entry;
866 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
868 if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
870 handle->state = ID_REST_STATE_POST_INIT;
874 if (ID_REST_STATE_INIT == handle->state) {
875 ego_entry = GNUNET_new (struct EgoEntry);
876 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
877 ego_entry->keystring =
878 GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
879 ego_entry->ego = ego;
880 GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
881 GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
887 * Function processing the REST call
889 * @param method HTTP method
890 * @param url URL of the HTTP request
891 * @param data body of the HTTP request (optional)
892 * @param data_size length of the body
893 * @param proc callback function for the result
894 * @param proc_cls closure for callback function
895 * @return GNUNET_OK if request accepted
898 rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
899 GNUNET_REST_ResultProcessor proc,
902 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
906 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
908 handle->proc_cls = proc_cls;
910 handle->state = ID_REST_STATE_INIT;
911 handle->conndata_handle = conndata_handle;
912 handle->data = conndata_handle->data;
913 handle->data_size = conndata_handle->data_size;
914 handle->method = conndata_handle->method;
915 GNUNET_asprintf (&handle->url, "%s", conndata_handle->url);
916 if (handle->url[strlen (handle->url)-1] == '/')
917 handle->url[strlen (handle->url)-1] = '\0';
918 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
920 handle->identity_handle = GNUNET_IDENTITY_connect (cfg,
923 handle->timeout_task =
924 GNUNET_SCHEDULER_add_delayed (handle->timeout,
929 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
934 * Entry point for the plugin.
936 * @param cls Config info
937 * @return NULL on error, otherwise the plugin context
940 libgnunet_plugin_rest_identity_init (void *cls)
942 static struct Plugin plugin;
943 struct GNUNET_REST_Plugin *api;
946 if (NULL != plugin.cfg)
947 return NULL; /* can only initialize once! */
948 memset (&plugin, 0, sizeof (struct Plugin));
950 api = GNUNET_new (struct GNUNET_REST_Plugin);
952 api->name = GNUNET_REST_API_NS_IDENTITY;
953 api->process_request = &rest_identity_process_request;
954 GNUNET_asprintf (&allow_methods,
955 "%s, %s, %s, %s, %s",
957 MHD_HTTP_METHOD_POST,
959 MHD_HTTP_METHOD_DELETE,
960 MHD_HTTP_METHOD_OPTIONS);
962 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
963 _("Identity REST API initialized\n"));
969 * Exit point from the plugin.
971 * @param cls the plugin context (as returned by "init")
972 * @return always NULL
975 libgnunet_plugin_rest_identity_done (void *cls)
977 struct GNUNET_REST_Plugin *api = cls;
978 struct Plugin *plugin = api->cls;
981 GNUNET_free_non_null (allow_methods);
983 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
984 "Identity REST plugin is finished\n");
988 /* end of plugin_rest_gns.c */