GNUnet  0.10.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 
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  struct MHD_Connection *con;
147 
148  struct MHD_Response *response;
149 
151 
153 
154  struct MHD_PostProcessor *pp;
155 
156  int status;
157 
158  int state;
159 };
160 
161 /* ************************* Global helpers ********************* */
162 
163 
169 static void
170 do_httpd(void *cls);
171 
172 
176 static void
178 {
179  if (NULL != httpd_task)
180  {
181  GNUNET_SCHEDULER_cancel(httpd_task);
182  httpd_task = NULL;
183  }
184  httpd_task = GNUNET_SCHEDULER_add_now(&do_httpd, NULL);
185 }
186 
195 static void
196 plugin_callback(void *cls, struct MHD_Response *resp, int status)
197 {
198  struct MhdConnectionHandle *handle = cls;
199 
200  handle->status = status;
201  handle->response = resp;
202  MHD_resume_connection(handle->con);
203  run_mhd_now();
204 }
205 
206 
207 static int
208 cleanup_url_map(void *cls, const struct GNUNET_HashCode *key, void *value)
209 {
210  GNUNET_free_non_null(value);
211  return GNUNET_YES;
212 }
213 
214 
215 static void
217 {
218  if (NULL != handle->response)
219  MHD_destroy_response(handle->response);
220  if (NULL != handle->data_handle)
221  {
222  if (NULL != handle->data_handle->header_param_map)
223  {
227  NULL);
229  handle->data_handle->header_param_map);
230  }
231  if (NULL != handle->data_handle->url_param_map)
232  {
235  NULL);
237  handle->data_handle->url_param_map);
238  }
239  GNUNET_free(handle->data_handle);
240  }
241  GNUNET_free(handle);
242 }
243 
244 static int
245 header_iterator(void *cls,
246  enum MHD_ValueKind kind,
247  const char *key,
248  const char *value)
249 {
250  struct GNUNET_REST_RequestHandle *handle = cls;
251  struct GNUNET_HashCode hkey;
252  char *val;
253  char *lowerkey;
254 
255  lowerkey = GNUNET_strdup(key);
256  GNUNET_STRINGS_utf8_tolower(key, lowerkey);
257  GNUNET_CRYPTO_hash(lowerkey, strlen(lowerkey), &hkey);
258  GNUNET_asprintf(&val, "%s", value);
260  handle->header_param_map,
261  &hkey,
262  val,
264  {
266  "Could not load add header `%s'=%s\n",
267  lowerkey,
268  value);
269  }
270  GNUNET_free(lowerkey);
271  return MHD_YES;
272 }
273 
274 
275 static int
276 url_iterator(void *cls,
277  enum MHD_ValueKind kind,
278  const char *key,
279  const char *value)
280 {
281  struct GNUNET_REST_RequestHandle *handle = cls;
282  struct GNUNET_HashCode hkey;
283  char *val;
284 
285  GNUNET_CRYPTO_hash(key, strlen(key), &hkey);
286  GNUNET_asprintf(&val, "%s", value);
288  handle->url_param_map,
289  &hkey,
290  val,
292  {
294  "Could not load add url param `%s'=%s\n",
295  key,
296  value);
297  }
298  return MHD_YES;
299 }
300 
301 static int
302 post_data_iter(void *cls,
303  enum MHD_ValueKind kind,
304  const char *key,
305  const char *filename,
306  const char *content_type,
307  const char *transfer_encoding,
308  const char *data,
309  uint64_t off,
310  size_t size)
311 {
312  struct GNUNET_REST_RequestHandle *handle = cls;
313  struct GNUNET_HashCode hkey;
314  char *val;
315 
316  if (MHD_POSTDATA_KIND != kind)
317  return MHD_YES;
318 
319  GNUNET_CRYPTO_hash(key, strlen(key), &hkey);
320  GNUNET_asprintf(&val, "%s", data);
322  handle->url_param_map,
323  &hkey,
324  val,
326  {
328  "Could not load add url param '%s'=%s\n",
329  key,
330  data);
331  GNUNET_free(val);
332  }
333  return MHD_YES;
334 }
335 
336 /* ********************************* MHD response generation ******************* */
337 
361 static int
362 create_response(void *cls,
363  struct MHD_Connection *con,
364  const char *url,
365  const char *meth,
366  const char *ver,
367  const char *upload_data,
368  size_t *upload_data_size,
369  void **con_cls)
370 {
371  char *plugin_name;
372  char *origin;
373  struct GNUNET_HashCode key;
374  struct MhdConnectionHandle *con_handle;
375  struct GNUNET_REST_RequestHandle *rest_conndata_handle;
376 
377  con_handle = *con_cls;
378 
379  if (NULL == *con_cls)
380  {
381  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New connection %s\n", url);
382  char tmp_url[strlen(url) + 1];
383  strcpy(tmp_url, url);
384  con_handle = GNUNET_new(struct MhdConnectionHandle);
385  con_handle->con = con;
386  con_handle->state = GN_REST_STATE_INIT;
387  *con_cls = con_handle;
388 
389  plugin_name = strtok(tmp_url, "/");
390 
391  if (NULL != plugin_name)
392  {
393  GNUNET_CRYPTO_hash(plugin_name, strlen(plugin_name), &key);
394 
395  con_handle->plugin = GNUNET_CONTAINER_multihashmap_get(plugin_map, &key);
396  }
397  if (NULL == con_handle->plugin)
398  {
399  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Queueing response with MHD\n");
400  GNUNET_free(con_handle);
401  return MHD_queue_response(con, MHD_HTTP_NOT_FOUND, failure_response);
402  }
403 
404  return MHD_YES;
405  }
406  if (GN_REST_STATE_INIT == con_handle->state)
407  {
408  rest_conndata_handle = GNUNET_new(struct GNUNET_REST_RequestHandle);
409  rest_conndata_handle->method = meth;
410  rest_conndata_handle->url = url;
411  rest_conndata_handle->data = upload_data;
412  rest_conndata_handle->data_size = *upload_data_size;
413  rest_conndata_handle->url_param_map =
415  rest_conndata_handle->header_param_map =
417  con_handle->data_handle = rest_conndata_handle;
418  MHD_get_connection_values(con,
419  MHD_GET_ARGUMENT_KIND,
420  (MHD_KeyValueIterator) & url_iterator,
421  rest_conndata_handle);
422  MHD_get_connection_values(con,
423  MHD_HEADER_KIND,
424  (MHD_KeyValueIterator) & header_iterator,
425  rest_conndata_handle);
426  con_handle->pp = MHD_create_post_processor(con,
427  65536,
429  rest_conndata_handle);
430  if (*upload_data_size)
431  {
432  MHD_post_process(con_handle->pp, upload_data, *upload_data_size);
433  }
434  MHD_destroy_post_processor(con_handle->pp);
435 
436  con_handle->state = GN_REST_STATE_PROCESSING;
437  con_handle->plugin->process_request(rest_conndata_handle,
439  con_handle);
440  *upload_data_size = 0;
441  run_mhd_now();
442  return MHD_YES;
443  }
444  if (NULL == con_handle->response)
445  {
446  //Suspend connection until plugin is done
447  MHD_suspend_connection(con_handle->con);
448  return MHD_YES;
449  }
450  MHD_resume_connection(con_handle->con);
452  "Queueing response from plugin with MHD\n");
453  //Handle Preflights for extensions
454  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Checking origin\n");
455  GNUNET_CRYPTO_hash("origin", strlen("origin"), &key);
458  &key);
459  if (NULL != origin)
460  {
461  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Origin: %s\n", origin);
462  //Only echo for browser plugins
463  if (GNUNET_YES == echo_origin)
464  {
465  if ((0 ==
466  strncmp("moz-extension://", origin, strlen("moz-extension://"))) ||
467  (0 == strncmp("chrome-extension://",
468  origin,
469  strlen("chrome-extension://"))))
470  {
471  MHD_add_response_header(con_handle->response,
472  MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
473  origin);
474  }
475  }
476  if (NULL != allow_origins)
477  {
478  char *tmp = GNUNET_strdup(allow_origins);
479  char *allow_origin = strtok(tmp, ",");
480  while (NULL != allow_origin)
481  {
482  if (0 == strncmp(allow_origin, origin, strlen(allow_origin)))
483  {
484  MHD_add_response_header(con_handle->response,
485  MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
486  allow_origin);
487  break;
488  }
489  allow_origin = strtok(NULL, ",");
490  }
491  GNUNET_free(tmp);
492  }
493  }
494  if (NULL != allow_credentials)
495  {
496  MHD_add_response_header(con_handle->response,
497  "Access-Control-Allow-Credentials",
499  }
500  if (NULL != allow_headers)
501  {
502  MHD_add_response_header(con_handle->response,
503  "Access-Control-Allow-Headers",
504  allow_headers);
505  }
506  run_mhd_now();
507  int ret = MHD_queue_response(con, con_handle->status, con_handle->response);
508  cleanup_handle(con_handle);
509  return ret;
510 }
511 
512 
513 /* ******************** MHD HTTP setup and event loop ******************** */
514 
524 static void
526  struct MHD_Connection *connection,
527  void **con_cls,
528  enum MHD_RequestTerminationCode toe)
529 {
530  if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe)
532  "MHD encountered error handling request: %d\n",
533  toe);
534 }
535 
536 
540 static void
542 {
543  if (NULL != httpd)
544  {
545  MHD_stop_daemon(httpd);
546  httpd = NULL;
547  }
548  if (NULL != httpd_task)
549  {
550  GNUNET_SCHEDULER_cancel(httpd_task);
551  httpd_task = NULL;
552  }
553  if (NULL != ltask4)
554  {
555  GNUNET_SCHEDULER_cancel(ltask4);
556  ltask4 = NULL;
557  }
558  if (NULL != ltask6)
559  {
560  GNUNET_SCHEDULER_cancel(ltask6);
561  ltask6 = NULL;
562  }
563 
564  if (NULL != lsock4)
565  {
567  lsock4 = NULL;
568  }
569  if (NULL != lsock6)
570  {
572  lsock6 = NULL;
573  }
574 }
575 
576 
584 static void
586 {
587  fd_set rs;
588  fd_set ws;
589  fd_set es;
590  struct GNUNET_NETWORK_FDSet *wrs;
591  struct GNUNET_NETWORK_FDSet *wws;
592  int max;
593  int haveto;
594  MHD_UNSIGNED_LONG_LONG timeout;
595  struct GNUNET_TIME_Relative tv;
596 
597  FD_ZERO(&rs);
598  FD_ZERO(&ws);
599  FD_ZERO(&es);
600  max = -1;
601  if (MHD_YES != MHD_get_fdset(httpd, &rs, &ws, &es, &max))
602  {
603  kill_httpd();
604  return;
605  }
606  haveto = MHD_get_timeout(httpd, &timeout);
607  if (MHD_YES == haveto)
608  tv.rel_value_us = (uint64_t)timeout * 1000LL;
609  else
611  if (-1 != max)
612  {
615  GNUNET_NETWORK_fdset_copy_native(wrs, &rs, max + 1);
616  GNUNET_NETWORK_fdset_copy_native(wws, &ws, max + 1);
617  }
618  else
619  {
620  wrs = NULL;
621  wws = NULL;
622  }
623  if (NULL != httpd_task)
624  {
625  GNUNET_SCHEDULER_cancel(httpd_task);
626  httpd_task = NULL;
627  }
628  if ((MHD_YES == haveto) || (-1 != max))
629  {
631  tv,
632  wrs,
633  wws,
634  &do_httpd,
635  NULL);
636  }
637  if (NULL != wrs)
639  if (NULL != wws)
641 }
642 
648 static void
649 do_httpd(void *cls)
650 {
651  httpd_task = NULL;
652  MHD_run(httpd);
653  schedule_httpd();
654 }
655 
656 
663 static void
664 do_accept(void *cls)
665 {
666  struct GNUNET_NETWORK_Handle *lsock = cls;
667  struct GNUNET_NETWORK_Handle *s;
668  int fd;
669  const struct sockaddr *addr;
670  socklen_t len;
671 
672  GNUNET_assert(NULL != lsock);
673  if (lsock == lsock4)
674  {
676  lsock,
677  &do_accept,
678  lsock);
679  }
680  else if (lsock == lsock6)
681  {
683  lsock,
684  &do_accept,
685  lsock);
686  }
687  else
688  GNUNET_assert(0);
689  s = GNUNET_NETWORK_socket_accept(lsock, NULL, NULL);
690  if (NULL == s)
691  {
693  return;
694  }
696  "Got an inbound connection, waiting for data\n");
697  fd = GNUNET_NETWORK_get_fd(s);
698  addr = GNUNET_NETWORK_get_addr(s);
700  if (MHD_YES != MHD_add_connection(httpd, fd, addr, len))
701  {
703  _("Failed to pass client to MHD\n"));
704  return;
705  }
706  GNUNET_free(s);
707  schedule_httpd();
708 }
709 
710 
716 static void
717 do_shutdown(void *cls)
718 {
719  GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
720  kill_httpd();
723 }
724 
725 
731 static struct GNUNET_NETWORK_Handle *
733 {
734  struct GNUNET_NETWORK_Handle *ls;
735  struct sockaddr_in sa4;
736  int eno;
737 
738  memset(&sa4, 0, sizeof(sa4));
739  sa4.sin_family = AF_INET;
740  sa4.sin_port = htons(port);
741  sa4.sin_addr.s_addr = address;
742 #if HAVE_SOCKADDR_IN_SIN_LEN
743  sa4.sin_len = sizeof(sa4);
744 #endif
745  ls = GNUNET_NETWORK_socket_create(AF_INET, SOCK_STREAM, 0);
746  if (NULL == ls)
747  return NULL;
749  (const struct sockaddr *)&sa4,
750  sizeof(sa4)))
751  {
752  eno = errno;
754  errno = eno;
755  return NULL;
756  }
757  return ls;
758 }
759 
760 
766 static struct GNUNET_NETWORK_Handle *
768 {
769  struct GNUNET_NETWORK_Handle *ls;
770  struct sockaddr_in6 sa6;
771  int eno;
772 
773  memset(&sa6, 0, sizeof(sa6));
774  sa6.sin6_family = AF_INET6;
775  sa6.sin6_port = htons(port);
776  sa6.sin6_addr = address6;
777 #if HAVE_SOCKADDR_IN_SIN_LEN
778  sa6.sin6_len = sizeof(sa6);
779 #endif
780  ls = GNUNET_NETWORK_socket_create(AF_INET6, SOCK_STREAM, 0);
781  if (NULL == ls)
782  return NULL;
784  (const struct sockaddr *)&sa6,
785  sizeof(sa6)))
786  {
787  eno = errno;
789  errno = eno;
790  return NULL;
791  }
792  return ls;
793 }
794 
795 
803 static void
804 load_plugin(void *cls, const char *libname, void *lib_ret)
805 {
806  struct GNUNET_REST_Plugin *plugin = lib_ret;
807  struct GNUNET_HashCode key;
808 
809  if (NULL == lib_ret)
810  {
812  "Could not load plugin `%s'\n",
813  libname);
814  return;
815  }
816  GNUNET_assert(1 < strlen(plugin->name));
817  GNUNET_assert('/' == *plugin->name);
818  GNUNET_CRYPTO_hash(plugin->name + 1, strlen(plugin->name + 1), &key);
820  plugin_map,
821  &key,
822  plugin,
824  {
826  "Could not load add plugin `%s'\n",
827  libname);
828  return;
829  }
830  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Loaded plugin `%s'\n", libname);
831 }
832 
833 
842 static void
843 run(void *cls,
844  char *const *args,
845  const char *cfgfile,
846  const struct GNUNET_CONFIGURATION_Handle *c)
847 {
848  char *addr_str;
849 
850  cfg = c;
852 
853  /* Get port to bind to */
854  if (GNUNET_OK !=
855  GNUNET_CONFIGURATION_get_value_number(cfg, "rest", "HTTP_PORT", &port))
856  {
857  //No address specified
858  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Using default port...\n");
860  }
861 
862  /* Get address to bind to */
863  if (GNUNET_OK !=
864  GNUNET_CONFIGURATION_get_value_string(cfg, "rest", "BIND_TO", &addr_str))
865  {
866  //No address specified
867  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Don't know what to bind to...\n");
869  return;
870  }
871  if (1 != inet_pton(AF_INET, addr_str, &address))
872  {
874  "Unable to parse address %s\n",
875  addr_str);
876  GNUNET_free(addr_str);
878  return;
879  }
880  GNUNET_free(addr_str);
881  /* Get address to bind to */
883  "rest",
884  "BIND_TO6",
885  &addr_str))
886  {
887  //No address specified
888  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Don't know what to bind6 to...\n");
890  return;
891  }
892  if (1 != inet_pton(AF_INET6, addr_str, &address6))
893  {
895  "Unable to parse IPv6 address %s\n",
896  addr_str);
897  GNUNET_free(addr_str);
899  return;
900  }
901  GNUNET_free(addr_str);
902 
903 
904  /* Get CORS data from cfg */
905  echo_origin =
907  "rest",
908  "REST_ECHO_ORIGIN_WEBEXT");
909  allow_origins = NULL;
911  "rest",
912  "REST_ALLOW_ORIGIN",
913  &allow_origins))
914  {
916  "No CORS Access-Control-Allow-Origin header will be sent...\n");
917  }
918  if (GNUNET_OK !=
920  "rest",
921  "REST_ALLOW_CREDENTIALS",
923  {
924  //No origin specified
926  "No CORS Credential Header will be sent...\n");
927  }
928 
930  "rest",
931  "REST_ALLOW_HEADERS",
932  &allow_headers))
933  {
934  //No origin specified
936  "No CORS Access-Control-Allow-Headers Header will be sent...\n");
937  }
938 
939  /* Open listen socket proxy */
940  lsock6 = bind_v6();
941  if (NULL == lsock6)
942  {
944  }
945  else
946  {
947  if (GNUNET_OK != GNUNET_NETWORK_socket_listen(lsock6, 5))
948  {
951  lsock6 = NULL;
952  }
953  else
954  {
956  lsock6,
957  &do_accept,
958  lsock6);
959  }
960  }
961  lsock4 = bind_v4();
962  if (NULL == lsock4)
963  {
965  }
966  else
967  {
968  if (GNUNET_OK != GNUNET_NETWORK_socket_listen(lsock4, 5))
969  {
972  lsock4 = NULL;
973  }
974  else
975  {
977  lsock4,
978  &do_accept,
979  lsock4);
980  }
981  }
982  if ((NULL == lsock4) && (NULL == lsock6))
983  {
985  return;
986  }
987  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Service listens on port %llu\n", port);
988  httpd = MHD_start_daemon(MHD_USE_DEBUG | MHD_USE_NO_LISTEN_SOCKET |
989  MHD_ALLOW_SUSPEND_RESUME,
990  0,
991  NULL,
992  NULL,
994  NULL,
995  MHD_OPTION_CONNECTION_TIMEOUT,
996  (unsigned int)16,
997  MHD_OPTION_NOTIFY_COMPLETED,
999  NULL,
1000  MHD_OPTION_END);
1001  if (NULL == httpd)
1002  {
1004  return;
1005  }
1006  /* Load plugins */
1007  GNUNET_PLUGIN_load_all("libgnunet_plugin_rest",
1008  (void *)cfg,
1009  &load_plugin,
1010  NULL);
1012 }
1013 
1014 
1024 int
1025 main(int argc, char *const *argv)
1026 {
1028  static const char *err_page = "{}";
1029  int ret;
1030 
1031  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv))
1032  return 2;
1033  GNUNET_log_setup("gnunet-rest-server", "WARNING", NULL);
1034  failure_response = MHD_create_response_from_buffer(strlen(err_page),
1035  (void *)err_page,
1036  MHD_RESPMEM_PERSISTENT);
1037  ret = (GNUNET_OK == GNUNET_PROGRAM_run(argc,
1038  argv,
1039  "gnunet-rest-server",
1040  _("GNUnet REST server"),
1041  options,
1042  &run,
1043  NULL))
1044  ? 0
1045  : 1;
1046  MHD_destroy_response(failure_response);
1047  GNUNET_free_non_null((char *)argv);
1048  return ret;
1049 }
1050 
1051 /* 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:696
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:1068
struct sockaddr * GNUNET_NETWORK_get_addr(const struct GNUNET_NETWORK_Handle *desc)
Return the sockaddr for this network handle.
Definition: network.c:1081
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:1094
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:1284
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1439
#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:474
struct GNUNET_REST_Plugin * plugin
struct returned by the initialization function of the plugin
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#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.
static int 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.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
static int ret
Final status code.
Definition: gnunet-arm.c:89
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:1108
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:181
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:420
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:1254
#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.
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1238
static int echo_origin
Echo request Origin in CORS.
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
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:44
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:1264
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:1784
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 char * plugin_name
Solver plugin name as string.
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.
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:66
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:370
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.
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:83
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:131
static struct MHD_Daemon * httpd
Daemon for HTTP.
handle to a socket
Definition: network.c:46
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
#define GNUNET_YES
Definition: gnunet_common.h:77
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:1467
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:548
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.
static int 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)
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:552
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:900
static struct GNUNET_NETWORK_Handle * bind_v4()
Create an IPv4 listen socket bound to our port.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956