GNUnet debian-0.24.3-29-g453fda2cf
 
Loading...
Searching...
No Matches
gnunet-rest-server.c File Reference
#include "platform.h"
#include <microhttpd.h>
#include "gnunet_util_lib.h"
#include "gnunet_rest_plugin.h"
#include "gnunet_mhd_compat.h"
#include "config_plugin.h"
#include "copying_plugin.h"
#include "identity_plugin.h"
#include "namestore_plugin.h"
#include "gns_plugin.h"
#include "reclaim_plugin.h"
Include dependency graph for gnunet-rest-server.c:

Go to the source code of this file.

Data Structures

struct  PluginListEntry
 A plugin list entry. More...
 
struct  MhdConnectionHandle
 MHD Connection handle. More...
 
struct  AcceptedRequest
 Accepted requests. More...
 

Macros

#define GNUNET_REST_SERVICE_PORT   7776
 Default Socks5 listen port.
 
#define MAX_HTTP_URI_LENGTH   2048
 Maximum supported length for a URI.
 
#define HTTP_PORT   80
 Port for plaintext HTTP.
 
#define HTTPS_PORT   443
 Port for HTTPS.
 
#define MHD_CACHE_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
 After how long do we clean up unused MHD SSL/TLS instances?
 
#define GN_REST_STATE_INIT   0
 
#define GN_REST_STATE_PROCESSING   1
 

Functions

static void do_httpd (void *cls)
 Task run whenever HTTP server operations are pending.
 
static void run_mhd_now ()
 Run MHD now, we have extra data ready for the callback.
 
static void plugin_callback (void *cls, struct MHD_Response *resp, int status)
 Plugin result callback.
 
static int cleanup_url_map (void *cls, const struct GNUNET_HashCode *key, void *value)
 
static void cleanup_handle (struct MhdConnectionHandle *handle)
 
static void cleanup_ar (struct AcceptedRequest *ar)
 
static int header_iterator (void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
 
static int url_iterator (void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
 
static MHD_RESULT post_data_iter (void *cls, enum MHD_ValueKind kind, const char *key, const char *filename, const char *content_type, const char *transfer_encoding, const char *data, uint64_t off, size_t size)
 
static MHD_RESULT create_response (void *cls, struct MHD_Connection *con, const char *url, const char *meth, const char *ver, const char *upload_data, size_t *upload_data_size, void **con_cls)
 Main MHD callback for handling requests.
 
static void kill_httpd ()
 Kill the MHD daemon.
 
static void schedule_httpd ()
 Schedule MHD.
 
static void * mhd_log_callback (void *cls, const char *url, struct MHD_Connection *connection)
 Function called when MHD first processes an incoming connection.
 
static void mhd_completed_cb (void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
 Function called when MHD decides that we are done with a connection.
 
static void mhd_connection_cb (void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_ConnectionNotificationCode cnc)
 Function called when MHD connection is opened or closed.
 
static void do_accept (void *cls)
 Accept new incoming connections.
 
static void do_shutdown (void *cls)
 Task run on shutdown.
 
static struct GNUNET_NETWORK_Handlebind_v4 ()
 Create an IPv4 listen socket bound to our port.
 
static struct GNUNET_NETWORK_Handlebind_v6 ()
 Create an IPv6 listen socket bound to our port.
 
static enum GNUNET_GenericReturnValue setup_plugin (const char *name, GNUNET_REST_ProcessingFunction proc, void *plugin_cls)
 Callback for plugin load.
 
static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
 Main function that will be run.
 

Variables

static struct GNUNET_SCHEDULER_Taskhttpd_task
 The task ID.
 
static in_addr_t address
 The address to bind to.
 
static struct in6_addr address6
 The IPv6 address to bind to.
 
static unsigned long long port = 7776
 The port the service is running on (default 7776)
 
static struct GNUNET_NETWORK_Handlelsock4
 The listen socket of the service for IPv4.
 
static struct GNUNET_NETWORK_Handlelsock6
 The listen socket of the service for IPv6.
 
static struct GNUNET_SCHEDULER_Taskltask4
 The listen task ID for IPv4.
 
static struct GNUNET_SCHEDULER_Taskltask6
 The listen task ID for IPv6.
 
static struct MHD_Daemon * httpd
 Daemon for HTTP.
 
static struct MHD_Response * failure_response
 Response we return on failures.
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 Our configuration.
 
static int echo_origin
 Echo request Origin in CORS.
 
static int basic_auth_enabled
 Do basic auth of user.
 
static char * basic_auth_secret
 Basic auth secret.
 
char cuser [_POSIX_LOGIN_NAME_MAX]
 User of the service.
 
static char * allow_origins
 Allowed Origins (CORS)
 
static char * allow_headers
 Allowed Headers (CORS)
 
static char * allow_credentials
 Allowed Credentials (CORS)
 
static struct PluginListEntryplugins_head
 Plugin list head.
 
static struct PluginListEntryplugins_tail
 Plugin list tail.
 
static struct AcceptedRequestreq_list_head
 AcceptedRequest list head.
 
static struct AcceptedRequestreq_list_tail
 AcceptedRequest list tail.
 
struct GNUNET_REST_Pluginconfig_plugin
 plugins
 
struct GNUNET_REST_Plugincopying_plugin
 
struct GNUNET_REST_Pluginidentity_plugin
 
struct GNUNET_REST_Pluginnamestore_plugin
 
struct GNUNET_REST_Plugingns_plugin
 
struct GNUNET_REST_Pluginreclaim_plugin
 

Macro Definition Documentation

◆ GNUNET_REST_SERVICE_PORT

#define GNUNET_REST_SERVICE_PORT   7776

Default Socks5 listen port.

Definition at line 45 of file gnunet-rest-server.c.

◆ MAX_HTTP_URI_LENGTH

#define MAX_HTTP_URI_LENGTH   2048

Maximum supported length for a URI.

Should die.

Deprecated:

Definition at line 51 of file gnunet-rest-server.c.

◆ HTTP_PORT

#define HTTP_PORT   80

Port for plaintext HTTP.

Definition at line 56 of file gnunet-rest-server.c.

◆ HTTPS_PORT

#define HTTPS_PORT   443

Port for HTTPS.

Definition at line 61 of file gnunet-rest-server.c.

◆ MHD_CACHE_TIMEOUT

#define MHD_CACHE_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)

After how long do we clean up unused MHD SSL/TLS instances?

Definition at line 66 of file gnunet-rest-server.c.

175{
176 /* DLL */
177 struct PluginListEntry *next;
178
179 /* DLL */
180 struct PluginListEntry *prev;
181
185 char *libname;
186
190 void *plugin;
191
196};
197
202{
203 struct MHD_Connection *con;
204
205 struct MHD_Response *response;
206
208
209 struct MHD_PostProcessor *pp;
210
211 int status;
212
213 int state;
214};
215
219struct AcceptedRequest
220{
224 struct AcceptedRequest *next;
225
229 struct AcceptedRequest *prev;
230
235
240
244 int socket_with_mhd;
245};
246
250static struct AcceptedRequest *req_list_head;
251
255static struct AcceptedRequest *req_list_tail;
256
257
267#if HAVE_JOSE
268struct GNUNET_REST_Plugin *openid_plugin;
269#endif
271
272/* ************************* Global helpers ********************* */
273
274
280static void
281do_httpd (void *cls);
282
283
287static void
289{
290 if (NULL != httpd_task)
291 {
293 httpd_task = NULL;
294 }
296}
297
298
307static void
308plugin_callback (void *cls, struct MHD_Response *resp, int status)
309{
310 struct MhdConnectionHandle *handle = cls;
311
312 handle->status = status;
313 handle->response = resp;
314 MHD_resume_connection (handle->con);
315 run_mhd_now ();
316}
317
318
319static int
320cleanup_url_map (void *cls, const struct GNUNET_HashCode *key, void *value)
321{
323 return GNUNET_YES;
324}
325
326
327static void
329{
330 if (NULL != handle->response)
331 MHD_destroy_response (handle->response);
332 if (NULL != handle->data_handle)
333 {
334 if (NULL != handle->data_handle->header_param_map)
335 {
337 ->header_param_map,
339 NULL);
341 handle->data_handle->header_param_map);
342 }
343 if (NULL != handle->data_handle->url_param_map)
344 {
345 GNUNET_CONTAINER_multihashmap_iterate (handle->data_handle->url_param_map,
347 NULL);
349 handle->data_handle->url_param_map);
350 }
351 GNUNET_free (handle->data_handle);
352 }
354}
355
356
357static void
358cleanup_ar (struct AcceptedRequest *ar)
359{
360 if (NULL != ar->con_handle)
361 {
363 }
364 if (GNUNET_YES == ar->socket_with_mhd)
365 {
367 }
368 else
369 {
371 }
372 ar->sock = NULL;
375 ar);
376 GNUNET_free (ar);
377}
378
379
380static int
381header_iterator (void *cls,
382 enum MHD_ValueKind kind,
383 const char *key,
384 const char *value)
385{
386 struct GNUNET_REST_RequestHandle *handle = cls;
387 struct GNUNET_HashCode hkey;
388 char *val;
389 char *lowerkey;
390
391 lowerkey = GNUNET_strdup (key);
393 GNUNET_CRYPTO_hash (lowerkey, strlen (lowerkey), &hkey);
394 GNUNET_asprintf (&val, "%s", value);
396 handle->header_param_map,
397 &hkey,
398 val,
400 {
402 "Could not load add header `%s'=%s\n",
403 lowerkey,
404 value);
405 }
406 GNUNET_free (lowerkey);
407 return MHD_YES;
408}
409
410
411static int
412url_iterator (void *cls,
413 enum MHD_ValueKind kind,
414 const char *key,
415 const char *value)
416{
417 struct GNUNET_REST_RequestHandle *handle = cls;
418 struct GNUNET_HashCode hkey;
419 char *val;
420
421 GNUNET_CRYPTO_hash (key, strlen (key), &hkey);
422 GNUNET_asprintf (&val, "%s", value);
424 handle->url_param_map,
425 &hkey,
426 val,
428 {
430 "Could not load add url param `%s'=%s\n",
431 key,
432 value);
433 }
434 return MHD_YES;
435}
436
437
438static MHD_RESULT
439post_data_iter (void *cls,
440 enum MHD_ValueKind kind,
441 const char *key,
442 const char *filename,
443 const char *content_type,
444 const char *transfer_encoding,
445 const char *data,
446 uint64_t off,
447 size_t size)
448{
449 struct GNUNET_REST_RequestHandle *handle = cls;
450 struct GNUNET_HashCode hkey;
451 char *val;
452
453 if (MHD_POSTDATA_KIND != kind)
454 return MHD_YES;
455
456 GNUNET_CRYPTO_hash (key, strlen (key), &hkey);
457 val = GNUNET_CONTAINER_multihashmap_get (handle->url_param_map,
458 &hkey);
459 if (NULL == val)
460 {
461 val = GNUNET_malloc (65536);
463 handle->url_param_map,
464 &hkey,
465 val,
467 {
469 "Could not add url param '%s'\n",
470 key);
471 GNUNET_free (val);
472 }
473 }
474 memcpy (val + off, data, size);
475 return MHD_YES;
476}
477
478
479/* ********************************* MHD response generation ******************* */
480
504static MHD_RESULT
505create_response (void *cls,
506 struct MHD_Connection *con,
507 const char *url,
508 const char *meth,
509 const char *ver,
510 const char *upload_data,
511 size_t *upload_data_size,
512 void **con_cls)
513{
514 char *origin;
515 char *pw;
516 char *user;
517 struct AcceptedRequest *ar;
518 struct GNUNET_HashCode key;
519 struct MhdConnectionHandle *con_handle;
520 struct GNUNET_REST_RequestHandle *rest_conndata_handle;
521 struct PluginListEntry *ple;
522
523 ar = *con_cls;
524 if (NULL == ar)
525 {
526 GNUNET_break (0);
527 return MHD_NO;
528 }
529
530 if (NULL == ar->con_handle)
531 {
532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New connection %s\n", url);
533 con_handle = GNUNET_new (struct MhdConnectionHandle);
534 con_handle->con = con;
535 con_handle->state = GN_REST_STATE_INIT;
536 ar->con_handle = con_handle;
537 return MHD_YES;
538 }
539 con_handle = ar->con_handle;
540 if (GN_REST_STATE_INIT == con_handle->state)
541 {
542 rest_conndata_handle = GNUNET_new (struct GNUNET_REST_RequestHandle);
543 rest_conndata_handle->method = meth;
544 rest_conndata_handle->url = url;
545 rest_conndata_handle->data = upload_data;
546 rest_conndata_handle->data_size = *upload_data_size;
547 rest_conndata_handle->url_param_map =
549 rest_conndata_handle->header_param_map =
551 con_handle->data_handle = rest_conndata_handle;
552 MHD_get_connection_values (con,
553 MHD_GET_ARGUMENT_KIND,
554 (MHD_KeyValueIterator) & url_iterator,
555 rest_conndata_handle);
556 MHD_get_connection_values (con,
557 MHD_HEADER_KIND,
558 (MHD_KeyValueIterator) & header_iterator,
559 rest_conndata_handle);
561 {
562 pw = NULL;
563 user = MHD_basic_auth_get_username_password (con, &pw);
564 if ((NULL == user) ||
565 (0 != strcmp (user, cuser)))
566 {
568 "Unknown user %s\n", user);
569 MHD_queue_basic_auth_fail_response (con, "gnunet", failure_response);
570 return MHD_YES;
571 }
572 if ((NULL == pw) ||
573 (0 != strcmp (pw, basic_auth_secret)))
574 {
576 "Password incorrect\n");
577 MHD_queue_basic_auth_fail_response (con, "gnunet", failure_response);
578 GNUNET_free (pw);
579 return MHD_YES;
580 }
581 GNUNET_free (pw);
582 }
583
584 con_handle->pp = MHD_create_post_processor (con,
585 65536,
587 rest_conndata_handle);
588 if (*upload_data_size)
589 {
590 MHD_post_process (con_handle->pp, upload_data, *upload_data_size);
591 }
592 MHD_destroy_post_processor (con_handle->pp);
593
594 con_handle->state = GN_REST_STATE_PROCESSING;
595 for (ple = plugins_head; NULL != ple; ple = ple->next)
596 {
597 if (GNUNET_YES == ple->process_request (ple->plugin,
598 rest_conndata_handle,
600 con_handle))
601 break; /* Request handled */
602 }
603 if (NULL == ple)
604 {
606 MHD_queue_response (con, MHD_HTTP_NOT_FOUND, failure_response);
607 }
608 *upload_data_size = 0;
609 run_mhd_now ();
610 return MHD_YES;
611 }
612 if (NULL == con_handle->response)
613 {
614 // Suspend connection until plugin is done
615 MHD_suspend_connection (con_handle->con);
616 return MHD_YES;
617 }
618 // MHD_resume_connection (con_handle->con);
620 "Queueing response from plugin with MHD\n");
621 // Handle Preflights for extensions
622 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking origin\n");
623 GNUNET_CRYPTO_hash ("origin", strlen ("origin"), &key);
626 &key);
627 if (NULL != origin)
628 {
629 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Origin: %s\n", origin);
630 // Only echo for browser plugins
631 if (GNUNET_YES == echo_origin)
632 {
633 if ((0 ==
634 strncmp ("moz-extension://", origin, strlen ("moz-extension://"))) ||
635 (0 == strncmp ("chrome-extension://",
636 origin,
637 strlen ("chrome-extension://"))))
638 {
639 GNUNET_assert (MHD_NO != MHD_add_response_header (con_handle->response,
640 MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
641 origin));
642 }
643 }
644 if (NULL != allow_origins)
645 {
646 char *tmp = GNUNET_strdup (allow_origins);
647 char *allow_origin = strtok (tmp, ",");
648 while (NULL != allow_origin)
649 {
650 if (0 == strncmp (allow_origin, origin, strlen (allow_origin)))
651 {
652 GNUNET_assert (MHD_NO != MHD_add_response_header (
653 con_handle->response,
654 MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
655 allow_origin));
656 break;
657 }
658 allow_origin = strtok (NULL, ",");
659 }
660 GNUNET_free (tmp);
661 }
662 }
663 if (NULL != allow_credentials)
664 {
665 GNUNET_assert (MHD_NO != MHD_add_response_header (con_handle->response,
666 "Access-Control-Allow-Credentials",
668 }
669 if (NULL != allow_headers)
670 {
671 GNUNET_assert (MHD_NO != MHD_add_response_header (con_handle->response,
672 "Access-Control-Allow-Headers",
674 }
675 run_mhd_now ();
676 {
677 MHD_RESULT ret = MHD_queue_response (con,
678 con_handle->status,
679 con_handle->response);
680 // cleanup_handle (con_handle);
681 return ret;
682 }
683}
684
685
686/* ******************** MHD HTTP setup and event loop ******************** */
687
688
692static void
693kill_httpd ()
694{
695 if (NULL != httpd)
696 {
697 MHD_stop_daemon (httpd);
698 httpd = NULL;
699 }
700 if (NULL != httpd_task)
701 {
703 httpd_task = NULL;
704 }
705 if (NULL != ltask4)
706 {
708 ltask4 = NULL;
709 }
710 if (NULL != ltask6)
711 {
713 ltask6 = NULL;
714 }
715
716 if (NULL != lsock4)
717 {
719 lsock4 = NULL;
720 }
721 if (NULL != lsock6)
722 {
724 lsock6 = NULL;
725 }
726}
727
728
736static void
738{
739 fd_set rs;
740 fd_set ws;
741 fd_set es;
742 struct GNUNET_NETWORK_FDSet *wrs;
743 struct GNUNET_NETWORK_FDSet *wws;
744 int max;
745 int haveto;
746 MHD_UNSIGNED_LONG_LONG timeout;
747 struct GNUNET_TIME_Relative tv;
748
749 FD_ZERO (&rs);
750 FD_ZERO (&ws);
751 FD_ZERO (&es);
752 max = -1;
753 if (MHD_YES != MHD_get_fdset (httpd, &rs, &ws, &es, &max))
754 {
755 kill_httpd ();
756 return;
757 }
758 haveto = MHD_get_timeout (httpd, &timeout);
759 if (MHD_YES == haveto)
760 tv.rel_value_us = (uint64_t) timeout * 1000LL;
761 else
763 if (-1 != max)
764 {
769 }
770 else
771 {
772 wrs = NULL;
773 wws = NULL;
774 }
775 if (NULL != httpd_task)
776 {
778 httpd_task = NULL;
779 }
780 if ((MHD_YES == haveto) || (-1 != max))
781 {
783 tv,
784 wrs,
785 wws,
786 &do_httpd,
787 NULL);
788 }
789 if (NULL != wrs)
791 if (NULL != wws)
793}
794
795
809static void *
810mhd_log_callback (void *cls,
811 const char *url,
812 struct MHD_Connection *connection)
813{
814 struct AcceptedRequest *ar;
815 const union MHD_ConnectionInfo *ci;
816
817 ci = MHD_get_connection_info (connection,
818 MHD_CONNECTION_INFO_SOCKET_CONTEXT);
819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing %s\n", url);
820 if (NULL == ci)
821 {
822 GNUNET_break (0);
823 return NULL;
824 }
825 ar = ci->socket_context;
826 return ar;
827}
828
829
839static void
840mhd_completed_cb (void *cls,
841 struct MHD_Connection *connection,
842 void **con_cls,
843 enum MHD_RequestTerminationCode toe)
844{
845 struct AcceptedRequest *ar = *con_cls;
846 if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe)
848 "MHD encountered error handling request: %d\n",
849 toe);
850 if (NULL == ar)
851 return;
852 if (NULL != ar->con_handle)
853 {
855 ar->con_handle = NULL;
856 }
858 *con_cls = NULL;
859}
860
861
871static void
872mhd_connection_cb (void *cls,
873 struct MHD_Connection *connection,
874 void **con_cls,
875 enum MHD_ConnectionNotificationCode cnc)
876{
877 struct AcceptedRequest *ar;
878 const union MHD_ConnectionInfo *ci;
879 int sock;
880
881 switch (cnc)
882 {
883 case MHD_CONNECTION_NOTIFY_STARTED:
884 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection started...\n");
885 ci = MHD_get_connection_info (connection,
886 MHD_CONNECTION_INFO_CONNECTION_FD);
887 if (NULL == ci)
888 {
889 GNUNET_break (0);
890 return;
891 }
892 sock = ci->connect_fd;
893 for (ar = req_list_head; NULL != ar; ar = ar->next)
894 {
895 if (GNUNET_NETWORK_get_fd (ar->sock) == sock)
896 {
898 "Context set...\n");
899 *con_cls = ar;
900 break;
901 }
902 }
903 break;
904
905 case MHD_CONNECTION_NOTIFY_CLOSED:
907 "Connection closed... cleaning up\n");
908 ar = *con_cls;
909 if (NULL == ar)
910 {
912 "Connection stale!\n");
913 return;
914 }
915 cleanup_ar (ar);
916 *con_cls = NULL;
917 break;
918
919 default:
920 GNUNET_break (0);
921 }
922}
923
924
930static void
931do_httpd (void *cls)
932{
933 httpd_task = NULL;
934 MHD_run (httpd);
936}
937
938
944static void
945do_accept (void *cls)
946{
947 struct GNUNET_NETWORK_Handle *lsock = cls;
948 struct AcceptedRequest *ar;
949 int fd;
950 const struct sockaddr *addr;
951 socklen_t len;
952
953 GNUNET_assert (NULL != lsock);
954 if (lsock == lsock4)
955 {
957 lsock,
958 &do_accept,
959 lsock);
960 }
961 else if (lsock == lsock6)
962 {
964 lsock,
965 &do_accept,
966 lsock);
967 }
968 else
969 GNUNET_assert (0);
970 ar = GNUNET_new (struct AcceptedRequest);
972 ar->sock = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL);
973 if (NULL == ar->sock)
974 {
975 GNUNET_free (ar);
977 return;
978 }
980 "Got an inbound connection, waiting for data\n");
981 fd = GNUNET_NETWORK_get_fd (ar->sock);
982 addr = GNUNET_NETWORK_get_addr (ar->sock);
986 ar);
987 if (MHD_YES != MHD_add_connection (httpd, fd, addr, len))
988 {
990 GNUNET_free (ar);
992 _ ("Failed to pass client to MHD\n"));
993 return;
994 }
996}
997
998
1004static void
1005do_shutdown (void *cls)
1006{
1007 struct PluginListEntry *ple;
1008
1009 while (NULL != plugins_head)
1010 {
1011 ple = plugins_head;
1014 ple);
1015 GNUNET_free (ple->libname);
1016 GNUNET_free (ple);
1017 }
1023#if HAVE_JOSE
1024 REST_openid_done (openid_plugin);
1025#endif
1027 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
1028 kill_httpd ();
1031 MHD_destroy_response (failure_response);
1032}
1033
1034
1040static struct GNUNET_NETWORK_Handle *
1041bind_v4 ()
1042{
1043 struct GNUNET_NETWORK_Handle *ls;
1044 struct sockaddr_in sa4;
1045 int eno;
1046
1047 memset (&sa4, 0, sizeof(sa4));
1048 sa4.sin_family = AF_INET;
1049 sa4.sin_port = htons (port);
1050 sa4.sin_addr.s_addr = address;
1051#if HAVE_SOCKADDR_IN_SIN_LEN
1052 sa4.sin_len = sizeof(sa4);
1053#endif
1054 ls = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0);
1055 if (NULL == ls)
1056 return NULL;
1058 (const struct sockaddr *) &sa4,
1059 sizeof(sa4)))
1060 {
1061 eno = errno;
1063 errno = eno;
1064 return NULL;
1065 }
1066 return ls;
1067}
1068
1069
1075static struct GNUNET_NETWORK_Handle *
1076bind_v6 ()
1077{
1078 struct GNUNET_NETWORK_Handle *ls;
1079 struct sockaddr_in6 sa6;
1080 int eno;
1081
1082 memset (&sa6, 0, sizeof(sa6));
1083 sa6.sin6_family = AF_INET6;
1084 sa6.sin6_port = htons (port);
1085 sa6.sin6_addr = address6;
1086#if HAVE_SOCKADDR_IN_SIN_LEN
1087 sa6.sin6_len = sizeof(sa6);
1088#endif
1089 ls = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_STREAM, 0);
1090 if (NULL == ls)
1091 return NULL;
1093 (const struct sockaddr *) &sa6,
1094 sizeof(sa6)))
1095 {
1096 eno = errno;
1098 errno = eno;
1099 return NULL;
1100 }
1101 return ls;
1102}
1103
1104
1112static enum GNUNET_GenericReturnValue
1113setup_plugin (const char *name,
1115 void *plugin_cls)
1116{
1117 struct PluginListEntry *ple;
1118
1119 if (NULL == plugin_cls)
1120 {
1122 "Could not load plugin\n");
1123 return GNUNET_SYSERR;
1124 }
1125 GNUNET_assert (1 < strlen (name));
1126 GNUNET_assert ('/' == *name);
1127 ple = GNUNET_new (struct PluginListEntry);
1128 ple->libname = GNUNET_strdup (name);
1129 ple->plugin = plugin_cls;
1130 ple->process_request = proc;
1133 ple);
1134 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded plugin `%s'\n", name);
1135 return GNUNET_OK;
1136}
1137
1138
1147static void
1148run (void *cls,
1149 char *const *args,
1150 const char *cfgfile,
1151 const struct GNUNET_CONFIGURATION_Handle *c)
1152{
1153 static const char *err_page = "{}";
1154 char *addr_str;
1155 char *basic_auth_file;
1156 uint64_t secret;
1157
1158 cfg = c;
1159 plugins_head = NULL;
1160 plugins_tail = NULL;
1161 failure_response = MHD_create_response_from_buffer (strlen (err_page),
1162 (void *) err_page,
1163 MHD_RESPMEM_PERSISTENT);
1164 /* Get port to bind to */
1165 if (GNUNET_OK !=
1166 GNUNET_CONFIGURATION_get_value_number (cfg, "rest", "HTTP_PORT", &port))
1167 {
1168 // No address specified
1169 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using default port...\n");
1171 }
1172
1173 /* Get address to bind to */
1174 if (GNUNET_OK !=
1175 GNUNET_CONFIGURATION_get_value_string (cfg, "rest", "BIND_TO", &addr_str))
1176 {
1177 // No address specified
1178 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Don't know what to bind to...\n");
1180 return;
1181 }
1182 if (1 != inet_pton (AF_INET, addr_str, &address))
1183 {
1185 "Unable to parse address %s\n",
1186 addr_str);
1187 GNUNET_free (addr_str);
1189 return;
1190 }
1191 GNUNET_free (addr_str);
1192 /* Get address to bind to */
1194 "rest",
1195 "BIND_TO6",
1196 &addr_str))
1197 {
1198 // No address specified
1199 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Don't know what to bind6 to...\n");
1201 return;
1202 }
1203 if (1 != inet_pton (AF_INET6, addr_str, &address6))
1204 {
1206 "Unable to parse IPv6 address %s\n",
1207 addr_str);
1208 GNUNET_free (addr_str);
1210 return;
1211 }
1212 GNUNET_free (addr_str);
1213
1215 "rest",
1216 "BASIC_AUTH_ENABLED");
1218 {
1220 "rest",
1221 "BASIC_AUTH_SECRET_FILE",
1222 &basic_auth_file))
1223 {
1225 "No basic auth secret file location set...\n");
1227 return;
1228 }
1229 if (GNUNET_YES != GNUNET_DISK_file_test (basic_auth_file))
1230 {
1232 "No basic auth secret found... generating\n");
1234 UINT64_MAX);
1236 sizeof(secret));
1237 if (GNUNET_OK !=
1238 GNUNET_DISK_fn_write (basic_auth_file,
1240 strlen (basic_auth_secret),
1244 "write",
1245 basic_auth_file);
1246 GNUNET_free (basic_auth_file);
1247 }
1248 else
1249 {
1250 char basic_auth_secret_tmp[16]; // Should be more than enough
1251 memset (basic_auth_secret_tmp, 0, 16);
1252 if (GNUNET_SYSERR == GNUNET_DISK_fn_read (basic_auth_file,
1253 basic_auth_secret_tmp,
1254 sizeof (basic_auth_secret_tmp)
1255 - 1))
1256 {
1258 "Unable to read basic auth secret file.\n");
1260 GNUNET_free (basic_auth_file);
1261 return;
1262 }
1263 GNUNET_free (basic_auth_file);
1264 if (0 != getlogin_r (cuser, _POSIX_LOGIN_NAME_MAX))
1265 {
1267 "Unable to get user.\n");
1269 return;
1270 }
1271 basic_auth_secret = GNUNET_strdup (basic_auth_secret_tmp);
1272 }
1273 }
1274
1275 /* Get CORS data from cfg */
1276 echo_origin =
1278 "rest",
1279 "REST_ECHO_ORIGIN_WEBEXT");
1280 allow_origins = NULL;
1282 "rest",
1283 "REST_ALLOW_ORIGIN",
1284 &allow_origins))
1285 {
1287 "No CORS Access-Control-Allow-Origin header will be sent...\n");
1288 }
1289 if (GNUNET_OK !=
1291 "rest",
1292 "REST_ALLOW_CREDENTIALS",
1294 {
1295 // No origin specified
1297 "No CORS Credential Header will be sent...\n");
1298 }
1299
1301 "rest",
1302 "REST_ALLOW_HEADERS",
1303 &allow_headers))
1304 {
1305 // No origin specified
1307 "No CORS Access-Control-Allow-Headers Header will be sent...\n");
1308 }
1309
1310/* Open listen socket proxy */
1311 lsock6 = bind_v6 ();
1312 if (NULL == lsock6)
1313 {
1315 }
1316 else
1317 {
1319 {
1322 lsock6 = NULL;
1323 }
1324 else
1325 {
1327 lsock6,
1328 &do_accept,
1329 lsock6);
1330 }
1331 }
1332 lsock4 = bind_v4 ();
1333 if (NULL == lsock4)
1334 {
1336 }
1337 else
1338 {
1340 {
1343 lsock4 = NULL;
1344 }
1345 else
1346 {
1348 lsock4,
1349 &do_accept,
1350 lsock4);
1351 }
1352 }
1353 if ((NULL == lsock4) && (NULL == lsock6))
1354 {
1356 return;
1357 }
1358 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service listens on port %llu\n",
1359 port);
1360 httpd = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_NO_LISTEN_SOCKET
1361 | MHD_ALLOW_SUSPEND_RESUME,
1362 0,
1363 NULL,
1364 NULL,
1366 NULL,
1367 MHD_OPTION_CONNECTION_TIMEOUT,
1368 (unsigned int) 16,
1369 MHD_OPTION_NOTIFY_CONNECTION,
1371 NULL,
1372 MHD_OPTION_URI_LOG_CALLBACK,
1374 NULL,
1375 MHD_OPTION_NOTIFY_COMPLETED,
1377 NULL,
1378 MHD_OPTION_END);
1379 if (NULL == httpd)
1380 {
1382 return;
1383 }
1384 /* Load plugins */
1385 // FIXME: Use per-plugin rest plugin structs
1389 {
1391 }
1395 {
1397 }
1402 {
1404 }
1409 {
1411 }
1414 gns_plugin))
1415 {
1417 }
1418#if HAVE_JOSE
1419 openid_plugin = REST_openid_init (cfg);
1420 if (GNUNET_OK != setup_plugin (openid_plugin->name,
1421 &REST_openid_process_request, openid_plugin))
1422 {
1424 }
1425#endif
1429 {
1431 }
1433}
1434
1435
1436GNUNET_DAEMON_MAIN ("rest", _ ("GNUnet REST service"), &run)
1437
1438/* end of gnunet-rest-server.c */
void * REST_config_init(const struct GNUNET_CONFIGURATION_Handle *c)
Entry point for the plugin.
enum GNUNET_GenericReturnValue REST_config_process_request(void *plugin, struct GNUNET_REST_RequestHandle *conndata_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
void REST_config_done(struct GNUNET_REST_Plugin *api)
Exit point from the plugin.
enum GNUNET_GenericReturnValue REST_copying_process_request(void *plugin, struct GNUNET_REST_RequestHandle *conndata_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
void REST_copying_done(struct GNUNET_REST_Plugin *api)
Exit point from the plugin.
void * REST_copying_init(const struct GNUNET_CONFIGURATION_Handle *c)
Entry point for the plugin.
void * REST_gns_init(const struct GNUNET_CONFIGURATION_Handle *c)
Entry point for the plugin.
Definition gns_plugin.c:431
void REST_gns_done(struct GNUNET_REST_Plugin *api)
Exit point from the plugin.
Definition gns_plugin.c:463
enum GNUNET_GenericReturnValue REST_gns_process_request(void *plugin, struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
Definition gns_plugin.c:386
static int ret
Final status code.
Definition gnunet-arm.c:93
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition gnunet-arm.c:118
static int do_shutdown
Set to GNUNET_YES if we are shutting down.
static struct GNUNET_TESTING_PluginFunctions * plugin
Plugin to dynamically load a test case.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static char * filename
static char * name
Name (label) of the records to list.
static char origin[GNUNET_DNSPARSER_MAX_NAME_LENGTH]
Current origin.
static char * value
Value of the record to add/remove.
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition gnunet-nat.c:85
static int status
The program status; 0 for success.
Definition gnunet-nse.c:39
static char * allow_origins
Allowed Origins (CORS)
static void plugin_callback(void *cls, struct MHD_Response *resp, int status)
Plugin result callback.
#define GNUNET_REST_SERVICE_PORT
Default Socks5 listen port.
static struct AcceptedRequest * req_list_head
AcceptedRequest list head.
static int basic_auth_enabled
Do basic auth of user.
static struct GNUNET_NETWORK_Handle * bind_v4()
Create an IPv4 listen socket bound to our port.
static void run_mhd_now()
Run MHD now, we have extra data ready for the callback.
static struct MHD_Daemon * httpd
Daemon for HTTP.
char cuser[_POSIX_LOGIN_NAME_MAX]
User of the service.
static MHD_RESULT post_data_iter(void *cls, enum MHD_ValueKind kind, const char *key, const char *filename, const char *content_type, const char *transfer_encoding, const char *data, uint64_t off, size_t size)
static struct GNUNET_NETWORK_Handle * bind_v6()
Create an IPv6 listen socket bound to our port.
static struct GNUNET_NETWORK_Handle * lsock6
The listen socket of the service for IPv6.
#define GN_REST_STATE_INIT
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static char * allow_headers
Allowed Headers (CORS)
static char * basic_auth_secret
Basic auth secret.
static MHD_RESULT create_response(void *cls, struct MHD_Connection *con, const char *url, const char *meth, const char *ver, const char *upload_data, size_t *upload_data_size, void **con_cls)
Main MHD callback for handling requests.
static struct GNUNET_NETWORK_Handle * lsock4
The listen socket of the service for IPv4.
static void kill_httpd()
Kill the MHD daemon.
static struct in6_addr address6
The IPv6 address to bind to.
static unsigned long long port
The port the service is running on (default 7776)
struct GNUNET_REST_Plugin * copying_plugin
#define GN_REST_STATE_PROCESSING
static void cleanup_ar(struct AcceptedRequest *ar)
static void * mhd_log_callback(void *cls, const char *url, struct MHD_Connection *connection)
Function called when MHD first processes an incoming connection.
static void mhd_completed_cb(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
Function called when MHD decides that we are done with a connection.
static int url_iterator(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
static int cleanup_url_map(void *cls, const struct GNUNET_HashCode *key, void *value)
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Main function that will be run.
static void do_httpd(void *cls)
Task run whenever HTTP server operations are pending.
struct GNUNET_REST_Plugin * reclaim_plugin
static enum GNUNET_GenericReturnValue setup_plugin(const char *name, GNUNET_REST_ProcessingFunction proc, void *plugin_cls)
Callback for plugin load.
struct GNUNET_REST_Plugin * namestore_plugin
static void do_accept(void *cls)
Accept new incoming connections.
static int header_iterator(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
static struct PluginListEntry * plugins_tail
Plugin list tail.
static struct GNUNET_SCHEDULER_Task * httpd_task
The task ID.
static int echo_origin
Echo request Origin in CORS.
struct GNUNET_REST_Plugin * gns_plugin
static struct AcceptedRequest * req_list_tail
AcceptedRequest list tail.
static char * allow_credentials
Allowed Credentials (CORS)
struct GNUNET_REST_Plugin * config_plugin
plugins
static void schedule_httpd()
Schedule MHD.
static struct MHD_Response * failure_response
Response we return on failures.
struct GNUNET_REST_Plugin * identity_plugin
static in_addr_t address
The address to bind to.
static void mhd_connection_cb(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_ConnectionNotificationCode cnc)
Function called when MHD connection is opened or closed.
static struct PluginListEntry * plugins_head
Plugin list head.
static void cleanup_handle(struct MhdConnectionHandle *handle)
static struct GNUNET_SCHEDULER_Task * ltask6
The listen task ID for IPv6.
static struct GNUNET_SCHEDULER_Task * ltask4
The listen task ID for IPv4.
static struct GNUNET_VPN_Handle * handle
Handle to vpn service.
Definition gnunet-vpn.c:35
#define MHD_RESULT
Data type to use for functions return an "MHD result".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory).
Definition disk.c:533
enum GNUNET_GenericReturnValue GNUNET_DISK_fn_write(const char *fn, const void *buf, size_t buf_size, enum GNUNET_DISK_AccessPermissions mode)
Write a buffer to a file atomically.
Definition disk.c:750
ssize_t GNUNET_DISK_fn_read(const char *fn, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition disk.c:687
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:41
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
#define GNUNET_log(kind,...)
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_SCHEDULER_PRIORITY_DEFAULT
Run with the default priority (normal P2P operations).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
struct sockaddr * GNUNET_NETWORK_get_addr(const struct GNUNET_NETWORK_Handle *desc)
Return the sockaddr for this network handle.
Definition network.c:1014
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_accept(const struct GNUNET_NETWORK_Handle *desc, struct sockaddr *address, socklen_t *address_len)
Accept a new connection on a socket.
Definition network.c:392
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition network.c:508
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition network.c:1185
socklen_t GNUNET_NETWORK_get_addrlen(const struct GNUNET_NETWORK_Handle *desc)
Return sockaddr length for this network handle.
Definition network.c:1027
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition network.c:1001
void GNUNET_NETWORK_fdset_copy_native(struct GNUNET_NETWORK_FDSet *to, const fd_set *from, int nfds)
Copy a native fd set into the GNUnet representation.
Definition network.c:1041
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition network.c:1169
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition network.c:833
void GNUNET_NETWORK_socket_free_memory_only_(struct GNUNET_NETWORK_Handle *desc)
Only free memory of a socket, keep the file descriptor untouched.
Definition network.c:566
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition network.c:439
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition network.c:652
#define GNUNET_DAEMON_MAIN(daemon_name, daemon_help, init_cb)
enum GNUNET_GenericReturnValue(* GNUNET_REST_ProcessingFunction)(void *plugin, struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:567
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1511
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition scheduler.c:1835
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1339
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1304
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition strings.c:807
enum GNUNET_GenericReturnValue GNUNET_STRINGS_utf8_tolower(const char *input, char *output)
Convert the utf-8 input string to lower case.
Definition strings.c:475
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
void REST_identity_done(struct GNUNET_REST_Plugin *api)
Exit point from the plugin.
void * REST_identity_init(const struct GNUNET_CONFIGURATION_Handle *c)
Entry point for the plugin.
enum GNUNET_GenericReturnValue REST_identity_process_request(void *plugin, struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
#define max(x, y)
void REST_namestore_done(struct GNUNET_REST_Plugin *api)
Exit point from the plugin.
void * REST_namestore_init(const struct GNUNET_CONFIGURATION_Handle *c)
Entry point for the plugin.
enum GNUNET_GenericReturnValue REST_namestore_process_request(void *plugin, struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
void REST_openid_done(struct GNUNET_REST_Plugin *api)
Exit point from the plugin.
enum GNUNET_GenericReturnValue REST_openid_process_request(void *plugin, struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
void * REST_openid_init(const struct GNUNET_CONFIGURATION_Handle *c)
Entry point for the plugin.
static unsigned int size
Size of the "table".
Definition peer.c:68
#define _(String)
GNU gettext support macro.
Definition platform.h:179
void * REST_reclaim_init(const struct GNUNET_CONFIGURATION_Handle *c)
Entry point for the plugin.
void REST_reclaim_done(struct GNUNET_REST_Plugin *api)
Exit point from the plugin.
enum GNUNET_GenericReturnValue REST_reclaim_process_request(void *plugin, struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
Accepted requests.
struct AcceptedRequest * prev
DLL.
struct MhdConnectionHandle * con_handle
Connection.
struct GNUNET_NETWORK_Handle * sock
Socket.
struct AcceptedRequest * next
DLL.
A 512-bit hashcode.
collection of IO descriptors
handle to a socket
Definition network.c:53
struct returned by the initialization function of the plugin
void * cls
The closure of the plugin.
const char * name
Plugin name.
struct GNUNET_CONTAINER_MultiHashMap * header_param_map
Map of headers.
const char * data
The POST data.
const char * url
The url as string.
const char * method
The HTTP method as MHD value (see microhttpd.h)
struct GNUNET_CONTAINER_MultiHashMap * url_param_map
Map of url parameters.
size_t data_size
The POST data size.
Time for relative time used by GNUnet, in microseconds.
MHD Connection handle.
struct GNUNET_REST_RequestHandle * data_handle
struct MHD_PostProcessor * pp
struct MHD_Response * response
struct MHD_Connection * con
A plugin list entry.
struct PluginListEntry * prev
char * libname
libname (to cleanup)
GNUNET_REST_ProcessingFunction process_request
Request function.
struct PluginListEntry * next
void * plugin
The plugin.

◆ GN_REST_STATE_INIT

#define GN_REST_STATE_INIT   0

Definition at line 69 of file gnunet-rest-server.c.

◆ GN_REST_STATE_PROCESSING

#define GN_REST_STATE_PROCESSING   1

Definition at line 70 of file gnunet-rest-server.c.

Function Documentation

◆ do_httpd()

static void do_httpd ( void *  cls)
static

Task run whenever HTTP server operations are pending.

Parameters
clsNULL

Definition at line 932 of file gnunet-rest-server.c.

933{
934 httpd_task = NULL;
935 MHD_run (httpd);
937}

References httpd, httpd_task, and schedule_httpd().

Referenced by run_mhd_now(), and schedule_httpd().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run_mhd_now()

static void run_mhd_now ( )
static

Run MHD now, we have extra data ready for the callback.

Definition at line 289 of file gnunet-rest-server.c.

290{
291 if (NULL != httpd_task)
292 {
294 httpd_task = NULL;
295 }
297}

References do_httpd(), GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_cancel(), and httpd_task.

Referenced by create_response(), create_response(), curl_download_cb(), curl_task_download(), curl_upload_cb(), and plugin_callback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ plugin_callback()

static void plugin_callback ( void *  cls,
struct MHD_Response *  resp,
int  status 
)
static

Plugin result callback.

Parameters
clsclosure (MHD connection handle)
datathe data to return to the caller
lenlength of the data
statusGNUNET_OK if successful

Definition at line 309 of file gnunet-rest-server.c.

310{
311 struct MhdConnectionHandle *handle = cls;
312
313 handle->status = status;
314 handle->response = resp;
315 MHD_resume_connection (handle->con);
316 run_mhd_now ();
317}

References handle, run_mhd_now(), and status.

Referenced by create_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cleanup_url_map()

static int cleanup_url_map ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 321 of file gnunet-rest-server.c.

322{
324 return GNUNET_YES;
325}

References GNUNET_free, GNUNET_YES, and value.

Referenced by cleanup_handle().

Here is the caller graph for this function:

◆ cleanup_handle()

static void cleanup_handle ( struct MhdConnectionHandle handle)
static

Definition at line 329 of file gnunet-rest-server.c.

330{
331 if (NULL != handle->response)
332 MHD_destroy_response (handle->response);
333 if (NULL != handle->data_handle)
334 {
335 if (NULL != handle->data_handle->header_param_map)
336 {
338 ->header_param_map,
340 NULL);
342 handle->data_handle->header_param_map);
343 }
344 if (NULL != handle->data_handle->url_param_map)
345 {
346 GNUNET_CONTAINER_multihashmap_iterate (handle->data_handle->url_param_map,
348 NULL);
350 handle->data_handle->url_param_map);
351 }
352 GNUNET_free (handle->data_handle);
353 }
355}

References cleanup_url_map(), GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_free, and handle.

Referenced by cleanup_ar(), and mhd_completed_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cleanup_ar()

static void cleanup_ar ( struct AcceptedRequest ar)
static

Definition at line 359 of file gnunet-rest-server.c.

360{
361 if (NULL != ar->con_handle)
362 {
364 }
365 if (GNUNET_YES == ar->socket_with_mhd)
366 {
368 }
369 else
370 {
372 }
373 ar->sock = NULL;
376 ar);
377 GNUNET_free (ar);
378}

References cleanup_handle(), AcceptedRequest::con_handle, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_free_memory_only_(), GNUNET_YES, req_list_head, req_list_tail, AcceptedRequest::sock, and AcceptedRequest::socket_with_mhd.

Referenced by mhd_connection_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ header_iterator()

static int header_iterator ( void *  cls,
enum MHD_ValueKind  kind,
const char *  key,
const char *  value 
)
static

Definition at line 382 of file gnunet-rest-server.c.

386{
387 struct GNUNET_REST_RequestHandle *handle = cls;
388 struct GNUNET_HashCode hkey;
389 char *val;
390 char *lowerkey;
391
392 lowerkey = GNUNET_strdup (key);
394 GNUNET_CRYPTO_hash (lowerkey, strlen (lowerkey), &hkey);
395 GNUNET_asprintf (&val, "%s", value);
397 handle->header_param_map,
398 &hkey,
399 val,
401 {
403 "Could not load add header `%s'=%s\n",
404 lowerkey,
405 value);
406 }
407 GNUNET_free (lowerkey);
408 return MHD_YES;
409}

References GNUNET_asprintf(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_OK, GNUNET_strdup, GNUNET_STRINGS_utf8_tolower(), handle, key, and value.

Referenced by create_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ url_iterator()

static int url_iterator ( void *  cls,
enum MHD_ValueKind  kind,
const char *  key,
const char *  value 
)
static

Definition at line 413 of file gnunet-rest-server.c.

417{
418 struct GNUNET_REST_RequestHandle *handle = cls;
419 struct GNUNET_HashCode hkey;
420 char *val;
421
422 GNUNET_CRYPTO_hash (key, strlen (key), &hkey);
423 GNUNET_asprintf (&val, "%s", value);
425 handle->url_param_map,
426 &hkey,
427 val,
429 {
431 "Could not load add url param `%s'=%s\n",
432 key,
433 value);
434 }
435 return MHD_YES;
436}

References GNUNET_asprintf(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, handle, key, and value.

Referenced by create_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ post_data_iter()

static MHD_RESULT post_data_iter ( void *  cls,
enum MHD_ValueKind  kind,
const char *  key,
const char *  filename,
const char *  content_type,
const char *  transfer_encoding,
const char *  data,
uint64_t  off,
size_t  size 
)
static

Definition at line 440 of file gnunet-rest-server.c.

449{
450 struct GNUNET_REST_RequestHandle *handle = cls;
451 struct GNUNET_HashCode hkey;
452 char *val;
453
454 if (MHD_POSTDATA_KIND != kind)
455 return MHD_YES;
456
457 GNUNET_CRYPTO_hash (key, strlen (key), &hkey);
458 val = GNUNET_CONTAINER_multihashmap_get (handle->url_param_map,
459 &hkey);
460 if (NULL == val)
461 {
462 val = GNUNET_malloc (65536);
464 handle->url_param_map,
465 &hkey,
466 val,
468 {
470 "Could not add url param '%s'\n",
471 key);
472 GNUNET_free (val);
473 }
474 }
475 memcpy (val + off, data, size);
476 return MHD_YES;
477}

References data, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_OK, handle, key, and size.

Referenced by create_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_response()

static MHD_RESULT create_response ( void *  cls,
struct MHD_Connection *  con,
const char *  url,
const char *  meth,
const char *  ver,
const char *  upload_data,
size_t *  upload_data_size,
void **  con_cls 
)
static

Main MHD callback for handling requests.

Parameters
clsunused
conMHD connection handle
urlthe url in the request
meththe HTTP method used ("GET", "PUT", etc.)
verthe HTTP version string ("HTTP/1.1" for version 1.1, etc.)
upload_datathe data being uploaded (excluding HEADERS, for a POST that fits into memory and that is encoded with a supported encoding, the POST data will NOT be given in upload_data and is instead available as part of MHD_get_connection_values; very large POST data will be made available incrementally in upload_data)
upload_data_sizeset initially to the size of the upload_data provided; the method must update this value to the number of bytes NOT processed;
con_clspointer to location where we store the 'struct Request'
Returns
#MHD_YES if the connection was handled successfully, #MHD_NO if the socket must be closed due to a serious error while handling the request

Request not handled

Definition at line 506 of file gnunet-rest-server.c.

514{
515 char *origin;
516 char *pw;
517 char *user;
518 struct AcceptedRequest *ar;
519 struct GNUNET_HashCode key;
520 struct MhdConnectionHandle *con_handle;
521 struct GNUNET_REST_RequestHandle *rest_conndata_handle;
522 struct PluginListEntry *ple;
523
524 ar = *con_cls;
525 if (NULL == ar)
526 {
527 GNUNET_break (0);
528 return MHD_NO;
529 }
530
531 if (NULL == ar->con_handle)
532 {
533 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New connection %s\n", url);
534 con_handle = GNUNET_new (struct MhdConnectionHandle);
535 con_handle->con = con;
536 con_handle->state = GN_REST_STATE_INIT;
537 ar->con_handle = con_handle;
538 return MHD_YES;
539 }
540 con_handle = ar->con_handle;
541 if (GN_REST_STATE_INIT == con_handle->state)
542 {
543 rest_conndata_handle = GNUNET_new (struct GNUNET_REST_RequestHandle);
544 rest_conndata_handle->method = meth;
545 rest_conndata_handle->url = url;
546 rest_conndata_handle->data = upload_data;
547 rest_conndata_handle->data_size = *upload_data_size;
548 rest_conndata_handle->url_param_map =
550 rest_conndata_handle->header_param_map =
552 con_handle->data_handle = rest_conndata_handle;
553 MHD_get_connection_values (con,
554 MHD_GET_ARGUMENT_KIND,
555 (MHD_KeyValueIterator) & url_iterator,
556 rest_conndata_handle);
557 MHD_get_connection_values (con,
558 MHD_HEADER_KIND,
559 (MHD_KeyValueIterator) & header_iterator,
560 rest_conndata_handle);
562 {
563 pw = NULL;
564 user = MHD_basic_auth_get_username_password (con, &pw);
565 if ((NULL == user) ||
566 (0 != strcmp (user, cuser)))
567 {
569 "Unknown user %s\n", user);
570 MHD_queue_basic_auth_fail_response (con, "gnunet", failure_response);
571 return MHD_YES;
572 }
573 if ((NULL == pw) ||
574 (0 != strcmp (pw, basic_auth_secret)))
575 {
577 "Password incorrect\n");
578 MHD_queue_basic_auth_fail_response (con, "gnunet", failure_response);
579 GNUNET_free (pw);
580 return MHD_YES;
581 }
582 GNUNET_free (pw);
583 }
584
585 con_handle->pp = MHD_create_post_processor (con,
586 65536,
588 rest_conndata_handle);
589 if (*upload_data_size)
590 {
591 MHD_post_process (con_handle->pp, upload_data, *upload_data_size);
592 }
593 MHD_destroy_post_processor (con_handle->pp);
594
595 con_handle->state = GN_REST_STATE_PROCESSING;
596 for (ple = plugins_head; NULL != ple; ple = ple->next)
597 {
598 if (GNUNET_YES == ple->process_request (ple->plugin,
599 rest_conndata_handle,
601 con_handle))
602 break; /* Request handled */
603 }
604 if (NULL == ple)
605 {
607 MHD_queue_response (con, MHD_HTTP_NOT_FOUND, failure_response);
608 }
609 *upload_data_size = 0;
610 run_mhd_now ();
611 return MHD_YES;
612 }
613 if (NULL == con_handle->response)
614 {
615 // Suspend connection until plugin is done
616 MHD_suspend_connection (con_handle->con);
617 return MHD_YES;
618 }
619 // MHD_resume_connection (con_handle->con);
621 "Queueing response from plugin with MHD\n");
622 // Handle Preflights for extensions
623 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking origin\n");
624 GNUNET_CRYPTO_hash ("origin", strlen ("origin"), &key);
627 &key);
628 if (NULL != origin)
629 {
630 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Origin: %s\n", origin);
631 // Only echo for browser plugins
632 if (GNUNET_YES == echo_origin)
633 {
634 if ((0 ==
635 strncmp ("moz-extension://", origin, strlen ("moz-extension://"))) ||
636 (0 == strncmp ("chrome-extension://",
637 origin,
638 strlen ("chrome-extension://"))))
639 {
640 GNUNET_assert (MHD_NO != MHD_add_response_header (con_handle->response,
641 MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
642 origin));
643 }
644 }
645 if (NULL != allow_origins)
646 {
647 char *tmp = GNUNET_strdup (allow_origins);
648 char *allow_origin = strtok (tmp, ",");
649 while (NULL != allow_origin)
650 {
651 if (0 == strncmp (allow_origin, origin, strlen (allow_origin)))
652 {
653 GNUNET_assert (MHD_NO != MHD_add_response_header (
654 con_handle->response,
655 MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
656 allow_origin));
657 break;
658 }
659 allow_origin = strtok (NULL, ",");
660 }
661 GNUNET_free (tmp);
662 }
663 }
664 if (NULL != allow_credentials)
665 {
666 GNUNET_assert (MHD_NO != MHD_add_response_header (con_handle->response,
667 "Access-Control-Allow-Credentials",
669 }
670 if (NULL != allow_headers)
671 {
672 GNUNET_assert (MHD_NO != MHD_add_response_header (con_handle->response,
673 "Access-Control-Allow-Headers",
675 }
676 run_mhd_now ();
677 {
678 MHD_RESULT ret = MHD_queue_response (con,
679 con_handle->status,
680 con_handle->response);
681 // cleanup_handle (con_handle);
682 return ret;
683 }
684}

References allow_credentials, allow_headers, allow_origins, basic_auth_enabled, basic_auth_secret, MhdConnectionHandle::con, AcceptedRequest::con_handle, cuser, GNUNET_REST_RequestHandle::data, MhdConnectionHandle::data_handle, GNUNET_REST_RequestHandle::data_size, echo_origin, failure_response, GN_REST_STATE_INIT, GN_REST_STATE_PROCESSING, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multihashmap_create(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_strdup, GNUNET_YES, header_iterator(), GNUNET_REST_RequestHandle::header_param_map, key, GNUNET_REST_RequestHandle::method, MHD_RESULT, PluginListEntry::next, origin, PluginListEntry::plugin, plugin_callback(), plugins_head, post_data_iter(), MhdConnectionHandle::pp, PluginListEntry::process_request, MhdConnectionHandle::response, ret, run_mhd_now(), MhdConnectionHandle::state, MhdConnectionHandle::status, GNUNET_REST_RequestHandle::url, url_iterator(), and GNUNET_REST_RequestHandle::url_param_map.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ kill_httpd()

static void kill_httpd ( )
static

Kill the MHD daemon.

Definition at line 694 of file gnunet-rest-server.c.

695{
696 if (NULL != httpd)
697 {
698 MHD_stop_daemon (httpd);
699 httpd = NULL;
700 }
701 if (NULL != httpd_task)
702 {
704 httpd_task = NULL;
705 }
706 if (NULL != ltask4)
707 {
709 ltask4 = NULL;
710 }
711 if (NULL != ltask6)
712 {
714 ltask6 = NULL;
715 }
716
717 if (NULL != lsock4)
718 {
720 lsock4 = NULL;
721 }
722 if (NULL != lsock6)
723 {
725 lsock6 = NULL;
726 }
727}

References GNUNET_NETWORK_socket_close(), GNUNET_SCHEDULER_cancel(), httpd, httpd_task, lsock4, lsock6, ltask4, and ltask6.

Referenced by do_shutdown(), do_shutdown(), kill_httpd_task(), schedule_httpd(), and schedule_httpd().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ schedule_httpd()

static void schedule_httpd ( )
static

Schedule MHD.

This function should be called initially when an MHD is first getting its client socket, and will then automatically always be called later whenever there is work to be done.

Parameters
hdthe daemon to schedule

Definition at line 738 of file gnunet-rest-server.c.

739{
740 fd_set rs;
741 fd_set ws;
742 fd_set es;
743 struct GNUNET_NETWORK_FDSet *wrs;
744 struct GNUNET_NETWORK_FDSet *wws;
745 int max;
746 int haveto;
747 MHD_UNSIGNED_LONG_LONG timeout;
748 struct GNUNET_TIME_Relative tv;
749
750 FD_ZERO (&rs);
751 FD_ZERO (&ws);
752 FD_ZERO (&es);
753 max = -1;
754 if (MHD_YES != MHD_get_fdset (httpd, &rs, &ws, &es, &max))
755 {
756 kill_httpd ();
757 return;
758 }
759 haveto = MHD_get_timeout (httpd, &timeout);
760 if (MHD_YES == haveto)
761 tv.rel_value_us = (uint64_t) timeout * 1000LL;
762 else
764 if (-1 != max)
765 {
770 }
771 else
772 {
773 wrs = NULL;
774 wws = NULL;
775 }
776 if (NULL != httpd_task)
777 {
779 httpd_task = NULL;
780 }
781 if ((MHD_YES == haveto) || (-1 != max))
782 {
784 tv,
785 wrs,
786 wws,
787 &do_httpd,
788 NULL);
789 }
790 if (NULL != wrs)
792 if (NULL != wws)
794}

References do_httpd(), GNUNET_NETWORK_fdset_copy_native(), GNUNET_NETWORK_fdset_create(), GNUNET_NETWORK_fdset_destroy(), GNUNET_SCHEDULER_add_select(), GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_TIME_UNIT_FOREVER_REL, httpd, httpd_task, kill_httpd(), max, GNUNET_TIME_Relative::rel_value_us, and timeout.

Referenced by do_accept(), do_httpd(), do_httpd(), and setup_data_transfer().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mhd_log_callback()

static void * mhd_log_callback ( void *  cls,
const char *  url,
struct MHD_Connection *  connection 
)
static

Function called when MHD first processes an incoming connection.

Gives us the respective URI information.

We use this to associate the struct MHD_Connection with our internal struct AcceptedRequest data structure (by checking for matching sockets).

Parameters
clsthe HTTP server handle (a struct MhdHttpList)
urlthe URL that is being requested
connectionMHD connection object for the request
Returns
the struct Socks5Request that this connection is for

Definition at line 811 of file gnunet-rest-server.c.

814{
815 struct AcceptedRequest *ar;
816 const union MHD_ConnectionInfo *ci;
817
818 ci = MHD_get_connection_info (connection,
819 MHD_CONNECTION_INFO_SOCKET_CONTEXT);
820 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing %s\n", url);
821 if (NULL == ci)
822 {
823 GNUNET_break (0);
824 return NULL;
825 }
826 ar = ci->socket_context;
827 return ar;
828}

References GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, and GNUNET_log.

Referenced by run().

Here is the caller graph for this function:

◆ mhd_completed_cb()

static void mhd_completed_cb ( void *  cls,
struct MHD_Connection *  connection,
void **  con_cls,
enum MHD_RequestTerminationCode  toe 
)
static

Function called when MHD decides that we are done with a connection.

Parameters
clsNULL
connectionconnection handle
con_clsvalue as set by the last call to the MHD_AccessHandlerCallback, should be our handle
toereason for request termination (ignored)

Definition at line 841 of file gnunet-rest-server.c.

845{
846 struct AcceptedRequest *ar = *con_cls;
847 if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe)
849 "MHD encountered error handling request: %d\n",
850 toe);
851 if (NULL == ar)
852 return;
853 if (NULL != ar->con_handle)
854 {
856 ar->con_handle = NULL;
857 }
859 *con_cls = NULL;
860}

References cleanup_handle(), AcceptedRequest::con_handle, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_YES, and AcceptedRequest::socket_with_mhd.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mhd_connection_cb()

static void mhd_connection_cb ( void *  cls,
struct MHD_Connection *  connection,
void **  con_cls,
enum MHD_ConnectionNotificationCode  cnc 
)
static

Function called when MHD connection is opened or closed.

Parameters
clsNULL
connectionconnection handle
con_clsvalue as set by the last call to the MHD_AccessHandlerCallback, should be our struct Socks5Request *
toeconnection notification type

Definition at line 873 of file gnunet-rest-server.c.

877{
878 struct AcceptedRequest *ar;
879 const union MHD_ConnectionInfo *ci;
880 int sock;
881
882 switch (cnc)
883 {
884 case MHD_CONNECTION_NOTIFY_STARTED:
885 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection started...\n");
886 ci = MHD_get_connection_info (connection,
887 MHD_CONNECTION_INFO_CONNECTION_FD);
888 if (NULL == ci)
889 {
890 GNUNET_break (0);
891 return;
892 }
893 sock = ci->connect_fd;
894 for (ar = req_list_head; NULL != ar; ar = ar->next)
895 {
896 if (GNUNET_NETWORK_get_fd (ar->sock) == sock)
897 {
899 "Context set...\n");
900 *con_cls = ar;
901 break;
902 }
903 }
904 break;
905
906 case MHD_CONNECTION_NOTIFY_CLOSED:
908 "Connection closed... cleaning up\n");
909 ar = *con_cls;
910 if (NULL == ar)
911 {
913 "Connection stale!\n");
914 return;
915 }
916 cleanup_ar (ar);
917 *con_cls = NULL;
918 break;
919
920 default:
921 GNUNET_break (0);
922 }
923}

References cleanup_ar(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_NETWORK_get_fd(), AcceptedRequest::next, req_list_head, and AcceptedRequest::sock.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_accept()

static void do_accept ( void *  cls)
static

Accept new incoming connections.

Parameters
clsthe closure with the lsock4 or lsock6

Definition at line 946 of file gnunet-rest-server.c.

947{
948 struct GNUNET_NETWORK_Handle *lsock = cls;
949 struct AcceptedRequest *ar;
950 int fd;
951 const struct sockaddr *addr;
952 socklen_t len;
953
954 GNUNET_assert (NULL != lsock);
955 if (lsock == lsock4)
956 {
958 lsock,
959 &do_accept,
960 lsock);
961 }
962 else if (lsock == lsock6)
963 {
965 lsock,
966 &do_accept,
967 lsock);
968 }
969 else
970 GNUNET_assert (0);
971 ar = GNUNET_new (struct AcceptedRequest);
973 ar->sock = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL);
974 if (NULL == ar->sock)
975 {
976 GNUNET_free (ar);
978 return;
979 }
981 "Got an inbound connection, waiting for data\n");
982 fd = GNUNET_NETWORK_get_fd (ar->sock);
983 addr = GNUNET_NETWORK_get_addr (ar->sock);
987 ar);
988 if (MHD_YES != MHD_add_connection (httpd, fd, addr, len))
989 {
991 GNUNET_free (ar);
993 _ ("Failed to pass client to MHD\n"));
994 return;
995 }
997}

References _, do_accept(), GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_get_addr(), GNUNET_NETWORK_get_addrlen(), GNUNET_NETWORK_get_fd(), GNUNET_NETWORK_socket_accept(), GNUNET_NETWORK_socket_close(), GNUNET_new, GNUNET_SCHEDULER_add_read_net(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, httpd, lsock4, lsock6, ltask4, ltask6, req_list_head, req_list_tail, schedule_httpd(), AcceptedRequest::sock, and AcceptedRequest::socket_with_mhd.

Referenced by do_accept(), and run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_shutdown()

static void do_shutdown ( void *  cls)
static

Task run on shutdown.

Parameters
clsclosure

Definition at line 1006 of file gnunet-rest-server.c.

1007{
1008 struct PluginListEntry *ple;
1009
1010 while (NULL != plugins_head)
1011 {
1012 ple = plugins_head;
1015 ple);
1016 GNUNET_free (ple->libname);
1017 GNUNET_free (ple);
1018 }
1024#if HAVE_JOSE
1025 REST_openid_done (openid_plugin);
1026#endif
1028 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
1029 kill_httpd ();
1032 MHD_destroy_response (failure_response);
1033}

References allow_credentials, allow_headers, config_plugin, copying_plugin, failure_response, gns_plugin, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_log, identity_plugin, kill_httpd(), PluginListEntry::libname, namestore_plugin, plugins_head, plugins_tail, reclaim_plugin, REST_config_done(), REST_copying_done(), REST_gns_done(), REST_identity_done(), REST_namestore_done(), REST_openid_done(), and REST_reclaim_done().

Here is the call graph for this function:

◆ bind_v4()

static struct GNUNET_NETWORK_Handle * bind_v4 ( )
static

Create an IPv4 listen socket bound to our port.

Returns
NULL on error

Definition at line 1042 of file gnunet-rest-server.c.

1043{
1044 struct GNUNET_NETWORK_Handle *ls;
1045 struct sockaddr_in sa4;
1046 int eno;
1047
1048 memset (&sa4, 0, sizeof(sa4));
1049 sa4.sin_family = AF_INET;
1050 sa4.sin_port = htons (port);
1051 sa4.sin_addr.s_addr = address;
1052#if HAVE_SOCKADDR_IN_SIN_LEN
1053 sa4.sin_len = sizeof(sa4);
1054#endif
1055 ls = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0);
1056 if (NULL == ls)
1057 return NULL;
1059 (const struct sockaddr *) &sa4,
1060 sizeof(sa4)))
1061 {
1062 eno = errno;
1064 errno = eno;
1065 return NULL;
1066 }
1067 return ls;
1068}

References address, GNUNET_NETWORK_socket_bind(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_OK, ls, and port.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ bind_v6()

static struct GNUNET_NETWORK_Handle * bind_v6 ( )
static

Create an IPv6 listen socket bound to our port.

Returns
NULL on error

Definition at line 1077 of file gnunet-rest-server.c.

1078{
1079 struct GNUNET_NETWORK_Handle *ls;
1080 struct sockaddr_in6 sa6;
1081 int eno;
1082
1083 memset (&sa6, 0, sizeof(sa6));
1084 sa6.sin6_family = AF_INET6;
1085 sa6.sin6_port = htons (port);
1086 sa6.sin6_addr = address6;
1087#if HAVE_SOCKADDR_IN_SIN_LEN
1088 sa6.sin6_len = sizeof(sa6);
1089#endif
1090 ls = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_STREAM, 0);
1091 if (NULL == ls)
1092 return NULL;
1094 (const struct sockaddr *) &sa6,
1095 sizeof(sa6)))
1096 {
1097 eno = errno;
1099 errno = eno;
1100 return NULL;
1101 }
1102 return ls;
1103}

References address6, GNUNET_NETWORK_socket_bind(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_OK, ls, and port.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_plugin()

static enum GNUNET_GenericReturnValue setup_plugin ( const char *  name,
GNUNET_REST_ProcessingFunction  proc,
void *  plugin_cls 
)
static

Callback for plugin load.

Parameters
clsNULL
libnamethe name of the library loaded
lib_retthe object returned by the plugin initializer

Definition at line 1114 of file gnunet-rest-server.c.

1117{
1118 struct PluginListEntry *ple;
1119
1120 if (NULL == plugin_cls)
1121 {
1123 "Could not load plugin\n");
1124 return GNUNET_SYSERR;
1125 }
1126 GNUNET_assert (1 < strlen (name));
1127 GNUNET_assert ('/' == *name);
1128 ple = GNUNET_new (struct PluginListEntry);
1129 ple->libname = GNUNET_strdup (name);
1130 ple->plugin = plugin_cls;
1131 ple->process_request = proc;
1134 ple);
1135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded plugin `%s'\n", name);
1136 return GNUNET_OK;
1137}

References GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_new, GNUNET_OK, GNUNET_strdup, GNUNET_SYSERR, PluginListEntry::libname, name, PluginListEntry::plugin, plugins_head, plugins_tail, and PluginListEntry::process_request.

Referenced by run().

Here is the caller graph for this function:

◆ run()

static void run ( void *  cls,
char *const *  args,
const char *  cfgfile,
const struct GNUNET_CONFIGURATION_Handle c 
)
static

Main function that will be run.

Parameters
clsclosure
argsremaining command-line arguments
cfgfilename of the configuration file used (for saving, can be NULL)
cconfiguration

Definition at line 1149 of file gnunet-rest-server.c.

1153{
1154 static const char *err_page = "{}";
1155 char *addr_str;
1156 char *basic_auth_file;
1157 uint64_t secret;
1158
1159 cfg = c;
1160 plugins_head = NULL;
1161 plugins_tail = NULL;
1162 failure_response = MHD_create_response_from_buffer (strlen (err_page),
1163 (void *) err_page,
1164 MHD_RESPMEM_PERSISTENT);
1165 /* Get port to bind to */
1166 if (GNUNET_OK !=
1167 GNUNET_CONFIGURATION_get_value_number (cfg, "rest", "HTTP_PORT", &port))
1168 {
1169 // No address specified
1170 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using default port...\n");
1172 }
1173
1174 /* Get address to bind to */
1175 if (GNUNET_OK !=
1176 GNUNET_CONFIGURATION_get_value_string (cfg, "rest", "BIND_TO", &addr_str))
1177 {
1178 // No address specified
1179 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Don't know what to bind to...\n");
1181 return;
1182 }
1183 if (1 != inet_pton (AF_INET, addr_str, &address))
1184 {
1186 "Unable to parse address %s\n",
1187 addr_str);
1188 GNUNET_free (addr_str);
1190 return;
1191 }
1192 GNUNET_free (addr_str);
1193 /* Get address to bind to */
1195 "rest",
1196 "BIND_TO6",
1197 &addr_str))
1198 {
1199 // No address specified
1200 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Don't know what to bind6 to...\n");
1202 return;
1203 }
1204 if (1 != inet_pton (AF_INET6, addr_str, &address6))
1205 {
1207 "Unable to parse IPv6 address %s\n",
1208 addr_str);
1209 GNUNET_free (addr_str);
1211 return;
1212 }
1213 GNUNET_free (addr_str);
1214
1216 "rest",
1217 "BASIC_AUTH_ENABLED");
1219 {
1221 "rest",
1222 "BASIC_AUTH_SECRET_FILE",
1223 &basic_auth_file))
1224 {
1226 "No basic auth secret file location set...\n");
1228 return;
1229 }
1230 if (GNUNET_YES != GNUNET_DISK_file_test (basic_auth_file))
1231 {
1233 "No basic auth secret found... generating\n");
1235 UINT64_MAX);
1237 sizeof(secret));
1238 if (GNUNET_OK !=
1239 GNUNET_DISK_fn_write (basic_auth_file,
1241 strlen (basic_auth_secret),
1245 "write",
1246 basic_auth_file);
1247 GNUNET_free (basic_auth_file);
1248 }
1249 else
1250 {
1251 char basic_auth_secret_tmp[16]; // Should be more than enough
1252 memset (basic_auth_secret_tmp, 0, 16);
1253 if (GNUNET_SYSERR == GNUNET_DISK_fn_read (basic_auth_file,
1254 basic_auth_secret_tmp,
1255 sizeof (basic_auth_secret_tmp)
1256 - 1))
1257 {
1259 "Unable to read basic auth secret file.\n");
1261 GNUNET_free (basic_auth_file);
1262 return;
1263 }
1264 GNUNET_free (basic_auth_file);
1265 if (0 != getlogin_r (cuser, _POSIX_LOGIN_NAME_MAX))
1266 {
1268 "Unable to get user.\n");
1270 return;
1271 }
1272 basic_auth_secret = GNUNET_strdup (basic_auth_secret_tmp);
1273 }
1274 }
1275
1276 /* Get CORS data from cfg */
1277 echo_origin =
1279 "rest",
1280 "REST_ECHO_ORIGIN_WEBEXT");
1281 allow_origins = NULL;
1283 "rest",
1284 "REST_ALLOW_ORIGIN",
1285 &allow_origins))
1286 {
1288 "No CORS Access-Control-Allow-Origin header will be sent...\n");
1289 }
1290 if (GNUNET_OK !=
1292 "rest",
1293 "REST_ALLOW_CREDENTIALS",
1295 {
1296 // No origin specified
1298 "No CORS Credential Header will be sent...\n");
1299 }
1300
1302 "rest",
1303 "REST_ALLOW_HEADERS",
1304 &allow_headers))
1305 {
1306 // No origin specified
1308 "No CORS Access-Control-Allow-Headers Header will be sent...\n");
1309 }
1310
1311/* Open listen socket proxy */
1312 lsock6 = bind_v6 ();
1313 if (NULL == lsock6)
1314 {
1316 }
1317 else
1318 {
1320 {
1323 lsock6 = NULL;
1324 }
1325 else
1326 {
1328 lsock6,
1329 &do_accept,
1330 lsock6);
1331 }
1332 }
1333 lsock4 = bind_v4 ();
1334 if (NULL == lsock4)
1335 {
1337 }
1338 else
1339 {
1341 {
1344 lsock4 = NULL;
1345 }
1346 else
1347 {
1349 lsock4,
1350 &do_accept,
1351 lsock4);
1352 }
1353 }
1354 if ((NULL == lsock4) && (NULL == lsock6))
1355 {
1357 return;
1358 }
1359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service listens on port %llu\n",
1360 port);
1361 httpd = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_NO_LISTEN_SOCKET
1362 | MHD_ALLOW_SUSPEND_RESUME,
1363 0,
1364 NULL,
1365 NULL,
1367 NULL,
1368 MHD_OPTION_CONNECTION_TIMEOUT,
1369 (unsigned int) 16,
1370 MHD_OPTION_NOTIFY_CONNECTION,
1372 NULL,
1373 MHD_OPTION_URI_LOG_CALLBACK,
1375 NULL,
1376 MHD_OPTION_NOTIFY_COMPLETED,
1378 NULL,
1379 MHD_OPTION_END);
1380 if (NULL == httpd)
1381 {
1383 return;
1384 }
1385 /* Load plugins */
1386 // FIXME: Use per-plugin rest plugin structs
1390 {
1392 }
1396 {
1398 }
1403 {
1405 }
1410 {
1412 }
1415 gns_plugin))
1416 {
1418 }
1419#if HAVE_JOSE
1420 openid_plugin = REST_openid_init (cfg);
1421 if (GNUNET_OK != setup_plugin (openid_plugin->name,
1422 &REST_openid_process_request, openid_plugin))
1423 {
1425 }
1426#endif
1430 {
1432 }
1434}

References address, address6, allow_credentials, allow_headers, allow_origins, basic_auth_enabled, basic_auth_secret, bind_v4(), bind_v6(), cfg, config_plugin, copying_plugin, create_response(), cuser, do_accept(), do_shutdown, echo_origin, failure_response, gns_plugin, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u64(), GNUNET_DISK_file_test(), GNUNET_DISK_fn_read(), GNUNET_DISK_fn_write(), GNUNET_DISK_PERM_USER_READ, GNUNET_DISK_PERM_USER_WRITE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_log_strerror, GNUNET_log_strerror_file, GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_listen(), GNUNET_OK, GNUNET_REST_SERVICE_PORT, GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), GNUNET_strdup, GNUNET_STRINGS_data_to_string_alloc(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, httpd, identity_plugin, lsock4, lsock6, ltask4, ltask6, mhd_completed_cb(), mhd_connection_cb(), mhd_log_callback(), GNUNET_REST_Plugin::name, namestore_plugin, plugins_head, plugins_tail, port, reclaim_plugin, REST_config_init(), REST_config_process_request(), REST_copying_init(), REST_copying_process_request(), REST_gns_init(), REST_gns_process_request(), REST_identity_init(), REST_identity_process_request(), REST_namestore_init(), REST_namestore_process_request(), REST_openid_init(), REST_openid_process_request(), REST_reclaim_init(), REST_reclaim_process_request(), and setup_plugin().

Here is the call graph for this function:

Variable Documentation

◆ httpd_task

struct GNUNET_SCHEDULER_Task* httpd_task
static

The task ID.

Definition at line 75 of file gnunet-rest-server.c.

Referenced by do_httpd(), kill_httpd(), run_mhd_now(), and schedule_httpd().

◆ address

in_addr_t address
static

The address to bind to.

Definition at line 80 of file gnunet-rest-server.c.

Referenced by bind_v4(), and run().

◆ address6

struct in6_addr address6
static

The IPv6 address to bind to.

Definition at line 85 of file gnunet-rest-server.c.

Referenced by bind_v6(), and run().

◆ port

unsigned long long port = 7776
static

The port the service is running on (default 7776)

Definition at line 90 of file gnunet-rest-server.c.

Referenced by bind_v4(), bind_v6(), and run().

◆ lsock4

struct GNUNET_NETWORK_Handle* lsock4
static

The listen socket of the service for IPv4.

Definition at line 95 of file gnunet-rest-server.c.

Referenced by do_accept(), kill_httpd(), and run().

◆ lsock6

struct GNUNET_NETWORK_Handle* lsock6
static

The listen socket of the service for IPv6.

Definition at line 100 of file gnunet-rest-server.c.

Referenced by do_accept(), kill_httpd(), and run().

◆ ltask4

struct GNUNET_SCHEDULER_Task* ltask4
static

The listen task ID for IPv4.

Definition at line 105 of file gnunet-rest-server.c.

Referenced by do_accept(), kill_httpd(), and run().

◆ ltask6

struct GNUNET_SCHEDULER_Task* ltask6
static

The listen task ID for IPv6.

Definition at line 110 of file gnunet-rest-server.c.

Referenced by do_accept(), kill_httpd(), and run().

◆ httpd

struct MHD_Daemon* httpd
static

Daemon for HTTP.

Definition at line 115 of file gnunet-rest-server.c.

Referenced by do_accept(), do_httpd(), kill_httpd(), run(), and schedule_httpd().

◆ failure_response

struct MHD_Response* failure_response
static

Response we return on failures.

Definition at line 120 of file gnunet-rest-server.c.

Referenced by create_response(), do_shutdown(), and run().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Our configuration.

Definition at line 125 of file gnunet-rest-server.c.

Referenced by run().

◆ echo_origin

int echo_origin
static

Echo request Origin in CORS.

Definition at line 130 of file gnunet-rest-server.c.

Referenced by create_response(), and run().

◆ basic_auth_enabled

int basic_auth_enabled
static

Do basic auth of user.

Definition at line 135 of file gnunet-rest-server.c.

Referenced by create_response(), and run().

◆ basic_auth_secret

char* basic_auth_secret
static

Basic auth secret.

Definition at line 140 of file gnunet-rest-server.c.

Referenced by create_response(), and run().

◆ cuser

char cuser[_POSIX_LOGIN_NAME_MAX]

User of the service.

Definition at line 145 of file gnunet-rest-server.c.

Referenced by create_response(), and run().

◆ allow_origins

char* allow_origins
static

Allowed Origins (CORS)

Definition at line 150 of file gnunet-rest-server.c.

Referenced by create_response(), and run().

◆ allow_headers

char* allow_headers
static

Allowed Headers (CORS)

Definition at line 155 of file gnunet-rest-server.c.

Referenced by create_response(), do_shutdown(), and run().

◆ allow_credentials

char* allow_credentials
static

Allowed Credentials (CORS)

Definition at line 160 of file gnunet-rest-server.c.

Referenced by create_response(), do_shutdown(), and run().

◆ plugins_head

struct PluginListEntry* plugins_head
static

Plugin list head.

Definition at line 165 of file gnunet-rest-server.c.

Referenced by create_response(), do_shutdown(), run(), and setup_plugin().

◆ plugins_tail

struct PluginListEntry* plugins_tail
static

Plugin list tail.

Definition at line 170 of file gnunet-rest-server.c.

Referenced by do_shutdown(), run(), and setup_plugin().

◆ req_list_head

struct AcceptedRequest* req_list_head
static

AcceptedRequest list head.

Definition at line 251 of file gnunet-rest-server.c.

Referenced by cleanup_ar(), do_accept(), and mhd_connection_cb().

◆ req_list_tail

struct AcceptedRequest* req_list_tail
static

AcceptedRequest list tail.

Definition at line 256 of file gnunet-rest-server.c.

Referenced by cleanup_ar(), and do_accept().

◆ config_plugin

struct GNUNET_REST_Plugin* config_plugin

plugins

Definition at line 263 of file gnunet-rest-server.c.

Referenced by do_shutdown(), and run().

◆ copying_plugin

struct GNUNET_REST_Plugin* copying_plugin

Definition at line 264 of file gnunet-rest-server.c.

Referenced by do_shutdown(), and run().

◆ identity_plugin

struct GNUNET_REST_Plugin* identity_plugin

Definition at line 265 of file gnunet-rest-server.c.

Referenced by do_shutdown(), and run().

◆ namestore_plugin

struct GNUNET_REST_Plugin* namestore_plugin

Definition at line 266 of file gnunet-rest-server.c.

Referenced by do_shutdown(), and run().

◆ gns_plugin

struct GNUNET_REST_Plugin* gns_plugin

Definition at line 267 of file gnunet-rest-server.c.

Referenced by do_shutdown(), and run().

◆ reclaim_plugin

struct GNUNET_REST_Plugin* reclaim_plugin

Definition at line 271 of file gnunet-rest-server.c.

Referenced by do_shutdown(), and run().