diff options
Diffstat (limited to 'src/topology/gnunet-daemon-topology.c')
-rw-r--r-- | src/topology/gnunet-daemon-topology.c | 132 |
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 | */ |
46 | struct FriendList | 53 | struct 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 | */ |
102 | static struct FriendList *friends; | 109 | static 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 | */ |
171 | static void | 178 | static void |
172 | attempt_connect (const struct GNUNET_PeerIdentity *peer, | 179 | attempt_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, | |||
189 | static int | 215 | static int |
190 | is_friend (const struct GNUNET_PeerIdentity * peer) | 216 | is_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, | |||
263 | static void | 290 | static void |
264 | drop_non_friends () | 291 | drop_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, | |||
415 | static void | 451 | static void |
416 | try_add_friends () | 452 | try_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 | */ | ||
472 | static void | ||
473 | discard_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 | |||
437 | find_more_peers (void *cls, | 508 | find_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) ) |