GNUnet  0.11.x
gnunet-rest-server.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2012-2015 GNUnet e.V.
4 
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.
9 
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.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
26 #include "platform.h"
27 #include <microhttpd.h>
28 #include "gnunet_util_lib.h"
29 #include "gnunet_rest_plugin.h"
30 #include "gnunet_mhd_compat.h"
31 
35 #define GNUNET_REST_SERVICE_PORT 7776
36 
41 #define MAX_HTTP_URI_LENGTH 2048
42 
46 #define HTTP_PORT 80
47 
51 #define HTTPS_PORT 443
52 
56 #define MHD_CACHE_TIMEOUT \
57  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
58 
59 #define GN_REST_STATE_INIT 0
60 #define GN_REST_STATE_PROCESSING 1
61 
66 
70 static in_addr_t address;
71 
75 static struct in6_addr address6;
76 
80 static unsigned long long port = GNUNET_REST_SERVICE_PORT;
81 
86 
91 
96 
101 
105 static struct MHD_Daemon *httpd;
106 
110 static struct MHD_Response *failure_response;
111 
115 static const struct GNUNET_CONFIGURATION_Handle *cfg;
116 
121 
125 static int echo_origin;
126 
130 static char *allow_origins;
131 
135 static char *allow_headers;
136 
140 static char *allow_credentials;
141 
146 {
147  struct MHD_Connection *con;
148 
149  struct MHD_Response *response;
150 
152 
154 
155  struct MHD_PostProcessor *pp;
156 
157  int status;
158 
159  int state;
160 };
161 
162 /* ************************* Global helpers ********************* */
163 
164 
170 static void
171 do_httpd (void *cls);
172 
173 
177 static void
179 {
180  if (NULL != httpd_task)
181  {
182  GNUNET_SCHEDULER_cancel (httpd_task);
183  httpd_task = NULL;
184  }
185  httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL);
186 }
187 
188 
197 static void
198 plugin_callback (void *cls, struct MHD_Response *resp, int status)
199 {
200  struct MhdConnectionHandle *handle = cls;
201 
202  handle->status = status;
203  handle->response = resp;
204  MHD_resume_connection (handle->con);
205  run_mhd_now ();
206 }
207 
208 
209 static int
210 cleanup_url_map (void *cls, const struct GNUNET_HashCode *key, void *value)
211 {
212  GNUNET_free (value);
213  return GNUNET_YES;
214 }
215 
216 
217 static void
219 {
220  if (NULL != handle->response)
221  MHD_destroy_response (handle->response);
222  if (NULL != handle->data_handle)
223  {
224  if (NULL != handle->data_handle->header_param_map)
225  {
229  NULL);
231  handle->data_handle->header_param_map);
232  }
233  if (NULL != handle->data_handle->url_param_map)
234  {
237  NULL);
239  handle->data_handle->url_param_map);
240  }
241  GNUNET_free (handle->data_handle);
242  }
243  GNUNET_free (handle);
244 }
245 
246 
247 static int
248 header_iterator (void *cls,
249  enum MHD_ValueKind kind,
250  const char *key,
251  const char *value)
252 {
253  struct GNUNET_REST_RequestHandle *handle = cls;
254  struct GNUNET_HashCode hkey;
255  char *val;
256  char *lowerkey;
257 
258  lowerkey = GNUNET_strdup (key);
259  GNUNET_STRINGS_utf8_tolower (key, lowerkey);
260  GNUNET_CRYPTO_hash (lowerkey, strlen (lowerkey), &hkey);
261  GNUNET_asprintf (&val, "%s", value);
263  handle->header_param_map,
264  &hkey,
265  val,
267  {
269  "Could not load add header `%s'=%s\n",
270  lowerkey,
271  value);
272  }
273  GNUNET_free (lowerkey);
274  return MHD_YES;
275 }
276 
277 
278 static int
279 url_iterator (void *cls,
280  enum MHD_ValueKind kind,
281  const char *key,
282  const char *value)
283 {
284  struct GNUNET_REST_RequestHandle *handle = cls;
285  struct GNUNET_HashCode hkey;
286  char *val;
287 
288  GNUNET_CRYPTO_hash (key, strlen (key), &hkey);
289  GNUNET_asprintf (&val, "%s", value);
291  handle->url_param_map,
292  &hkey,
293  val,
295  {
297  "Could not load add url param `%s'=%s\n",
298  key,
299  value);
300  }
301  return MHD_YES;
302 }
303 
304 
305 static MHD_RESULT
306 post_data_iter (void *cls,
307  enum MHD_ValueKind kind,
308  const char *key,
309  const char *filename,
310  const char *content_type,
311  const char *transfer_encoding,
312  const char *data,
313  uint64_t off,
314  size_t size)
315 {
316  struct GNUNET_REST_RequestHandle *handle = cls;
317  struct GNUNET_HashCode hkey;
318  char *val;
319 
320  if (MHD_POSTDATA_KIND != kind)
321  return MHD_YES;
322 
323  GNUNET_CRYPTO_hash (key, strlen (key), &hkey);
324  GNUNET_asprintf (&val, "%s", data);
326  handle->url_param_map,
327  &hkey,
328  val,
330  {
332  "Could not load add url param '%s'=%s\n",
333  key,
334  data);
335  GNUNET_free (val);
336  }
337  return MHD_YES;
338 }
339 
340 
341 /* ********************************* MHD response generation ******************* */
342 
366 static MHD_RESULT
367 create_response (void *cls,
368  struct MHD_Connection *con,
369  const char *url,
370  const char *meth,
371  const char *ver,
372  const char *upload_data,
373  size_t *upload_data_size,
374  void **con_cls)
375 {
376  char *plugin_name;
377  char *origin;
378  struct GNUNET_HashCode key;
379  struct MhdConnectionHandle *con_handle;
380  struct GNUNET_REST_RequestHandle *rest_conndata_handle;
381 
382  con_handle = *con_cls;
383 
384  if (NULL == *con_cls)
385  {
386  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New connection %s\n", url);
387  char tmp_url[strlen (url) + 1];
388  strcpy (tmp_url, url);
389  con_handle = GNUNET_new (struct MhdConnectionHandle);
390  con_handle->con = con;
391  con_handle->state = GN_REST_STATE_INIT;
392  *con_cls = con_handle;
393 
394  plugin_name = strtok (tmp_url, "/");
395 
396  if (NULL != plugin_name)
397  {
398  GNUNET_CRYPTO_hash (plugin_name, strlen (plugin_name), &key);
399 
400  con_handle->plugin = GNUNET_CONTAINER_multihashmap_get (plugin_map, &key);
401  }
402  if (NULL == con_handle->plugin)
403  {
404  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Queueing response with MHD\n");
405  GNUNET_free (con_handle);
406  return MHD_queue_response (con, MHD_HTTP_NOT_FOUND, failure_response);
407  }
408 
409  return MHD_YES;
410  }
411  if (GN_REST_STATE_INIT == con_handle->state)
412  {
413  rest_conndata_handle = GNUNET_new (struct GNUNET_REST_RequestHandle);
414  rest_conndata_handle->method = meth;
415  rest_conndata_handle->url = url;
416  rest_conndata_handle->data = upload_data;
417  rest_conndata_handle->data_size = *upload_data_size;
418  rest_conndata_handle->url_param_map =
420  rest_conndata_handle->header_param_map =
422  con_handle->data_handle = rest_conndata_handle;
423  MHD_get_connection_values (con,
424  MHD_GET_ARGUMENT_KIND,
425  (MHD_KeyValueIterator) & url_iterator,
426  rest_conndata_handle);
427  MHD_get_connection_values (con,
428  MHD_HEADER_KIND,
429  (MHD_KeyValueIterator) & header_iterator,
430  rest_conndata_handle);
431  con_handle->pp = MHD_create_post_processor (con,
432  65536,
434  rest_conndata_handle);
435  if (*upload_data_size)
436  {
437  MHD_post_process (con_handle->pp, upload_data, *upload_data_size);
438  }
439  MHD_destroy_post_processor (con_handle->pp);
440 
441  con_handle->state = GN_REST_STATE_PROCESSING;
442  con_handle->plugin->process_request (rest_conndata_handle,
444  con_handle);
445  *upload_data_size = 0;
446  run_mhd_now ();
447  return MHD_YES;
448  }
449  if (NULL == con_handle->response)
450  {
451  // Suspend connection until plugin is done
452  MHD_suspend_connection (con_handle->con);
453  return MHD_YES;
454  }
455  MHD_resume_connection (con_handle->con);
457  "Queueing response from plugin with MHD\n");
458  // Handle Preflights for extensions
459  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking origin\n");
460  GNUNET_CRYPTO_hash ("origin", strlen ("origin"), &key);
461  origin = GNUNET_CONTAINER_multihashmap_get (con_handle->data_handle
463  &key);
464  if (NULL != origin)
465  {
466  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Origin: %s\n", origin);
467  // Only echo for browser plugins
468  if (GNUNET_YES == echo_origin)
469  {
470  if ((0 ==
471  strncmp ("moz-extension://", origin, strlen ("moz-extension://"))) ||
472  (0 == strncmp ("chrome-extension://",
473  origin,
474  strlen ("chrome-extension://"))))
475  {
476  MHD_add_response_header (con_handle->response,
477  MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
478  origin);
479  }
480  }
481  if (NULL != allow_origins)
482  {
483  char *tmp = GNUNET_strdup (allow_origins);
484  char *allow_origin = strtok (tmp, ",");
485  while (NULL != allow_origin)
486  {
487  if (0 == strncmp (allow_origin, origin, strlen (allow_origin)))
488  {
489  MHD_add_response_header (con_handle->response,
490  MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
491  allow_origin);
492  break;
493  }
494  allow_origin = strtok (NULL, ",");
495  }
496  GNUNET_free (tmp);
497  }
498  }
499  if (NULL != allow_credentials)
500  {
501  MHD_add_response_header (con_handle->response,
502  "Access-Control-Allow-Credentials",
504  }
505  if (NULL != allow_headers)
506  {
507  MHD_add_response_header (con_handle->response,
508  "Access-Control-Allow-Headers",
509  allow_headers);
510  }
511  run_mhd_now ();
512  {
513  MHD_RESULT ret = MHD_queue_response (con,
514  con_handle->status,
515  con_handle->response);
516  cleanup_handle (con_handle);
517  return ret;
518  }
519 }
520 
521 
522 /* ******************** MHD HTTP setup and event loop ******************** */
523 
533 static void
534 mhd_completed_cb (void *cls,
535  struct MHD_Connection *connection,
536  void **con_cls,
537  enum MHD_RequestTerminationCode toe)
538 {
539  if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe)
541  "MHD encountered error handling request: %d\n",
542  toe);
543 }
544 
545 
549 static void
551 {
552  if (NULL != httpd)
553  {
554  MHD_stop_daemon (httpd);
555  httpd = NULL;
556  }
557  if (NULL != httpd_task)
558  {
559  GNUNET_SCHEDULER_cancel (httpd_task);
560  httpd_task = NULL;
561  }
562  if (NULL != ltask4)
563  {
564  GNUNET_SCHEDULER_cancel (ltask4);
565  ltask4 = NULL;
566  }
567  if (NULL != ltask6)
568  {
569  GNUNET_SCHEDULER_cancel (ltask6);
570  ltask6 = NULL;
571  }
572 
573  if (NULL != lsock4)
574  {
576  lsock4 = NULL;
577  }
578  if (NULL != lsock6)
579  {
581  lsock6 = NULL;
582  }
583 }
584 
585 
593 static void
595 {
596  fd_set rs;
597  fd_set ws;
598  fd_set es;
599  struct GNUNET_NETWORK_FDSet *wrs;
600  struct GNUNET_NETWORK_FDSet *wws;
601  int max;
602  int haveto;
603  MHD_UNSIGNED_LONG_LONG timeout;
604  struct GNUNET_TIME_Relative tv;
605 
606  FD_ZERO (&rs);
607  FD_ZERO (&ws);
608  FD_ZERO (&es);
609  max = -1;
610  if (MHD_YES != MHD_get_fdset (httpd, &rs, &ws, &es, &max))
611  {
612  kill_httpd ();
613  return;
614  }
615  haveto = MHD_get_timeout (httpd, &timeout);
616  if (MHD_YES == haveto)
617  tv.rel_value_us = (uint64_t) timeout * 1000LL;
618  else
620  if (-1 != max)
621  {
624  GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
625  GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
626  }
627  else
628  {
629  wrs = NULL;
630  wws = NULL;
631  }
632  if (NULL != httpd_task)
633  {
634  GNUNET_SCHEDULER_cancel (httpd_task);
635  httpd_task = NULL;
636  }
637  if ((MHD_YES == haveto) || (-1 != max))
638  {
640  tv,
641  wrs,
642  wws,
643  &do_httpd,
644  NULL);
645  }
646  if (NULL != wrs)
648  if (NULL != wws)
650 }
651 
652 
658 static void
659 do_httpd (void *cls)
660 {
661  httpd_task = NULL;
662  MHD_run (httpd);
663  schedule_httpd ();
664 }
665 
666 
673 static void
674 do_accept (void *cls)
675 {
676  struct GNUNET_NETWORK_Handle *lsock = cls;
677  struct GNUNET_NETWORK_Handle *s;
678  int fd;
679  const struct sockaddr *addr;
680  socklen_t len;
681 
682  GNUNET_assert (NULL != lsock);
683  if (lsock == lsock4)
684  {
686  lsock,
687  &do_accept,
688  lsock);
689  }
690  else if (lsock == lsock6)
691  {
693  lsock,
694  &do_accept,
695  lsock);
696  }
697  else
698  GNUNET_assert (0);
699  s = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL);
700  if (NULL == s)
701  {
703  return;
704  }
706  "Got an inbound connection, waiting for data\n");
707  fd = GNUNET_NETWORK_get_fd (s);
708  addr = GNUNET_NETWORK_get_addr (s);
709  len = GNUNET_NETWORK_get_addrlen (s);
710  if (MHD_YES != MHD_add_connection (httpd, fd, addr, len))
711  {
713  _ ("Failed to pass client to MHD\n"));
714  return;
715  }
716  GNUNET_free (s);
717  schedule_httpd ();
718 }
719 
720 
726 static void
727 do_shutdown (void *cls)
728 {
729  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
730  kill_httpd ();
733 }
734 
735 
741 static struct GNUNET_NETWORK_Handle *
743 {
744  struct GNUNET_NETWORK_Handle *ls;
745  struct sockaddr_in sa4;
746  int eno;
747 
748  memset (&sa4, 0, sizeof(sa4));
749  sa4.sin_family = AF_INET;
750  sa4.sin_port = htons (port);
751  sa4.sin_addr.s_addr = address;
752 #if HAVE_SOCKADDR_IN_SIN_LEN
753  sa4.sin_len = sizeof(sa4);
754 #endif
755  ls = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0);
756  if (NULL == ls)
757  return NULL;
759  (const struct sockaddr *) &sa4,
760  sizeof(sa4)))
761  {
762  eno = errno;
764  errno = eno;
765  return NULL;
766  }
767  return ls;
768 }
769 
770 
776 static struct GNUNET_NETWORK_Handle *
778 {
779  struct GNUNET_NETWORK_Handle *ls;
780  struct sockaddr_in6 sa6;
781  int eno;
782 
783  memset (&sa6, 0, sizeof(sa6));
784  sa6.sin6_family = AF_INET6;
785  sa6.sin6_port = htons (port);
786  sa6.sin6_addr = address6;
787 #if HAVE_SOCKADDR_IN_SIN_LEN
788  sa6.sin6_len = sizeof(sa6);
789 #endif
790  ls = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_STREAM, 0);
791  if (NULL == ls)
792  return NULL;
794  (const struct sockaddr *) &sa6,
795  sizeof(sa6)))
796  {
797  eno = errno;
799  errno = eno;
800  return NULL;
801  }
802  return ls;
803 }
804 
805 
813 static void
814 load_plugin (void *cls, const char *libname, void *lib_ret)
815 {
816  struct GNUNET_REST_Plugin *plugin = lib_ret;
817  struct GNUNET_HashCode key;
818 
819  if (NULL == lib_ret)
820  {
822  "Could not load plugin `%s'\n",
823  libname);
824  return;
825  }
826  GNUNET_assert (1 < strlen (plugin->name));
827  GNUNET_assert ('/' == *plugin->name);
828  GNUNET_CRYPTO_hash (plugin->name + 1, strlen (plugin->name + 1), &key);
830  plugin_map,
831  &key,
832  plugin,
834  {
836  "Could not load add plugin `%s'\n",
837  libname);
838  return;
839  }
840  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded plugin `%s'\n", libname);
841 }
842 
843 
852 static void
853 run (void *cls,
854  char *const *args,
855  const char *cfgfile,
856  const struct GNUNET_CONFIGURATION_Handle *c)
857 {
858  char *addr_str;
859 
860  cfg = c;
862 
863  /* Get port to bind to */
864  if (GNUNET_OK !=
865  GNUNET_CONFIGURATION_get_value_number (cfg, "rest", "HTTP_PORT", &port))
866  {
867  // No address specified
868  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using default port...\n");
870  }
871 
872  /* Get address to bind to */
873  if (GNUNET_OK !=
874  GNUNET_CONFIGURATION_get_value_string (cfg, "rest", "BIND_TO", &addr_str))
875  {
876  // No address specified
877  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Don't know what to bind to...\n");
879  return;
880  }
881  if (1 != inet_pton (AF_INET, addr_str, &address))
882  {
884  "Unable to parse address %s\n",
885  addr_str);
886  GNUNET_free (addr_str);
888  return;
889  }
890  GNUNET_free (addr_str);
891  /* Get address to bind to */
893  "rest",
894  "BIND_TO6",
895  &addr_str))
896  {
897  // No address specified
898  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Don't know what to bind6 to...\n");
900  return;
901  }
902  if (1 != inet_pton (AF_INET6, addr_str, &address6))
903  {
905  "Unable to parse IPv6 address %s\n",
906  addr_str);
907  GNUNET_free (addr_str);
909  return;
910  }
911  GNUNET_free (addr_str);
912 
913 
914  /* Get CORS data from cfg */
915  echo_origin =
917  "rest",
918  "REST_ECHO_ORIGIN_WEBEXT");
919  allow_origins = NULL;
921  "rest",
922  "REST_ALLOW_ORIGIN",
923  &allow_origins))
924  {
926  "No CORS Access-Control-Allow-Origin header will be sent...\n");
927  }
928  if (GNUNET_OK !=
930  "rest",
931  "REST_ALLOW_CREDENTIALS",
933  {
934  // No origin specified
936  "No CORS Credential Header will be sent...\n");
937  }
938 
940  "rest",
941  "REST_ALLOW_HEADERS",
942  &allow_headers))
943  {
944  // No origin specified
946  "No CORS Access-Control-Allow-Headers Header will be sent...\n");
947  }
948 
949  /* Open listen socket proxy */
950  lsock6 = bind_v6 ();
951  if (NULL == lsock6)
952  {
954  }
955  else
956  {
957  if (GNUNET_OK != GNUNET_NETWORK_socket_listen (lsock6, 5))
958  {
961  lsock6 = NULL;
962  }
963  else
964  {
966  lsock6,
967  &do_accept,
968  lsock6);
969  }
970  }
971  lsock4 = bind_v4 ();
972  if (NULL == lsock4)
973  {
975  }
976  else
977  {
978  if (GNUNET_OK != GNUNET_NETWORK_socket_listen (lsock4, 5))
979  {
982  lsock4 = NULL;
983  }
984  else
985  {
987  lsock4,
988  &do_accept,
989  lsock4);
990  }
991  }
992  if ((NULL == lsock4) && (NULL == lsock6))
993  {
995  return;
996  }
997  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service listens on port %llu\n", port);
998  httpd = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_NO_LISTEN_SOCKET
999  | MHD_ALLOW_SUSPEND_RESUME,
1000  0,
1001  NULL,
1002  NULL,
1003  &create_response,
1004  NULL,
1005  MHD_OPTION_CONNECTION_TIMEOUT,
1006  (unsigned int) 16,
1007  MHD_OPTION_NOTIFY_COMPLETED,
1009  NULL,
1010  MHD_OPTION_END);
1011  if (NULL == httpd)
1012  {
1014  return;
1015  }
1016  /* Load plugins */
1017  GNUNET_PLUGIN_load_all ("libgnunet_plugin_rest",
1018  (void *) cfg,
1019  &load_plugin,
1020  NULL);
1022 }
1023 
1024 
1034 int
1035 main (int argc, char *const *argv)
1036 {
1037  struct GNUNET_GETOPT_CommandLineOption options[] =
1039  static const char *err_page = "{}";
1040  int ret;
1041 
1042  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1043  return 2;
1044  GNUNET_log_setup ("gnunet-rest-server", "WARNING", NULL);
1045  failure_response = MHD_create_response_from_buffer (strlen (err_page),
1046  (void *) err_page,
1047  MHD_RESPMEM_PERSISTENT);
1048  ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc,
1049  argv,
1050  "gnunet-rest-server",
1051  _ ("GNUnet REST server"),
1052  options,
1053  &run,
1054  NULL))
1055  ? 0
1056  : 1;
1057  MHD_destroy_response (failure_response);
1058  GNUNET_free_nz ((char *) argv);
1059  return ret;
1060 }
1061 
1062 
1063 /* end of gnunet-rest-server.c */
int GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition: network.c:708
static char * allow_headers
Allowed Headers (CORS)
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1080
struct sockaddr * GNUNET_NETWORK_get_addr(const struct GNUNET_NETWORK_Handle *desc)
Return the sockaddr for this network handle.
Definition: network.c:1093
static struct MHD_Response * failure_response
Response we return on failures.
static unsigned long long port
The port the service is running on (default 7776)
int 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.
uint64_t rel_value_us
The actual value.
static void load_plugin(void *cls, const char *libname, void *lib_ret)
Callback for plugin load.
static struct GNUNET_SCHEDULER_Task * httpd_task
The task ID.
#define GNUNET_REST_SERVICE_PORT
Default Socks5 listen port.
socklen_t GNUNET_NETWORK_get_addrlen(const struct GNUNET_NETWORK_Handle *desc)
Return sockaddr length for this network handle.
Definition: network.c:1106
size_t data_size
The POST data size.
MHD Connection handle.
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, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1331
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1457
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void do_accept(void *cls)
Accept new incoming connections.
static struct in6_addr address6
The IPv6 address to bind to.
static void kill_httpd()
Kill the MHD daemon.
struct GNUNET_REST_RequestHandle * data_handle
int 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:485
struct GNUNET_REST_Plugin * plugin
struct returned by the initialization function of the plugin
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Definition of a command line option.
void(* process_request)(struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function to process a REST call.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:531
static void cleanup_handle(struct MhdConnectionHandle *handle)
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
Internal representation of the hash map.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
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:1120
static int url_iterator(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
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.
#define _(String)
GNU gettext support macro.
Definition: platform.h:184
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:430
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.
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1266
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
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.
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1250
static int echo_origin
Echo request Origin in CORS.
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static char * value
Value of the record to add/remove.
#define GN_REST_STATE_INIT
struct GNUNET_CONTAINER_MultiHashMap * url_param_map
Map of url parameters.
static struct GNUNET_NETWORK_Handle * lsock4
The listen socket of the service for IPv4.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
const char * url
The url as string.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
static struct GNUNET_SCHEDULER_Task * ltask6
The listen task ID for IPv6.
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:1296
char * name
Plugin name.
static char * allow_origins
Allowed Origins (CORS)
collection of IO descriptors
const char * method
The HTTP method as MHD value (see microhttpd.h)
static char * filename
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:1841
static int header_iterator(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static void do_shutdown(void *cls)
Task run on shutdown.
static in_addr_t address
The address to bind to.
A 512-bit hashcode.
static struct GNUNET_NETWORK_Handle * lsock6
The listen socket of the service for IPv6.
int 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.
#define GN_REST_STATE_PROCESSING
const char * data
The POST data.
#define GNUNET_free_nz(ptr)
Wrapper around free.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_HashCode key
The key used in the DHT.
static unsigned int size
Size of the "table".
Definition: peer.c:67
static struct GNUNET_SCHEDULER_Task * ltask4
The listen task ID for IPv4.
void GNUNET_PLUGIN_load_all(const char *basename, void *arg, GNUNET_PLUGIN_LoaderCallback cb, void *cb_cls)
Load all compatible plugins with the given base name.
Definition: plugin.c:372
static char * allow_credentials
Allowed Credentials (CORS)
struct MHD_Connection * con
static struct GNUNET_CONTAINER_MultiHashMap * plugin_map
Map of loaded plugins.
int 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.
#define MHD_RESULT
Data type to use for functions return an "MHD result".
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition: gnunet-nat.c:85
struct MHD_PostProcessor * pp
static int cleanup_url_map(void *cls, const struct GNUNET_HashCode *key, void *value)
static struct GNUNET_NETWORK_Handle * bind_v6()
Create an IPv6 listen socket bound to our port.
configuration data
Definition: configuration.c:84
static void do_httpd(void *cls)
Task run whenever HTTP server operations are pending.
static void schedule_httpd()
Schedule MHD.
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
static struct MHD_Daemon * httpd
Daemon for HTTP.
handle to a socket
Definition: network.c:52
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
int GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration, parse options).
Definition: program.c:367
struct GNUNET_CONTAINER_MultiHashMap * header_param_map
Map of headers.
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:1517
Run with the default priority (normal P2P operations).
int GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
Setup logging.
int 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".
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
static void plugin_callback(void *cls, struct MHD_Response *resp, int status)
Plugin result callback.
uint32_t data
The data value.
struct MHD_Response * response
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static void run_mhd_now()
Run MHD now, we have extra data ready for the callback.
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:560
static char * plugin_name
Name of our plugin.
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Main function that will be run.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
int main(int argc, char *const *argv)
The main function for gnunet-rest-service.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
void GNUNET_STRINGS_utf8_tolower(const char *input, char *output)
Convert the utf-8 input string to lower case.
Definition: strings.c:567
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:912
static struct GNUNET_NETWORK_Handle * bind_v4()
Create an IPv4 listen socket bound to our port.
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)
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972