GNUnet 0.28.1-dev.6-3-gbc381df64
 
Loading...
Searching...
No Matches
gnunet-daemon-hostlist_server.c File Reference

application to provide an integrated hostlist HTTP server More...

#include "platform.h"
#include "gnunet_common.h"
#include <microhttpd.h>
#include "gnunet-daemon-hostlist_server.h"
#include "gnunet_hello_uri_lib.h"
#include "gnunet_peerstore_service.h"
#include "gnunet-daemon-hostlist.h"
#include "gnunet_resolver_service.h"
#include "gnunet_mhd_compat.h"
#include <jansson.h>
#include <strings.h>
Include dependency graph for gnunet-daemon-hostlist_server.c:

Go to the source code of this file.

Data Structures

struct  HostSet
 Context for host_processor(). More...
 

Macros

#define GNUNET_ADV_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
 How long until our hostlist advertisement transmission via CORE should time out?
 
#define REBUILD_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
 How long do we wait after learning about a HELLO before we rebuild the hostlist we serve? Rebuilding walks every HELLO we know and re-encodes all of them, so a PEERSTORE notification must not trigger one on its own: they arrive in batches (the initial iteration of the monitor, or everything our own client half just downloaded), and one rebuild per batch is all that batch is worth.
 

Functions

static void add_cors_headers (struct MHD_Response *resp)
 Add headers to a request indicating that we allow Cross-Origin Resource Sharing.
 
static struct MHD_Response * build_json_response (const struct HostSet *host_set)
 
static void finish_response ()
 Function that assembles our response.
 
static enum GNUNET_GenericReturnValue host_processor (void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
 Callback that processes each of the known HELLOs for the hostlist response construction.
 
static enum GNUNET_GenericReturnValue free_hello (void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
 Free one HELLO of hellos.
 
static void rebuild_hostlist (void *cls)
 Rebuild the hostlist we serve from all the HELLOs we know.
 
static void schedule_rebuild ()
 Ask for the hostlist to be rebuilt, unless that is already pending.
 
static MHD_RESULT accept_policy_callback (void *cls, const struct sockaddr *addr, socklen_t addrlen)
 Hostlist access policy (very permissive, allows everything).
 
static int header_iterator (void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
 
static MHD_RESULT access_handler_callback (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 **con_cls)
 Main request handler.
 
static void adv_transmit (struct GNUNET_MQ_Handle *mq)
 Handler called by CORE when CORE is ready to transmit message.
 
static void * connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq, enum GNUNET_CORE_PeerClass class)
 Method called whenever a given peer connects.
 
static void process_notify (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *err_msg)
 PEERSTORE calls this function to let us know about a possible peer that we might want to connect to.
 
static struct GNUNET_SCHEDULER_Taskprepare_daemon (struct MHD_Daemon *daemon_handle)
 Function that queries MHD's select sets and starts the task waiting for them.
 
static void run_daemon (void *cls)
 Call MHD to process pending requests and then go back and schedule the next run.
 
static void error_cb (void *cls)
 
static void sync_cb (void *cls)
 
static void start_notify (void *cls)
 
int GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_STATISTICS_Handle *st, struct GNUNET_CORE_Handle *co, GNUNET_CORE_ConnectEventHandler *server_ch, int advertise)
 Start server offering our hostlist.
 
void GNUNET_HOSTLIST_server_stop ()
 Stop server offering our hostlist.
 

Variables

struct GNUNET_CONTAINER_MultiPeerMaphellos
 Map with hellos we build the hostlist with.
 
static struct MHD_Daemon * daemon_handle_v6
 Handle to the HTTP server as provided by libmicrohttpd for IPv6.
 
static struct MHD_Daemon * daemon_handle_v4
 Handle to the HTTP server as provided by libmicrohttpd for IPv4.
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 Our configuration.
 
static struct GNUNET_STATISTICS_Handlestats
 For keeping statistics.
 
static struct GNUNET_CORE_Handlecore
 Handle to the core service (NULL until we've connected to it).
 
struct GNUNET_SCHEDULER_Taskpeerstore_notify_task
 The task to delayed start the notification process initially.
 
static struct GNUNET_PEERSTORE_Monitorpeerstore_notify
 Our peerstore notification context.
 
static struct GNUNET_SCHEDULER_Taskhostlist_task_v4
 Our primary task for IPv4.
 
static struct GNUNET_SCHEDULER_Taskhostlist_task_v6
 Our primary task for IPv6.
 
static struct GNUNET_SCHEDULER_Taskrebuild_task
 Task that rebuilds our response from hellos, or NULL if no rebuild is pending.
 
static struct MHD_Response * response
 Our canonical response.
 
static struct MHD_Response * response_json
 Our json response.
 
static struct GNUNET_PEERSTORE_Handlepeerstore
 Handle to the PEERSTORE service.
 
static int advertising
 Set if we are allowed to advertise our hostlist to others.
 
static char * hostlist_uri
 Buffer for the hostlist address.
 
static struct HostSetbuilder
 NULL if we are not currently iterating over peer information.
 

Detailed Description

application to provide an integrated hostlist HTTP server

Author
Christian Grothoff
Matthias Wachs
David Barksdale

Definition in file gnunet-daemon-hostlist_server.c.

Macro Definition Documentation

◆ GNUNET_ADV_TIMEOUT

#define GNUNET_ADV_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)

How long until our hostlist advertisement transmission via CORE should time out?

Definition at line 44 of file gnunet-daemon-hostlist_server.c.

145{
149 char *data;
150
154 unsigned int size;
155};
156
157
161static struct HostSet *builder;
162
163
170static void
171add_cors_headers (struct MHD_Response *resp)
172{
173 GNUNET_assert (MHD_NO !=
174 MHD_add_response_header (resp,
175 "Access-Control-Allow-Origin", "*"));
176 GNUNET_assert (MHD_NO !=
177 MHD_add_response_header (resp,
178 "Access-Control-Allow-Methods",
179 "GET, OPTIONS"));
180 GNUNET_assert (MHD_NO !=
181 MHD_add_response_header (resp, "Access-Control-Max-Age",
182 "86400"));
183}
184
185
186static struct MHD_Response*
187build_json_response (const struct HostSet *host_set)
188{
189 struct GNUNET_MessageHeader *hello;
190 struct GNUNET_HELLO_Parser *hparser;
191 json_t*hello_uri_j;
192 json_t*hello_array;
193 char *hello_uri;
194 char *hello_uris;
195 size_t offset = 0;
196
197 hello_uri_j = json_object ();
198 hello_array = json_array ();
199 while (offset < host_set->size)
200 {
201 hello = (struct GNUNET_MessageHeader*) (host_set->data + offset);
202 /* #process_notify() verified this HELLO when it entered #hellos, and
203 these are our own bytes since. Verifying again here cost one EdDSA
204 verification per HELLO in the set, on every rebuild. */
205 hparser = GNUNET_HELLO_parser_from_msg_ (hello, NULL, GNUNET_YES);
206 if (NULL == hparser)
207 {
209 "HELLO from host set malformed, skipping...\n");
210 offset += ntohs (hello->size);
211 continue;
212 }
213 hello_uri = GNUNET_HELLO_parser_to_url (hparser);
214 json_array_append_new (hello_array, json_string (hello_uri));
215 GNUNET_free (hello_uri);
216 GNUNET_HELLO_parser_free (hparser);
217 offset += ntohs (hello->size);
218 }
219 json_object_set_new (hello_uri_j, "hellos", hello_array);
220 hello_uris = json_dumps (hello_uri_j, JSON_INDENT (2));
221 json_decref (hello_uri_j);
222 return MHD_create_response_from_buffer (strlen (hello_uris),
223 hello_uris,
224 MHD_RESPMEM_MUST_FREE);
225}
226
227
231static void
233{
234 if (NULL != response)
235 MHD_destroy_response (response);
236 if (NULL != response_json)
237 MHD_destroy_response (response_json);
239 "Creating hostlist response with %u bytes\n",
240 (unsigned int) builder->size);
241 response = MHD_create_response_from_buffer (builder->size,
242 builder->data,
243 MHD_RESPMEM_MUST_FREE);
245 GNUNET_assert (MHD_NO != MHD_add_response_header (response_json,
246 "Content-Type",
247 "application/json"));
249 if ((NULL == daemon_handle_v4) && (NULL == daemon_handle_v6))
250 {
251 MHD_destroy_response (response);
252 response = NULL;
253 MHD_destroy_response (response_json);
254 response_json = NULL;
255 }
257 gettext_noop ("bytes in hostlist"),
258 builder->size,
259 GNUNET_YES);
261 builder = NULL;
262}
263
264
275host_processor (void *cls,
276 const struct GNUNET_PeerIdentity *peer,
277 void *value)
278{
279 size_t old;
280 size_t s;
281 struct GNUNET_MessageHeader *hello = value;
282 (void) cls;
283
285 "host_processor\n");
286 old = builder->size;
287 s = ntohs (hello->size);
289 "Received %u bytes of `%s' from peer `%s' for hostlist.\n",
290 (unsigned int) s,
291 "HELLO",
292 GNUNET_i2s (peer));
293 if ((old + s >= GNUNET_MAX_MALLOC_CHECKED) ||
294 (old + s >= MAX_BYTES_PER_HOSTLISTS))
295 {
296 /* too large, skip! */
299 "bytes not included in hostlist (size limit)"),
300 s,
301 GNUNET_NO);
302 return GNUNET_YES;
303 }
305 "Adding peer `%s' to hostlist (%u bytes)\n",
306 GNUNET_i2s (peer),
307 (unsigned int) s);
309 GNUNET_memcpy (&builder->data[old], hello, s);
310
311 return GNUNET_YES;
312}
313
314
324free_hello (void *cls,
325 const struct GNUNET_PeerIdentity *peer,
326 void *value)
327{
328 (void) cls;
329 (void) peer;
331 return GNUNET_YES;
332}
333
334
340static void
341rebuild_hostlist (void *cls)
342{
343 (void) cls;
344 rebuild_task = NULL;
345 if (NULL != builder)
346 {
348 builder->size = 0;
349 builder->data = NULL;
350 }
351 else
352 {
353 builder = GNUNET_new (struct HostSet);
354 }
356 "Rebuilding hostlist from %u HELLOs\n",
360 NULL))
362}
363
364
368static void
370{
371 if (NULL != rebuild_task)
372 return;
375 NULL);
376}
377
378
388static MHD_RESULT
389accept_policy_callback (void *cls,
390 const struct sockaddr *addr,
391 socklen_t addrlen)
392{
393 if (NULL == response)
394 {
395 GNUNET_log (
397 "Received request for hostlist, but I am not yet ready; rejecting!\n");
398 return MHD_NO;
399 }
400 return MHD_YES; /* accept all */
401}
402
403
404static int
405header_iterator (void *cls,
406 enum MHD_ValueKind kind,
407 const char *key,
408 const char *value)
409{
410 enum GNUNET_GenericReturnValue *want_json = cls;
411
412 if (0 != strcasecmp (key, "Accept"))
413 return GNUNET_YES;
414 if (0 == strcasecmp (value, "application/json"))
415 *want_json = GNUNET_YES;
416 return MHD_YES;
417}
418
419
455static MHD_RESULT
456access_handler_callback (void *cls,
457 struct MHD_Connection *connection,
458 const char *url,
459 const char *method,
460 const char *version,
461 const char *upload_data,
462 size_t *upload_data_size,
463 void **con_cls)
464{
465 static int dummy;
466 struct MHD_Response *selected_response;
467 enum GNUNET_GenericReturnValue want_json = GNUNET_NO;
468
469 /* CORS pre-flight request */
470 if (0 == strcmp (MHD_HTTP_METHOD_OPTIONS, method))
471 {
472 struct MHD_Response *options_response;
473 int rc;
474
475 options_response =
476 MHD_create_response_from_buffer (0, NULL, MHD_RESPMEM_PERSISTENT);
477 add_cors_headers (options_response);
478 rc = MHD_queue_response (connection, MHD_HTTP_OK, options_response);
479 MHD_destroy_response (options_response);
480 return rc;
481 }
482 if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
483 {
485 _ ("Refusing `%s' request to hostlist server\n"),
486 method);
489 "hostlist requests refused (not HTTP GET)"),
490 1,
491 GNUNET_YES);
492 return MHD_NO;
493 }
494 if (NULL == *con_cls)
495 {
496 (*con_cls) = &dummy;
497 return MHD_YES;
498 }
499 if (0 != *upload_data_size)
500 {
502 _ ("Refusing `%s' request with %llu bytes of upload data\n"),
503 method,
504 (unsigned long long) *upload_data_size);
507 "hostlist requests refused (upload data)"),
508 1,
509 GNUNET_YES);
510 return MHD_NO; /* do not support upload data */
511 }
512 selected_response = response;
513 MHD_get_connection_values (connection,
514 MHD_HEADER_KIND,
515 (MHD_KeyValueIterator) & header_iterator,
516 &want_json);
517 if (GNUNET_YES == want_json)
518 {
519 selected_response = response_json;
520 }
521 if (NULL == selected_response)
522 {
523 GNUNET_log (
525 _ (
526 "Could not handle hostlist request since I do not have a response yet\n"));
529 "hostlist requests refused (not ready)"),
530 1,
531 GNUNET_YES);
532 return MHD_NO; /* internal error, no response yet */
533 }
535 _ ("Received request for our hostlist\n"));
537 gettext_noop ("hostlist requests processed"),
538 1,
539 GNUNET_YES);
540 return MHD_queue_response (connection, MHD_HTTP_OK, selected_response);
541}
542
543
553static void
555{
556 static uint64_t hostlist_adv_count;
557 size_t uri_size; /* Including \0 termination! */
558 struct GNUNET_MessageHeader *header;
559 struct GNUNET_MQ_Envelope *env;
560
561 uri_size = strlen (hostlist_uri) + 1;
562 env = GNUNET_MQ_msg_extra (header,
563 uri_size,
565 GNUNET_memcpy (&header[1], hostlist_uri, uri_size);
571 "Sent advertisement message: Copied %u bytes into buffer!\n",
572 (unsigned int) uri_size);
573 hostlist_adv_count++;
575 " # Sent advertisement message: %llu\n",
576 (unsigned long long) hostlist_adv_count);
578 gettext_noop ("# hostlist advertisements send"),
579 1,
580 GNUNET_NO);
581}
582
583
593static void *
594connect_handler (void *cls,
595 const struct GNUNET_PeerIdentity *peer,
596 struct GNUNET_MQ_Handle *mq,
597 enum GNUNET_CORE_PeerClass class)
598{
599 size_t size;
600
601 if (! advertising)
602 return NULL;
603 if (NULL == hostlist_uri)
604 return NULL;
605 size = strlen (hostlist_uri) + 1;
606 if (size + sizeof(struct GNUNET_MessageHeader) >= GNUNET_MAX_MESSAGE_SIZE)
607 {
608 GNUNET_break (0);
609 return NULL;
610 }
611 size += sizeof(struct GNUNET_MessageHeader);
612 if (NULL == core)
613 {
614 GNUNET_break (0);
615 return NULL;
616 }
617 GNUNET_log (
619 "Asked CORE to transmit advertisement message with a size of %u bytes to peer `%s'\n",
620 (unsigned int) size,
621 GNUNET_i2s (peer));
623 return NULL;
624}
625
626
636static void
637process_notify (void *cls,
638 const struct GNUNET_PEERSTORE_Record *record,
639 const char *err_msg)
640{
641 unsigned int map_size;
642 struct GNUNET_MessageHeader *hello_cpy;
643 struct GNUNET_MessageHeader *old_hello;
644 struct GNUNET_MessageHeader *hello;
645
648 "Peerstore is notifying us to rebuild our hostlist map size %u\n",
649 map_size);
650 if (NULL != err_msg)
651 {
653 _ ("Error in communication with PEERSTORE service: %s\n"),
654 err_msg);
656 return;
657 }
658 if (NULL == record)
659 {
660 GNUNET_break (0);
662 return;
663 }
664 hello = record->value;
665 /* @e value and @e value_size are independent, and the HELLO is an
666 unvalidated blob a remote peer published: a zero-length value leaves
667 @a hello NULL, and a @e size field larger than @e value_size makes the
668 GNUNET_memcpy() below read past the end of the record. */
669 if ((NULL == hello) ||
670 (record->value_size < sizeof (*hello)) ||
671 (ntohs (hello->size) > record->value_size))
672 {
673 GNUNET_break_op (0);
675 return;
676 }
677 /* PEERSTORE stores what it is given (handle_store() validates nothing),
678 and these records were published by other peers. Check the signature
679 once, here, instead of leaving it to whoever happens to parse the set
680 later: it kept malformed HELLOs out of the JSON response only because
681 build_json_response() had to parse to build a URL, and never kept
682 them out of the binary one at all. */
683 {
685 const struct GNUNET_PeerIdentity *pid;
686
688 &record->peer);
689 if (NULL == parser)
690 {
691 /* Not #GNUNET_break_op(): this is also how an expired HELLO fails,
692 and a record outliving the signature over it is routine. */
694 "HELLO for `%s' is expired or does not verify, skipping\n",
695 GNUNET_i2s (&record->peer));
697 return;
698 }
699 pid = GNUNET_HELLO_parser_get_id (parser);
700 if ((NULL == pid) ||
701 (0 != GNUNET_memcmp (pid, &record->peer)))
702 {
703 /* We key the map by the record's peer, so a HELLO filed under
704 somebody else's identity would evict that peer's real one. */
705 GNUNET_break_op (0);
708 return;
709 }
711 }
712 /* A peer has exactly one current HELLO, and PEERSTORE tells us about
713 every store of it -- our own client half alone re-stores everything
714 it downloads, on every download round. Appending here (as
715 #GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE did) meant the map grew
716 without bound, every entry was leaked, and each rebuild re-encoded
717 the same HELLO once per copy. */
718 hello_cpy = GNUNET_malloc (ntohs (hello->size));
719 GNUNET_memcpy (hello_cpy, hello, ntohs (hello->size));
721 &record->peer);
722 if (NULL != old_hello)
723 {
726 &record->peer,
727 old_hello));
728 GNUNET_free (old_hello);
729 }
732 &record->peer,
733 hello_cpy,
738 "1 Peerstore is notifying us to rebuild our hostlist map size %u peer %s\n",
739 map_size,
740 GNUNET_i2s (&record->peer));
742}
743
744
749static struct GNUNET_SCHEDULER_Task *
750prepare_daemon (struct MHD_Daemon *daemon_handle);
751
752
759static void
760run_daemon (void *cls)
761{
762 struct MHD_Daemon *daemon_handle = cls;
763
764 if (daemon_handle == daemon_handle_v4)
765 hostlist_task_v4 = NULL;
766 else
767 hostlist_task_v6 = NULL;
768 GNUNET_assert (MHD_YES == MHD_run (daemon_handle));
769 if (daemon_handle == daemon_handle_v4)
770 hostlist_task_v4 = prepare_daemon (daemon_handle);
771 else
772 hostlist_task_v6 = prepare_daemon (daemon_handle);
773}
774
775
782static struct GNUNET_SCHEDULER_Task *
783prepare_daemon (struct MHD_Daemon *daemon_handle)
784{
786 fd_set rs;
787 fd_set ws;
788 fd_set es;
789 struct GNUNET_NETWORK_FDSet *wrs;
790 struct GNUNET_NETWORK_FDSet *wws;
791 int max;
792 MHD_UNSIGNED_LONG_LONG timeout;
793 int haveto;
794 struct GNUNET_TIME_Relative tv;
795
796 FD_ZERO (&rs);
797 FD_ZERO (&ws);
798 FD_ZERO (&es);
801 max = -1;
802 GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es, &max));
803 haveto = MHD_get_timeout (daemon_handle, &timeout);
804 if (haveto == MHD_YES)
805 tv.rel_value_us = (uint64_t) timeout * 1000LL;
806 else
811 tv,
812 wrs,
813 wws,
814 &run_daemon,
815 daemon_handle);
818 return ret;
819}
820
821
822static void
823error_cb (void *cls)
824{
826 "Error in PEERSTORE monitoring\n");
827}
828
829
830static void
831sync_cb (void *cls)
832{
834 "Done with initial PEERSTORE iteration during monitoring\n");
835}
836
837
838static void
839start_notify (void *cls)
840{
841 (void) cls;
842
844 "Starting to process new hellos to add to hostlist.\n");
847 "peerstore",
848 NULL,
850 &error_cb,
851 NULL,
852 &sync_cb,
853 NULL,
854 &process_notify, NULL);
855}
856
857
868int
871 struct GNUNET_CORE_Handle *co,
873 int advertise)
874{
875 unsigned long long port;
876 char *hostname;
877 char *ipv4;
878 char *ipv6;
879 size_t size;
880 struct in_addr i4;
881 struct in6_addr i6;
882 struct sockaddr_in v4;
883 struct sockaddr_in6 v6;
884 const struct sockaddr *sa4;
885 const struct sockaddr *sa6;
886
887 /* Keys are copied: #process_notify() puts the identity of a borrowed
888 PEERSTORE record, which does not outlive the callback. */
890 advertising = advertise;
891 if (! advertising)
892 {
894 "Advertising not enabled on this hostlist server\n");
895 }
896 else
897 {
899 "Advertising enabled on this hostlist server\n");
900 }
901 cfg = c;
902 stats = st;
904 if (NULL == peerstore)
905 {
907 _ ("Could not access PEERSTORE service. Exiting.\n"));
908 return GNUNET_SYSERR;
909 }
911 "HOSTLIST",
912 "HTTPPORT",
913 &port))
914 return GNUNET_SYSERR;
915 if ((0 == port) || (port > UINT16_MAX))
916 {
918 _ ("Invalid port number %llu. Exiting.\n"),
919 port);
920 return GNUNET_SYSERR;
921 }
922
923 if (GNUNET_SYSERR ==
925 "HOSTLIST",
926 "EXTERNAL_DNS_NAME",
927 &hostname))
928 hostname = GNUNET_RESOLVER_local_fqdn_get ();
930 _ ("Hostlist service starts on %s:%llu\n"),
931 hostname,
932 port);
933 if (NULL != hostname)
934 {
935 size = strlen (hostname);
936 if (size + 15 > MAX_URL_LEN)
937 {
938 GNUNET_break (0);
939 }
940 else
941 {
943 "http://%s:%u/",
944 hostname,
945 (unsigned int) port);
947 _ ("Address to obtain hostlist: `%s'\n"),
949 }
950 GNUNET_free (hostname);
951 }
952
953 if (GNUNET_CONFIGURATION_have_value (cfg, "HOSTLIST", "BINDTOIPV4"))
954 {
956 "HOSTLIST",
957 "BINDTOIP",
958 &ipv4))
959 {
960 GNUNET_log (
962 _ ("BINDTOIP does not a valid IPv4 address! Ignoring BINDTOIPV4.\n"));
963 }
964 }
965 else
966 ipv4 = NULL;
967 if (GNUNET_CONFIGURATION_have_value (cfg, "HOSTLIST", "BINDTOIPV6"))
968 {
970 "HOSTLIST",
971 "BINDTOIP",
972 &ipv6))
973 {
974 GNUNET_log (
976 _ ("BINDTOIP does not a valid IPv4 address! Ignoring BINDTOIPV6.\n"));
977 }
978 }
979 else
980 ipv6 = NULL;
981 sa4 = NULL;
982 if (NULL != ipv4)
983 {
984 if (1 == inet_pton (AF_INET, ipv4, &i4))
985 {
986 memset (&v4, 0, sizeof(v4));
987 v4.sin_family = AF_INET;
988 v4.sin_addr = i4;
989 v4.sin_port = htons (port);
990#if HAVE_SOCKADDR_IN_SIN_LEN
991 v4.sin_len = sizeof(v4);
992#endif
993 sa4 = (const struct sockaddr *) &v4;
994 }
995 else
997 _ (
998 "`%s' is not a valid IPv4 address! Ignoring BINDTOIPV4.\n"),
999 ipv4);
1000 GNUNET_free (ipv4);
1001 }
1002 sa6 = NULL;
1003 if (NULL != ipv6)
1004 {
1005 if (1 == inet_pton (AF_INET6, ipv6, &i6))
1006 {
1007 memset (&v6, 0, sizeof(v6));
1008 v6.sin6_family = AF_INET6;
1009 v6.sin6_addr = i6;
1010 v6.sin6_port = htons (port);
1011#if HAVE_SOCKADDR_IN_SIN_LEN
1012 v6.sin6_len = sizeof(v6);
1013#endif
1014 sa6 = (const struct sockaddr *) &v6;
1015 }
1016 else
1018 _ (
1019 "`%s' is not a valid IPv6 address! Ignoring BINDTOIPV6.\n"),
1020 ipv6);
1021 GNUNET_free (ipv6);
1022 }
1023
1024 daemon_handle_v6 = MHD_start_daemon (MHD_USE_IPv6 | MHD_USE_DEBUG,
1025 (uint16_t) port,
1027 NULL,
1029 NULL,
1030 MHD_OPTION_CONNECTION_LIMIT,
1031 (unsigned int) 128,
1032 MHD_OPTION_PER_IP_CONNECTION_LIMIT,
1033 (unsigned int) 32,
1034 MHD_OPTION_CONNECTION_TIMEOUT,
1035 (unsigned int) 16,
1036 MHD_OPTION_CONNECTION_MEMORY_LIMIT,
1037 (size_t) (16 * 1024),
1038 MHD_OPTION_SOCK_ADDR,
1039 sa6,
1040 MHD_OPTION_END);
1041 daemon_handle_v4 = MHD_start_daemon (MHD_NO_FLAG | MHD_USE_DEBUG,
1042 (uint16_t) port,
1044 NULL,
1046 NULL,
1047 MHD_OPTION_CONNECTION_LIMIT,
1048 (unsigned int) 128,
1049 MHD_OPTION_PER_IP_CONNECTION_LIMIT,
1050 (unsigned int) 32,
1051 MHD_OPTION_CONNECTION_TIMEOUT,
1052 (unsigned int) 16,
1053 MHD_OPTION_CONNECTION_MEMORY_LIMIT,
1054 (size_t) (16 * 1024),
1055 MHD_OPTION_SOCK_ADDR,
1056 sa4,
1057 MHD_OPTION_END);
1058
1059 if ((NULL == daemon_handle_v6) && (NULL == daemon_handle_v4))
1060 {
1062 _ ("Could not start hostlist HTTP server on port %u\n"),
1063 (unsigned short) port);
1064 return GNUNET_SYSERR;
1065 }
1066
1067 core = co;
1069 if (NULL != daemon_handle_v4)
1071 if (NULL != daemon_handle_v6)
1076 NULL);
1077 return GNUNET_OK;
1078}
1079
1080
1084void
1086{
1087 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlist server shutdown\n");
1088 if (NULL != rebuild_task)
1089 {
1091 rebuild_task = NULL;
1092 }
1093 if (NULL != hostlist_task_v6)
1094 {
1096 hostlist_task_v6 = NULL;
1097 }
1098 if (NULL != hostlist_task_v4)
1099 {
1101 hostlist_task_v4 = NULL;
1102 }
1103 if (NULL != daemon_handle_v4)
1104 {
1105 MHD_stop_daemon (daemon_handle_v4);
1106 daemon_handle_v4 = NULL;
1107 }
1108 if (NULL != daemon_handle_v6)
1109 {
1110 MHD_stop_daemon (daemon_handle_v6);
1111 daemon_handle_v6 = NULL;
1112 }
1113 if (NULL != response)
1114 {
1115 MHD_destroy_response (response);
1116 response = NULL;
1117 }
1118 if (NULL != response_json)
1119 {
1120 MHD_destroy_response (response_json);
1121 response_json = NULL;
1122 }
1123 if (NULL != peerstore_notify)
1124 {
1126 peerstore_notify = NULL;
1127 }
1128 else if (NULL != peerstore_notify_task)
1129 {
1131 }
1132 if (NULL != builder)
1133 {
1136 builder = NULL;
1137 }
1138 if (NULL != hellos)
1139 {
1141 &free_hello,
1142 NULL);
1144 hellos = NULL;
1145 }
1146 if (NULL != peerstore)
1147 {
1149 peerstore = NULL;
1150 }
1151 cfg = NULL;
1152 stats = NULL;
1153 core = NULL;
1154}
1155
1156
1157/* end of gnunet-daemon-hostlist_server.c */
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
#define gettext_noop(String)
Definition gettext.h:74
static int ret
Final status code.
Definition gnunet-arm.c:93
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition gnunet-arm.c:118
static uint16_t port
Port number.
Definition gnunet-bcd.c:146
static struct GNUNET_SCHEDULER_Task * st
The shutdown task.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static GNUNET_CORE_ConnectEventHandler server_ch
Handle to hostlist server's connect handler.
#define MAX_URL_LEN
How long can hostlist URLs be?
#define MAX_BYTES_PER_HOSTLISTS
How many bytes do we download at most from a hostlist server?
static struct MHD_Daemon * daemon_handle_v6
Handle to the HTTP server as provided by libmicrohttpd for IPv6.
static struct MHD_Response * response
Our canonical response.
static void * connect_handler(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq, enum GNUNET_CORE_PeerClass class)
Method called whenever a given peer connects.
static void sync_cb(void *cls)
static struct MHD_Daemon * daemon_handle_v4
Handle to the HTTP server as provided by libmicrohttpd for IPv4.
static struct GNUNET_SCHEDULER_Task * hostlist_task_v4
Our primary task for IPv4.
static struct HostSet * builder
NULL if we are not currently iterating over peer information.
static struct GNUNET_CORE_Handle * core
Handle to the core service (NULL until we've connected to it).
static int advertising
Set if we are allowed to advertise our hostlist to others.
static void schedule_rebuild()
Ask for the hostlist to be rebuilt, unless that is already pending.
static struct MHD_Response * build_json_response(const struct HostSet *host_set)
static void add_cors_headers(struct MHD_Response *resp)
Add headers to a request indicating that we allow Cross-Origin Resource Sharing.
static struct GNUNET_PEERSTORE_Monitor * peerstore_notify
Our peerstore notification context.
static struct GNUNET_STATISTICS_Handle * stats
For keeping statistics.
struct GNUNET_CONTAINER_MultiPeerMap * hellos
Map with hellos we build the hostlist with.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static struct GNUNET_SCHEDULER_Task * hostlist_task_v6
Our primary task for IPv6.
static struct GNUNET_PEERSTORE_Handle * peerstore
Handle to the PEERSTORE service.
static void rebuild_hostlist(void *cls)
Rebuild the hostlist we serve from all the HELLOs we know.
static enum GNUNET_GenericReturnValue host_processor(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Callback that processes each of the known HELLOs for the hostlist response construction.
static struct GNUNET_SCHEDULER_Task * prepare_daemon(struct MHD_Daemon *daemon_handle)
Function that queries MHD's select sets and starts the task waiting for them.
static void start_notify(void *cls)
static struct MHD_Response * response_json
Our json response.
static void adv_transmit(struct GNUNET_MQ_Handle *mq)
Handler called by CORE when CORE is ready to transmit message.
struct GNUNET_SCHEDULER_Task * peerstore_notify_task
The task to delayed start the notification process initially.
int GNUNET_HOSTLIST_server_start(const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_STATISTICS_Handle *st, struct GNUNET_CORE_Handle *co, GNUNET_CORE_ConnectEventHandler *server_ch, int advertise)
Start server offering our hostlist.
static void run_daemon(void *cls)
Call MHD to process pending requests and then go back and schedule the next run.
static int header_iterator(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
static void finish_response()
Function that assembles our response.
#define REBUILD_DELAY
How long do we wait after learning about a HELLO before we rebuild the hostlist we serve?...
static void error_cb(void *cls)
static MHD_RESULT access_handler_callback(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 **con_cls)
Main request handler.
static void process_notify(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *err_msg)
PEERSTORE calls this function to let us know about a possible peer that we might want to connect to.
static enum GNUNET_GenericReturnValue free_hello(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Free one HELLO of hellos.
void GNUNET_HOSTLIST_server_stop()
Stop server offering our hostlist.
static char * hostlist_uri
Buffer for the hostlist address.
static MHD_RESULT accept_policy_callback(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Hostlist access policy (very permissive, allows everything).
static struct GNUNET_SCHEDULER_Task * rebuild_task
Task that rebuilds our response from hellos, or NULL if no rebuild is pending.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
static char * value
Value of the record to add/remove.
static int ipv4
Option -4: IPv4 requested.
Definition gnunet-vpn.c:60
static int ipv6
Option -6: IPv6 requested.
Definition gnunet-vpn.c:65
static unsigned int map_size
Command-line argument specifying desired size of the hash map with all of our pending names.
#define MHD_RESULT
Data type to use for functions return an "MHD result".
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
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_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
GNUNET_CORE_PeerClass
The peer class gives a hint about the capabilities of a peer.
void *(* GNUNET_CORE_ConnectEventHandler)(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq, enum GNUNET_CORE_PeerClass class)
Method called whenever a given peer connects.
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
void GNUNET_HELLO_parser_free(struct GNUNET_HELLO_Parser *parser)
Release resources of a builder.
Definition hello-uri.c:380
char * GNUNET_HELLO_parser_to_url(const struct GNUNET_HELLO_Parser *parser)
Generate GNUnet HELLO URI from a parser.
Definition hello-uri.c:880
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_msg_(const struct GNUNET_MessageHeader *msg, const struct GNUNET_PeerIdentity *pid, int noverify)
Parse msg.
Definition hello-uri.c:426
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_get_id(const struct GNUNET_HELLO_Parser *parser)
Get the PeerIdentity for this builder.
Definition hello-uri.c:354
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_msg(const struct GNUNET_MessageHeader *msg, const struct GNUNET_PeerIdentity *pid)
Parse msg.
Definition hello-uri.c:416
#define GNUNET_log(kind,...)
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_SCHEDULER_PRIORITY_HIGH
Run with high priority (important requests).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#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_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_env_set_options(struct GNUNET_MQ_Envelope *env, enum GNUNET_MQ_PriorityPreferences pp)
Set application-specific options for this envelope.
Definition mq.c:879
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition mq.c:337
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
@ GNUNET_MQ_PREF_CORK_ALLOWED
Flag to indicate that CORKing is acceptable.
@ GNUNET_MQ_PREF_UNRELIABLE
Flag to indicate that unreliable delivery is acceptable.
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition network.c:1184
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
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition network.c:1168
void GNUNET_PEERSTORE_monitor_stop(struct GNUNET_PEERSTORE_Monitor *zm)
Stop monitoring.
void GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
Disconnect from the PEERSTORE service.
struct GNUNET_PEERSTORE_Monitor * GNUNET_PEERSTORE_monitor_start(const struct GNUNET_CONFIGURATION_Handle *cfg, int iterate_first, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_SCHEDULER_TaskCallback sync_cb, void *sync_cb_cls, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Request watching a given key The monitoring can be filtered to contain only records matching peer and...
struct GNUNET_PEERSTORE_Handle * GNUNET_PEERSTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the PEERSTORE service.
void GNUNET_PEERSTORE_monitor_next(struct GNUNET_PEERSTORE_Monitor *zm, uint64_t limit)
Calls the monitor processor specified in GNUNET_PEERSTORE_monitor_start for the next record(s).
#define GNUNET_PEERSTORE_HELLO_KEY
Key used for storing HELLO in the peerstore.
#define GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT
Hostlist advertisement message.
char * GNUNET_RESOLVER_local_fqdn_get(void)
Get local fully qualified domain name.
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
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_TIME_UNIT_MINUTES
One minute.
#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:179
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
Context for the core service connection.
Definition core_api.c:78
Context for parsing HELLOs.
Definition hello-uri.c:233
Handle to a message queue.
Definition mq.c:87
Header for all communications.
collection of IO descriptors
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition scheduler.c:141
Handle for the service.
Time for relative time used by GNUnet, in microseconds.
Context for host_processor().
char * data
Place where we accumulate all of the HELLO messages.
unsigned int size
Number of bytes in data.

◆ REBUILD_DELAY

#define REBUILD_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)

How long do we wait after learning about a HELLO before we rebuild the hostlist we serve? Rebuilding walks every HELLO we know and re-encodes all of them, so a PEERSTORE notification must not trigger one on its own: they arrive in batches (the initial iteration of the monitor, or everything our own client half just downloaded), and one rebuild per batch is all that batch is worth.

Definition at line 55 of file gnunet-daemon-hostlist_server.c.

Function Documentation

◆ add_cors_headers()

static void add_cors_headers ( struct MHD_Response *  resp)
static

Add headers to a request indicating that we allow Cross-Origin Resource Sharing.

Parameters
responseresponse to add headers to

Definition at line 172 of file gnunet-daemon-hostlist_server.c.

173{
174 GNUNET_assert (MHD_NO !=
175 MHD_add_response_header (resp,
176 "Access-Control-Allow-Origin", "*"));
177 GNUNET_assert (MHD_NO !=
178 MHD_add_response_header (resp,
179 "Access-Control-Allow-Methods",
180 "GET, OPTIONS"));
181 GNUNET_assert (MHD_NO !=
182 MHD_add_response_header (resp, "Access-Control-Max-Age",
183 "86400"));
184}

References GNUNET_assert.

Referenced by access_handler_callback(), and finish_response().

Here is the caller graph for this function:

◆ build_json_response()

static struct MHD_Response * build_json_response ( const struct HostSet host_set)
static

Definition at line 188 of file gnunet-daemon-hostlist_server.c.

189{
190 struct GNUNET_MessageHeader *hello;
191 struct GNUNET_HELLO_Parser *hparser;
192 json_t*hello_uri_j;
193 json_t*hello_array;
194 char *hello_uri;
195 char *hello_uris;
196 size_t offset = 0;
197
198 hello_uri_j = json_object ();
199 hello_array = json_array ();
200 while (offset < host_set->size)
201 {
202 hello = (struct GNUNET_MessageHeader*) (host_set->data + offset);
203 /* #process_notify() verified this HELLO when it entered #hellos, and
204 these are our own bytes since. Verifying again here cost one EdDSA
205 verification per HELLO in the set, on every rebuild. */
206 hparser = GNUNET_HELLO_parser_from_msg_ (hello, NULL, GNUNET_YES);
207 if (NULL == hparser)
208 {
210 "HELLO from host set malformed, skipping...\n");
211 offset += ntohs (hello->size);
212 continue;
213 }
214 hello_uri = GNUNET_HELLO_parser_to_url (hparser);
215 json_array_append_new (hello_array, json_string (hello_uri));
216 GNUNET_free (hello_uri);
217 GNUNET_HELLO_parser_free (hparser);
218 offset += ntohs (hello->size);
219 }
220 json_object_set_new (hello_uri_j, "hellos", hello_array);
221 hello_uris = json_dumps (hello_uri_j, JSON_INDENT (2));
222 json_decref (hello_uri_j);
223 return MHD_create_response_from_buffer (strlen (hello_uris),
224 hello_uris,
225 MHD_RESPMEM_MUST_FREE);
226}

References HostSet::data, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_HELLO_parser_free(), GNUNET_HELLO_parser_from_msg_(), GNUNET_HELLO_parser_to_url(), GNUNET_log, GNUNET_YES, GNUNET_MessageHeader::size, and size.

Referenced by finish_response().

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

◆ finish_response()

static void finish_response ( )
static

Function that assembles our response.

Definition at line 233 of file gnunet-daemon-hostlist_server.c.

234{
235 if (NULL != response)
236 MHD_destroy_response (response);
237 if (NULL != response_json)
238 MHD_destroy_response (response_json);
240 "Creating hostlist response with %u bytes\n",
241 (unsigned int) builder->size);
242 response = MHD_create_response_from_buffer (builder->size,
243 builder->data,
244 MHD_RESPMEM_MUST_FREE);
246 GNUNET_assert (MHD_NO != MHD_add_response_header (response_json,
247 "Content-Type",
248 "application/json"));
250 if ((NULL == daemon_handle_v4) && (NULL == daemon_handle_v6))
251 {
252 MHD_destroy_response (response);
253 response = NULL;
254 MHD_destroy_response (response_json);
255 response_json = NULL;
256 }
258 gettext_noop ("bytes in hostlist"),
259 builder->size,
260 GNUNET_YES);
262 builder = NULL;
263}

References add_cors_headers(), build_json_response(), builder, daemon_handle_v4, daemon_handle_v6, HostSet::data, gettext_noop, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_STATISTICS_set(), GNUNET_YES, response, response_json, HostSet::size, and stats.

Referenced by rebuild_hostlist().

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

◆ host_processor()

static enum GNUNET_GenericReturnValue host_processor ( void *  cls,
const struct GNUNET_PeerIdentity peer,
void *  value 
)
static

Callback that processes each of the known HELLOs for the hostlist response construction.

Parameters
clsclosure, NULL
peerid of the peer, NULL for last call
hellohello message for the peer (can be NULL)
err_msgmessage

Definition at line 276 of file gnunet-daemon-hostlist_server.c.

279{
280 size_t old;
281 size_t s;
282 struct GNUNET_MessageHeader *hello = value;
283 (void) cls;
284
286 "host_processor\n");
287 old = builder->size;
288 s = ntohs (hello->size);
290 "Received %u bytes of `%s' from peer `%s' for hostlist.\n",
291 (unsigned int) s,
292 "HELLO",
293 GNUNET_i2s (peer));
294 if ((old + s >= GNUNET_MAX_MALLOC_CHECKED) ||
295 (old + s >= MAX_BYTES_PER_HOSTLISTS))
296 {
297 /* too large, skip! */
300 "bytes not included in hostlist (size limit)"),
301 s,
302 GNUNET_NO);
303 return GNUNET_YES;
304 }
306 "Adding peer `%s' to hostlist (%u bytes)\n",
307 GNUNET_i2s (peer),
308 (unsigned int) s);
310 GNUNET_memcpy (&builder->data[old], hello, s);
311
312 return GNUNET_YES;
313}

References builder, HostSet::data, gettext_noop, GNUNET_array_grow, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_i2s(), GNUNET_log, GNUNET_MAX_MALLOC_CHECKED, GNUNET_memcpy, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_YES, MAX_BYTES_PER_HOSTLISTS, GNUNET_MessageHeader::size, HostSet::size, stats, and value.

Referenced by rebuild_hostlist().

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

◆ free_hello()

static enum GNUNET_GenericReturnValue free_hello ( void *  cls,
const struct GNUNET_PeerIdentity peer,
void *  value 
)
static

Free one HELLO of hellos.

Parameters
clsclosure, NULL
peerthe peer the HELLO is for
valuethe struct GNUNET_MessageHeader * to free
Returns
GNUNET_YES (continue to iterate)

Definition at line 325 of file gnunet-daemon-hostlist_server.c.

328{
329 (void) cls;
330 (void) peer;
332 return GNUNET_YES;
333}

References GNUNET_free, GNUNET_YES, and value.

Referenced by GNUNET_HOSTLIST_server_stop().

Here is the caller graph for this function:

◆ rebuild_hostlist()

static void rebuild_hostlist ( void *  cls)
static

Rebuild the hostlist we serve from all the HELLOs we know.

Parameters
clsclosure, NULL

Definition at line 342 of file gnunet-daemon-hostlist_server.c.

343{
344 (void) cls;
345 rebuild_task = NULL;
346 if (NULL != builder)
347 {
349 builder->size = 0;
350 builder->data = NULL;
351 }
352 else
353 {
354 builder = GNUNET_new (struct HostSet);
355 }
357 "Rebuilding hostlist from %u HELLOs\n",
361 NULL))
363}

References builder, HostSet::data, finish_response(), GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_CONTAINER_multipeermap_size(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_new, hellos, host_processor(), rebuild_task, and HostSet::size.

Referenced by schedule_rebuild().

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

◆ schedule_rebuild()

static void schedule_rebuild ( )
static

Ask for the hostlist to be rebuilt, unless that is already pending.

Definition at line 370 of file gnunet-daemon-hostlist_server.c.

371{
372 if (NULL != rebuild_task)
373 return;
376 NULL);
377}

References GNUNET_SCHEDULER_add_delayed(), REBUILD_DELAY, rebuild_hostlist(), and rebuild_task.

Referenced by process_notify().

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

◆ accept_policy_callback()

static MHD_RESULT accept_policy_callback ( void *  cls,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

Hostlist access policy (very permissive, allows everything).

Returns #MHD_NO only if we are not yet ready to serve.

Parameters
clsclosure
addraddress information from the client
addrlenlength of addr
Returns
#MHD_YES if connection is allowed, #MHD_NO if not (we are not ready)

Definition at line 390 of file gnunet-daemon-hostlist_server.c.

393{
394 if (NULL == response)
395 {
396 GNUNET_log (
398 "Received request for hostlist, but I am not yet ready; rejecting!\n");
399 return MHD_NO;
400 }
401 return MHD_YES; /* accept all */
402}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, and response.

Referenced by GNUNET_HOSTLIST_server_start().

Here is the caller graph for this function:

◆ header_iterator()

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

Definition at line 406 of file gnunet-daemon-hostlist_server.c.

410{
411 enum GNUNET_GenericReturnValue *want_json = cls;
412
413 if (0 != strcasecmp (key, "Accept"))
414 return GNUNET_YES;
415 if (0 == strcasecmp (value, "application/json"))
416 *want_json = GNUNET_YES;
417 return MHD_YES;
418}

References GNUNET_YES, key, and value.

Referenced by access_handler_callback().

Here is the caller graph for this function:

◆ access_handler_callback()

static MHD_RESULT access_handler_callback ( 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 **  con_cls 
)
static

Main request handler.

Parameters
clsargument given together with the function pointer when the handler was registered with MHD
connection
urlthe requested url
methodthe HTTP method used (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT, etc.)
versionthe HTTP version string (e.g. #MHD_HTTP_VERSION_1_1)
upload_datathe data being uploaded (excluding HEADERS, for a POST that fits into memory and that is encoded with a supported encoding, the POST data will NOT be given in upload_data and is instead available as part of #MHD_get_connection_values; very large POST data will be made available incrementally in upload_data)
upload_data_sizeset initially to the size of the upload_data provided; the method must update this value to the number of bytes NOT processed;
con_clspointer that the callback can set to some address and that will be preserved by MHD for future calls for this request; since the access handler may be called many times (e.g. for a PUT/POST operation with plenty of upload data) this allows the application to easily associate some request-specific state. If necessary, this state can be cleaned up in the global #MHD_RequestCompletedCallback (which can be set with the #MHD_OPTION_NOTIFY_COMPLETED). Initially, *con_cls will be NULL.
Returns
#MHD_YES if the connection was handled successfully, #MHD_NO if the socket must be closed due to a serious error while handling the request

Definition at line 457 of file gnunet-daemon-hostlist_server.c.

465{
466 static int dummy;
467 struct MHD_Response *selected_response;
468 enum GNUNET_GenericReturnValue want_json = GNUNET_NO;
469
470 /* CORS pre-flight request */
471 if (0 == strcmp (MHD_HTTP_METHOD_OPTIONS, method))
472 {
473 struct MHD_Response *options_response;
474 int rc;
475
476 options_response =
477 MHD_create_response_from_buffer (0, NULL, MHD_RESPMEM_PERSISTENT);
478 add_cors_headers (options_response);
479 rc = MHD_queue_response (connection, MHD_HTTP_OK, options_response);
480 MHD_destroy_response (options_response);
481 return rc;
482 }
483 if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
484 {
486 _ ("Refusing `%s' request to hostlist server\n"),
487 method);
490 "hostlist requests refused (not HTTP GET)"),
491 1,
492 GNUNET_YES);
493 return MHD_NO;
494 }
495 if (NULL == *con_cls)
496 {
497 (*con_cls) = &dummy;
498 return MHD_YES;
499 }
500 if (0 != *upload_data_size)
501 {
503 _ ("Refusing `%s' request with %llu bytes of upload data\n"),
504 method,
505 (unsigned long long) *upload_data_size);
508 "hostlist requests refused (upload data)"),
509 1,
510 GNUNET_YES);
511 return MHD_NO; /* do not support upload data */
512 }
513 selected_response = response;
514 MHD_get_connection_values (connection,
515 MHD_HEADER_KIND,
516 (MHD_KeyValueIterator) & header_iterator,
517 &want_json);
518 if (GNUNET_YES == want_json)
519 {
520 selected_response = response_json;
521 }
522 if (NULL == selected_response)
523 {
524 GNUNET_log (
526 _ (
527 "Could not handle hostlist request since I do not have a response yet\n"));
530 "hostlist requests refused (not ready)"),
531 1,
532 GNUNET_YES);
533 return MHD_NO; /* internal error, no response yet */
534 }
536 _ ("Received request for our hostlist\n"));
538 gettext_noop ("hostlist requests processed"),
539 1,
540 GNUNET_YES);
541 return MHD_queue_response (connection, MHD_HTTP_OK, selected_response);
542}

References _, add_cors_headers(), dummy, gettext_noop, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_YES, header_iterator(), response, response_json, and stats.

Referenced by GNUNET_HOSTLIST_server_start().

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

◆ adv_transmit()

static void adv_transmit ( struct GNUNET_MQ_Handle mq)
static

Handler called by CORE when CORE is ready to transmit message.

Parameters
clsclosure with the const struct GNUNET_PeerIdentity * of the peer we are sending to
sizesize of buffer to copy message to
bufbuffer to copy message to
Returns
number of bytes copied to buf

Definition at line 555 of file gnunet-daemon-hostlist_server.c.

556{
557 static uint64_t hostlist_adv_count;
558 size_t uri_size; /* Including \0 termination! */
559 struct GNUNET_MessageHeader *header;
560 struct GNUNET_MQ_Envelope *env;
561
562 uri_size = strlen (hostlist_uri) + 1;
563 env = GNUNET_MQ_msg_extra (header,
564 uri_size,
566 GNUNET_memcpy (&header[1], hostlist_uri, uri_size);
572 "Sent advertisement message: Copied %u bytes into buffer!\n",
573 (unsigned int) uri_size);
574 hostlist_adv_count++;
576 " # Sent advertisement message: %llu\n",
577 (unsigned long long) hostlist_adv_count);
579 gettext_noop ("# hostlist advertisements send"),
580 1,
581 GNUNET_NO);
582}

References env, gettext_noop, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT, GNUNET_MQ_env_set_options(), GNUNET_MQ_msg_extra, GNUNET_MQ_PREF_CORK_ALLOWED, GNUNET_MQ_PREF_UNRELIABLE, GNUNET_MQ_send(), GNUNET_NO, GNUNET_STATISTICS_update(), hostlist_uri, mq, and stats.

Referenced by connect_handler().

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

◆ connect_handler()

static void * connect_handler ( void *  cls,
const struct GNUNET_PeerIdentity peer,
struct GNUNET_MQ_Handle mq,
enum GNUNET_CORE_PeerClass  class 
)
static

Method called whenever a given peer connects.

Parameters
clsclosure
peerpeer identity this notification is about
mqqueue for transmission to peer
classclass of the connecting peer
Returns
NULL (must!)

Definition at line 595 of file gnunet-daemon-hostlist_server.c.

599{
600 size_t size;
601
602 if (! advertising)
603 return NULL;
604 if (NULL == hostlist_uri)
605 return NULL;
606 size = strlen (hostlist_uri) + 1;
607 if (size + sizeof(struct GNUNET_MessageHeader) >= GNUNET_MAX_MESSAGE_SIZE)
608 {
609 GNUNET_break (0);
610 return NULL;
611 }
612 size += sizeof(struct GNUNET_MessageHeader);
613 if (NULL == core)
614 {
615 GNUNET_break (0);
616 return NULL;
617 }
618 GNUNET_log (
620 "Asked CORE to transmit advertisement message with a size of %u bytes to peer `%s'\n",
621 (unsigned int) size,
622 GNUNET_i2s (peer));
624 return NULL;
625}

References adv_transmit(), advertising, core, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_MAX_MESSAGE_SIZE, hostlist_uri, mq, and size.

Referenced by GNUNET_HOSTLIST_server_start().

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

◆ process_notify()

static void process_notify ( void *  cls,
const struct GNUNET_PEERSTORE_Record record,
const char *  err_msg 
)
static

PEERSTORE calls this function to let us know about a possible peer that we might want to connect to.

Parameters
clsclosure (not used)
peerpotential peer to connect to
helloHELLO for this peer (or NULL)
err_msgNULL if successful, otherwise contains error message

Definition at line 638 of file gnunet-daemon-hostlist_server.c.

641{
642 unsigned int map_size;
643 struct GNUNET_MessageHeader *hello_cpy;
644 struct GNUNET_MessageHeader *old_hello;
645 struct GNUNET_MessageHeader *hello;
646
649 "Peerstore is notifying us to rebuild our hostlist map size %u\n",
650 map_size);
651 if (NULL != err_msg)
652 {
654 _ ("Error in communication with PEERSTORE service: %s\n"),
655 err_msg);
657 return;
658 }
659 if (NULL == record)
660 {
661 GNUNET_break (0);
663 return;
664 }
665 hello = record->value;
666 /* @e value and @e value_size are independent, and the HELLO is an
667 unvalidated blob a remote peer published: a zero-length value leaves
668 @a hello NULL, and a @e size field larger than @e value_size makes the
669 GNUNET_memcpy() below read past the end of the record. */
670 if ((NULL == hello) ||
671 (record->value_size < sizeof (*hello)) ||
672 (ntohs (hello->size) > record->value_size))
673 {
674 GNUNET_break_op (0);
676 return;
677 }
678 /* PEERSTORE stores what it is given (handle_store() validates nothing),
679 and these records were published by other peers. Check the signature
680 once, here, instead of leaving it to whoever happens to parse the set
681 later: it kept malformed HELLOs out of the JSON response only because
682 build_json_response() had to parse to build a URL, and never kept
683 them out of the binary one at all. */
684 {
686 const struct GNUNET_PeerIdentity *pid;
687
689 &record->peer);
690 if (NULL == parser)
691 {
692 /* Not #GNUNET_break_op(): this is also how an expired HELLO fails,
693 and a record outliving the signature over it is routine. */
695 "HELLO for `%s' is expired or does not verify, skipping\n",
696 GNUNET_i2s (&record->peer));
698 return;
699 }
700 pid = GNUNET_HELLO_parser_get_id (parser);
701 if ((NULL == pid) ||
702 (0 != GNUNET_memcmp (pid, &record->peer)))
703 {
704 /* We key the map by the record's peer, so a HELLO filed under
705 somebody else's identity would evict that peer's real one. */
706 GNUNET_break_op (0);
709 return;
710 }
712 }
713 /* A peer has exactly one current HELLO, and PEERSTORE tells us about
714 every store of it -- our own client half alone re-stores everything
715 it downloads, on every download round. Appending here (as
716 #GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE did) meant the map grew
717 without bound, every entry was leaked, and each rebuild re-encoded
718 the same HELLO once per copy. */
719 hello_cpy = GNUNET_malloc (ntohs (hello->size));
720 GNUNET_memcpy (hello_cpy, hello, ntohs (hello->size));
722 &record->peer);
723 if (NULL != old_hello)
724 {
727 &record->peer,
728 old_hello));
729 GNUNET_free (old_hello);
730 }
733 &record->peer,
734 hello_cpy,
739 "1 Peerstore is notifying us to rebuild our hostlist map size %u peer %s\n",
740 map_size,
741 GNUNET_i2s (&record->peer));
743}

References _, GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_get(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_CONTAINER_multipeermap_remove(), GNUNET_CONTAINER_multipeermap_size(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_HELLO_parser_free(), GNUNET_HELLO_parser_from_msg(), GNUNET_HELLO_parser_get_id(), GNUNET_i2s(), GNUNET_log, GNUNET_malloc, GNUNET_memcmp, GNUNET_memcpy, GNUNET_PEERSTORE_monitor_next(), GNUNET_YES, hellos, map_size, peerstore_notify, record(), schedule_rebuild(), and GNUNET_MessageHeader::size.

Referenced by start_notify().

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

◆ prepare_daemon()

static struct GNUNET_SCHEDULER_Task * prepare_daemon ( struct MHD_Daemon *  daemon_handle)
static

Function that queries MHD's select sets and starts the task waiting for them.

Parameters
daemon_handleHTTP server to prepare to run

Definition at line 784 of file gnunet-daemon-hostlist_server.c.

785{
787 fd_set rs;
788 fd_set ws;
789 fd_set es;
790 struct GNUNET_NETWORK_FDSet *wrs;
791 struct GNUNET_NETWORK_FDSet *wws;
792 int max;
793 MHD_UNSIGNED_LONG_LONG timeout;
794 int haveto;
795 struct GNUNET_TIME_Relative tv;
796
797 FD_ZERO (&rs);
798 FD_ZERO (&ws);
799 FD_ZERO (&es);
802 max = -1;
803 GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es, &max));
804 haveto = MHD_get_timeout (daemon_handle, &timeout);
805 if (haveto == MHD_YES)
806 tv.rel_value_us = (uint64_t) timeout * 1000LL;
807 else
812 tv,
813 wrs,
814 wws,
815 &run_daemon,
816 daemon_handle);
819 return ret;
820}

References GNUNET_assert, GNUNET_NETWORK_fdset_copy_native(), GNUNET_NETWORK_fdset_create(), GNUNET_NETWORK_fdset_destroy(), GNUNET_SCHEDULER_add_select(), GNUNET_SCHEDULER_PRIORITY_HIGH, GNUNET_TIME_UNIT_FOREVER_REL, max, GNUNET_TIME_Relative::rel_value_us, ret, run_daemon(), and timeout.

Referenced by GNUNET_HOSTLIST_server_start(), and run_daemon().

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

◆ run_daemon()

static void run_daemon ( void *  cls)
static

Call MHD to process pending requests and then go back and schedule the next run.

Parameters
clsthe struct MHD_Daemon of the HTTP server to run

Definition at line 761 of file gnunet-daemon-hostlist_server.c.

762{
763 struct MHD_Daemon *daemon_handle = cls;
764
765 if (daemon_handle == daemon_handle_v4)
766 hostlist_task_v4 = NULL;
767 else
768 hostlist_task_v6 = NULL;
769 GNUNET_assert (MHD_YES == MHD_run (daemon_handle));
770 if (daemon_handle == daemon_handle_v4)
771 hostlist_task_v4 = prepare_daemon (daemon_handle);
772 else
773 hostlist_task_v6 = prepare_daemon (daemon_handle);
774}

References daemon_handle_v4, GNUNET_assert, hostlist_task_v4, hostlist_task_v6, and prepare_daemon().

Referenced by prepare_daemon().

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

◆ error_cb()

static void error_cb ( void *  cls)
static

Definition at line 824 of file gnunet-daemon-hostlist_server.c.

825{
827 "Error in PEERSTORE monitoring\n");
828}

References GNUNET_ERROR_TYPE_WARNING, and GNUNET_log.

Referenced by start_notify().

Here is the caller graph for this function:

◆ sync_cb()

static void sync_cb ( void *  cls)
static

Definition at line 832 of file gnunet-daemon-hostlist_server.c.

833{
835 "Done with initial PEERSTORE iteration during monitoring\n");
836}

References GNUNET_ERROR_TYPE_WARNING, and GNUNET_log.

Referenced by start_notify().

Here is the caller graph for this function:

◆ start_notify()

static void start_notify ( void *  cls)
static

Definition at line 840 of file gnunet-daemon-hostlist_server.c.

841{
842 (void) cls;
843
845 "Starting to process new hellos to add to hostlist.\n");
848 "peerstore",
849 NULL,
851 &error_cb,
852 NULL,
853 &sync_cb,
854 NULL,
855 &process_notify, NULL);
856}

References cfg, error_cb(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_PEERSTORE_HELLO_KEY, GNUNET_PEERSTORE_monitor_start(), GNUNET_YES, peerstore_notify, process_notify(), and sync_cb().

Referenced by GNUNET_HOSTLIST_server_start().

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

◆ GNUNET_HOSTLIST_server_start()

int GNUNET_HOSTLIST_server_start ( const struct GNUNET_CONFIGURATION_Handle c,
struct GNUNET_STATISTICS_Handle st,
struct GNUNET_CORE_Handle co,
GNUNET_CORE_ConnectEventHandler server_ch,
int  advertise 
)

Start server offering our hostlist.

Parameters
cconfiguration to use
ststatistics handle to use
cocore handle to use
[out]server_chset to handler for CORE connect events
advertiseGNUNET_YES if we should advertise our hostlist
Returns
GNUNET_OK on success

Definition at line 870 of file gnunet-daemon-hostlist_server.c.

875{
876 unsigned long long port;
877 char *hostname;
878 char *ipv4;
879 char *ipv6;
880 size_t size;
881 struct in_addr i4;
882 struct in6_addr i6;
883 struct sockaddr_in v4;
884 struct sockaddr_in6 v6;
885 const struct sockaddr *sa4;
886 const struct sockaddr *sa6;
887
888 /* Keys are copied: #process_notify() puts the identity of a borrowed
889 PEERSTORE record, which does not outlive the callback. */
891 advertising = advertise;
892 if (! advertising)
893 {
895 "Advertising not enabled on this hostlist server\n");
896 }
897 else
898 {
900 "Advertising enabled on this hostlist server\n");
901 }
902 cfg = c;
903 stats = st;
905 if (NULL == peerstore)
906 {
908 _ ("Could not access PEERSTORE service. Exiting.\n"));
909 return GNUNET_SYSERR;
910 }
912 "HOSTLIST",
913 "HTTPPORT",
914 &port))
915 return GNUNET_SYSERR;
916 if ((0 == port) || (port > UINT16_MAX))
917 {
919 _ ("Invalid port number %llu. Exiting.\n"),
920 port);
921 return GNUNET_SYSERR;
922 }
923
924 if (GNUNET_SYSERR ==
926 "HOSTLIST",
927 "EXTERNAL_DNS_NAME",
928 &hostname))
929 hostname = GNUNET_RESOLVER_local_fqdn_get ();
931 _ ("Hostlist service starts on %s:%llu\n"),
932 hostname,
933 port);
934 if (NULL != hostname)
935 {
936 size = strlen (hostname);
937 if (size + 15 > MAX_URL_LEN)
938 {
939 GNUNET_break (0);
940 }
941 else
942 {
944 "http://%s:%u/",
945 hostname,
946 (unsigned int) port);
948 _ ("Address to obtain hostlist: `%s'\n"),
950 }
951 GNUNET_free (hostname);
952 }
953
954 if (GNUNET_CONFIGURATION_have_value (cfg, "HOSTLIST", "BINDTOIPV4"))
955 {
957 "HOSTLIST",
958 "BINDTOIP",
959 &ipv4))
960 {
961 GNUNET_log (
963 _ ("BINDTOIP does not a valid IPv4 address! Ignoring BINDTOIPV4.\n"));
964 }
965 }
966 else
967 ipv4 = NULL;
968 if (GNUNET_CONFIGURATION_have_value (cfg, "HOSTLIST", "BINDTOIPV6"))
969 {
971 "HOSTLIST",
972 "BINDTOIP",
973 &ipv6))
974 {
975 GNUNET_log (
977 _ ("BINDTOIP does not a valid IPv4 address! Ignoring BINDTOIPV6.\n"));
978 }
979 }
980 else
981 ipv6 = NULL;
982 sa4 = NULL;
983 if (NULL != ipv4)
984 {
985 if (1 == inet_pton (AF_INET, ipv4, &i4))
986 {
987 memset (&v4, 0, sizeof(v4));
988 v4.sin_family = AF_INET;
989 v4.sin_addr = i4;
990 v4.sin_port = htons (port);
991#if HAVE_SOCKADDR_IN_SIN_LEN
992 v4.sin_len = sizeof(v4);
993#endif
994 sa4 = (const struct sockaddr *) &v4;
995 }
996 else
998 _ (
999 "`%s' is not a valid IPv4 address! Ignoring BINDTOIPV4.\n"),
1000 ipv4);
1001 GNUNET_free (ipv4);
1002 }
1003 sa6 = NULL;
1004 if (NULL != ipv6)
1005 {
1006 if (1 == inet_pton (AF_INET6, ipv6, &i6))
1007 {
1008 memset (&v6, 0, sizeof(v6));
1009 v6.sin6_family = AF_INET6;
1010 v6.sin6_addr = i6;
1011 v6.sin6_port = htons (port);
1012#if HAVE_SOCKADDR_IN_SIN_LEN
1013 v6.sin6_len = sizeof(v6);
1014#endif
1015 sa6 = (const struct sockaddr *) &v6;
1016 }
1017 else
1019 _ (
1020 "`%s' is not a valid IPv6 address! Ignoring BINDTOIPV6.\n"),
1021 ipv6);
1022 GNUNET_free (ipv6);
1023 }
1024
1025 daemon_handle_v6 = MHD_start_daemon (MHD_USE_IPv6 | MHD_USE_DEBUG,
1026 (uint16_t) port,
1028 NULL,
1030 NULL,
1031 MHD_OPTION_CONNECTION_LIMIT,
1032 (unsigned int) 128,
1033 MHD_OPTION_PER_IP_CONNECTION_LIMIT,
1034 (unsigned int) 32,
1035 MHD_OPTION_CONNECTION_TIMEOUT,
1036 (unsigned int) 16,
1037 MHD_OPTION_CONNECTION_MEMORY_LIMIT,
1038 (size_t) (16 * 1024),
1039 MHD_OPTION_SOCK_ADDR,
1040 sa6,
1041 MHD_OPTION_END);
1042 daemon_handle_v4 = MHD_start_daemon (MHD_NO_FLAG | MHD_USE_DEBUG,
1043 (uint16_t) port,
1045 NULL,
1047 NULL,
1048 MHD_OPTION_CONNECTION_LIMIT,
1049 (unsigned int) 128,
1050 MHD_OPTION_PER_IP_CONNECTION_LIMIT,
1051 (unsigned int) 32,
1052 MHD_OPTION_CONNECTION_TIMEOUT,
1053 (unsigned int) 16,
1054 MHD_OPTION_CONNECTION_MEMORY_LIMIT,
1055 (size_t) (16 * 1024),
1056 MHD_OPTION_SOCK_ADDR,
1057 sa4,
1058 MHD_OPTION_END);
1059
1060 if ((NULL == daemon_handle_v6) && (NULL == daemon_handle_v4))
1061 {
1063 _ ("Could not start hostlist HTTP server on port %u\n"),
1064 (unsigned short) port);
1065 return GNUNET_SYSERR;
1066 }
1067
1068 core = co;
1070 if (NULL != daemon_handle_v4)
1072 if (NULL != daemon_handle_v6)
1077 NULL);
1078 return GNUNET_OK;
1079}

References _, accept_policy_callback(), access_handler_callback(), advertising, cfg, connect_handler(), core, daemon_handle_v4, daemon_handle_v6, GNUNET_asprintf(), GNUNET_break, GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_have_value(), GNUNET_CONTAINER_multipeermap_create(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_PEERSTORE_connect(), GNUNET_RESOLVER_local_fqdn_get(), GNUNET_SCHEDULER_add_delayed(), GNUNET_SYSERR, GNUNET_TIME_UNIT_MINUTES, hellos, hostlist_task_v4, hostlist_task_v6, hostlist_uri, ipv4, ipv6, MAX_URL_LEN, peerstore, peerstore_notify_task, port, prepare_daemon(), server_ch, size, st, start_notify(), and stats.

Referenced by run().

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

◆ GNUNET_HOSTLIST_server_stop()

void GNUNET_HOSTLIST_server_stop ( void  )

Stop server offering our hostlist.

Definition at line 1086 of file gnunet-daemon-hostlist_server.c.

1087{
1088 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlist server shutdown\n");
1089 if (NULL != rebuild_task)
1090 {
1092 rebuild_task = NULL;
1093 }
1094 if (NULL != hostlist_task_v6)
1095 {
1097 hostlist_task_v6 = NULL;
1098 }
1099 if (NULL != hostlist_task_v4)
1100 {
1102 hostlist_task_v4 = NULL;
1103 }
1104 if (NULL != daemon_handle_v4)
1105 {
1106 MHD_stop_daemon (daemon_handle_v4);
1107 daemon_handle_v4 = NULL;
1108 }
1109 if (NULL != daemon_handle_v6)
1110 {
1111 MHD_stop_daemon (daemon_handle_v6);
1112 daemon_handle_v6 = NULL;
1113 }
1114 if (NULL != response)
1115 {
1116 MHD_destroy_response (response);
1117 response = NULL;
1118 }
1119 if (NULL != response_json)
1120 {
1121 MHD_destroy_response (response_json);
1122 response_json = NULL;
1123 }
1124 if (NULL != peerstore_notify)
1125 {
1127 peerstore_notify = NULL;
1128 }
1129 else if (NULL != peerstore_notify_task)
1130 {
1132 }
1133 if (NULL != builder)
1134 {
1137 builder = NULL;
1138 }
1139 if (NULL != hellos)
1140 {
1142 &free_hello,
1143 NULL);
1145 hellos = NULL;
1146 }
1147 if (NULL != peerstore)
1148 {
1150 peerstore = NULL;
1151 }
1152 cfg = NULL;
1153 stats = NULL;
1154 core = NULL;
1155}

References builder, cfg, core, daemon_handle_v4, daemon_handle_v6, HostSet::data, free_hello(), GNUNET_CONTAINER_multipeermap_destroy(), GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_PEERSTORE_disconnect(), GNUNET_PEERSTORE_monitor_stop(), GNUNET_SCHEDULER_cancel(), hellos, hostlist_task_v4, hostlist_task_v6, peerstore, peerstore_notify, peerstore_notify_task, rebuild_task, response, response_json, and stats.

Referenced by cleaning_task().

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

Variable Documentation

◆ hellos

Map with hellos we build the hostlist with.

At most one HELLO per peer.

Definition at line 61 of file gnunet-daemon-hostlist_server.c.

Referenced by GNUNET_HOSTLIST_server_start(), GNUNET_HOSTLIST_server_stop(), process_notify(), and rebuild_hostlist().

◆ daemon_handle_v6

struct MHD_Daemon* daemon_handle_v6
static

Handle to the HTTP server as provided by libmicrohttpd for IPv6.

Definition at line 66 of file gnunet-daemon-hostlist_server.c.

Referenced by finish_response(), GNUNET_HOSTLIST_server_start(), and GNUNET_HOSTLIST_server_stop().

◆ daemon_handle_v4

struct MHD_Daemon* daemon_handle_v4
static

Handle to the HTTP server as provided by libmicrohttpd for IPv4.

Definition at line 71 of file gnunet-daemon-hostlist_server.c.

Referenced by finish_response(), GNUNET_HOSTLIST_server_start(), GNUNET_HOSTLIST_server_stop(), and run_daemon().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Our configuration.

Definition at line 76 of file gnunet-daemon-hostlist_server.c.

Referenced by GNUNET_HOSTLIST_server_start(), GNUNET_HOSTLIST_server_stop(), and start_notify().

◆ stats

◆ core

struct GNUNET_CORE_Handle* core
static

Handle to the core service (NULL until we've connected to it).

Definition at line 86 of file gnunet-daemon-hostlist_server.c.

Referenced by connect_handler(), GNUNET_HOSTLIST_server_start(), and GNUNET_HOSTLIST_server_stop().

◆ peerstore_notify_task

struct GNUNET_SCHEDULER_Task* peerstore_notify_task

The task to delayed start the notification process initially.

We like to give transport some time to give us our hello to distribute it.

Definition at line 92 of file gnunet-daemon-hostlist_server.c.

Referenced by GNUNET_HOSTLIST_server_start(), and GNUNET_HOSTLIST_server_stop().

◆ peerstore_notify

struct GNUNET_PEERSTORE_Monitor* peerstore_notify
static

Our peerstore notification context.

We use notification to instantly learn about new peers as they are discovered.

Definition at line 98 of file gnunet-daemon-hostlist_server.c.

Referenced by GNUNET_HOSTLIST_server_stop(), process_notify(), and start_notify().

◆ hostlist_task_v4

struct GNUNET_SCHEDULER_Task* hostlist_task_v4
static

Our primary task for IPv4.

Definition at line 103 of file gnunet-daemon-hostlist_server.c.

Referenced by GNUNET_HOSTLIST_server_start(), GNUNET_HOSTLIST_server_stop(), and run_daemon().

◆ hostlist_task_v6

struct GNUNET_SCHEDULER_Task* hostlist_task_v6
static

Our primary task for IPv6.

Definition at line 108 of file gnunet-daemon-hostlist_server.c.

Referenced by GNUNET_HOSTLIST_server_start(), GNUNET_HOSTLIST_server_stop(), and run_daemon().

◆ rebuild_task

struct GNUNET_SCHEDULER_Task* rebuild_task
static

Task that rebuilds our response from hellos, or NULL if no rebuild is pending.

Definition at line 114 of file gnunet-daemon-hostlist_server.c.

Referenced by GNUNET_HOSTLIST_server_stop(), rebuild_hostlist(), and schedule_rebuild().

◆ response

◆ response_json

struct MHD_Response* response_json
static

Our json response.

Definition at line 124 of file gnunet-daemon-hostlist_server.c.

Referenced by access_handler_callback(), finish_response(), and GNUNET_HOSTLIST_server_stop().

◆ peerstore

struct GNUNET_PEERSTORE_Handle* peerstore
static

Handle to the PEERSTORE service.

Definition at line 129 of file gnunet-daemon-hostlist_server.c.

Referenced by GNUNET_HOSTLIST_server_start(), and GNUNET_HOSTLIST_server_stop().

◆ advertising

int advertising
static

Set if we are allowed to advertise our hostlist to others.

Definition at line 134 of file gnunet-daemon-hostlist_server.c.

Referenced by connect_handler(), and GNUNET_HOSTLIST_server_start().

◆ hostlist_uri

char* hostlist_uri
static

Buffer for the hostlist address.

Definition at line 139 of file gnunet-daemon-hostlist_server.c.

Referenced by adv_transmit(), connect_handler(), and GNUNET_HOSTLIST_server_start().

◆ builder