GNUnet  0.10.x
gnunet-daemon-topology.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2007-2016 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 
39 #include "platform.h"
40 #include "gnunet_util_lib.h"
41 #include "gnunet_friends_lib.h"
42 #include "gnunet_constants.h"
43 #include "gnunet_core_service.h"
44 #include "gnunet_protocols.h"
48 #include "gnunet_ats_service.h"
49 
50 
54 #define HELLO_ADVERTISEMENT_MIN_FREQUENCY \
55  GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
56 
60 #define HELLO_ADVERTISEMENT_MIN_REPEAT_FREQUENCY \
61  GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_HOURS, 4)
62 
63 
67 struct Peer {
71  struct GNUNET_PeerIdentity pid;
72 
78 
83 
89 
94 
99 
105 
110 
114  uint32_t strength;
115 
120 };
121 
122 
128 
132 static const struct GNUNET_CONFIGURATION_Handle *cfg;
133 
137 static struct GNUNET_CORE_Handle *handle;
138 
142 static struct GNUNET_PEERINFO_Handle *pi;
143 
148 
153 
160 
165 
170 
176 
181 
185 static int friends_only;
186 
191 static unsigned int minimum_friend_count;
192 
196 static unsigned int connection_count;
197 
201 static unsigned int target_connection_count;
202 
206 static unsigned int friend_count;
207 
208 
218 static int
220 {
221  struct Peer *pos;
222 
223  pos = GNUNET_CONTAINER_multipeermap_get(peers, pid);
224  if ((NULL != pos) && (GNUNET_YES == pos->is_friend))
225  return GNUNET_OK;
227  gettext_noop("# peers blacklisted"),
228  1,
229  GNUNET_NO);
230  return GNUNET_SYSERR;
231 }
232 
233 
238 static void
240 {
241  if (NULL != blacklist)
242  {
244  blacklist = NULL;
245  }
246 }
247 
248 
257 static int
258 free_peer(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
259 {
260  struct Peer *pos = value;
261 
262  GNUNET_break(NULL == pos->mq);
264  GNUNET_CONTAINER_multipeermap_remove(peers, pid, pos));
265  if (NULL != pos->hello_delay_task)
266  {
268  pos->hello_delay_task = NULL;
269  }
270  if (NULL != pos->sh)
271  {
273  pos->sh = NULL;
274  }
275  if (NULL != pos->hello)
276  {
278  pos->hello = NULL;
279  }
280  if (NULL != pos->filter)
281  {
283  pos->filter = NULL;
284  }
285  GNUNET_free(pos);
286  return GNUNET_YES;
287 }
288 
289 
296 static void
297 attempt_connect(struct Peer *pos)
298 {
299  uint32_t strength;
300 
301  if (0 == GNUNET_memcmp(&my_identity, &pos->pid))
302  return; /* This is myself, nothing to do. */
304  strength = 1;
305  else
306  strength = 0;
308  {
309  if (pos->is_friend)
310  strength += 10; /* urgently needed */
311  else
312  strength = 0; /* disallowed */
313  }
314  if (pos->is_friend)
315  strength *= 2; /* friends always count more */
316  if (NULL != pos->mq)
317  strength *= 2; /* existing connections preferred */
318  if (strength == pos->strength)
319  return; /* nothing to do */
320  if (NULL != pos->sh)
321  {
323  pos->sh = NULL;
324  }
325  pos->strength = strength;
326  if (0 != strength)
327  {
329  "Asking to connect to `%s' with strength %u\n",
330  GNUNET_i2s(&pos->pid),
331  (unsigned int)strength);
333  gettext_noop("# connect requests issued to ATS"),
334  1,
335  GNUNET_NO);
336  pos->sh = GNUNET_ATS_connectivity_suggest(ats, &pos->pid, strength);
337  }
338 }
339 
340 
349 static struct Peer *
351  const struct GNUNET_HELLO_Message *hello,
352  int is_friend)
353 {
354  struct Peer *ret;
355 
356  ret = GNUNET_new(struct Peer);
357  ret->pid = *peer;
358  ret->is_friend = is_friend;
359  if (NULL != hello)
360  {
361  ret->hello = GNUNET_malloc(GNUNET_HELLO_size(hello));
362  GNUNET_memcpy(ret->hello, hello, GNUNET_HELLO_size(hello));
363  }
366  peers,
367  peer,
368  ret,
370  return ret;
371 }
372 
373 
379 static void
381 {
382  struct GNUNET_HashCode hc;
383 
384  /* 2^{-5} chance of not sending a HELLO to a peer is
385  * acceptably small (if the filter is 50% full);
386  * 64 bytes of memory are small compared to the rest
387  * of the data structure and would only really become
388  * "useless" once a HELLO has been passed on to ~100
389  * other peers, which is likely more than enough in
390  * any case; hence 64, 5 as bloomfilter parameters. */
391  peer->filter = GNUNET_CONTAINER_bloomfilter_init(NULL, 64, 5);
392  peer->filter_expiration =
394  /* never send a peer its own HELLO */
395  GNUNET_CRYPTO_hash(&peer->pid, sizeof(struct GNUNET_PeerIdentity), &hc);
397 }
398 
399 
407  struct Peer *peer;
408 
412  struct Peer *result;
413 
417  size_t max_size;
418 
419  struct GNUNET_TIME_Relative next_adv;
420 };
421 
422 
431 static int
433  const struct GNUNET_PeerIdentity *pid,
434  void *value)
435 {
436  struct FindAdvHelloContext *fah = cls;
437  struct Peer *pos = value;
438  struct GNUNET_TIME_Relative rst_time;
439  struct GNUNET_HashCode hc;
440  size_t hs;
441 
442  if (pos == fah->peer)
443  return GNUNET_YES;
444  if (pos->hello == NULL)
445  return GNUNET_YES;
447  if (0 == rst_time.rel_value_us)
448  {
449  /* time to discard... */
451  setup_filter(pos);
452  }
453  fah->next_adv = GNUNET_TIME_relative_min(rst_time, fah->next_adv);
454  hs = GNUNET_HELLO_size(pos->hello);
455  if (hs > fah->max_size)
456  return GNUNET_YES;
457  GNUNET_CRYPTO_hash(&fah->peer->pid,
458  sizeof(struct GNUNET_PeerIdentity),
459  &hc);
461  fah->result = pos;
462  return GNUNET_YES;
463 }
464 
465 
472 static void
474 {
475  struct Peer *pl = cls;
476  struct FindAdvHelloContext fah;
477  struct GNUNET_MQ_Envelope *env;
478  size_t want;
479  struct GNUNET_TIME_Relative delay;
480  struct GNUNET_HashCode hc;
481 
482  pl->hello_delay_task = NULL;
483  GNUNET_assert(NULL != pl->mq);
484  /* find applicable HELLOs */
485  fah.peer = pl;
486  fah.result = NULL;
490  pl->hello_delay_task =
492  if (NULL == fah.result)
493  return;
495  if (0 != delay.rel_value_us)
496  return;
497 
498  want = GNUNET_HELLO_size(fah.result->hello);
500  "Sending HELLO with %u bytes",
501  (unsigned int)want);
502  env = GNUNET_MQ_msg_copy(&fah.result->hello->header);
503  GNUNET_MQ_send(pl->mq, env);
504 
505  /* avoid sending this one again soon */
506  GNUNET_CRYPTO_hash(&pl->pid, sizeof(struct GNUNET_PeerIdentity), &hc);
508 
510  gettext_noop("# HELLO messages gossipped"),
511  1,
512  GNUNET_NO);
513  /* prepare to send the next one */
514  pl->next_hello_allowed =
516  if (NULL != pl->hello_delay_task)
519 }
520 
521 
532 static int
534  const struct GNUNET_PeerIdentity *pid,
535  void *value)
536 {
537  struct Peer *peer = value;
538  struct Peer *skip = cls;
539 
540  if (skip == peer)
541  return GNUNET_YES;
542  if (NULL == peer->mq)
543  return GNUNET_YES;
544  if (NULL != peer->hello_delay_task)
545  {
547  peer->hello_delay_task = NULL;
548  }
549  peer->hello_delay_task =
551  return GNUNET_YES;
552 }
553 
554 
563 static void *
564 connect_notify(void *cls,
565  const struct GNUNET_PeerIdentity *peer,
566  struct GNUNET_MQ_Handle *mq)
567 {
568  struct Peer *pos;
569 
571  "Core told us that we are connecting to `%s'\n",
572  GNUNET_i2s(peer));
573  if (0 == GNUNET_memcmp(&my_identity, peer))
574  return NULL;
577  GNUNET_STATISTICS_set(stats,
578  gettext_noop("# peers connected"),
580  GNUNET_NO);
581  pos = GNUNET_CONTAINER_multipeermap_get(peers, peer);
582  if (NULL == pos)
583  {
584  pos = make_peer(peer, NULL, GNUNET_NO);
585  }
586  else
587  {
588  GNUNET_assert(NULL == pos->mq);
589  }
590  pos->mq = mq;
591  if (pos->is_friend)
592  {
593  friend_count++;
595  whitelist_peers();
596  GNUNET_STATISTICS_set(stats,
597  gettext_noop("# friends connected"),
598  friend_count,
599  GNUNET_NO);
600  }
601  reschedule_hellos(NULL, peer, pos);
602  return pos;
603 }
604 
605 
614 static int
615 try_add_peers(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
616 {
617  struct Peer *pos = value;
618 
619  attempt_connect(pos);
620  return GNUNET_YES;
621 }
622 
623 
629 static void
630 add_peer_task(void *cls)
631 {
632  add_task = NULL;
633 
635 }
636 
637 
645 static void
647  const struct GNUNET_PeerIdentity *peer,
648  void *internal_cls)
649 {
650  struct Peer *pos = internal_cls;
651 
652  if (NULL == pos)
653  return; /* myself, we're shutting down */
655  "Core told us that we disconnected from `%s'\n",
656  GNUNET_i2s(peer));
657  if (NULL == pos->mq)
658  {
659  GNUNET_break(0);
660  return;
661  }
662  pos->mq = NULL;
664  if (NULL != pos->hello_delay_task)
665  {
667  pos->hello_delay_task = NULL;
668  }
669  GNUNET_STATISTICS_set(stats,
670  gettext_noop("# peers connected"),
672  GNUNET_NO);
673  if (pos->is_friend)
674  {
675  friend_count--;
676  GNUNET_STATISTICS_set(stats,
677  gettext_noop("# friends connected"),
678  friend_count,
679  GNUNET_NO);
680  }
683  (NULL == add_task))
684  add_task = GNUNET_SCHEDULER_add_now(&add_peer_task, NULL);
685  if ((friend_count < minimum_friend_count) && (NULL == blacklist))
686  blacklist = GNUNET_TRANSPORT_blacklist(cfg, &blacklist_check, NULL);
687 }
688 
689 
698 static int
700  const struct GNUNET_HELLO_Address *address,
702 {
703  int *flag = cls;
704 
705  *flag = GNUNET_YES;
706  return GNUNET_SYSERR;
707 }
708 
709 
716 static void
718 {
719  int have_address;
720  struct GNUNET_PeerIdentity pid;
721  struct GNUNET_TIME_Absolute dt;
722  struct GNUNET_HELLO_Message *nh;
723  struct Peer *peer;
724  uint16_t size;
725 
726  if (GNUNET_OK != GNUNET_HELLO_get_id(hello, &pid))
727  {
728  GNUNET_break(0);
729  return;
730  }
731  if (0 == GNUNET_memcmp(&pid, &my_identity))
732  return; /* that's me! */
733  have_address = GNUNET_NO;
735  GNUNET_NO,
737  &have_address);
738  if (GNUNET_NO == have_address)
739  return; /* no point in advertising this one... */
740  peer = GNUNET_CONTAINER_multipeermap_get(peers, &pid);
741  if (NULL == peer)
742  {
743  peer = make_peer(&pid, hello, GNUNET_NO);
744  }
745  else if (NULL != peer->hello)
746  {
747  dt = GNUNET_HELLO_equals(peer->hello, hello, GNUNET_TIME_absolute_get());
748  if (dt.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
749  return; /* nothing new here */
750  }
752  "Found HELLO from peer `%s' for advertising\n",
753  GNUNET_i2s(&pid));
754  if (NULL != peer->hello)
755  {
756  nh = GNUNET_HELLO_merge(peer->hello, hello);
757  GNUNET_free(peer->hello);
758  peer->hello = nh;
759  }
760  else
761  {
762  size = GNUNET_HELLO_size(hello);
763  peer->hello = GNUNET_malloc(size);
764  GNUNET_memcpy(peer->hello, hello, size);
765  }
766  if (NULL != peer->filter)
767  {
769  peer->filter = NULL;
770  }
771  setup_filter(peer);
772  /* since we have a new HELLO to pick from, re-schedule all
773  * HELLO requests that are not bound by the HELLO send rate! */
775 }
776 
777 
787 static void
788 process_peer(void *cls,
789  const struct GNUNET_PeerIdentity *peer,
790  const struct GNUNET_HELLO_Message *hello,
791  const char *err_msg)
792 {
793  struct Peer *pos;
794 
795  if (NULL != err_msg)
796  {
798  _("Error in communication with PEERINFO service: %s\n"),
799  err_msg);
800  GNUNET_PEERINFO_notify_cancel(peerinfo_notify);
801  peerinfo_notify =
803  return;
804  }
805  GNUNET_assert(NULL != peer);
806  if (0 == GNUNET_memcmp(&my_identity, peer))
807  return; /* that's me! */
808  if (NULL == hello)
809  {
810  /* free existing HELLO, if any */
811  pos = GNUNET_CONTAINER_multipeermap_get(peers, peer);
812  if (NULL != pos)
813  {
815  pos->hello = NULL;
816  if (NULL != pos->filter)
817  {
819  pos->filter = NULL;
820  }
821  if ((NULL == pos->mq) && (GNUNET_NO == pos->is_friend))
822  free_peer(NULL, &pos->pid, pos);
823  }
824  return;
825  }
827  pos = GNUNET_CONTAINER_multipeermap_get(peers, peer);
828  if (NULL == pos)
829  pos = make_peer(peer, hello, GNUNET_NO);
830  attempt_connect(pos);
831 }
832 
833 
841 static void
842 core_init(void *cls, const struct GNUNET_PeerIdentity *my_id)
843 {
844  if (NULL == my_id)
845  {
846  GNUNET_log(
848  _("Failed to connect to core service, can not manage topology!\n"));
850  return;
851  }
852  my_identity = *my_id;
853  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "I am peer `%s'\n", GNUNET_i2s(my_id));
854  peerinfo_notify =
856 }
857 
858 
865 static void
866 handle_friend(void *cls, const struct GNUNET_PeerIdentity *pid)
867 {
868  unsigned int *entries_found = cls;
869  struct Peer *fl;
870 
871  if (0 == GNUNET_memcmp(pid, &my_identity))
872  {
874  _("Found myself `%s' in friend list (useless, ignored)\n"),
875  GNUNET_i2s(pid));
876  return;
877  }
878  (*entries_found)++;
879  fl = make_peer(pid, NULL, GNUNET_YES);
881  _("Found friend `%s' in configuration\n"),
882  GNUNET_i2s(&fl->pid));
883 }
884 
885 
889 static void
891 {
892  unsigned int entries_found;
893 
894  entries_found = 0;
895  if (GNUNET_OK != GNUNET_FRIENDS_parse(cfg, &handle_friend, &entries_found))
896  {
897  if ((GNUNET_YES == friends_only) || (minimum_friend_count > 0))
899  _("Encountered errors parsing friends list!\n"));
900  }
902  gettext_noop("# friends in configuration"),
903  entries_found,
904  GNUNET_NO);
905  if ((minimum_friend_count > entries_found) && (GNUNET_NO == friends_only))
906  {
907  GNUNET_log(
909  _(
910  "Fewer friends specified than required by minimum friend count. Will only connect to friends.\n"));
911  }
913  (GNUNET_NO == friends_only))
914  {
915  GNUNET_log(
917  _(
918  "More friendly connections required than target total number of connections.\n"));
919  }
920 }
921 
922 
932 static int
933 check_hello(void *cls, const struct GNUNET_HELLO_Message *message)
934 {
935  struct GNUNET_PeerIdentity pid;
936 
937  if (GNUNET_OK != GNUNET_HELLO_get_id(message, &pid))
938  {
939  GNUNET_break_op(0);
940  return GNUNET_SYSERR;
941  }
942  return GNUNET_OK;
943 }
944 
945 
953 static void
954 handle_hello(void *cls, const struct GNUNET_HELLO_Message *message)
955 {
956  const struct GNUNET_PeerIdentity *other = cls;
957  struct Peer *peer;
958  struct GNUNET_PeerIdentity pid;
959 
961  "Received encrypted HELLO from peer `%s'",
962  GNUNET_i2s(other));
963  GNUNET_assert(GNUNET_OK == GNUNET_HELLO_get_id(message, &pid));
965  gettext_noop("# HELLO messages received"),
966  1,
967  GNUNET_NO);
968  peer = GNUNET_CONTAINER_multipeermap_get(peers, &pid);
969  if (NULL == peer)
970  {
972  return;
973  }
974  else
975  {
976  if ((GNUNET_YES != peer->is_friend) && (GNUNET_YES == friends_only))
977  return;
978  if ((GNUNET_YES != peer->is_friend) &&
980  return;
981  }
982  (void)GNUNET_PEERINFO_add_peer(pi, message, NULL, NULL);
983 }
984 
985 
992 static void
993 cleaning_task(void *cls)
994 {
995  if (NULL != peerinfo_notify)
996  {
997  GNUNET_PEERINFO_notify_cancel(peerinfo_notify);
998  peerinfo_notify = NULL;
999  }
1000  if (NULL != handle)
1001  {
1002  GNUNET_CORE_disconnect(handle);
1003  handle = NULL;
1004  }
1005  whitelist_peers();
1006  if (NULL != add_task)
1007  {
1008  GNUNET_SCHEDULER_cancel(add_task);
1009  add_task = NULL;
1010  }
1011  if (NULL != oh)
1012  {
1014  oh = NULL;
1015  }
1018  peers = NULL;
1019  if (NULL != ats)
1020  {
1022  ats = NULL;
1023  }
1024  if (NULL != pi)
1025  {
1027  pi = NULL;
1028  }
1029  if (NULL != stats)
1030  {
1032  stats = NULL;
1033  }
1034 }
1035 
1036 
1045 static void
1046 run(void *cls,
1047  char *const *args,
1048  const char *cfgfile,
1049  const struct GNUNET_CONFIGURATION_Handle *c)
1050 {
1051  struct GNUNET_MQ_MessageHandler handlers[] =
1054  struct GNUNET_HELLO_Message,
1055  NULL),
1057  unsigned long long opt;
1058 
1059  cfg = c;
1060  stats = GNUNET_STATISTICS_create("topology", cfg);
1061  friends_only =
1062  GNUNET_CONFIGURATION_get_value_yesno(cfg, "TOPOLOGY", "FRIENDS-ONLY");
1064  "TOPOLOGY",
1065  "MINIMUM-FRIENDS",
1066  &opt))
1067  opt = 0;
1068  minimum_friend_count = (unsigned int)opt;
1069  if (GNUNET_OK !=
1071  "TOPOLOGY",
1072  "TARGET-CONNECTION-COUNT",
1073  &opt))
1074  opt = 16;
1075  target_connection_count = (unsigned int)opt;
1077  GNUNET_NO);
1078  read_friends_file(cfg);
1080  "Topology would like %u connections with at least %u friends\n",
1083  if ((GNUNET_YES == friends_only) || (minimum_friend_count > 0))
1084  blacklist = GNUNET_TRANSPORT_blacklist(cfg, &blacklist_check, NULL);
1085  ats = GNUNET_ATS_connectivity_init(cfg);
1086  pi = GNUNET_PEERINFO_connect(cfg);
1087  handle = GNUNET_CORE_connect(cfg,
1088  NULL,
1089  &core_init,
1090  &connect_notify,
1092  handlers);
1094  if (NULL == handle)
1095  {
1097  _("Failed to connect to `%s' service.\n"),
1098  "core");
1100  return;
1101  }
1102 }
1103 
1104 
1112 int
1113 main(int argc, char *const *argv)
1114 {
1115  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1117  };
1118  int ret;
1119 
1120  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv))
1121  return 2;
1122 
1123  ret = (GNUNET_OK == GNUNET_PROGRAM_run(argc,
1124  argv,
1125  "gnunet-daemon-topology",
1126  _("GNUnet topology control"),
1127  options,
1128  &run,
1129  NULL))
1130  ? 0
1131  : 1;
1132  GNUNET_free((void *)argv);
1133  return ret;
1134 }
1135 
1136 
1137 #if defined(LINUX) && defined(__GLIBC__)
1138 #include <malloc.h>
1139 
1143 void __attribute__ ((constructor)) GNUNET_ARM_memory_init()
1144 {
1145  mallopt(M_TRIM_THRESHOLD, 4 * 1024);
1146  mallopt(M_TOP_PAD, 1 * 1024);
1147  malloc_trim(0);
1148 }
1149 #endif
1150 
1151 /* end of gnunet-daemon-topology.c */
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_init(const char *data, size_t size, unsigned int k)
Create a Bloom filter from raw bits.
int GNUNET_HELLO_get_id(const struct GNUNET_HELLO_Message *hello, struct GNUNET_PeerIdentity *peer)
Get the peer identity from a HELLO message.
Definition: hello.c:662
static int friends_only
Flag to disallow non-friend connections (pure F2F mode).
struct GNUNET_MQ_Envelope * GNUNET_MQ_msg_copy(const struct GNUNET_MessageHeader *hdr)
Create a new envelope by copying an existing message.
Definition: mq.c:651
Handle to the peerinfo service.
Definition: peerinfo_api.c:83
A HELLO message is used to exchange information about transports with other peers.
Entry in linked list for all offer-HELLO requests.
static char * expiration
Credential TTL.
void GNUNET_CONTAINER_bloomfilter_add(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Add an element to the filter.
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
uint64_t rel_value_us
The actual value.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
Context for the core service connection.
Definition: core_api.c:76
struct GNUNET_HELLO_Message * GNUNET_HELLO_merge(const struct GNUNET_HELLO_Message *h1, const struct GNUNET_HELLO_Message *h2)
Construct a HELLO message by merging the addresses in two existing HELLOs (which must be for the same...
Definition: hello.c:519
uint32_t strength
How much would we like to connect to this peer?
static struct GNUNET_SCHEDULER_Task * add_task
Task scheduled to asynchronously reconsider adding/removing peer connectivity suggestions.
struct GNUNET_PEERINFO_Handle * GNUNET_PEERINFO_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the peerinfo service.
Definition: peerinfo_api.c:128
Context for the info handler.
static int blacklist_check(void *cls, const struct GNUNET_PeerIdentity *pid)
Function that decides if a connection is acceptable or not.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1284
#define HELLO_ADVERTISEMENT_MIN_FREQUENCY
At what frequency do we sent HELLOs to a peer?
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1439
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
static void whitelist_peers()
Whitelist all peers that we blacklisted; we&#39;ve passed the minimum number of friends.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int GNUNET_FRIENDS_parse(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_FRIENDS_Callback cb, void *cb_cls)
Parse the FRIENDS file.
Definition: friends.c:39
void GNUNET_PEERINFO_notify_cancel(struct GNUNET_PEERINFO_NotifyContext *nc)
Stop notifying about changes.
static void schedule_next_hello(void *cls)
Calculate when we would like to send the next HELLO to this peer and ask for it.
struct GNUNET_TIME_Absolute GNUNET_HELLO_equals(const struct GNUNET_HELLO_Message *h1, const struct GNUNET_HELLO_Message *h2, struct GNUNET_TIME_Absolute now)
Test if two HELLO messages contain the same addresses.
Definition: hello.c:824
static struct GNUNET_TRANSPORT_Blacklist * blacklist
Blacklist (NULL if we have none).
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
int 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.
static int try_add_peers(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Try to add more peers to our connection set.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Definition of a command line option.
void GNUNET_ATS_connectivity_suggest_cancel(struct GNUNET_ATS_ConnectivitySuggestHandle *sh)
We no longer care about being connected to a peer.
void GNUNET_TRANSPORT_blacklist_cancel(struct GNUNET_TRANSPORT_Blacklist *br)
Abort the blacklist.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
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).
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
static int ret
Final status code.
Definition: gnunet-arm.c:89
Handle for the service.
uint64_t abs_value_us
The actual value.
static void setup_filter(struct Peer *peer)
Setup bloom filter for the given peer entry.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static void read_friends_file(const struct GNUNET_CONFIGURATION_Handle *cfg)
Read the friends file.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
int main(int argc, char *const *argv)
The main function for the topology daemon.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
struct GNUNET_PEERINFO_NotifyContext * GNUNET_PEERINFO_notify(const struct GNUNET_CONFIGURATION_Handle *cfg, int include_friend_only, GNUNET_PEERINFO_Processor callback, void *callback_cls)
Call a method whenever our known information about peers changes.
struct GNUNET_ATS_ConnectivitySuggestHandle * sh
Handle for our connectivity suggestion for this peer.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct GNUNET_ATS_ConnectivitySuggestHandle * GNUNET_ATS_connectivity_suggest(struct GNUNET_ATS_ConnectivityHandle *ch, const struct GNUNET_PeerIdentity *peer, uint32_t strength)
We would like to receive address suggestions for a peer.
static struct Peer * make_peer(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, int is_friend)
Create a new entry in the peer list.
Best-effort traffic (i.e.
static unsigned int target_connection_count
Target number of connections.
static struct GNUNET_ATS_ConnectivityHandle * ats
Handle to the ATS service.
static int reschedule_hellos(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Cancel existing requests for sending HELLOs to this peer and recalculate when we should send HELLOs t...
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:1237
static struct GNUNET_STATISTICS_Handle * stats
Handle for reporting statistics.
static char * value
Value of the record to add/remove.
int GNUNET_CONTAINER_bloomfilter_test(const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Test if an element is in the filter.
static struct GNUNET_TRANSPORT_OfferHelloHandle * oh
Active HELLO offering to transport service.
struct GNUNET_HELLO_Message * GNUNET_HELLO_iterate_addresses(const struct GNUNET_HELLO_Message *msg, int return_modified, GNUNET_HELLO_AddressIterator it, void *it_cls)
Iterate over all of the addresses in the HELLO.
Definition: hello.c:252
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1264
struct GNUNET_TRANSPORT_Blacklist * GNUNET_TRANSPORT_blacklist(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_TRANSPORT_BlacklistCallback cb, void *cb_cls)
Install a blacklist callback.
struct GNUNET_CONFIGURATION_Handle * cfg
The modified (by GNUNET_TESTING_peer_configure) configuration this peer is configured with...
struct Peer * peer
Peer we want to advertise to.
Handle for ATS address suggestion requests.
static void core_init(void *cls, const struct GNUNET_PeerIdentity *my_id)
Function called after GNUNET_CORE_connect has succeeded (or failed for good).
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TESTING_Peer * peer
The peer handle from testing API.
Internal representation of the hash map.
static void attempt_connect(struct Peer *pos)
Recalculate how much we want to be connected to the specified peer and let ATS know about the result...
static void consider_for_advertising(const struct GNUNET_HELLO_Message *hello)
We&#39;ve gotten a HELLO from another peer.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
A 512-bit hashcode.
struct GNUNET_MQ_Envelope * GNUNET_PEERINFO_add_peer(struct GNUNET_PEERINFO_Handle *h, const struct GNUNET_HELLO_Message *hello, GNUNET_SCHEDULER_TaskCallback cont, void *cont_cls)
Add a host to the persistent list.
Definition: peerinfo_api.c:552
Message handler for a specific message type.
static struct GNUNET_NAT_Handle * nh
Handle to NAT operation.
Definition: gnunet-nat.c:80
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
void GNUNET_TRANSPORT_offer_hello_cancel(struct GNUNET_TRANSPORT_OfferHelloHandle *ohh)
Cancel the request to transport to offer the HELLO message.
static int address_iterator(void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
Iterator called on each address.
static struct GNUNET_PEERINFO_Handle * pi
Handle to the PEERINFO service.
Handle for blacklisting requests.
static void add_peer_task(void *cls)
Add peers and schedule connection attempt.
static void handle_hello(void *cls, const struct GNUNET_HELLO_Message *message)
This function is called whenever an encrypted HELLO message is received.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition: time.c:272
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:66
struct GNUNET_TIME_Relative next_adv
struct GNUNET_CORE_Handle * GNUNET_CORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, GNUNET_CORE_StartupCallback init, GNUNET_CORE_ConnectEventHandler connects, GNUNET_CORE_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Connect to the core service.
Definition: core_api.c:690
int is_friend
Is this peer listed here because it is a friend?
struct GNUNET_TIME_Absolute next_hello_allowed
Next time we are allowed to transmit a HELLO to this peer?
void GNUNET_CORE_disconnect(struct GNUNET_CORE_Handle *handle)
Disconnect from the core service.
Definition: core_api.c:728
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
struct GNUNET_PeerIdentity pid
Which peer is this for?
static void process_peer(void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg)
PEERINFO calls this function to let us know about a possible peer that we might want to connect to...
static int find_advertisable_hello(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Find a peer that would be reasonable for advertising.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
Handle to a message queue.
Definition: mq.c:84
static int check_hello(void *cls, const struct GNUNET_HELLO_Message *message)
This function is called whenever an encrypted HELLO message is received.
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.
struct GNUNET_ATS_ConnectivityHandle * GNUNET_ATS_connectivity_init(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the ATS connectivity suggestion client handle.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
static unsigned int connection_count
Number of peers (friends and others) that we are currently connected to.
void GNUNET_MQ_set_options(struct GNUNET_MQ_Handle *mq, enum GNUNET_MQ_PriorityPreferences pp)
Set application-specific options for this queue.
Definition: mq.c:1063
enum RadiotapType __attribute__
The identity of the host (wraps the signing key of the peer).
struct GNUNET_MQ_Handle * mq
Our handle for transmitting to this peer; NULL if peer is not connected.
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_HELLO.
configuration data
Definition: configuration.c:83
Information about preferences and sessions we track per peer.
An address for communicating with a peer.
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.
Automatic transport selection and outbound bandwidth determination.
#define GNUNET_log(kind,...)
static struct GNUNET_PEERINFO_NotifyContext * peerinfo_notify
Our peerinfo notification context.
static void * connect_notify(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq)
Method called whenever a peer connects.
Entry in list of pending tasks.
Definition: scheduler.c:131
size_t max_size
Maximum HELLO size we can use right now.
uint16_t GNUNET_HELLO_size(const struct GNUNET_HELLO_Message *hello)
Return the size of the given HELLO message.
Definition: hello.c:643
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Main function that will be run.
void GNUNET_PEERINFO_disconnect(struct GNUNET_PEERINFO_Handle *h)
Disconnect from the peerinfo service.
Definition: peerinfo_api.c:154
struct GNUNET_HELLO_Message * hello
Pointer to the HELLO message of this peer; can be NULL.
int GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration, parse options).
Definition: program.c:367
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
struct GNUNET_CONTAINER_BloomFilter * filter
Bloom filter used to mark which peers already got the HELLO from this peer.
static struct GNUNET_CORE_Handle * handle
Handle to the CORE service.
#define HELLO_ADVERTISEMENT_MIN_REPEAT_FREQUENCY
After what time period do we expire the HELLO Bloom filter?
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_SCHEDULER_Task * hello_delay_task
ID of task we use to wait for the time to send the next HELLO to this peer.
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:351
struct GNUNET_TIME_Absolute filter_expiration
When should we reset the bloom filter of this entry?
Closure for find_advertisable_hello().
static void handle_friend(void *cls, const struct GNUNET_PeerIdentity *pid)
Process friend found in FRIENDS file.
#define GNUNET_MESSAGE_TYPE_HELLO
HELLO message with friend only flag used for communicating peer addresses.
static struct GNUNET_CONTAINER_MultiPeerMap * peers
All of our friends, all of our current neighbours and all peers for which we have HELLOs...
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
Handle to the ATS subsystem for connectivity management.
void GNUNET_ATS_connectivity_done(struct GNUNET_ATS_ConnectivityHandle *ch)
Client is done with ATS connectivity management, release resources.
static char * address
GNS address for this phone.
static int free_peer(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free all resources associated with the given peer.
static unsigned int minimum_friend_count
Minimum number of friends to have in the connection set before we allow non-friends.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
void GNUNET_CONTAINER_bloomfilter_free(struct GNUNET_CONTAINER_BloomFilter *bf)
Free the space associcated with a filter in memory, flush to drive if needed (do not free the space o...
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
struct Peer * result
Where to store the result (peer selected for advertising).
#define GNUNET_malloc(size)
Wrapper around malloc.
static void cleaning_task(void *cls)
Last task run during shutdown.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
#define gettext_noop(String)
Definition: gettext.h:69
static unsigned int friend_count
Number of friends that we are currently connected to.
static void disconnect_notify(void *cls, const struct GNUNET_PeerIdentity *peer, void *internal_cls)
Method called whenever a peer disconnects.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956