aboutsummaryrefslogtreecommitdiff
path: root/src/topology/gnunet-daemon-topology.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/topology/gnunet-daemon-topology.c')
-rw-r--r--src/topology/gnunet-daemon-topology.c132
1 files changed, 105 insertions, 27 deletions
diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c
index 4db35a17c..2b25dccdd 100644
--- a/src/topology/gnunet-daemon-topology.c
+++ b/src/topology/gnunet-daemon-topology.c
@@ -22,11 +22,6 @@
22 * @file topology/gnunet-daemon-topology.c 22 * @file topology/gnunet-daemon-topology.c
23 * @brief code for bootstrapping via topology servers 23 * @brief code for bootstrapping via topology servers
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - blacklisting & respect for blacklist
28 * - calculate target_connection_count!
29 * - calculate peer_search retry delay
30 */ 25 */
31 26
32#include <stdlib.h> 27#include <stdlib.h>
@@ -39,17 +34,29 @@
39 34
40#define DEBUG_TOPOLOGY GNUNET_NO 35#define DEBUG_TOPOLOGY GNUNET_NO
41 36
37/**
38 * For how long do we blacklist a peer after a failed
39 * connection attempt?
40 */
41#define BLACKLIST_AFTER_ATTEMPT GNUNET_TIME_UNIT_HOURS
42 42
43/** 43/**
44 * List of neighbours and friends. 44 * For how long do we blacklist a friend after a failed
45 * connection attempt?
46 */
47#define BLACKLIST_AFTER_ATTEMPT_FRIEND GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
48
49
50/**
51 * List of neighbours, friends and blacklisted peers.
45 */ 52 */
46struct FriendList 53struct PeerList
47{ 54{
48 55
49 /** 56 /**
50 * This is a linked list. 57 * This is a linked list.
51 */ 58 */
52 struct FriendList *next; 59 struct PeerList *next;
53 60
54 /** 61 /**
55 * Is this peer listed here because he is a friend? 62 * Is this peer listed here because he is a friend?
@@ -99,7 +106,7 @@ static struct GNUNET_PeerIdentity my_identity;
99 * Linked list of all of our friends and all of our current 106 * Linked list of all of our friends and all of our current
100 * neighbours. 107 * neighbours.
101 */ 108 */
102static struct FriendList *friends; 109static struct PeerList *friends;
103 110
104/** 111/**
105 * Flag to disallow non-friend connections (pure F2F mode). 112 * Flag to disallow non-friend connections (pure F2F mode).
@@ -170,9 +177,28 @@ ready_callback (void *cls,
170 */ 177 */
171static void 178static void
172attempt_connect (const struct GNUNET_PeerIdentity *peer, 179attempt_connect (const struct GNUNET_PeerIdentity *peer,
173 struct FriendList *pos) 180 struct PeerList *pos)
174{ 181{
175 /* FIXME: do blacklist! */ 182 if (pos == NULL)
183 {
184 pos = friends;
185 while (pos != NULL)
186 {
187 if (0 == memcmp (&pos->id, peer, sizeof (struct GNUNET_PeerIdentity)))
188 break;
189 }
190 }
191 if (pos == NULL)
192 {
193 pos = GNUNET_malloc (sizeof(struct PeerList));
194 pos->id = *peer;
195 pos->next = friends;
196 friends = pos;
197 }
198 if (GNUNET_YES == pos->is_friend)
199 pos->blacklisted_until = GNUNET_TIME_relative_to_absolute (BLACKLIST_AFTER_ATTEMPT_FRIEND);
200 else
201 pos->blacklisted_until = GNUNET_TIME_relative_to_absolute (BLACKLIST_AFTER_ATTEMPT);
176 GNUNET_CORE_notify_transmit_ready (handle, 202 GNUNET_CORE_notify_transmit_ready (handle,
177 0 /* priority */, 203 0 /* priority */,
178 GNUNET_TIME_UNIT_MINUTES, 204 GNUNET_TIME_UNIT_MINUTES,
@@ -189,7 +215,7 @@ attempt_connect (const struct GNUNET_PeerIdentity *peer,
189static int 215static int
190is_friend (const struct GNUNET_PeerIdentity * peer) 216is_friend (const struct GNUNET_PeerIdentity * peer)
191{ 217{
192 struct FriendList *pos; 218 struct PeerList *pos;
193 219
194 pos = friends; 220 pos = friends;
195 while (pos != NULL) 221 while (pos != NULL)
@@ -231,7 +257,7 @@ static void connect_notify (void *cls,
231 const struct 257 const struct
232 GNUNET_PeerIdentity * peer) 258 GNUNET_PeerIdentity * peer)
233{ 259{
234 struct FriendList *pos; 260 struct PeerList *pos;
235 261
236 connection_count++; 262 connection_count++;
237 pos = friends; 263 pos = friends;
@@ -242,12 +268,13 @@ static void connect_notify (void *cls,
242 { 268 {
243 GNUNET_assert (GNUNET_NO == pos->is_connected); 269 GNUNET_assert (GNUNET_NO == pos->is_connected);
244 pos->is_connected = GNUNET_YES; 270 pos->is_connected = GNUNET_YES;
271 pos->blacklisted_until.value = 0; /* remove blacklisting */
245 friend_count++; 272 friend_count++;
246 return; 273 return;
247 } 274 }
248 pos = pos->next; 275 pos = pos->next;
249 } 276 }
250 pos = GNUNET_malloc (sizeof(struct FriendList)); 277 pos = GNUNET_malloc (sizeof(struct PeerList));
251 pos->id = *peer; 278 pos->id = *peer;
252 pos->is_connected = GNUNET_YES; 279 pos->is_connected = GNUNET_YES;
253 pos->next = friends; 280 pos->next = friends;
@@ -263,7 +290,7 @@ static void connect_notify (void *cls,
263static void 290static void
264drop_non_friends () 291drop_non_friends ()
265{ 292{
266 struct FriendList *pos; 293 struct PeerList *pos;
267 294
268 pos = friends; 295 pos = friends;
269 while (pos != NULL) 296 while (pos != NULL)
@@ -288,8 +315,8 @@ static void disconnect_notify (void *cls,
288 const struct 315 const struct
289 GNUNET_PeerIdentity * peer) 316 GNUNET_PeerIdentity * peer)
290{ 317{
291 struct FriendList *pos; 318 struct PeerList *pos;
292 struct FriendList *prev; 319 struct PeerList *prev;
293 320
294 connection_count--; 321 connection_count--;
295 pos = friends; 322 pos = friends;
@@ -327,6 +354,7 @@ static void disconnect_notify (void *cls,
327 GNUNET_break (0); 354 GNUNET_break (0);
328} 355}
329 356
357
330/** 358/**
331 * Find more peers that we should connect to and ask the 359 * Find more peers that we should connect to and ask the
332 * core to establish connections. 360 * core to establish connections.
@@ -345,9 +373,16 @@ schedule_peer_search ()
345{ 373{
346 struct GNUNET_TIME_Relative delay; 374 struct GNUNET_TIME_Relative delay;
347 375
348 /* FIXME: calculate reasonable delay here */ 376 /* Typically, we try again every 15 minutes; the minimum period is
349 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 377 15s; if we are above the connection target, we reduce re-trying
350 42); 378 by the square of how much we are above; so for example, with 200%
379 of the connection target we would only look for more peers once
380 every hour (after all, we're quite busy processing twice as many
381 connections as we intended to have); similarly, if we are at only
382 25% of our connectivity goal, we will try 16x as hard to connect
383 (so roughly once a minute, plus the 15s minimum delay */
384 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
385 15 + 15 * 60 * connection_count * connection_count / target_connection_count / target_connection_count);
351 GNUNET_SCHEDULER_add_delayed (sched, 386 GNUNET_SCHEDULER_add_delayed (sched,
352 GNUNET_NO, 387 GNUNET_NO,
353 GNUNET_SCHEDULER_PRIORITY_DEFAULT, 388 GNUNET_SCHEDULER_PRIORITY_DEFAULT,
@@ -368,7 +403,7 @@ process_peer (void *cls,
368 const struct GNUNET_HELLO_Message * hello, 403 const struct GNUNET_HELLO_Message * hello,
369 uint32_t trust) 404 uint32_t trust)
370{ 405{
371 struct FriendList *pos; 406 struct PeerList *pos;
372 407
373 if (peer == NULL) 408 if (peer == NULL)
374 { 409 {
@@ -392,7 +427,8 @@ process_peer (void *cls,
392 { 427 {
393 if (GNUNET_YES == pos->is_connected) 428 if (GNUNET_YES == pos->is_connected)
394 return; 429 return;
395 /* FIXME: check blacklisted... */ 430 if (GNUNET_TIME_absolute_get_remaining (pos->blacklisted_until).value > 0)
431 return; /* peer still blacklisted */
396 if (GNUNET_YES == pos->is_friend) 432 if (GNUNET_YES == pos->is_friend)
397 { 433 {
398 attempt_connect (peer, pos); 434 attempt_connect (peer, pos);
@@ -415,13 +451,13 @@ process_peer (void *cls,
415static void 451static void
416try_add_friends () 452try_add_friends ()
417{ 453{
418 struct FriendList *pos; 454 struct PeerList *pos;
419 455
420 pos = friends; 456 pos = friends;
421 while (pos != NULL) 457 while (pos != NULL)
422 { 458 {
423 /* FIXME: check friends for blacklisting... */ 459 if ( (GNUNET_TIME_absolute_get_remaining (pos->blacklisted_until).value == 0) &&
424 if ( (GNUNET_YES == pos->is_friend) && 460 (GNUNET_YES == pos->is_friend) &&
425 (GNUNET_YES != pos->is_connected) ) 461 (GNUNET_YES != pos->is_connected) )
426 attempt_connect (&pos->id, pos); 462 attempt_connect (&pos->id, pos);
427 pos = pos->next; 463 pos = pos->next;
@@ -430,6 +466,41 @@ try_add_friends ()
430 466
431 467
432/** 468/**
469 * Discard peer entries for blacklisted peers
470 * where the blacklisting has expired.
471 */
472static void
473discard_old_blacklist_entries ()
474{
475 struct PeerList *pos;
476 struct PeerList *next;
477 struct PeerList *prev;
478
479 next = friends;
480 prev = NULL;
481 while (NULL != (pos = next))
482 {
483 next = pos->next;
484 if ( (GNUNET_NO == pos->is_friend) &&
485 (GNUNET_NO == pos->is_connected) &&
486 (0 == GNUNET_TIME_absolute_get_remaining (pos->blacklisted_until).value) )
487 {
488 /* delete 'pos' from list */
489 if (prev == NULL)
490 friends = next;
491 else
492 prev->next = next;
493 GNUNET_free (pos);
494 }
495 else
496 {
497 prev = pos;
498 }
499 }
500}
501
502
503/**
433 * Find more peers that we should connect to and ask the 504 * Find more peers that we should connect to and ask the
434 * core to establish connections. 505 * core to establish connections.
435 */ 506 */
@@ -437,6 +508,7 @@ static void
437find_more_peers (void *cls, 508find_more_peers (void *cls,
438 const struct GNUNET_SCHEDULER_TaskContext *tc) 509 const struct GNUNET_SCHEDULER_TaskContext *tc)
439{ 510{
511 discard_old_blacklist_entries ();
440 if (target_connection_count <= connection_count) 512 if (target_connection_count <= connection_count)
441 { 513 {
442 schedule_peer_search (); 514 schedule_peer_search ();
@@ -515,7 +587,7 @@ read_friends_file (struct GNUNET_CONFIGURATION_Handle *cfg)
515 struct stat frstat; 587 struct stat frstat;
516 struct GNUNET_CRYPTO_HashAsciiEncoded enc; 588 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
517 unsigned int entries_found; 589 unsigned int entries_found;
518 struct FriendList *fl; 590 struct PeerList *fl;
519 591
520 fn = NULL; 592 fn = NULL;
521 GNUNET_CONFIGURATION_get_value_filename (cfg, 593 GNUNET_CONFIGURATION_get_value_filename (cfg,
@@ -581,7 +653,7 @@ read_friends_file (struct GNUNET_CONFIGURATION_Handle *cfg)
581 else 653 else
582 { 654 {
583 entries_found++; 655 entries_found++;
584 fl = GNUNET_malloc (sizeof(struct FriendList)); 656 fl = GNUNET_malloc (sizeof(struct PeerList));
585 fl->is_friend = GNUNET_YES; 657 fl->is_friend = GNUNET_YES;
586 fl->id.hashPubKey = hc; 658 fl->id.hashPubKey = hc;
587 fl->next = friends; 659 fl->next = friends;
@@ -644,6 +716,12 @@ run (void *cls,
644 "MINIMUM-FRIENDS", 716 "MINIMUM-FRIENDS",
645 &opt); 717 &opt);
646 minimum_friend_count = (unsigned int) opt; 718 minimum_friend_count = (unsigned int) opt;
719 opt = 16;
720 GNUNET_CONFIGURATION_get_value_number (cfg,
721 "TOPOLOGY",
722 "TARGET-CONNECTION-COUNT",
723 &opt);
724 target_connection_count = (unsigned int) opt;
647 725
648 if ( (friends_only == GNUNET_YES) || 726 if ( (friends_only == GNUNET_YES) ||
649 (minimum_friend_count > 0) ) 727 (minimum_friend_count > 0) )