2 This file is part of GNUnet.
3 (C) 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file topology/gnunet-daemon-topology.c
23 * @brief code for maintaining the mesh topology
24 * @author Christian Grothoff
29 #include "gnunet_core_service.h"
30 #include "gnunet_protocols.h"
31 #include "gnunet_peerinfo_service.h"
32 #include "gnunet_transport_service.h"
33 #include "gnunet_util_lib.h"
36 #define DEBUG_TOPOLOGY GNUNET_YES
39 * For how long do we blacklist a peer after a failed
42 #define BLACKLIST_AFTER_ATTEMPT GNUNET_TIME_UNIT_HOURS
45 * For how long do we blacklist a friend after a failed
48 #define BLACKLIST_AFTER_ATTEMPT_FRIEND GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
51 * How frequently are we allowed to ask PEERINFO for more
52 * HELLO's to advertise (at most)?
54 #define MIN_HELLO_GATHER_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 27)
57 * How often do we at most advertise the same HELLO to the same peer?
58 * Also used to remove HELLOs of peers that PEERINFO no longer lists
61 #define HELLO_ADVERTISEMENT_MIN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
65 * List of neighbours, friends and blacklisted peers.
71 * This is a linked list.
73 struct PeerList *next;
76 * Is this peer listed here because he is a friend?
81 * Are we connected to this peer right now?
86 * Until what time should we not try to connect again
89 struct GNUNET_TIME_Absolute blacklisted_until;
92 * Last time we transmitted a HELLO to this peer?
94 struct GNUNET_TIME_Absolute last_hello_sent;
99 struct GNUNET_PeerIdentity id;
105 * List of HELLOs we may consider for advertising.
110 * This is a linked list.
112 struct HelloList *next;
115 * Pointer to the HELLO message. Memory allocated as part
116 * of the "struct HelloList" --- do not free!
118 struct GNUNET_HELLO_Message *msg;
121 * Bloom filter used to mark which peers already got
124 struct GNUNET_CONTAINER_BloomFilter *filter;
127 * What peer is this HELLO for?
129 struct GNUNET_PeerIdentity id;
132 * When should we remove this entry from the linked list (either
133 * resetting the filter or possibly eliminating it for good because
134 * we no longer consider the peer to be participating in the
137 struct GNUNET_TIME_Absolute expiration;
142 * Linked list of HELLOs for advertising.
144 static struct HelloList *hellos;
149 static struct GNUNET_SCHEDULER_Handle * sched;
154 static const struct GNUNET_CONFIGURATION_Handle * cfg;
157 * Handle to the core API.
159 static struct GNUNET_CORE_Handle *handle;
162 * Handle to the transport API.
164 static struct GNUNET_TRANSPORT_Handle *transport;
167 * Identity of this peer.
169 static struct GNUNET_PeerIdentity my_identity;
172 * Linked list of all of our friends and all of our current
175 static struct PeerList *friends;
178 * Timestamp from the last time we tried to gather HELLOs.
180 static struct GNUNET_TIME_Absolute last_hello_gather_time;
183 * Flag to disallow non-friend connections (pure F2F mode).
185 static int friends_only;
188 * Minimum number of friends to have in the
189 * connection set before we allow non-friends.
191 static unsigned int minimum_friend_count;
194 * Number of peers (friends and others) that we are currently connected to.
196 static unsigned int connection_count;
199 * Target number of connections.
201 static unsigned int target_connection_count;
204 * Number of friends that we are currently connected to.
206 static unsigned int friend_count;
209 * Should the topology daemon try to establish connections?
211 static int autoconnect;
214 * Are we currently having a request pending with
215 * PEERINFO asking for HELLOs for advertising?
217 static int hello_gathering_active;
222 * Force a disconnect from the specified peer.
225 force_disconnect (const struct GNUNET_PeerIdentity *peer)
227 GNUNET_CORE_peer_configure (handle,
229 GNUNET_TIME_UNIT_FOREVER_REL,
239 * Function called by core when our attempt to connect
240 * succeeded. Does nothing.
243 ready_callback (void *cls,
244 size_t size, void *buf)
247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
249 ? "Core told us that our attempt to connect failed.\n"
250 : "Core told us that our attempt to connect worked. Good!\n");
257 * Try to connect to the specified peer.
259 * @param peer who we should try to connect to
260 * @param pos entry in our friend list; NULL if not in friend list yet
263 attempt_connect (const struct GNUNET_PeerIdentity *peer,
264 struct PeerList *pos)
271 if (0 == memcmp (&pos->id, peer, sizeof (struct GNUNET_PeerIdentity)))
277 pos = GNUNET_malloc (sizeof(struct PeerList));
282 if (GNUNET_YES == pos->is_friend)
283 pos->blacklisted_until = GNUNET_TIME_relative_to_absolute (BLACKLIST_AFTER_ATTEMPT_FRIEND);
285 pos->blacklisted_until = GNUNET_TIME_relative_to_absolute (BLACKLIST_AFTER_ATTEMPT);
287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
288 "Asking core to connect to `%s'\n",
291 GNUNET_CORE_notify_transmit_ready (handle,
293 GNUNET_TIME_UNIT_MINUTES,
295 sizeof(struct GNUNET_MessageHeader),
302 * Is this peer one of our friends?
305 is_friend (const struct GNUNET_PeerIdentity * peer)
307 struct PeerList *pos;
312 if ( (GNUNET_YES == pos->is_friend) &&
313 (0 == memcmp (&pos->id, peer, sizeof (struct GNUNET_PeerIdentity))) )
316 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
317 "Determined that `%s' is a friend\n",
329 * Check if an additional connection from the given peer is allowed.
332 is_connection_allowed (const struct GNUNET_PeerIdentity * peer)
334 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
335 return GNUNET_SYSERR; /* disallow connections to self */
336 if (is_friend (peer))
338 if (GNUNET_YES == friends_only)
341 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
342 "Determined that `%s' is not allowed to connect (not a friend)\n",
345 return GNUNET_SYSERR;
347 if (friend_count >= minimum_friend_count)
350 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
351 "Determined that `%s' is not allowed to connect (not enough connected friends)\n",
354 return GNUNET_SYSERR;
359 * Method called whenever a peer connects.
362 * @param peer peer identity this notification is about
364 static void connect_notify (void *cls,
366 GNUNET_PeerIdentity * peer)
368 struct PeerList *pos;
371 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
372 "Core told us that we connected to `%s'\n",
379 if ( (GNUNET_YES == pos->is_friend) &&
380 (0 == memcmp (&pos->id, peer, sizeof (struct GNUNET_PeerIdentity))) )
382 GNUNET_assert (GNUNET_NO == pos->is_connected);
383 pos->is_connected = GNUNET_YES;
384 pos->blacklisted_until.value = 0; /* remove blacklisting */
390 pos = GNUNET_malloc (sizeof(struct PeerList));
392 pos->is_connected = GNUNET_YES;
395 if (GNUNET_OK != is_connection_allowed (peer))
398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
399 "Connection to `%s' is forbidden, forcing disconnect!\n",
402 force_disconnect (peer);
408 * Disconnect from all non-friends (we're below quota).
413 struct PeerList *pos;
418 if (GNUNET_NO == pos->is_friend)
420 GNUNET_assert (GNUNET_YES == pos->is_connected);
422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
423 "Connection to `%s' is not from a friend, forcing disconnect!\n",
424 GNUNET_i2s (&pos->id));
426 force_disconnect (&pos->id);
434 * Method called whenever a peer disconnects.
437 * @param peer peer identity this notification is about
439 static void disconnect_notify (void *cls,
441 GNUNET_PeerIdentity * peer)
443 struct PeerList *pos;
444 struct PeerList *prev;
447 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
448 "Core told us that we disconnected from `%s'\n",
456 if (0 == memcmp (&pos->id, peer, sizeof (struct GNUNET_PeerIdentity)))
458 GNUNET_assert (GNUNET_YES == pos->is_connected);
459 pos->is_connected = GNUNET_NO;
460 if (GNUNET_YES == pos->is_friend)
463 if (friend_count < minimum_friend_count)
465 /* disconnect from all non-friends */
467 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
468 "Not enough friendly connections, dropping all non-friend connections\n");
471 attempt_connect (peer, pos);
480 prev->next = pos->next;
493 * Find more peers that we should connect to and ask the
494 * core to establish connections.
497 find_more_peers (void *cls,
498 const struct GNUNET_SCHEDULER_TaskContext *tc);
502 * Determine when we should try again to find more peers and
506 schedule_peer_search ()
508 struct GNUNET_TIME_Relative delay;
510 /* Typically, we try again every 15 minutes; the minimum period is
511 15s; if we are above the connection target, we reduce re-trying
512 by the square of how much we are above; so for example, with 200%
513 of the connection target we would only look for more peers once
514 every hour (after all, we're quite busy processing twice as many
515 connections as we intended to have); similarly, if we are at only
516 25% of our connectivity goal, we will try 16x as hard to connect
517 (so roughly once a minute, plus the 15s minimum delay */
518 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
519 15 + 15 * 60 * connection_count * connection_count / target_connection_count / target_connection_count);
521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
522 "Will try to find more peers in %llums\n",
523 (unsigned long long) delay.value);
525 GNUNET_SCHEDULER_add_delayed (sched,
535 * Iterator called on each address.
537 * @param cls flag that we will set if we see any addresses
538 * @param tname name of the transport
539 * @param expiration when will the given address expire
540 * @param addr the address of the peer
541 * @param addrlen number of bytes in addr
542 * @return GNUNET_SYSERR always, to terminate iteration
545 address_iterator (void *cls,
547 struct GNUNET_TIME_Absolute expiration,
548 const void *addr, size_t addrlen)
552 return GNUNET_SYSERR;
557 * We've gotten a HELLO from another peer.
558 * Consider it for advertising.
561 consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
564 struct GNUNET_PeerIdentity pid;
565 struct HelloList *pos;
568 have_address = GNUNET_NO;
569 GNUNET_HELLO_iterate_addresses (hello,
573 if (GNUNET_NO == have_address)
574 return; /* no point in advertising this one... */
575 GNUNET_break (GNUNET_OK == GNUNET_HELLO_get_id (hello, &pid));
579 if (0 == memcmp (&pos->id,
581 sizeof(struct GNUNET_PeerIdentity)))
582 return; /* duplicate, at least "mostly" */
586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
587 "Found `%s' from peer `%s' for advertising\n",
591 size = GNUNET_HELLO_size (hello);
592 pos = GNUNET_malloc (sizeof(struct HelloList) + size);
593 pos->msg = (struct GNUNET_HELLO_Message*) &pos[1];
594 memcpy (&pos->msg, hello, size);
596 pos->expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADVERTISEMENT_MIN_FREQUENCY);
597 /* 2^{-5} chance of not sending a HELLO to a peer is
598 acceptably small (if the filter is 50% full);
599 64 bytes of memory are small compared to the rest
600 of the data structure and would only really become
601 "useless" once a HELLO has been passed on to ~100
602 other peers, which is likely more than enough in
603 any case; hence 64, 5 as bloomfilter parameters. */
604 pos->filter = GNUNET_CONTAINER_bloomfilter_load (NULL, 64, 5);
605 /* never send a peer its own HELLO */
606 GNUNET_CONTAINER_bloomfilter_add (pos->filter, &pos->id.hashPubKey);
613 * Peerinfo calls this function to let us know about a
614 * possible peer that we might want to connect to.
617 process_peer (void *cls,
618 const struct GNUNET_PeerIdentity *peer,
619 const struct GNUNET_HELLO_Message *hello,
622 struct PeerList *pos;
626 /* last call, schedule 'find_more_peers' again... */
627 if (0 != (GNUNET_SCHEDULER_get_reason (sched) & GNUNET_SCHEDULER_REASON_SHUTDOWN))
630 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
631 "Received shutdown request, stopping search for peers to connect to.\n");
635 schedule_peer_search ();
640 /* no HELLO known; can not connect, ignore! */
643 if (0 == memcmp (&my_identity,
644 peer, sizeof (struct GNUNET_PeerIdentity)))
645 return; /* that's me! */
647 consider_for_advertising (hello);
649 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
650 "Considering connecting to peer `%s'\n",
656 if (0 == memcmp (&pos->id, peer, sizeof (struct GNUNET_PeerIdentity)))
658 if (GNUNET_YES == pos->is_connected)
661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
662 "Already connected to peer `%s'\n",
667 if (GNUNET_TIME_absolute_get_remaining (pos->blacklisted_until).value > 0)
670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
671 "Already tried peer `%s' recently\n",
674 return; /* peer still blacklisted */
676 if (GNUNET_YES == pos->is_friend)
678 attempt_connect (peer, pos);
684 if ( (GNUNET_YES == friends_only) ||
685 (friend_count < minimum_friend_count) )
688 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
689 "Peer `%s' is not a friend, and we currently only connect to friends\n",
694 attempt_connect (peer, NULL);
699 * Try to add more friends to our connection set.
704 struct PeerList *pos;
707 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
708 "Considering all of our friends for new connections\n");
713 if ( (GNUNET_TIME_absolute_get_remaining (pos->blacklisted_until).value == 0) &&
714 (GNUNET_YES == pos->is_friend) &&
715 (GNUNET_YES != pos->is_connected) )
716 attempt_connect (&pos->id, pos);
723 * Discard peer entries for blacklisted peers
724 * where the blacklisting has expired.
727 discard_old_blacklist_entries ()
729 struct PeerList *pos;
730 struct PeerList *next;
731 struct PeerList *prev;
735 while (NULL != (pos = next))
738 if ( (GNUNET_NO == pos->is_friend) &&
739 (GNUNET_NO == pos->is_connected) &&
740 (0 == GNUNET_TIME_absolute_get_remaining (pos->blacklisted_until).value) )
742 /* delete 'pos' from list */
744 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
745 "Deleting peer `%s' from our list (not connected, not a friend and blacklist expired)\n",
746 GNUNET_i2s (&pos->id));
763 * Find more peers that we should connect to and ask the
764 * core to establish connections.
767 find_more_peers (void *cls,
768 const struct GNUNET_SCHEDULER_TaskContext *tc)
770 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
773 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
774 "Received shutdown request, stopping search for peers to connect to.\n");
778 discard_old_blacklist_entries ();
779 if (connection_count <= target_connection_count)
781 schedule_peer_search ();
784 if ( (GNUNET_YES == friends_only) ||
785 (friend_count < minimum_friend_count) )
788 schedule_peer_search ();
792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
793 "Got sufficient (%u/%u, %u friends) number of connections, won't try to create more.\n",
795 target_connection_count,
798 GNUNET_PEERINFO_for_all (cfg,
801 0, GNUNET_TIME_UNIT_FOREVER_REL,
802 &process_peer, NULL);
807 * Function called after GNUNET_CORE_connect has succeeded
808 * (or failed for good).
811 * @param server handle to the server, NULL if we failed
812 * @param my_id ID of this peer, NULL if we failed
813 * @param publicKey public key of this peer, NULL if we failed
816 core_init (void *cls,
817 struct GNUNET_CORE_Handle * server,
818 const struct GNUNET_PeerIdentity *
821 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *
826 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
827 _("Failed to connect to core service, can not manage topology!\n"));
828 GNUNET_SCHEDULER_shutdown (sched);
832 my_identity = *my_id;
834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
839 GNUNET_SCHEDULER_add_delayed (sched,
840 GNUNET_TIME_UNIT_SECONDS /* give core time to tell us about existing connections */,
847 * gnunet-daemon-topology command line options.
849 static struct GNUNET_GETOPT_CommandLineOption options[] = {
850 GNUNET_GETOPT_OPTION_END
855 * Read the friends file.
858 read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
865 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
866 unsigned int entries_found;
870 GNUNET_CONFIGURATION_get_value_filename (cfg,
875 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
876 _("Option `%s' in section `%s' not specified!\n"),
881 if (GNUNET_OK != GNUNET_DISK_file_test (fn))
882 GNUNET_DISK_fn_write (fn, NULL, 0, GNUNET_DISK_PERM_USER_READ
883 | GNUNET_DISK_PERM_USER_WRITE);
884 if (0 != STAT (fn, &frstat))
886 if ((friends_only) || (minimum_friend_count > 0))
888 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
889 _("Could not read friends list `%s'\n"), fn);
894 if (frstat.st_size == 0)
896 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
897 _("Friends file `%s' is empty.\n"),
902 data = GNUNET_malloc_large (frstat.st_size);
903 if (frstat.st_size !=
904 GNUNET_DISK_fn_read (fn, data, frstat.st_size))
906 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
907 _("Failed to read friends list from `%s'\n"), fn);
914 while ((pos < frstat.st_size) && isspace (data[pos]))
916 while ((frstat.st_size >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) &&
917 (pos <= frstat.st_size - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
919 memcpy (&enc, &data[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
920 if (!isspace (enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1]))
922 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
923 _("Syntax error in topology specification at offset %llu, skipping bytes.\n"),
924 (unsigned long long) pos);
926 while ((pos < frstat.st_size) && (!isspace (data[pos])))
930 enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
931 if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char *) &enc, &hc))
933 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
934 _("Syntax error in topology specification at offset %llu, skipping bytes `%s'.\n"),
935 (unsigned long long) pos,
941 fl = GNUNET_malloc (sizeof(struct PeerList));
942 fl->is_friend = GNUNET_YES;
943 fl->id.hashPubKey = hc;
947 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
948 "Found friend `%s' in configuration\n",
949 GNUNET_i2s (&fl->id));
952 pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded);
953 while ((pos < frstat.st_size) && isspace (data[pos]))
958 if ( (minimum_friend_count > entries_found) &&
959 (friends_only == GNUNET_NO) )
961 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
962 _("Fewer friends specified than required by minimum friend count. Will only connect to friends.\n"));
964 if ( (minimum_friend_count > target_connection_count) &&
965 (friends_only == GNUNET_NO) )
967 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
968 _("More friendly connections required than target total number of connections.\n"));
974 * This function is called whenever an encrypted HELLO message is
978 * @param other the other peer involved (sender or receiver, NULL
979 * for loopback messages where we are both sender and receiver)
980 * @param message the actual HELLO message
981 * @return GNUNET_OK to keep the connection open,
982 * GNUNET_SYSERR to close it (signal serious error)
985 handle_encrypted_hello (void *cls,
986 const struct GNUNET_PeerIdentity * other,
987 const struct GNUNET_MessageHeader *
991 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
992 "Received encrypted `%s' from peer `%s'",
996 if (transport != NULL)
997 GNUNET_TRANSPORT_offer_hello (transport,
1004 * Peerinfo calls this function to let us know about a
1005 * possible peer that we might want to connect to.
1008 * @param peer NULL for the end of the list, otherwise a peer identity
1009 * @param hello a HELLO for a peer, or NULL
1010 * @param trust how much do we trust the given peer?
1013 gather_hello_callback (void *cls,
1014 const struct GNUNET_PeerIdentity *peer,
1015 const struct GNUNET_HELLO_Message *hello,
1020 hello_gathering_active = GNUNET_NO;
1024 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1025 "Received `%s' for peer `%s'",
1030 consider_for_advertising (hello);
1035 * Function to fill send buffer with HELLO.
1038 * @param receiver the receiver of the message
1039 * @param position is the reference to the
1040 * first unused position in the buffer where GNUnet is building
1042 * @param padding is the number of bytes left in that buffer.
1043 * @return the number of bytes written to
1044 * that buffer (must be a positive number).
1047 hello_advertising (void *cls,
1048 const struct GNUNET_PeerIdentity *
1053 struct PeerList *pl;
1054 struct HelloList *pos;
1055 struct HelloList *prev;
1056 struct HelloList *next;
1060 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1061 "Data solicited for `%s', considering sending `%s's",
1062 GNUNET_i2s (receiver),
1068 if (0 == memcmp (&pl->id, receiver, sizeof (struct GNUNET_PeerIdentity)))
1077 /* find applicable HELLOs */
1080 while (NULL != (pos = next))
1084 GNUNET_CONTAINER_bloomfilter_test (pos->filter,
1085 &receiver->hashPubKey))
1087 if (0 == GNUNET_TIME_absolute_get_remaining (pos->expiration).value)
1089 /* time to discard... */
1094 GNUNET_CONTAINER_bloomfilter_free (pos->filter);
1104 size = GNUNET_HELLO_size (pos->msg);
1107 memcpy (position, pos->msg, size);
1108 GNUNET_CONTAINER_bloomfilter_add (pos->filter,
1109 &receiver->hashPubKey);
1116 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1117 "Sending %u bytes of `%s's",
1118 (unsigned int) size,
1123 if ( (GNUNET_NO == hello_gathering_active) &&
1124 (GNUNET_TIME_absolute_get_duration (last_hello_gather_time).value >
1125 MIN_HELLO_GATHER_DELAY.value) )
1128 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1129 "Have no `%s's, trying to get some from `%s' for next time",
1133 hello_gathering_active = GNUNET_YES;
1134 last_hello_gather_time = GNUNET_TIME_absolute_get();
1135 GNUNET_PEERINFO_for_all (cfg,
1138 0, GNUNET_TIME_UNIT_FOREVER_REL,
1139 &gather_hello_callback, NULL);
1146 * Last task run during shutdown. Disconnects us from
1147 * the transport and core.
1150 cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1152 struct PeerList *pl;
1154 GNUNET_TRANSPORT_disconnect (transport);
1158 GNUNET_CORE_disconnect (handle);
1161 while (NULL != (pl = friends))
1170 * Main function that will be run.
1172 * @param cls closure
1173 * @param s the scheduler to use
1174 * @param args remaining command-line arguments
1175 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1176 * @param c configuration
1180 struct GNUNET_SCHEDULER_Handle * s,
1182 const char *cfgfile,
1183 const struct GNUNET_CONFIGURATION_Handle * c)
1185 struct GNUNET_CORE_MessageHandler handlers[] =
1187 { &handle_encrypted_hello, GNUNET_MESSAGE_TYPE_HELLO, 0},
1190 unsigned long long opt;
1194 autoconnect = GNUNET_CONFIGURATION_get_value_yesno (cfg,
1197 friends_only = GNUNET_CONFIGURATION_get_value_yesno (cfg,
1201 GNUNET_CONFIGURATION_get_value_number (cfg,
1206 minimum_friend_count = (unsigned int) opt;
1208 GNUNET_CONFIGURATION_get_value_number (cfg,
1210 "TARGET-CONNECTION-COUNT",
1213 target_connection_count = (unsigned int) opt;
1215 if ( (friends_only == GNUNET_YES) ||
1216 (minimum_friend_count > 0) )
1217 read_friends_file (cfg);
1219 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1220 "Topology would like %u connections with at least %u friends (%s)\n",
1221 target_connection_count,
1222 minimum_friend_count,
1223 autoconnect ? "autoconnect enabled" : "autoconnect disabled");
1225 transport = GNUNET_TRANSPORT_connect (sched,
1231 handle = GNUNET_CORE_connect (sched,
1233 GNUNET_TIME_UNIT_FOREVER_REL,
1242 GNUNET_SCHEDULER_add_delayed (sched,
1243 GNUNET_TIME_UNIT_FOREVER_REL,
1244 &cleaning_task, NULL);
1245 if (NULL == transport)
1247 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1248 _("Failed to connect to `%s' service.\n"),
1250 GNUNET_SCHEDULER_shutdown (sched);
1255 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1256 _("Failed to connect to `%s' service.\n"),
1258 GNUNET_SCHEDULER_shutdown (sched);
1265 * The main function for the topology daemon.
1267 * @param argc number of arguments from the command line
1268 * @param argv command line arguments
1269 * @return 0 ok, 1 on error
1272 main (int argc, char *const *argv)
1277 GNUNET_PROGRAM_run (argc,
1280 _("GNUnet topology control (maintaining P2P mesh and F2F constraints)"),
1282 &run, NULL)) ? 0 : 1;
1286 /* end of gnunet-daemon-topology.c */