2 This file is part of GNUnet.
3 (C) 2007, 2008, 2009, 2010 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 * Our peerinfo notification context. We use notification
143 * to instantly learn about new peers as they are discovered
144 * as well as periodic iteration to try peers again after
147 static struct GNUNET_PEERINFO_NotifyContext *peerinfo_notify;
150 * Linked list of HELLOs for advertising.
152 static struct HelloList *hellos;
157 static struct GNUNET_SCHEDULER_Handle * sched;
162 static const struct GNUNET_CONFIGURATION_Handle * cfg;
165 * Handle to the core API.
167 static struct GNUNET_CORE_Handle *handle;
170 * Handle to the transport API.
172 static struct GNUNET_TRANSPORT_Handle *transport;
175 * Identity of this peer.
177 static struct GNUNET_PeerIdentity my_identity;
180 * Linked list of all of our friends and all of our current
183 static struct PeerList *friends;
186 * Timestamp from the last time we tried to gather HELLOs.
188 static struct GNUNET_TIME_Absolute last_hello_gather_time;
191 * Flag to disallow non-friend connections (pure F2F mode).
193 static int friends_only;
196 * Minimum number of friends to have in the
197 * connection set before we allow non-friends.
199 static unsigned int minimum_friend_count;
202 * Number of peers (friends and others) that we are currently connected to.
204 static unsigned int connection_count;
207 * Target number of connections.
209 static unsigned int target_connection_count;
212 * Number of friends that we are currently connected to.
214 static unsigned int friend_count;
217 * Should the topology daemon try to establish connections?
219 static int autoconnect;
222 * Are we currently having a request pending with
223 * PEERINFO asking for HELLOs for advertising?
225 static int hello_gathering_active;
230 * Force a disconnect from the specified peer.
233 force_disconnect (const struct GNUNET_PeerIdentity *peer)
235 GNUNET_CORE_peer_configure (handle,
237 GNUNET_TIME_UNIT_FOREVER_REL,
247 * Function called by core when our attempt to connect
248 * succeeded. Does nothing.
251 ready_callback (void *cls,
252 size_t size, void *buf)
255 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
257 ? "Core told us that our attempt to connect failed.\n"
258 : "Core told us that our attempt to connect worked. Good!\n");
265 * Try to connect to the specified peer.
267 * @param peer who we should try to connect to
268 * @param pos entry in our friend list; NULL if not in friend list yet
271 attempt_connect (const struct GNUNET_PeerIdentity *peer,
272 struct PeerList *pos)
279 if (0 == memcmp (&pos->id, peer, sizeof (struct GNUNET_PeerIdentity)))
286 pos = GNUNET_malloc (sizeof(struct PeerList));
291 if (GNUNET_YES == pos->is_friend)
292 pos->blacklisted_until = GNUNET_TIME_relative_to_absolute (BLACKLIST_AFTER_ATTEMPT_FRIEND);
294 pos->blacklisted_until = GNUNET_TIME_relative_to_absolute (BLACKLIST_AFTER_ATTEMPT);
296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
297 "Asking core to connect to `%s'\n",
300 GNUNET_CORE_notify_transmit_ready (handle,
302 GNUNET_TIME_UNIT_MINUTES,
304 sizeof(struct GNUNET_MessageHeader),
311 * Is this peer one of our friends?
314 is_friend (const struct GNUNET_PeerIdentity * peer)
316 struct PeerList *pos;
321 if ( (GNUNET_YES == pos->is_friend) &&
322 (0 == memcmp (&pos->id, peer, sizeof (struct GNUNET_PeerIdentity))) )
325 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
326 "Determined that `%s' is a friend\n",
338 * Check if an additional connection from the given peer is allowed.
341 is_connection_allowed (const struct GNUNET_PeerIdentity * peer)
343 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
344 return GNUNET_SYSERR; /* disallow connections to self */
345 if (is_friend (peer))
347 if (GNUNET_YES == friends_only)
350 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
351 "Determined that `%s' is not allowed to connect (not a friend)\n",
354 return GNUNET_SYSERR;
356 if (friend_count >= minimum_friend_count)
359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
360 "Determined that `%s' is not allowed to connect (not enough connected friends)\n",
363 return GNUNET_SYSERR;
368 * Method called whenever a peer connects.
371 * @param peer peer identity this notification is about
373 static void connect_notify (void *cls,
375 GNUNET_PeerIdentity * peer)
377 struct PeerList *pos;
380 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
381 "Core told us that we connected to `%s'\n",
388 if ( (GNUNET_YES == pos->is_friend) &&
389 (0 == memcmp (&pos->id, peer, sizeof (struct GNUNET_PeerIdentity))) )
391 GNUNET_assert (GNUNET_NO == pos->is_connected);
392 pos->is_connected = GNUNET_YES;
393 pos->blacklisted_until.value = 0; /* remove blacklisting */
399 pos = GNUNET_malloc (sizeof(struct PeerList));
401 pos->is_connected = GNUNET_YES;
404 if (GNUNET_OK != is_connection_allowed (peer))
407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
408 "Connection to `%s' is forbidden, forcing disconnect!\n",
411 force_disconnect (peer);
417 * Disconnect from all non-friends (we're below quota).
422 struct PeerList *pos;
427 if (GNUNET_NO == pos->is_friend)
429 GNUNET_assert (GNUNET_YES == pos->is_connected);
431 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
432 "Connection to `%s' is not from a friend, forcing disconnect!\n",
433 GNUNET_i2s (&pos->id));
435 force_disconnect (&pos->id);
443 * Method called whenever a peer disconnects.
446 * @param peer peer identity this notification is about
448 static void disconnect_notify (void *cls,
450 GNUNET_PeerIdentity * peer)
452 struct PeerList *pos;
453 struct PeerList *prev;
456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
457 "Core told us that we disconnected from `%s'\n",
465 if (0 == memcmp (&pos->id, peer, sizeof (struct GNUNET_PeerIdentity)))
467 GNUNET_assert (GNUNET_YES == pos->is_connected);
468 pos->is_connected = GNUNET_NO;
469 if (GNUNET_YES == pos->is_friend)
472 if (friend_count < minimum_friend_count)
474 /* disconnect from all non-friends */
476 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
477 "Not enough friendly connections, dropping all non-friend connections\n");
480 attempt_connect (peer, pos);
489 prev->next = pos->next;
502 * Find more peers that we should connect to and ask the
503 * core to establish connections.
506 find_more_peers (void *cls,
507 const struct GNUNET_SCHEDULER_TaskContext *tc);
511 * Determine when we should try again to find more peers and
515 schedule_peer_search ()
517 struct GNUNET_TIME_Relative delay;
519 /* Typically, we try again every 15 minutes; the minimum period is
520 15s; if we are above the connection target, we reduce re-trying
521 by the square of how much we are above; so for example, with 200%
522 of the connection target we would only look for more peers once
523 every hour (after all, we're quite busy processing twice as many
524 connections as we intended to have); similarly, if we are at only
525 25% of our connectivity goal, we will try 16x as hard to connect
526 (so roughly once a minute, plus the 15s minimum delay */
527 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
528 15 + 15 * 60 * connection_count * connection_count / target_connection_count / target_connection_count);
530 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
531 "Will try to find more peers in %llums\n",
532 (unsigned long long) delay.value);
534 GNUNET_SCHEDULER_add_delayed (sched,
544 * Iterator called on each address.
546 * @param cls flag that we will set if we see any addresses
547 * @param tname name of the transport
548 * @param expiration when will the given address expire
549 * @param addr the address of the peer
550 * @param addrlen number of bytes in addr
551 * @return GNUNET_SYSERR always, to terminate iteration
554 address_iterator (void *cls,
556 struct GNUNET_TIME_Absolute expiration,
557 const void *addr, size_t addrlen)
561 return GNUNET_SYSERR;
566 * We've gotten a HELLO from another peer.
567 * Consider it for advertising.
570 consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
573 struct GNUNET_PeerIdentity pid;
574 struct HelloList *pos;
577 have_address = GNUNET_NO;
578 GNUNET_HELLO_iterate_addresses (hello,
582 if (GNUNET_NO == have_address)
583 return; /* no point in advertising this one... */
584 GNUNET_break (GNUNET_OK == GNUNET_HELLO_get_id (hello, &pid));
588 if (0 == memcmp (&pos->id,
590 sizeof(struct GNUNET_PeerIdentity)))
591 return; /* duplicate, at least "mostly" */
595 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
596 "Found `%s' from peer `%s' for advertising\n",
600 size = GNUNET_HELLO_size (hello);
601 pos = GNUNET_malloc (sizeof(struct HelloList) + size);
602 pos->msg = (struct GNUNET_HELLO_Message*) &pos[1];
603 memcpy (&pos->msg, hello, size);
605 pos->expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADVERTISEMENT_MIN_FREQUENCY);
606 /* 2^{-5} chance of not sending a HELLO to a peer is
607 acceptably small (if the filter is 50% full);
608 64 bytes of memory are small compared to the rest
609 of the data structure and would only really become
610 "useless" once a HELLO has been passed on to ~100
611 other peers, which is likely more than enough in
612 any case; hence 64, 5 as bloomfilter parameters. */
613 pos->filter = GNUNET_CONTAINER_bloomfilter_load (NULL, 64, 5);
614 /* never send a peer its own HELLO */
615 GNUNET_CONTAINER_bloomfilter_add (pos->filter, &pos->id.hashPubKey);
622 * Peerinfo calls this function to let us know about a
623 * possible peer that we might want to connect to.
626 process_peer (void *cls,
627 const struct GNUNET_PeerIdentity *peer,
628 const struct GNUNET_HELLO_Message *hello,
631 struct PeerList *pos;
635 /* last call, schedule 'find_more_peers' again... */
636 if (0 != (GNUNET_SCHEDULER_get_reason (sched) & GNUNET_SCHEDULER_REASON_SHUTDOWN))
639 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
640 "Received shutdown request, stopping search for peers to connect to.\n");
644 schedule_peer_search ();
649 /* no HELLO known; can not connect, ignore! */
652 if (0 == memcmp (&my_identity,
653 peer, sizeof (struct GNUNET_PeerIdentity)))
654 return; /* that's me! */
656 consider_for_advertising (hello);
658 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
659 "Considering connecting to peer `%s'\n",
665 if (0 == memcmp (&pos->id, peer, sizeof (struct GNUNET_PeerIdentity)))
667 if (GNUNET_YES == pos->is_connected)
670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
671 "Already connected to peer `%s'\n",
676 if (GNUNET_TIME_absolute_get_remaining (pos->blacklisted_until).value > 0)
679 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
680 "Already tried peer `%s' recently\n",
683 return; /* peer still blacklisted */
685 if (GNUNET_YES == pos->is_friend)
687 attempt_connect (peer, pos);
693 if ( (GNUNET_YES == friends_only) ||
694 (friend_count < minimum_friend_count) )
697 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
698 "Peer `%s' is not a friend, and we currently only connect to friends\n",
703 attempt_connect (peer, NULL);
708 * Try to add more friends to our connection set.
713 struct PeerList *pos;
716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
717 "Considering all of our friends for new connections\n");
722 if ( (GNUNET_TIME_absolute_get_remaining (pos->blacklisted_until).value == 0) &&
723 (GNUNET_YES == pos->is_friend) &&
724 (GNUNET_YES != pos->is_connected) )
725 attempt_connect (&pos->id, pos);
732 * Discard peer entries for blacklisted peers
733 * where the blacklisting has expired.
736 discard_old_blacklist_entries ()
738 struct PeerList *pos;
739 struct PeerList *next;
740 struct PeerList *prev;
744 while (NULL != (pos = next))
747 if ( (GNUNET_NO == pos->is_friend) &&
748 (GNUNET_NO == pos->is_connected) &&
749 (0 == GNUNET_TIME_absolute_get_remaining (pos->blacklisted_until).value) )
751 /* delete 'pos' from list */
753 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
754 "Deleting peer `%s' from our list (not connected, not a friend and blacklist expired)\n",
755 GNUNET_i2s (&pos->id));
772 * Find more peers that we should connect to and ask the
773 * core to establish connections.
776 find_more_peers (void *cls,
777 const struct GNUNET_SCHEDULER_TaskContext *tc)
779 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
783 "Received shutdown request, stopping search for peers to connect to.\n");
787 discard_old_blacklist_entries ();
788 if (connection_count <= target_connection_count)
790 schedule_peer_search ();
793 if ( (GNUNET_YES == friends_only) ||
794 (friend_count < minimum_friend_count) )
797 schedule_peer_search ();
801 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
802 "Got sufficient (%u/%u, %u friends) number of connections, won't try to create more.\n",
804 target_connection_count,
807 GNUNET_PEERINFO_for_all (cfg,
810 0, GNUNET_TIME_UNIT_FOREVER_REL,
811 &process_peer, NULL);
816 * Function called after GNUNET_CORE_connect has succeeded
817 * (or failed for good).
820 * @param server handle to the server, NULL if we failed
821 * @param my_id ID of this peer, NULL if we failed
822 * @param publicKey public key of this peer, NULL if we failed
825 core_init (void *cls,
826 struct GNUNET_CORE_Handle * server,
827 const struct GNUNET_PeerIdentity *
830 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *
835 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
836 _("Failed to connect to core service, can not manage topology!\n"));
837 GNUNET_SCHEDULER_shutdown (sched);
841 my_identity = *my_id;
843 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
848 GNUNET_SCHEDULER_add_delayed (sched,
849 GNUNET_TIME_UNIT_SECONDS /* give core time to tell us about existing connections */,
856 * gnunet-daemon-topology command line options.
858 static struct GNUNET_GETOPT_CommandLineOption options[] = {
859 GNUNET_GETOPT_OPTION_END
864 * Read the friends file.
867 read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
874 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
875 unsigned int entries_found;
879 GNUNET_CONFIGURATION_get_value_filename (cfg,
884 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
885 _("Option `%s' in section `%s' not specified!\n"),
890 if (GNUNET_OK != GNUNET_DISK_file_test (fn))
891 GNUNET_DISK_fn_write (fn, NULL, 0, GNUNET_DISK_PERM_USER_READ
892 | GNUNET_DISK_PERM_USER_WRITE);
893 if (0 != STAT (fn, &frstat))
895 if ((friends_only) || (minimum_friend_count > 0))
897 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
898 _("Could not read friends list `%s'\n"), fn);
903 if (frstat.st_size == 0)
905 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
906 _("Friends file `%s' is empty.\n"),
911 data = GNUNET_malloc_large (frstat.st_size);
912 if (frstat.st_size !=
913 GNUNET_DISK_fn_read (fn, data, frstat.st_size))
915 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
916 _("Failed to read friends list from `%s'\n"), fn);
923 while ((pos < frstat.st_size) && isspace (data[pos]))
925 while ((frstat.st_size >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) &&
926 (pos <= frstat.st_size - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
928 memcpy (&enc, &data[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
929 if (!isspace (enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1]))
931 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
932 _("Syntax error in topology specification at offset %llu, skipping bytes.\n"),
933 (unsigned long long) pos);
935 while ((pos < frstat.st_size) && (!isspace (data[pos])))
939 enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
940 if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char *) &enc, &hc))
942 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
943 _("Syntax error in topology specification at offset %llu, skipping bytes `%s'.\n"),
944 (unsigned long long) pos,
950 fl = GNUNET_malloc (sizeof(struct PeerList));
951 fl->is_friend = GNUNET_YES;
952 fl->id.hashPubKey = hc;
956 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
957 "Found friend `%s' in configuration\n",
958 GNUNET_i2s (&fl->id));
961 pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded);
962 while ((pos < frstat.st_size) && isspace (data[pos]))
967 if ( (minimum_friend_count > entries_found) &&
968 (friends_only == GNUNET_NO) )
970 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
971 _("Fewer friends specified than required by minimum friend count. Will only connect to friends.\n"));
973 if ( (minimum_friend_count > target_connection_count) &&
974 (friends_only == GNUNET_NO) )
976 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
977 _("More friendly connections required than target total number of connections.\n"));
983 * This function is called whenever an encrypted HELLO message is
987 * @param other the other peer involved (sender or receiver, NULL
988 * for loopback messages where we are both sender and receiver)
989 * @param message the actual HELLO message
990 * @return GNUNET_OK to keep the connection open,
991 * GNUNET_SYSERR to close it (signal serious error)
994 handle_encrypted_hello (void *cls,
995 const struct GNUNET_PeerIdentity * other,
996 const struct GNUNET_MessageHeader *
1000 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1001 "Received encrypted `%s' from peer `%s'",
1003 GNUNET_i2s (other));
1005 if (transport != NULL)
1006 GNUNET_TRANSPORT_offer_hello (transport,
1013 * Peerinfo calls this function to let us know about a
1014 * possible peer that we might want to connect to.
1017 * @param peer NULL for the end of the list, otherwise a peer identity
1018 * @param hello a HELLO for a peer, or NULL
1019 * @param trust how much do we trust the given peer?
1022 gather_hello_callback (void *cls,
1023 const struct GNUNET_PeerIdentity *peer,
1024 const struct GNUNET_HELLO_Message *hello,
1029 hello_gathering_active = GNUNET_NO;
1033 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1034 "Received `%s' for peer `%s'",
1039 consider_for_advertising (hello);
1044 * Function to fill send buffer with HELLO.
1047 * @param receiver the receiver of the message
1048 * @param position is the reference to the
1049 * first unused position in the buffer where GNUnet is building
1051 * @param padding is the number of bytes left in that buffer.
1052 * @return the number of bytes written to
1053 * that buffer (must be a positive number).
1056 hello_advertising (void *cls,
1057 const struct GNUNET_PeerIdentity *
1062 struct PeerList *pl;
1063 struct HelloList *pos;
1064 struct HelloList *prev;
1065 struct HelloList *next;
1069 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1070 "Data solicited for `%s', considering sending `%s's",
1071 GNUNET_i2s (receiver),
1077 if (0 == memcmp (&pl->id, receiver, sizeof (struct GNUNET_PeerIdentity)))
1086 /* find applicable HELLOs */
1089 while (NULL != (pos = next))
1093 GNUNET_CONTAINER_bloomfilter_test (pos->filter,
1094 &receiver->hashPubKey))
1096 if (0 == GNUNET_TIME_absolute_get_remaining (pos->expiration).value)
1098 /* time to discard... */
1103 GNUNET_CONTAINER_bloomfilter_free (pos->filter);
1113 size = GNUNET_HELLO_size (pos->msg);
1116 memcpy (position, pos->msg, size);
1117 GNUNET_CONTAINER_bloomfilter_add (pos->filter,
1118 &receiver->hashPubKey);
1125 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1126 "Sending %u bytes of `%s's",
1127 (unsigned int) size,
1132 if ( (GNUNET_NO == hello_gathering_active) &&
1133 (GNUNET_TIME_absolute_get_duration (last_hello_gather_time).value >
1134 MIN_HELLO_GATHER_DELAY.value) )
1137 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1138 "Have no `%s's, trying to get some from `%s' for next time",
1142 hello_gathering_active = GNUNET_YES;
1143 last_hello_gather_time = GNUNET_TIME_absolute_get();
1144 GNUNET_PEERINFO_for_all (cfg,
1147 0, GNUNET_TIME_UNIT_FOREVER_REL,
1148 &gather_hello_callback, NULL);
1155 * Last task run during shutdown. Disconnects us from
1156 * the transport and core.
1159 cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1161 struct PeerList *pl;
1163 if (NULL != peerinfo_notify)
1165 GNUNET_PEERINFO_notify_cancel (peerinfo_notify);
1166 peerinfo_notify = NULL;
1168 GNUNET_TRANSPORT_disconnect (transport);
1172 GNUNET_CORE_disconnect (handle);
1175 while (NULL != (pl = friends))
1184 * Main function that will be run.
1186 * @param cls closure
1187 * @param s the scheduler to use
1188 * @param args remaining command-line arguments
1189 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1190 * @param c configuration
1194 struct GNUNET_SCHEDULER_Handle * s,
1196 const char *cfgfile,
1197 const struct GNUNET_CONFIGURATION_Handle * c)
1199 struct GNUNET_CORE_MessageHandler handlers[] =
1201 { &handle_encrypted_hello, GNUNET_MESSAGE_TYPE_HELLO, 0},
1204 unsigned long long opt;
1208 autoconnect = GNUNET_CONFIGURATION_get_value_yesno (cfg,
1211 friends_only = GNUNET_CONFIGURATION_get_value_yesno (cfg,
1215 GNUNET_CONFIGURATION_get_value_number (cfg,
1220 minimum_friend_count = (unsigned int) opt;
1222 GNUNET_CONFIGURATION_get_value_number (cfg,
1224 "TARGET-CONNECTION-COUNT",
1227 target_connection_count = (unsigned int) opt;
1229 if ( (friends_only == GNUNET_YES) ||
1230 (minimum_friend_count > 0) )
1231 read_friends_file (cfg);
1233 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1234 "Topology would like %u connections with at least %u friends (%s)\n",
1235 target_connection_count,
1236 minimum_friend_count,
1237 autoconnect ? "autoconnect enabled" : "autoconnect disabled");
1239 transport = GNUNET_TRANSPORT_connect (sched,
1245 handle = GNUNET_CORE_connect (sched,
1247 GNUNET_TIME_UNIT_FOREVER_REL,
1256 GNUNET_SCHEDULER_add_delayed (sched,
1257 GNUNET_TIME_UNIT_FOREVER_REL,
1258 &cleaning_task, NULL);
1259 if (NULL == transport)
1261 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1262 _("Failed to connect to `%s' service.\n"),
1264 GNUNET_SCHEDULER_shutdown (sched);
1269 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1270 _("Failed to connect to `%s' service.\n"),
1272 GNUNET_SCHEDULER_shutdown (sched);
1275 peerinfo_notify = GNUNET_PEERINFO_notify (cfg, sched,
1282 * The main function for the topology daemon.
1284 * @param argc number of arguments from the command line
1285 * @param argv command line arguments
1286 * @return 0 ok, 1 on error
1289 main (int argc, char *const *argv)
1294 GNUNET_PROGRAM_run (argc,
1297 _("GNUnet topology control (maintaining P2P mesh and F2F constraints)"),
1299 &run, NULL)) ? 0 : 1;
1303 /* end of gnunet-daemon-topology.c */