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
68 {
72  struct GNUNET_PeerIdentity pid;
73 
79 
84 
90 
95 
100 
106 
111 
115  uint32_t strength;
116 
121 };
122 
123 
129 
133 static const struct GNUNET_CONFIGURATION_Handle *cfg;
134 
138 static struct GNUNET_CORE_Handle *handle;
139 
143 static struct GNUNET_PEERINFO_Handle *pi;
144 
149 
154 
161 
166 
171 
177 
182 
186 static int friends_only;
187 
192 static unsigned int minimum_friend_count;
193 
197 static unsigned int connection_count;
198 
202 static unsigned int target_connection_count;
203 
207 static unsigned int friend_count;
208 
209 
219 static int
221 {
222  struct Peer *pos;
223 
224  pos = GNUNET_CONTAINER_multipeermap_get (peers, pid);
225  if ((NULL != pos) && (GNUNET_YES == pos->is_friend))
226  return GNUNET_OK;
228  gettext_noop ("# peers blacklisted"),
229  1,
230  GNUNET_NO);
231  return GNUNET_SYSERR;
232 }
233 
234 
239 static void
241 {
242  if (NULL != blacklist)
243  {
245  blacklist = NULL;
246  }
247 }
248 
249 
258 static int
259 free_peer (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
260 {
261  struct Peer *pos = value;
262 
263  GNUNET_break (NULL == pos->mq);
265  GNUNET_CONTAINER_multipeermap_remove (peers, pid, pos));
266  if (NULL != pos->hello_delay_task)
267  {
269  pos->hello_delay_task = NULL;
270  }
271  if (NULL != pos->sh)
272  {
274  pos->sh = NULL;
275  }
276  if (NULL != pos->hello)
277  {
279  pos->hello = NULL;
280  }
281  if (NULL != pos->filter)
282  {
284  pos->filter = NULL;
285  }
286  GNUNET_free (pos);
287  return GNUNET_YES;
288 }
289 
290 
297 static void
298 attempt_connect (struct Peer *pos)
299 {
300  uint32_t strength;
301 
302  if (0 == GNUNET_memcmp (&my_identity, &pos->pid))
303  return; /* This is myself, nothing to do. */
305  strength = 1;
306  else
307  strength = 0;
309  {
310  if (pos->is_friend)
311  strength += 10; /* urgently needed */
312  else
313  strength = 0; /* disallowed */
314  }
315  if (pos->is_friend)
316  strength *= 2; /* friends always count more */
317  if (NULL != pos->mq)
318  strength *= 2; /* existing connections preferred */
319  if (strength == pos->strength)
320  return; /* nothing to do */
321  if (NULL != pos->sh)
322  {
324  pos->sh = NULL;
325  }
326  pos->strength = strength;
327  if (0 != strength)
328  {
330  "Asking to connect to `%s' with strength %u\n",
331  GNUNET_i2s (&pos->pid),
332  (unsigned int) strength);
334  gettext_noop ("# connect requests issued to ATS"),
335  1,
336  GNUNET_NO);
337  pos->sh = GNUNET_ATS_connectivity_suggest (ats, &pos->pid, strength);
338  }
339 }
340 
341 
350 static struct Peer *
352  const struct GNUNET_HELLO_Message *hello,
353  int is_friend)
354 {
355  struct Peer *ret;
356 
357  ret = GNUNET_new (struct Peer);
358  ret->pid = *peer;
359  ret->is_friend = is_friend;
360  if (NULL != hello)
361  {
362  ret->hello = GNUNET_malloc (GNUNET_HELLO_size (hello));
363  GNUNET_memcpy (ret->hello, hello, GNUNET_HELLO_size (hello));
364  }
367  peers,
368  peer,
369  ret,
371  return ret;
372 }
373 
374 
380 static void
382 {
383  struct GNUNET_HashCode hc;
384 
385  /* 2^{-5} chance of not sending a HELLO to a peer is
386  * acceptably small (if the filter is 50% full);
387  * 64 bytes of memory are small compared to the rest
388  * of the data structure and would only really become
389  * "useless" once a HELLO has been passed on to ~100
390  * other peers, which is likely more than enough in
391  * any case; hence 64, 5 as bloomfilter parameters. */
392  peer->filter = GNUNET_CONTAINER_bloomfilter_init (NULL, 64, 5);
393  peer->filter_expiration =
395  /* never send a peer its own HELLO */
396  GNUNET_CRYPTO_hash (&peer->pid, sizeof (struct GNUNET_PeerIdentity), &hc);
398 }
399 
400 
405 {
406 
410  struct Peer *peer;
411 
415  struct Peer *result;
416 
420  size_t max_size;
421 
422  struct GNUNET_TIME_Relative next_adv;
423 };
424 
425 
434 static int
436  const struct GNUNET_PeerIdentity *pid,
437  void *value)
438 {
439  struct FindAdvHelloContext *fah = cls;
440  struct Peer *pos = value;
441  struct GNUNET_TIME_Relative rst_time;
442  struct GNUNET_HashCode hc;
443  size_t hs;
444 
445  if (pos == fah->peer)
446  return GNUNET_YES;
447  if (pos->hello == NULL)
448  return GNUNET_YES;
450  if (0 == rst_time.rel_value_us)
451  {
452  /* time to discard... */
454  setup_filter (pos);
455  }
456  fah->next_adv = GNUNET_TIME_relative_min (rst_time, fah->next_adv);
457  hs = GNUNET_HELLO_size (pos->hello);
458  if (hs > fah->max_size)
459  return GNUNET_YES;
460  GNUNET_CRYPTO_hash (&fah->peer->pid,
461  sizeof (struct GNUNET_PeerIdentity),
462  &hc);
464  fah->result = pos;
465  return GNUNET_YES;
466 }
467 
468 
475 static void
477 {
478  struct Peer *pl = cls;
479  struct FindAdvHelloContext fah;
480  struct GNUNET_MQ_Envelope *env;
481  size_t want;
482  struct GNUNET_TIME_Relative delay;
483  struct GNUNET_HashCode hc;
484 
485  pl->hello_delay_task = NULL;
486  GNUNET_assert (NULL != pl->mq);
487  /* find applicable HELLOs */
488  fah.peer = pl;
489  fah.result = NULL;
493  pl->hello_delay_task =
495  if (NULL == fah.result)
496  return;
498  if (0 != delay.rel_value_us)
499  return;
500 
501  want = GNUNET_HELLO_size (fah.result->hello);
503  "Sending HELLO with %u bytes",
504  (unsigned int) want);
505  env = GNUNET_MQ_msg_copy (&fah.result->hello->header);
506  GNUNET_MQ_send (pl->mq, env);
507 
508  /* avoid sending this one again soon */
509  GNUNET_CRYPTO_hash (&pl->pid, sizeof (struct GNUNET_PeerIdentity), &hc);
511 
513  gettext_noop ("# HELLO messages gossipped"),
514  1,
515  GNUNET_NO);
516  /* prepare to send the next one */
517  pl->next_hello_allowed =
519  if (NULL != pl->hello_delay_task)
522 }
523 
524 
535 static int
536 reschedule_hellos (void *cls,
537  const struct GNUNET_PeerIdentity *pid,
538  void *value)
539 {
540  struct Peer *peer = value;
541  struct Peer *skip = cls;
542 
543  if (skip == peer)
544  return GNUNET_YES;
545  if (NULL == peer->mq)
546  return GNUNET_YES;
547  if (NULL != peer->hello_delay_task)
548  {
550  peer->hello_delay_task = NULL;
551  }
552  peer->hello_delay_task =
554  return GNUNET_YES;
555 }
556 
557 
566 static void *
567 connect_notify (void *cls,
568  const struct GNUNET_PeerIdentity *peer,
569  struct GNUNET_MQ_Handle *mq)
570 {
571  struct Peer *pos;
572 
574  "Core told us that we are connecting to `%s'\n",
575  GNUNET_i2s (peer));
576  if (0 == GNUNET_memcmp (&my_identity, peer))
577  return NULL;
580  GNUNET_STATISTICS_set (stats,
581  gettext_noop ("# peers connected"),
583  GNUNET_NO);
584  pos = GNUNET_CONTAINER_multipeermap_get (peers, peer);
585  if (NULL == pos)
586  {
587  pos = make_peer (peer, NULL, GNUNET_NO);
588  }
589  else
590  {
591  GNUNET_assert (NULL == pos->mq);
592  }
593  pos->mq = mq;
594  if (pos->is_friend)
595  {
596  friend_count++;
598  whitelist_peers ();
599  GNUNET_STATISTICS_set (stats,
600  gettext_noop ("# friends connected"),
601  friend_count,
602  GNUNET_NO);
603  }
604  reschedule_hellos (NULL, peer, pos);
605  return pos;
606 }
607 
608 
617 static int
618 try_add_peers (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
619 {
620  struct Peer *pos = value;
621 
622  attempt_connect (pos);
623  return GNUNET_YES;
624 }
625 
626 
632 static void
633 add_peer_task (void *cls)
634 {
635  add_task = NULL;
636 
638 }
639 
640 
648 static void
649 disconnect_notify (void *cls,
650  const struct GNUNET_PeerIdentity *peer,
651  void *internal_cls)
652 {
653  struct Peer *pos = internal_cls;
654 
655  if (NULL == pos)
656  return; /* myself, we're shutting down */
658  "Core told us that we disconnected from `%s'\n",
659  GNUNET_i2s (peer));
660  if (NULL == pos->mq)
661  {
662  GNUNET_break (0);
663  return;
664  }
665  pos->mq = NULL;
667  if (NULL != pos->hello_delay_task)
668  {
670  pos->hello_delay_task = NULL;
671  }
672  GNUNET_STATISTICS_set (stats,
673  gettext_noop ("# peers connected"),
675  GNUNET_NO);
676  if (pos->is_friend)
677  {
678  friend_count--;
679  GNUNET_STATISTICS_set (stats,
680  gettext_noop ("# friends connected"),
681  friend_count,
682  GNUNET_NO);
683  }
686  (NULL == add_task))
687  add_task = GNUNET_SCHEDULER_add_now (&add_peer_task, NULL);
688  if ((friend_count < minimum_friend_count) && (NULL == blacklist))
689  blacklist = GNUNET_TRANSPORT_blacklist (cfg, &blacklist_check, NULL);
690 }
691 
692 
701 static int
702 address_iterator (void *cls,
703  const struct GNUNET_HELLO_Address *address,
705 {
706  int *flag = cls;
707 
708  *flag = GNUNET_YES;
709  return GNUNET_SYSERR;
710 }
711 
712 
719 static void
721 {
722  int have_address;
723  struct GNUNET_PeerIdentity pid;
724  struct GNUNET_TIME_Absolute dt;
725  struct GNUNET_HELLO_Message *nh;
726  struct Peer *peer;
727  uint16_t size;
728 
729  if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
730  {
731  GNUNET_break (0);
732  return;
733  }
734  if (0 == GNUNET_memcmp (&pid, &my_identity))
735  return; /* that's me! */
736  have_address = GNUNET_NO;
738  GNUNET_NO,
740  &have_address);
741  if (GNUNET_NO == have_address)
742  return; /* no point in advertising this one... */
743  peer = GNUNET_CONTAINER_multipeermap_get (peers, &pid);
744  if (NULL == peer)
745  {
746  peer = make_peer (&pid, hello, GNUNET_NO);
747  }
748  else if (NULL != peer->hello)
749  {
750  dt = GNUNET_HELLO_equals (peer->hello, hello, GNUNET_TIME_absolute_get ());
751  if (dt.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
752  return; /* nothing new here */
753  }
755  "Found HELLO from peer `%s' for advertising\n",
756  GNUNET_i2s (&pid));
757  if (NULL != peer->hello)
758  {
759  nh = GNUNET_HELLO_merge (peer->hello, hello);
760  GNUNET_free (peer->hello);
761  peer->hello = nh;
762  }
763  else
764  {
765  size = GNUNET_HELLO_size (hello);
766  peer->hello = GNUNET_malloc (size);
767  GNUNET_memcpy (peer->hello, hello, size);
768  }
769  if (NULL != peer->filter)
770  {
772  peer->filter = NULL;
773  }
774  setup_filter (peer);
775  /* since we have a new HELLO to pick from, re-schedule all
776  * HELLO requests that are not bound by the HELLO send rate! */
778 }
779 
780 
790 static void
791 process_peer (void *cls,
792  const struct GNUNET_PeerIdentity *peer,
793  const struct GNUNET_HELLO_Message *hello,
794  const char *err_msg)
795 {
796  struct Peer *pos;
797 
798  if (NULL != err_msg)
799  {
801  _ ("Error in communication with PEERINFO service: %s\n"),
802  err_msg);
803  GNUNET_PEERINFO_notify_cancel (peerinfo_notify);
804  peerinfo_notify =
806  return;
807  }
808  GNUNET_assert (NULL != peer);
809  if (0 == GNUNET_memcmp (&my_identity, peer))
810  return; /* that's me! */
811  if (NULL == hello)
812  {
813  /* free existing HELLO, if any */
814  pos = GNUNET_CONTAINER_multipeermap_get (peers, peer);
815  if (NULL != pos)
816  {
818  pos->hello = NULL;
819  if (NULL != pos->filter)
820  {
822  pos->filter = NULL;
823  }
824  if ((NULL == pos->mq) && (GNUNET_NO == pos->is_friend))
825  free_peer (NULL, &pos->pid, pos);
826  }
827  return;
828  }
829  consider_for_advertising (hello);
830  pos = GNUNET_CONTAINER_multipeermap_get (peers, peer);
831  if (NULL == pos)
832  pos = make_peer (peer, hello, GNUNET_NO);
833  attempt_connect (pos);
834 }
835 
836 
844 static void
845 core_init (void *cls, const struct GNUNET_PeerIdentity *my_id)
846 {
847  if (NULL == my_id)
848  {
849  GNUNET_log (
851  _ ("Failed to connect to core service, can not manage topology!\n"));
853  return;
854  }
855  my_identity = *my_id;
856  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "I am peer `%s'\n", GNUNET_i2s (my_id));
857  peerinfo_notify =
859 }
860 
861 
868 static void
869 handle_friend (void *cls, const struct GNUNET_PeerIdentity *pid)
870 {
871  unsigned int *entries_found = cls;
872  struct Peer *fl;
873 
874  if (0 == GNUNET_memcmp (pid, &my_identity))
875  {
877  _ ("Found myself `%s' in friend list (useless, ignored)\n"),
878  GNUNET_i2s (pid));
879  return;
880  }
881  (*entries_found)++;
882  fl = make_peer (pid, NULL, GNUNET_YES);
884  _ ("Found friend `%s' in configuration\n"),
885  GNUNET_i2s (&fl->pid));
886 }
887 
888 
892 static void
894 {
895  unsigned int entries_found;
896 
897  entries_found = 0;
898  if (GNUNET_OK != GNUNET_FRIENDS_parse (cfg, &handle_friend, &entries_found))
899  {
900  if ((GNUNET_YES == friends_only) || (minimum_friend_count > 0))
902  _ ("Encountered errors parsing friends list!\n"));
903  }
905  gettext_noop ("# friends in configuration"),
906  entries_found,
907  GNUNET_NO);
908  if ((minimum_friend_count > entries_found) && (GNUNET_NO == friends_only))
909  {
910  GNUNET_log (
912  _ (
913  "Fewer friends specified than required by minimum friend count. Will only connect to friends.\n"));
914  }
916  (GNUNET_NO == friends_only))
917  {
918  GNUNET_log (
920  _ (
921  "More friendly connections required than target total number of connections.\n"));
922  }
923 }
924 
925 
935 static int
936 check_hello (void *cls, const struct GNUNET_HELLO_Message *message)
937 {
938  struct GNUNET_PeerIdentity pid;
939 
940  if (GNUNET_OK != GNUNET_HELLO_get_id (message, &pid))
941  {
942  GNUNET_break_op (0);
943  return GNUNET_SYSERR;
944  }
945  return GNUNET_OK;
946 }
947 
948 
956 static void
957 handle_hello (void *cls, const struct GNUNET_HELLO_Message *message)
958 {
959  const struct GNUNET_PeerIdentity *other = cls;
960  struct Peer *peer;
961  struct GNUNET_PeerIdentity pid;
962 
964  "Received encrypted HELLO from peer `%s'",
965  GNUNET_i2s (other));
966  GNUNET_assert (GNUNET_OK == GNUNET_HELLO_get_id (message, &pid));
968  gettext_noop ("# HELLO messages received"),
969  1,
970  GNUNET_NO);
971  peer = GNUNET_CONTAINER_multipeermap_get (peers, &pid);
972  if (NULL == peer)
973  {
975  return;
976  }
977  else
978  {
979  if ((GNUNET_YES != peer->is_friend) && (GNUNET_YES == friends_only))
980  return;
981  if ((GNUNET_YES != peer->is_friend) &&
983  return;
984  }
985  (void) GNUNET_PEERINFO_add_peer (pi, message, NULL, NULL);
986 }
987 
988 
995 static void
996 cleaning_task (void *cls)
997 {
998  if (NULL != peerinfo_notify)
999  {
1000  GNUNET_PEERINFO_notify_cancel (peerinfo_notify);
1001  peerinfo_notify = NULL;
1002  }
1003  if (NULL != handle)
1004  {
1005  GNUNET_CORE_disconnect (handle);
1006  handle = NULL;
1007  }
1008  whitelist_peers ();
1009  if (NULL != add_task)
1010  {
1011  GNUNET_SCHEDULER_cancel (add_task);
1012  add_task = NULL;
1013  }
1014  if (NULL != oh)
1015  {
1017  oh = NULL;
1018  }
1021  peers = NULL;
1022  if (NULL != ats)
1023  {
1025  ats = NULL;
1026  }
1027  if (NULL != pi)
1028  {
1030  pi = NULL;
1031  }
1032  if (NULL != stats)
1033  {
1035  stats = NULL;
1036  }
1037 }
1038 
1039 
1048 static void
1049 run (void *cls,
1050  char *const *args,
1051  const char *cfgfile,
1052  const struct GNUNET_CONFIGURATION_Handle *c)
1053 {
1054  struct GNUNET_MQ_MessageHandler handlers[] =
1057  struct GNUNET_HELLO_Message,
1058  NULL),
1060  unsigned long long opt;
1061 
1062  cfg = c;
1063  stats = GNUNET_STATISTICS_create ("topology", cfg);
1064  friends_only =
1065  GNUNET_CONFIGURATION_get_value_yesno (cfg, "TOPOLOGY", "FRIENDS-ONLY");
1067  "TOPOLOGY",
1068  "MINIMUM-FRIENDS",
1069  &opt))
1070  opt = 0;
1071  minimum_friend_count = (unsigned int) opt;
1072  if (GNUNET_OK !=
1074  "TOPOLOGY",
1075  "TARGET-CONNECTION-COUNT",
1076  &opt))
1077  opt = 16;
1078  target_connection_count = (unsigned int) opt;
1080  GNUNET_NO);
1081  read_friends_file (cfg);
1083  "Topology would like %u connections with at least %u friends\n",
1086  if ((GNUNET_YES == friends_only) || (minimum_friend_count > 0))
1087  blacklist = GNUNET_TRANSPORT_blacklist (cfg, &blacklist_check, NULL);
1088  ats = GNUNET_ATS_connectivity_init (cfg);
1089  pi = GNUNET_PEERINFO_connect (cfg);
1090  handle = GNUNET_CORE_connect (cfg,
1091  NULL,
1092  &core_init,
1093  &connect_notify,
1095  handlers);
1097  if (NULL == handle)
1098  {
1100  _ ("Failed to connect to `%s' service.\n"),
1101  "core");
1103  return;
1104  }
1105 }
1106 
1107 
1115 int
1116 main (int argc, char *const *argv)
1117 {
1118  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1120  int ret;
1121 
1122  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1123  return 2;
1124 
1125  ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc,
1126  argv,
1127  "gnunet-daemon-topology",
1128  _ ("GNUnet topology control"),
1129  options,
1130  &run,
1131  NULL))
1132  ? 0
1133  : 1;
1134  GNUNET_free ((void *) argv);
1135  return ret;
1136 }
1137 
1138 
1139 #if defined(LINUX) && defined(__GLIBC__)
1140 #include <malloc.h>
1141 
1145 void __attribute__ ((constructor)) GNUNET_ARM_memory_init ()
1146 {
1147  mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1148  mallopt (M_TOP_PAD, 1 * 1024);
1149  malloc_trim (0);
1150 }
1151 #endif
1152 
1153 /* 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:668
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:653
Handle to the peerinfo service.
Definition: peerinfo_api.c:86
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:78
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:524
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:133
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:1293
#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:1521
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:245
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:832
static struct GNUNET_TRANSPORT_Blacklist * blacklist
Blacklist (NULL if we have none).
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:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#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:524
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:208
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:1246
static struct GNUNET_STATISTICS_Handle * stats
Handle for reporting statistics.
#define GNUNET_memcpy(dst, src, n)
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:254
#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:1273
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:557
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:271
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
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:694
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:732
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:85
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:1066
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:85
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:134
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:649
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:159
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:361
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:80
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:353
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:965