GNUnet  0.11.x
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_IDENTITY_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);
376  rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
377  run_httpd_now ();
378 }
379 
380 
390 static void
391 search_done_cb (void *cls,
392  const struct GNUNET_IDENTITY_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);
430  rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
431  run_httpd_now ();
432 }
433 
434 
442 static void
443 register_done_cb (void *cls,
444  int32_t status,
445  const char *emsg)
446 {
447  struct RequestData *rd = cls;
448 
449  MHD_resume_connection (rd->c);
450  rd->searching = NULL;
451 
452  if ((GNUNET_SYSERR == status) || (GNUNET_NO == status))
453  {
455  _ ("Failed to create record for `%s': %s\n"),
456  rd->register_name,
457  emsg);
458  rd->body = make_json ("error", "true",
459  "message", emsg,
460  NULL);
461  rd->body_length = strlen (rd->body);
462  rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
463  }
464  else
465  {
466  rd->body = make_json ("error", "false",
467  "message", _ ("no errors"),
468  NULL);
469  rd->body_length = strlen (rd->body);
470  rd->code = MHD_HTTP_OK;
471  }
472 
473  run_httpd_now ();
474 }
475 
476 
486 static void
487 register_do_cb (void *cls,
488  const struct GNUNET_IDENTITY_PrivateKey *key,
489  const char *label,
490  unsigned int count,
491  const struct GNUNET_GNSRECORD_Data *d)
492 {
493  (void) key;
494  (void) d;
495 
496  struct RequestData *rd = cls;
497 
498  rd->searching = NULL;
499 
500  if (0 != count)
501  {
503  _ ("The requested key `%s' exists as `%s'\n"),
504  rd->register_key,
505  label);
506 
507  MHD_resume_connection (rd->c);
508  rd->searching = NULL;
509  rd->body = make_json ("error", "true",
510  "message", _ ("key exists"),
511  NULL);
512  rd->body_length = strlen (rd->body);
513  rd->code = MHD_HTTP_FORBIDDEN;
514  run_httpd_now ();
515  return;
516  }
517 
518  struct GNUNET_GNSRECORD_Data gd;
519  char *gdraw = NULL;
520 
522  &gdraw,
523  &(gd.data_size),
524  &(gd.record_type)))
525  {
527  _ ("Error creating record data\n"));
528  MHD_resume_connection (rd->c);
529  rd->searching = NULL;
530  rd->body = make_json ("error", "true",
531  "message", _ ("unable to store record"),
532  NULL);
533  rd->body_length = strlen (rd->body);
534  rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
535  run_httpd_now ();
536  return;
537  }
538 
539  gd.data = gdraw;
542 
544  zone_key,
545  rd->register_name,
546  1,
547  &gd,
549  rd);
550 
551  GNUNET_free (gdraw);
552 }
553 
554 
560 static void
561 iterate_error_cb (void *cls)
562 {
563  struct RequestData *rd = cls;
564 
565  MHD_resume_connection (rd->c);
566  rd->iterating = NULL;
567  rd->body = make_json ("error", "true",
568  "message", _ ("unable to scan namestore"),
569  NULL);
570  rd->body_length = strlen (rd->body);
571  rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
572  run_httpd_now ();
573 }
574 
575 
585 static void
586 iterate_do_cb (void *cls,
587  const struct GNUNET_IDENTITY_PrivateKey *key,
588  const char *label,
589  unsigned int count,
590  const struct GNUNET_GNSRECORD_Data *d)
591 {
592  (void) key;
593  (void) label;
594  (void) d;
595 
596  struct RequestData *rd = cls;
597 
598  if (0 == strcmp (label, rd->register_name))
599  {
600  GNUNET_break (0 != count);
602  _ ("Requested name `%s' exists with `%u' records\n"),
603  rd->register_name,
604  count);
605 
606  MHD_resume_connection (rd->c);
607  rd->body = make_json ("error", "true",
608  "message", _ ("name exists\n"),
609  NULL);
610  rd->body_length = strlen (rd->body);
611  rd->code = MHD_HTTP_FORBIDDEN;
613  run_httpd_now ();
614  return;
615  }
616 
618 }
619 
620 
626 static void
627 iterate_done_cb (void *cls)
628 {
629  struct RequestData *rd = cls;
630 
631  rd->iterating = NULL;
632 
633  /* See if the key was not registered already */
635  zone_key,
636  &(rd->key),
638  rd,
640  rd);
641 }
642 
643 
653 static MHD_RESULT
654 serve_json (struct MHD_Connection *c,
655  char *body,
656  size_t length,
657  int code)
658 {
659  struct MHD_Response *response =
660  MHD_create_response_from_buffer (length,
661  body,
662  MHD_RESPMEM_PERSISTENT);
663  MHD_RESULT r = MHD_queue_response (c, code, response);
664  MHD_destroy_response (response);
665  return r;
666 }
667 
668 
682 static MHD_RESULT
683 create_response (void *cls,
684  struct MHD_Connection *connection,
685  const char *url,
686  const char *method,
687  const char *version,
688  const char *upload_data,
689  size_t *upload_data_size,
690  void **ptr)
691 {
692  (void) cls;
693  (void) version;
694 
695  struct RequestData *rd = *ptr;
696 
697  if (0 == strcmp (method, MHD_HTTP_METHOD_GET))
698  {
699  /* Handle a previously suspended request */
700  if (NULL != rd)
701  {
702  return serve_json (rd->c, rd->body, rd->body_length, rd->code);
703  }
704 
705  if (0 == strcmp ("/", url))
706  {
707  return MHD_queue_response (connection,
708  MHD_HTTP_OK,
710  }
711 
712  if (0 == strcmp ("/search", url))
713  {
714  const char *name = MHD_lookup_connection_value (connection,
715  MHD_GET_ARGUMENT_KIND,
716  "name");
717  if (NULL == name)
718  {
719  return MHD_queue_response (connection,
720  MHD_HTTP_BAD_REQUEST,
722  }
723 
724  MHD_suspend_connection (connection);
725  rd = GNUNET_new (struct RequestData);
726  rd->c = connection;
728  zone_key,
729  name,
731  rd,
733  rd);
734  *ptr = rd;
735  return MHD_YES;
736  }
737 
738  return MHD_queue_response (connection,
739  MHD_HTTP_NOT_FOUND,
741  }
742 
743  if (0 == strcmp (method, MHD_HTTP_METHOD_HEAD))
744  {
745  /* We take a shortcut here by always serving the main page: starting a
746  namestore lookup, allocating the necessary resources, waiting for the
747  lookup to complete and then discard everything just because it was a HEAD
748  and thus only the headers are significative, is an unnecessary waste of
749  resources. The handling of this method could be smarter, for example by
750  sending a proper content type header based on the endpoint, but this is
751  not a service in which HEAD requests are significant, so there's no need
752  to spend too much time here. */
753  return MHD_queue_response (connection,
754  MHD_HTTP_OK,
756  }
757 
758  if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
759  {
760  if (0 == strcmp ("/register", url))
761  {
762  /* Handle a previously suspended request */
763  if ((NULL != rd) && (NULL != rd->body))
764  {
765  return serve_json (rd->c, rd->body, rd->body_length, rd->code);
766  }
767 
768  if (NULL == rd)
769  {
770  rd = GNUNET_new (struct RequestData);
771  rd->c = connection;
772  rd->body = NULL;
773  rd->ptr = NULL;
774  *ptr = rd;
775  }
776 
777  json_t *json = NULL;
779  GNUNET_JSON_post_parser (32 * 1024,
780  connection,
781  &(rd->ptr),
782  upload_data,
783  upload_data_size,
784  &json);
785 
786  switch (result)
787  {
789  /* Keep processing POST data */
790  return MHD_YES;
793  rd->body = make_json ("error", "true",
794  "message", _ ("unable to process submitted data"),
795  NULL);
796  rd->body_length = strlen (rd->body);
797 #ifdef MHD_HTTP_CONTENT_TOO_LARGE
798  rd->code = MHD_HTTP_CONTENT_TOO_LARGE;
799 #else
800  rd->code = MHD_HTTP_PAYLOAD_TOO_LARGE;
801 #endif
802  return MHD_YES;
804  rd->body = make_json ("error", "true",
805  "message", _ ("the submitted data is invalid"),
806  NULL);
807  rd->body_length = strlen (rd->body);
808  rd->code = MHD_HTTP_BAD_REQUEST;
809  return MHD_YES;
810  default:
811  break;
812  }
813 
814  /* POST data has been read in its entirety */
815 
816  const char *name = json_string_value (json_object_get (json, "name"));
817  const char *key = json_string_value (json_object_get (json, "key"));
818  if ((NULL == name) || (NULL == key) || (0 == strlen (name)) || (0 ==
819  strlen (
820  key)))
821  {
822  json_decref (json);
823  rd->body = make_json ("error", "true",
824  "message", _ ("invalid parameters"),
825  NULL);
826  rd->body_length = strlen (rd->body);
827  rd->code = MHD_HTTP_BAD_REQUEST;
828  return MHD_YES;
829  }
830 
831  rd->register_name = strdup (name);
832  rd->register_key = strdup (key);
833 
834  json_decref (json);
836 
837  if ((NULL != strchr (rd->register_name, '.')) ||
838  (NULL != strchr (rd->register_name, '+')))
839  {
840  rd->body = make_json ("error", "true",
841  "message", _ ("invalid name"),
842  NULL);
843  rd->body_length = strlen (rd->body);
844  rd->code = MHD_HTTP_BAD_REQUEST;
845  return MHD_YES;
846  }
847 
849  &(rd->key)))
850  {
852  _ ("Unable to parse key %s\n"),
853  rd->register_key);
854 
855  rd->body = make_json ("error", "true",
856  "message", _ ("unable to parse key"),
857  NULL);
858  rd->body_length = strlen (rd->body);
859  rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
860  return MHD_YES;
861  }
862 
863  MHD_suspend_connection (connection);
864  /* See if the requested name is free */
865  rd->iterating =
867  zone_key,
869  rd,
870  &iterate_do_cb,
871  rd,
873  rd);
874  return MHD_YES;
875  }
876 
877  return MHD_queue_response (connection,
878  MHD_HTTP_FORBIDDEN,
880  }
881 
882  return MHD_queue_response (connection,
883  MHD_HTTP_NOT_IMPLEMENTED,
885 }
886 
887 
896 static void
897 completed_cb (void *cls,
898  struct MHD_Connection *connection,
899  void **ptr,
900  enum MHD_RequestTerminationCode status)
901 {
902  (void) cls;
903  (void) connection;
904  (void) status;
905 
906  struct RequestData *rd = *ptr;
907 
908  if (NULL == rd)
909  {
910  return;
911  }
912 
913  if (NULL == rd->body)
914  {
915  GNUNET_free (rd->body);
916  }
917 
918  if (NULL != rd->searching)
919  {
921  }
922 
923  if (NULL != rd->register_name)
924  {
926  }
927 
928  if (NULL != rd->register_key)
929  {
931  }
932 
933  if (NULL != rd->iterating)
934  {
936  }
937 
938  GNUNET_free (rd);
939 }
940 
941 
950 static void
951 identity_cb (void *cls,
952  struct GNUNET_IDENTITY_Ego *ego,
953  void **ctx,
954  const char *name)
955 {
956  (void) cls;
957  (void) ctx;
958 
959  if ((NULL == name) || (0 != strcmp (name, zone)))
960  {
961  return;
962  }
963 
964  if (NULL == ego)
965  {
967  _ ("No ego configured for `fcfsd` subsystem\n"));
969  return;
970  }
971 
973 
974  int flags = MHD_USE_DUAL_STACK | MHD_USE_DEBUG | MHD_ALLOW_SUSPEND_RESUME;
975  do
976  {
977  httpd = MHD_start_daemon (flags,
978  (uint16_t) port,
979  NULL, NULL,
980  &create_response, NULL,
981  MHD_OPTION_CONNECTION_LIMIT, 128,
982  MHD_OPTION_PER_IP_CONNECTION_LIMIT, 1,
983  MHD_OPTION_CONNECTION_TIMEOUT, 4 * 1024,
984  MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL,
985  MHD_OPTION_END);
986  flags = MHD_USE_DEBUG;
987  } while (NULL == httpd && flags != MHD_USE_DEBUG);
988 
989  if (NULL == httpd)
990  {
992  _ ("Failed to start HTTP server\n"));
994  return;
995  }
996 
997  run_httpd ();
998 }
999 
1000 
1008 static struct StaticPage *
1009 open_static_page (const char *name, const char *basedir)
1010 {
1011  char *fullname = NULL;
1012  GNUNET_asprintf (&fullname, "%s/fcfsd-%s", basedir, name);
1013 
1014  struct GNUNET_DISK_FileHandle *f =
1015  GNUNET_DISK_file_open (fullname,
1018  GNUNET_free (fullname);
1019 
1020  if (NULL == f)
1021  {
1022  return NULL;
1023  }
1024 
1025  off_t size = 0;
1027  {
1029  return NULL;
1030  }
1031 
1032  struct MHD_Response *response =
1033  MHD_create_response_from_fd64 (size,
1034  f->fd);
1035 
1036  if (NULL == response)
1037  {
1039  return NULL;
1040  }
1041 
1042  struct StaticPage *page = GNUNET_new (struct StaticPage);
1043  page->handle = f;
1044  page->size = (uint64_t) size;
1045  page->response = response;
1046  return page;
1047 }
1048 
1049 
1058 static void
1059 run_service (void *cls,
1060  char *const *args,
1061  const char *cfgfile,
1062  const struct GNUNET_CONFIGURATION_Handle *cfg)
1063 {
1064  (void) cls;
1065  (void) args;
1066  (void) cfgfile;
1067 
1068  GNUNET_log_setup ("fcfsd", "WARNING", NULL);
1069 
1071  "fcfsd",
1072  "RELATIVE_RECORD_EXPIRATION",
1073  &record_exp))
1074  {
1076  _("No expiration specified for records.\n"));
1078  return;
1079  }
1080 
1082  "fcfsd",
1083  "HTTPPORT",
1084  &port))
1085  {
1087  _ ("No port specified, using default value\n"));
1088  }
1089 
1091 
1093  if (NULL == namestore)
1094  {
1096  _ ("Failed to connect to namestore\n"));
1098  return;
1099  }
1100 
1102  if (NULL == identity)
1103  {
1105  _ ("Failed to connect to identity\n"));
1107  return;
1108  }
1109 
1110  char *basedir = NULL;
1112  "fcfsd",
1113  "HTMLDIR",
1114  &basedir))
1115  {
1117  }
1118 
1119  main_page = open_static_page ("index.html", basedir);
1120  notfound_page = open_static_page ("notfound.html", basedir);
1121  forbidden_page = open_static_page ("forbidden.html", basedir);
1122 
1123  GNUNET_free (basedir);
1124 
1125  if ((NULL == main_page) || (NULL == notfound_page) || (NULL ==
1126  forbidden_page) )
1127  {
1129  _ ("Unable to set up the daemon\n"));
1131  return;
1132  }
1133 }
1134 
1135 
1143 int
1144 main (int argc, char *const *argv)
1145 {
1149  "zone",
1150  "EGO",
1151  gettext_noop (
1152  "name of the zone managed by FCFSD"),
1153  &zone)),
1155  };
1156 
1157  return ((GNUNET_OK == GNUNET_PROGRAM_run (argc,
1158  argv,
1159  "gnunet-namestore-fcfsd",
1160  _ (
1161  "GNU Name System First-Come-First-Served name registration service"),
1162  options,
1163  &run_service,
1164  NULL)) ?
1165  0 :
1166  1);
1167 }
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
#define gettext_noop(String)
Definition: gettext.h:69
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static struct MHD_Response * response
Our canonical response.
struct GNUNET_HashCode key
The key used in the DHT.
uint16_t status
See PRISM_STATUS_*-constants.
static void register_error_cb(void *cls)
An error occurred while registering a name.
static void run_httpd_now(void)
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 void register_do_cb(void *cls, const struct GNUNET_IDENTITY_PrivateKey *key, const char *label, unsigned int count, const struct GNUNET_GNSRECORD_Data *d)
Attempt to register the requested name.
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 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 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 void search_done_cb(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const char *label, unsigned int count, const struct GNUNET_GNSRECORD_Data *d)
The lookup terminated with some results.
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.
static void iterate_do_cb(void *cls, const struct GNUNET_IDENTITY_PrivateKey *key, const char *label, unsigned int count, const struct GNUNET_GNSRECORD_Data *d)
A block was received from the namestore.
int main(int argc, char *const *argv)
The main function of the fcfs daemon.
static void register_done_cb(void *cls, int32_t status, const char *emsg)
A name/key pair has been successfully registered, or maybe not.
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 const struct GNUNET_IDENTITY_PrivateKey * zone_key
Private key of the zone.
static char * value
Value of the record to add/remove.
static int result
Global testing status.
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
#define GNUNET_log(kind,...)
@ GNUNET_SCHEDULER_PRIORITY_HIGH
Run with high priority (important requests).
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_NO
Definition: gnunet_common.h:94
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
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
Data type to use for functions return an "MHD result".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_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:1235
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1306
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:193
@ 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_IDENTITY_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).
const struct GNUNET_IDENTITY_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:639
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_public_key_from_string(const char *str, struct GNUNET_IDENTITY_PublicKey *key)
Parses a (Base32) string representation of the public key.
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:610
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:921
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).
struct GNUNET_NAMESTORE_ZoneIterator * GNUNET_NAMESTORE_zone_iteration_start(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_IDENTITY_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)
Starts a new zone iteration (used to periodically PUT all of our records into our DHT).
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_lookup(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_IDENTITY_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.
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_QueueEntry * GNUNET_NAMESTORE_records_store(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_IDENTITY_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_zone_to_name(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *zone, const struct GNUNET_IDENTITY_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:1193
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1209
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:1063
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:399
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:531
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
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
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:1331
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
#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:483
#define max(x, y)
static unsigned int size
Size of the "table".
Definition: peer.c:67
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
const char * name
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:96
A private key for an identity as per LSD0001.
An identity key as per LSD0001.
Connection to the NAMESTORE service.
An QueueEntry used to store information for a pending NAMESTORE record operation.
Definition: namestore_api.c:54
Handle for a zone iterator operation.
collection of IO descriptors
Entry in list of pending tasks.
Definition: scheduler.c:135
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Structure containing some request-specific data.
size_t body_length
Length in bytes of the body.
int code
Response code.
struct GNUNET_IDENTITY_PublicKey key
Key to be associated with the requested name.
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.