GNUnet  0.21.0
gnunet-namestore-fcfsd.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2012-2021 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  */
20 
27 #include "platform.h"
28 #include <microhttpd.h>
29 #include "gnunet_util_lib.h"
31 #include "gnunet_gnsrecord_lib.h"
33 #include "gnunet_mhd_compat.h"
34 #include "gnunet_json_lib.h"
35 
42 struct StaticPage
43 {
48 
52  uint64_t size;
53 
57  struct MHD_Response *response;
58 };
59 
64 {
68  struct MHD_Connection *c;
69 
73  char *body;
74 
78  size_t body_length;
79 
83  int code;
84 
89 
94 
98  void *ptr;
99 
104 
109 
114 };
115 
119 static char *zone = NULL;
120 
124 static unsigned long long port = 18080;
125 
129 static struct GNUNET_NAMESTORE_Handle *namestore = NULL;
130 
134 static struct GNUNET_IDENTITY_Handle *identity = NULL;
135 
139 static const struct GNUNET_CRYPTO_PrivateKey *zone_key = NULL;
140 
144 static struct MHD_Daemon *httpd = NULL;
145 
149 static struct GNUNET_SCHEDULER_Task *httpd_task = NULL;
150 
154 static struct StaticPage *main_page = NULL;
155 
159 static struct StaticPage *notfound_page = NULL;
160 
165 static struct StaticPage *forbidden_page = NULL;
166 
170 static struct GNUNET_TIME_Relative record_exp;
171 
177 static void
178 do_shutdown (void *cls)
179 {
180  /* We cheat a bit here: the file descriptor is implicitly closed by MHD, so
181  calling `GNUNET_DISK_file_close' would generate a spurious warning message
182  in the log. Since that function does nothing but close the descriptor and
183  free the allocated memory, After destroying the response all that's left to
184  do is call `GNUNET_free'. */
185  if (NULL != main_page)
186  {
187  MHD_destroy_response (main_page->response);
190  }
191  if (NULL != notfound_page)
192  {
193  MHD_destroy_response (notfound_page->response);
196  }
197  if (NULL != forbidden_page)
198  {
199  MHD_destroy_response (forbidden_page->response);
202  }
203 
204  if (NULL != namestore)
205  {
207  }
208 
209  if (NULL != identity)
210  {
212  }
213 
214  if (NULL != httpd_task)
215  {
217  }
218  if (NULL != httpd)
219  {
220  MHD_stop_daemon (httpd);
221  }
222 }
223 
224 
230 static void
231 do_httpd (void *cls);
232 
236 static void
237 run_httpd (void)
238 {
239  fd_set rs;
240  fd_set ws;
241  fd_set es;
242 
246 
247  FD_ZERO (&rs);
248  FD_ZERO (&ws);
249  FD_ZERO (&es);
250 
251  int max = -1;
252  GNUNET_assert (MHD_YES == MHD_get_fdset (httpd, &rs, &ws, &es, &max));
253 
254  unsigned MHD_LONG_LONG timeout = 0;
256  if (MHD_YES == MHD_get_timeout (httpd, &timeout))
257  {
259  timeout);
260  }
261 
262  GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
263  GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
264  GNUNET_NETWORK_fdset_copy_native (ges, &es, max + 1);
265 
267  gtime,
268  grs,
269  gws,
270  &do_httpd,
271  NULL);
275 }
276 
277 
283 static void
284 do_httpd (void *cls)
285 {
286  httpd_task = NULL;
287  MHD_run (httpd);
288  run_httpd ();
289 }
290 
291 
292 static void
294 {
295  if (NULL != httpd_task)
296  {
298  httpd_task = NULL;
299  }
301 }
302 
303 
312 static char *
313 make_json (const char *key, const char *value, ...)
314 {
315  va_list args;
316  va_start (args, value);
317 
318  json_t *obj = NULL;
319 
320  obj = json_object ();
321  if ((NULL == key) || (NULL == value))
322  {
323  va_end (args);
324  return json_dumps (obj, JSON_COMPACT);
325  }
326 
327  json_object_set (obj, key, json_string (value));
328 
329  char *k = va_arg (args, char *);
330  if (NULL == k)
331  {
332  va_end (args);
333  return json_dumps (obj, JSON_COMPACT);
334  }
335  char *v = va_arg (args, char *);
336  if (NULL == v)
337  {
338  va_end (args);
339  return json_dumps (obj, JSON_COMPACT);
340  }
341 
342  while (NULL != k && NULL != v)
343  {
344  json_object_set (obj, k, json_string (v));
345  k = va_arg (args, char *);
346  if (NULL != k)
347  {
348  v = va_arg (args, char *);
349  }
350  }
351 
352  va_end (args);
353 
354  char *json = json_dumps (obj, JSON_COMPACT);
355  json_decref (obj);
356 
357  return json;
358 }
359 
360 
366 static void
367 search_error_cb (void *cls)
368 {
369  struct RequestData *rd = cls;
370  MHD_resume_connection (rd->c);
371  rd->searching = NULL;
372  rd->body = make_json ("error", "true",
373  "message", _ ("can not search the namestore"),
374  NULL);
375  rd->body_length = strlen (rd->body);
377  run_httpd_now ();
378 }
379 
380 
390 static void
391 search_done_cb (void *cls,
392  const struct GNUNET_CRYPTO_PrivateKey *zone,
393  const char *label,
394  unsigned int count,
395  const struct GNUNET_GNSRECORD_Data *d)
396 {
397  (void) zone;
398  (void) d;
399 
400  struct RequestData *rd = cls;
401  MHD_resume_connection (rd->c);
402 
403  rd->searching = NULL;
404  rd->body = make_json ("error", "false",
405  "free", (0 == count) ? "true" : "false",
406  NULL);
407  rd->body_length = strlen (rd->body);
408  rd->code = MHD_HTTP_OK;
409 
410  run_httpd_now ();
411 }
412 
413 
419 static void
420 register_error_cb (void *cls)
421 {
422  struct RequestData *rd = cls;
423 
424  MHD_resume_connection (rd->c);
425  rd->searching = NULL;
426  rd->body = make_json ("error", "true",
427  "message", _ ("unable to scan namestore"),
428  NULL);
429  rd->body_length = strlen (rd->body);
431  run_httpd_now ();
432 }
433 
434 
435 static void
436 register_done_cb (void *cls,
437  enum GNUNET_ErrorCode ec)
438 {
439  struct RequestData *rd = cls;
440 
441  MHD_resume_connection (rd->c);
442  rd->searching = NULL;
443 
444  if (GNUNET_EC_NONE != ec)
445  {
447  _ ("Failed to create record for `%s': %s\n"),
448  rd->register_name,
450  rd->body = make_json ("error", "true",
451  "message",
453  NULL);
454  rd->body_length = strlen (rd->body);
456  }
457  else
458  {
459  rd->body = make_json ("error", "false",
460  "message", _ ("no errors"),
461  NULL);
462  rd->body_length = strlen (rd->body);
463  rd->code = MHD_HTTP_OK;
464  }
465 
466  run_httpd_now ();
467 }
468 
469 
479 static void
480 register_do_cb (void *cls,
481  const struct GNUNET_CRYPTO_PrivateKey *key,
482  const char *label,
483  unsigned int count,
484  const struct GNUNET_GNSRECORD_Data *d)
485 {
486  (void) key;
487  (void) d;
488 
489  struct RequestData *rd = cls;
490 
491  rd->searching = NULL;
492 
493  if (0 != count)
494  {
496  _ ("The requested key `%s' exists as `%s'\n"),
497  rd->register_key,
498  label);
499 
500  MHD_resume_connection (rd->c);
501  rd->searching = NULL;
502  rd->body = make_json ("error", "true",
503  "message", _ ("key exists"),
504  NULL);
505  rd->body_length = strlen (rd->body);
506  rd->code = MHD_HTTP_FORBIDDEN;
507  run_httpd_now ();
508  return;
509  }
510 
511  struct GNUNET_GNSRECORD_Data gd;
512  char *gdraw = NULL;
513 
515  &gdraw,
516  &(gd.data_size),
517  &(gd.record_type)))
518  {
520  _ ("Error creating record data\n"));
521  MHD_resume_connection (rd->c);
522  rd->searching = NULL;
523  rd->body = make_json ("error", "true",
524  "message", _ ("unable to store record"),
525  NULL);
526  rd->body_length = strlen (rd->body);
528  run_httpd_now ();
529  return;
530  }
531 
532  gd.data = gdraw;
535 
537  zone_key,
538  rd->register_name,
539  1,
540  &gd,
542  rd);
543 
544  GNUNET_free (gdraw);
545 }
546 
547 
553 static void
554 iterate_error_cb (void *cls)
555 {
556  struct RequestData *rd = cls;
557 
558  MHD_resume_connection (rd->c);
559  rd->iterating = NULL;
560  rd->body = make_json ("error", "true",
561  "message", _ ("unable to scan namestore"),
562  NULL);
563  rd->body_length = strlen (rd->body);
565  run_httpd_now ();
566 }
567 
568 
578 static void
579 iterate_do_cb (void *cls,
580  const struct GNUNET_CRYPTO_PrivateKey *key,
581  const char *label,
582  unsigned int count,
583  const struct GNUNET_GNSRECORD_Data *d)
584 {
585  (void) key;
586  (void) label;
587  (void) d;
588 
589  struct RequestData *rd = cls;
590 
591  if (0 == strcmp (label, rd->register_name))
592  {
593  GNUNET_break (0 != count);
595  _ ("Requested name `%s' exists with `%u' records\n"),
596  rd->register_name,
597  count);
598 
599  MHD_resume_connection (rd->c);
600  rd->body = make_json ("error", "true",
601  "message", _ ("name exists\n"),
602  NULL);
603  rd->body_length = strlen (rd->body);
604  rd->code = MHD_HTTP_FORBIDDEN;
606  run_httpd_now ();
607  return;
608  }
609 
610  GNUNET_NAMESTORE_zone_iterator_next (rd->iterating, 1);
611 }
612 
613 
619 static void
620 iterate_done_cb (void *cls)
621 {
622  struct RequestData *rd = cls;
623 
624  rd->iterating = NULL;
625 
626  /* See if the key was not registered already */
628  zone_key,
629  &(rd->key),
631  rd,
633  rd);
634 }
635 
636 
646 static MHD_RESULT
647 serve_json (struct MHD_Connection *c,
648  char *body,
649  size_t length,
650  int code)
651 {
652  struct MHD_Response *response =
653  MHD_create_response_from_buffer (length,
654  body,
655  MHD_RESPMEM_PERSISTENT);
656  MHD_RESULT r = MHD_queue_response (c, code, response);
657  MHD_destroy_response (response);
658  return r;
659 }
660 
661 
675 static MHD_RESULT
676 create_response (void *cls,
677  struct MHD_Connection *connection,
678  const char *url,
679  const char *method,
680  const char *version,
681  const char *upload_data,
682  size_t *upload_data_size,
683  void **ptr)
684 {
685  (void) cls;
686  (void) version;
687 
688  struct RequestData *rd = *ptr;
689 
690  if (0 == strcmp (method, MHD_HTTP_METHOD_GET))
691  {
692  /* Handle a previously suspended request */
693  if (NULL != rd)
694  {
695  return serve_json (rd->c, rd->body, rd->body_length, rd->code);
696  }
697 
698  if (0 == strcmp ("/", url))
699  {
700  return MHD_queue_response (connection,
701  MHD_HTTP_OK,
703  }
704 
705  if (0 == strcmp ("/search", url))
706  {
707  const char *name = MHD_lookup_connection_value (connection,
708  MHD_GET_ARGUMENT_KIND,
709  "name");
710  if (NULL == name)
711  {
712  return MHD_queue_response (connection,
715  }
716 
717  MHD_suspend_connection (connection);
718  rd = GNUNET_new (struct RequestData);
719  rd->c = connection;
721  zone_key,
722  name,
724  rd,
726  rd);
727  *ptr = rd;
728  return MHD_YES;
729  }
730 
731  return MHD_queue_response (connection,
734  }
735 
736  if (0 == strcmp (method, MHD_HTTP_METHOD_HEAD))
737  {
738  /* We take a shortcut here by always serving the main page: starting a
739  namestore lookup, allocating the necessary resources, waiting for the
740  lookup to complete and then discard everything just because it was a HEAD
741  and thus only the headers are significative, is an unnecessary waste of
742  resources. The handling of this method could be smarter, for example by
743  sending a proper content type header based on the endpoint, but this is
744  not a service in which HEAD requests are significant, so there's no need
745  to spend too much time here. */
746  return MHD_queue_response (connection,
747  MHD_HTTP_OK,
749  }
750 
751  if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
752  {
753  if (0 == strcmp ("/register", url))
754  {
755  /* Handle a previously suspended request */
756  if ((NULL != rd) && (NULL != rd->body))
757  {
758  return serve_json (rd->c, rd->body, rd->body_length, rd->code);
759  }
760 
761  if (NULL == rd)
762  {
763  rd = GNUNET_new (struct RequestData);
764  rd->c = connection;
765  rd->body = NULL;
766  rd->ptr = NULL;
767  *ptr = rd;
768  }
769 
770  json_t *json = NULL;
772  GNUNET_JSON_post_parser (32 * 1024,
773  connection,
774  &(rd->ptr),
775  upload_data,
776  upload_data_size,
777  &json);
778 
779  switch (result)
780  {
782  /* Keep processing POST data */
783  return MHD_YES;
786  rd->body = make_json ("error", "true",
787  "message", _ ("unable to process submitted data"),
788  NULL);
789  rd->body_length = strlen (rd->body);
790 #ifdef MHD_HTTP_CONTENT_TOO_LARGE
792 #else
793  rd->code = MHD_HTTP_PAYLOAD_TOO_LARGE;
794 #endif
795  return MHD_YES;
797  rd->body = make_json ("error", "true",
798  "message", _ ("the submitted data is invalid"),
799  NULL);
800  rd->body_length = strlen (rd->body);
801  rd->code = MHD_HTTP_BAD_REQUEST;
802  return MHD_YES;
803  default:
804  break;
805  }
806 
807  /* POST data has been read in its entirety */
808 
809  const char *name = json_string_value (json_object_get (json, "name"));
810  const char *key = json_string_value (json_object_get (json, "key"));
811  if ((NULL == name) || (NULL == key) || (0 == strlen (name)) || (0 ==
812  strlen (
813  key)))
814  {
815  json_decref (json);
816  rd->body = make_json ("error", "true",
817  "message", _ ("invalid parameters"),
818  NULL);
819  rd->body_length = strlen (rd->body);
820  rd->code = MHD_HTTP_BAD_REQUEST;
821  return MHD_YES;
822  }
823 
824  rd->register_name = strdup (name);
825  rd->register_key = strdup (key);
826 
827  json_decref (json);
829 
830  if ((NULL != strchr (rd->register_name, '.')) ||
831  (NULL != strchr (rd->register_name, '+')))
832  {
833  rd->body = make_json ("error", "true",
834  "message", _ ("invalid name"),
835  NULL);
836  rd->body_length = strlen (rd->body);
837  rd->code = MHD_HTTP_BAD_REQUEST;
838  return MHD_YES;
839  }
840 
841  if (GNUNET_OK != GNUNET_CRYPTO_public_key_from_string (rd->register_key,
842  &(rd->key)))
843  {
845  _ ("Unable to parse key %s\n"),
846  rd->register_key);
847 
848  rd->body = make_json ("error", "true",
849  "message", _ ("unable to parse key"),
850  NULL);
851  rd->body_length = strlen (rd->body);
853  return MHD_YES;
854  }
855 
856  MHD_suspend_connection (connection);
857  /* See if the requested name is free */
858  rd->iterating =
860  zone_key,
862  rd,
863  &iterate_do_cb,
864  rd,
866  rd);
867  return MHD_YES;
868  }
869 
870  return MHD_queue_response (connection,
873  }
874 
875  return MHD_queue_response (connection,
878 }
879 
880 
889 static void
890 completed_cb (void *cls,
891  struct MHD_Connection *connection,
892  void **ptr,
893  enum MHD_RequestTerminationCode status)
894 {
895  (void) cls;
896  (void) connection;
897  (void) status;
898 
899  struct RequestData *rd = *ptr;
900 
901  if (NULL == rd)
902  {
903  return;
904  }
905 
906  if (NULL == rd->body)
907  {
908  GNUNET_free (rd->body);
909  }
910 
911  if (NULL != rd->searching)
912  {
913  GNUNET_NAMESTORE_cancel (rd->searching);
914  }
915 
916  if (NULL != rd->register_name)
917  {
918  GNUNET_free (rd->register_name);
919  }
920 
921  if (NULL != rd->register_key)
922  {
923  GNUNET_free (rd->register_key);
924  }
925 
926  if (NULL != rd->iterating)
927  {
929  }
930 
931  GNUNET_free (rd);
932 }
933 
934 
943 static void
944 identity_cb (void *cls,
945  struct GNUNET_IDENTITY_Ego *ego,
946  void **ctx,
947  const char *name)
948 {
949  (void) cls;
950  (void) ctx;
951 
952  if ((NULL == name) || (0 != strcmp (name, zone)))
953  {
954  return;
955  }
956 
957  if (NULL == ego)
958  {
960  _ ("No ego configured for `fcfsd` subsystem\n"));
962  return;
963  }
964 
966 
967  int flags = MHD_USE_DUAL_STACK | MHD_USE_DEBUG | MHD_ALLOW_SUSPEND_RESUME;
968  do
969  {
970  httpd = MHD_start_daemon (flags,
971  (uint16_t) port,
972  NULL, NULL,
973  &create_response, NULL,
974  MHD_OPTION_CONNECTION_LIMIT, 128,
975  MHD_OPTION_PER_IP_CONNECTION_LIMIT, 1,
976  MHD_OPTION_CONNECTION_TIMEOUT, 4 * 1024,
977  MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL,
978  MHD_OPTION_END);
979  flags = MHD_USE_DEBUG;
980  } while (NULL == httpd && flags != MHD_USE_DEBUG);
981 
982  if (NULL == httpd)
983  {
985  _ ("Failed to start HTTP server\n"));
987  return;
988  }
989 
990  run_httpd ();
991 }
992 
993 
1001 static struct StaticPage *
1002 open_static_page (const char *name, const char *basedir)
1003 {
1004  char *fullname = NULL;
1005  GNUNET_asprintf (&fullname, "%s/fcfsd-%s", basedir, name);
1006 
1007  struct GNUNET_DISK_FileHandle *f =
1008  GNUNET_DISK_file_open (fullname,
1011  GNUNET_free (fullname);
1012 
1013  if (NULL == f)
1014  {
1015  return NULL;
1016  }
1017 
1018  off_t size = 0;
1020  {
1022  return NULL;
1023  }
1024 
1025  struct MHD_Response *response =
1026  MHD_create_response_from_fd64 (size,
1027  f->fd);
1028 
1029  if (NULL == response)
1030  {
1032  return NULL;
1033  }
1034 
1035  struct StaticPage *page = GNUNET_new (struct StaticPage);
1036  page->handle = f;
1037  page->size = (uint64_t) size;
1038  page->response = response;
1039  return page;
1040 }
1041 
1042 
1051 static void
1052 run_service (void *cls,
1053  char *const *args,
1054  const char *cfgfile,
1055  const struct GNUNET_CONFIGURATION_Handle *cfg)
1056 {
1057  (void) cls;
1058  (void) args;
1059  (void) cfgfile;
1060 
1061  GNUNET_log_setup ("fcfsd", "WARNING", NULL);
1062 
1064  "fcfsd",
1065  "RELATIVE_RECORD_EXPIRATION",
1066  &record_exp))
1067  {
1069  _ ("No expiration specified for records.\n"));
1071  return;
1072  }
1073 
1075  "fcfsd",
1076  "HTTPPORT",
1077  &port))
1078  {
1080  _ ("No port specified, using default value\n"));
1081  }
1082 
1084 
1086  if (NULL == namestore)
1087  {
1089  _ ("Failed to connect to namestore\n"));
1091  return;
1092  }
1093 
1095  if (NULL == identity)
1096  {
1098  _ ("Failed to connect to identity\n"));
1100  return;
1101  }
1102 
1103  char *basedir = NULL;
1105  "fcfsd",
1106  "HTMLDIR",
1107  &basedir))
1108  {
1110  }
1111 
1112  main_page = open_static_page ("index.html", basedir);
1113  notfound_page = open_static_page ("notfound.html", basedir);
1114  forbidden_page = open_static_page ("forbidden.html", basedir);
1115 
1116  GNUNET_free (basedir);
1117 
1118  if ((NULL == main_page) || (NULL == notfound_page) || (NULL ==
1119  forbidden_page) )
1120  {
1122  _ ("Unable to set up the daemon\n"));
1124  return;
1125  }
1126 }
1127 
1128 
1136 int
1137 main (int argc, char *const *argv)
1138 {
1142  "zone",
1143  "EGO",
1144  gettext_noop (
1145  "name of the zone managed by FCFSD"),
1146  &zone)),
1148  };
1149 
1150  return ((GNUNET_OK == GNUNET_PROGRAM_run (argc,
1151  argv,
1152  "gnunet-namestore-fcfsd",
1153  _ (
1154  "GNU Name System First-Come-First-Served name registration service"),
1155  options,
1156  &run_service,
1157  NULL)) ?
1158  0 :
1159  1);
1160 }
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
const char * GNUNET_ErrorCode_get_hint(enum GNUNET_ErrorCode ec)
Returns a hint for a given error code.
GNUNET_ErrorCode
Taler error codes.
@ GNUNET_EC_NONE
No error (success).
#define gettext_noop(String)
Definition: gettext.h:70
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:109
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:119
static struct MHD_Response * response
Our canonical response.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_FS_Handle * ctx
static char * name
Name (label) of the records to list.
static void register_error_cb(void *cls)
An error occurred while registering a name.
static void run_httpd_now(void)
static void search_done_cb(void *cls, const struct GNUNET_CRYPTO_PrivateKey *zone, const char *label, unsigned int count, const struct GNUNET_GNSRECORD_Data *d)
The lookup terminated with some results.
static MHD_RESULT create_response(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **ptr)
Send a response back to a connected client.
static struct GNUNET_TIME_Relative record_exp
The relative expiration time for added records.
static char * zone
Name of the zone being managed.
static struct MHD_Daemon * httpd
The HTTP daemon.
static MHD_RESULT serve_json(struct MHD_Connection *c, char *body, size_t length, int code)
Generate a response containing JSON and send it to the client.
static struct StaticPage * open_static_page(const char *name, const char *basedir)
Open a file on disk and generate a response object for it.
static void register_do_cb(void *cls, const struct GNUNET_CRYPTO_PrivateKey *key, const char *label, unsigned int count, const struct GNUNET_GNSRECORD_Data *d)
Attempt to register the requested name.
static void completed_cb(void *cls, struct MHD_Connection *connection, void **ptr, enum MHD_RequestTerminationCode status)
Called when a request is completed.
static unsigned long long port
The port the daemon is listening to for HTTP requests.
static void iterate_do_cb(void *cls, const struct GNUNET_CRYPTO_PrivateKey *key, const char *label, unsigned int count, const struct GNUNET_GNSRECORD_Data *d)
A block was received from the namestore.
static void do_shutdown(void *cls)
Task ran at shutdown to clean up everything.
static void iterate_error_cb(void *cls)
An error occurred while iterating the namestore.
static void run_httpd(void)
Schedule a task to run MHD.
static void do_httpd(void *cls)
Called when the HTTP server has some pending operations.
static void run_service(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Called after the service is up.
static struct GNUNET_NAMESTORE_Handle * namestore
Connection with the namestore service.
static const struct GNUNET_CRYPTO_PrivateKey * zone_key
Private key of the zone.
static struct StaticPage * main_page
The main page, a.k.a.
static struct StaticPage * notfound_page
Page indicating the requested resource could not be found.
static struct GNUNET_SCHEDULER_Task * httpd_task
Task executing the HTTP daemon.
static struct StaticPage * forbidden_page
Page indicating the requested resource could not be accessed, and other errors.
static struct GNUNET_IDENTITY_Handle * identity
Connection with the identity service.
static void iterate_done_cb(void *cls)
All entries in the namestore have been iterated over.
static void identity_cb(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name)
Called for each ego provided by the identity service.
int main(int argc, char *const *argv)
The main function of the fcfs daemon.
static void register_done_cb(void *cls, enum GNUNET_ErrorCode ec)
static void search_error_cb(void *cls)
The namestore search task failed.
static char * make_json(const char *key, const char *value,...)
Generate a JSON object.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static char * value
Value of the record to add/remove.
static int status
The program status; 0 for success.
Definition: gnunet-nse.c:38
static int result
Global testing status.
API that can be used to manipulate GNS record data.
Identity service; implements identity management for GNUnet.
functions to parse JSON objects into GNUnet objects
GNUNET_JSON_PostResult
Return codes from GNUNET_JSON_post_parser().
@ GNUNET_JSON_PR_CONTINUE
Parsing continues, call again soon!
@ GNUNET_JSON_PR_OUT_OF_MEMORY
Sorry, memory allocation (malloc()) failed.
@ GNUNET_JSON_PR_JSON_INVALID
JSON parsing failed.
@ GNUNET_JSON_PR_REQUEST_TOO_LARGE
Request size exceeded buffer_max argument.
enum GNUNET_JSON_PostResult GNUNET_JSON_post_parser(size_t buffer_max, struct MHD_Connection *connection, void **con_cls, const char *upload_data, size_t *upload_data_size, json_t **json)
Process a POST request containing a JSON object.
Definition: json_mhd.c:265
void GNUNET_JSON_post_parser_cleanup(void *con_cls)
Function called whenever we are done with a request to clean up our state.
Definition: json_mhd.c:367
#define MHD_RESULT
API that can be used to store naming information on a GNUnet node;.
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_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1237
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1308
enum GNUNET_GenericReturnValue GNUNET_DISK_file_handle_size(struct GNUNET_DISK_FileHandle *fh, off_t *size)
Get the size of an open file.
Definition: disk.c:192
@ GNUNET_DISK_OPEN_READ
Open the file for reading.
@ GNUNET_DISK_PERM_NONE
Nobody is allowed to do anything to the file.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_mandatory(struct GNUNET_GETOPT_CommandLineOption opt)
Make the given option mandatory.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_string(char shortName, const char *name, const char *argumentHelp, const char *description, char **str)
Allow user to specify a string.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_data_from_identity(const struct GNUNET_CRYPTO_PublicKey *key, char **data, size_t *data_size, uint32_t *type)
Create record data and size from an identity key.
@ GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION
This expiration time of the record is a relative time (not an absolute time).
struct GNUNET_IDENTITY_Handle * GNUNET_IDENTITY_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_IDENTITY_Callback cb, void *cb_cls)
Connect to the identity service.
Definition: identity_api.c:487
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:732
const struct GNUNET_CRYPTO_PrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:517
#define GNUNET_log(kind,...)
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_public_key_from_string(const char *str, struct GNUNET_CRYPTO_PublicKey *key)
Parses a (Base32) string representation of the public key.
Definition: crypto_pkey.c:568
@ GNUNET_SCHEDULER_PRIORITY_HIGH
Run with high priority (important requests).
@ GNUNET_OK
@ GNUNET_SYSERR
int GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
Setup logging.
#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.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_NAMESTORE_disconnect(struct GNUNET_NAMESTORE_Handle *h)
Disconnect from the namestore service (and free associated resources).
void GNUNET_NAMESTORE_zone_iterator_next(struct GNUNET_NAMESTORE_ZoneIterator *it, uint64_t limit)
Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start for the next record.
void GNUNET_NAMESTORE_cancel(struct GNUNET_NAMESTORE_QueueEntry *qe)
Cancel a namestore operation.
struct GNUNET_NAMESTORE_ZoneIterator * GNUNET_NAMESTORE_zone_iteration_start(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *zone, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_NAMESTORE_RecordMonitor proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls)
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_record_set_store(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *pkey, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, GNUNET_NAMESTORE_ContinuationWithStatus cont, void *cont_cls)
Store an item in the namestore.
struct GNUNET_NAMESTORE_Handle * GNUNET_NAMESTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the namestore service.
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_lookup(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *pkey, const char *label, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_NAMESTORE_RecordMonitor rm, void *rm_cls)
Lookup an item in the namestore.
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_zone_to_name(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *zone, const struct GNUNET_CRYPTO_PublicKey *value_zone, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_NAMESTORE_RecordMonitor proc, void *proc_cls)
Look for an existing PKEY delegation record for a given public key.
void GNUNET_NAMESTORE_zone_iteration_stop(struct GNUNET_NAMESTORE_ZoneIterator *it)
Stops iteration and releases the namestore handle for further calls.
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1170
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1186
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:1040
char * GNUNET_OS_installation_get_path(enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX,...
@ GNUNET_OS_IPK_DATADIR
Return the directory where data is installed (share/gnunet/)
enum GNUNET_GenericReturnValue 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,...
Definition: program.c:400
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:562
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:1299
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:1830
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:1334
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:484
@ MHD_HTTP_BAD_REQUEST
Bad Request [RFC7231, Section 6.5.1].
@ MHD_HTTP_OK
OK [RFC7231, Section 6.3.1].
@ MHD_HTTP_NOT_FOUND
Not Found [RFC7231, Section 6.5.4].
@ MHD_HTTP_INTERNAL_SERVER_ERROR
Internal Server Error [RFC7231, Section 6.6.1].
@ MHD_HTTP_FORBIDDEN
Forbidden [RFC7231, Section 6.5.3].
@ MHD_HTTP_CONTENT_TOO_LARGE
Content Too Large [RFC9110, Section 15.5.14].
@ MHD_HTTP_NOT_IMPLEMENTED
Not Implemented [RFC7231, Section 6.6.2].
#define max(x, y)
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
A private key for an identity as per LSD0001.
An identity key as per LSD0001.
Handle used to access files (and pipes).
Definition of a command line option.
uint32_t record_type
Type of the GNS/DNS record.
const void * data
Binary value stored in the DNS record.
size_t data_size
Number of bytes in data.
enum GNUNET_GNSRECORD_Flags flags
Flags for the record.
uint64_t expiration_time
Expiration time for the DNS record.
Handle for an ego.
Definition: identity.h:37
Handle for the service.
Definition: identity_api.c:97
Connection to the NAMESTORE service.
An QueueEntry used to store information for a pending NAMESTORE record operation.
Definition: namestore_api.c:49
Handle for a zone iterator operation.
collection of IO descriptors
Entry in list of pending tasks.
Definition: scheduler.c:136
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Structure containing some request-specific data.
struct GNUNET_CRYPTO_PublicKey key
Key to be associated with the requested name.
size_t body_length
Length in bytes of the body.
int code
Response code.
struct MHD_Connection * c
The connection this request was sent in.
struct GNUNET_NAMESTORE_ZoneIterator * iterating
Task started to iterate over the namestore.
char * body
Body of the response object.
struct GNUNET_NAMESTORE_QueueEntry * searching
Task started to search for an entry in the namestore.
void * ptr
Pointer used while processing POST data.
char * register_key
Key (encoded as a string) to be associated with the requested name.
char * register_name
Name requested to be registered.
Structure representing a static page.
struct GNUNET_DISK_FileHandle * handle
Handle to file on disk.
struct MHD_Response * response
Cached response object to send to clients.
uint64_t size
Size in bytes of the file.