aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/topology/Makefile.am1
-rw-r--r--src/topology/gnunet-daemon-topology.c777
2 files changed, 374 insertions, 404 deletions
diff --git a/src/topology/Makefile.am b/src/topology/Makefile.am
index 87939ac3f..6c6cbf8ff 100644
--- a/src/topology/Makefile.am
+++ b/src/topology/Makefile.am
@@ -36,6 +36,7 @@ gnunet_daemon_topology_LDADD = \
36 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 36 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
37 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 37 $(top_builddir)/src/statistics/libgnunetstatistics.la \
38 $(top_builddir)/src/transport/libgnunettransport.la \ 38 $(top_builddir)/src/transport/libgnunettransport.la \
39 $(top_builddir)/src/ats/libgnunetats.la \
39 $(top_builddir)/src/hello/libgnunethello.la \ 40 $(top_builddir)/src/hello/libgnunethello.la \
40 $(top_builddir)/src/util/libgnunetutil.la \ 41 $(top_builddir)/src/util/libgnunetutil.la \
41 $(GN_LIBINTL) 42 $(GN_LIBINTL)
diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c
index c2dce5c42..7a124c107 100644
--- a/src/topology/gnunet-daemon-topology.c
+++ b/src/topology/gnunet-daemon-topology.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2007-2013 Christian Grothoff (and other contributing authors) 3 Copyright (C) 2007-2015 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -20,8 +20,21 @@
20 20
21/** 21/**
22 * @file topology/gnunet-daemon-topology.c 22 * @file topology/gnunet-daemon-topology.c
23 * @brief code for maintaining the cadet topology 23 * @brief code for maintaining the overlay topology
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 *
26 * This daemon combines three functions:
27 * - suggesting to ATS which peers we might want to connect to
28 * - enforcing the F2F restrictions (by blacklisting)
29 * - gossping HELLOs
30 *
31 * All three require similar information (who are our friends
32 * impacts connectivity suggestions; connectivity suggestions
33 * should consider blacklisting; connectivity suggestions
34 * should consider available/known HELLOs; gossip requires
35 * connectivity data; connectivity suggestions require
36 * connectivity data), which is why they are combined in this
37 * program.
25 */ 38 */
26#include "platform.h" 39#include "platform.h"
27#include "gnunet_util_lib.h" 40#include "gnunet_util_lib.h"
@@ -32,47 +45,10 @@
32#include "gnunet_peerinfo_service.h" 45#include "gnunet_peerinfo_service.h"
33#include "gnunet_statistics_service.h" 46#include "gnunet_statistics_service.h"
34#include "gnunet_transport_service.h" 47#include "gnunet_transport_service.h"
48#include "gnunet_ats_service.h"
35 49
36 50
37/** 51/**
38 * Minimum required delay between calls to GNUNET_TRANSPORT_try_connect.
39 */
40#define MAX_CONNECT_FREQUENCY_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)
41
42/**
43 * Maximum delay allowed delay between calls to GNUNET_TRANSPORT_try_connect.
44 */
45#define MIN_CONNECT_FREQUENCY_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 2500)
46
47/**
48 * For how long do we blacklist a peer after a failed connection
49 * attempt? This is the baseline factor which is then multiplied by
50 * two to the power of the number of failed attempts.
51 */
52#define GREYLIST_AFTER_ATTEMPT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
53
54/**
55 * For how long do we blacklist a friend after a failed connection
56 * attempt? This is the baseline factor which is then multiplied by
57 * two to the power of the number of failed attempts.
58 */
59#define GREYLIST_AFTER_ATTEMPT_FRIEND GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
60
61/**
62 * For how long do we blacklist anyone under any cirumstances at least after a failed connection
63 * attempt? This is the absolute minimum, regardless of what the calculation based on
64 * exponential backoff returns.
65 */
66#define GREYLIST_AFTER_ATTEMPT_MIN GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
67
68/**
69 * For how long do we blacklist anyone under any cirumstances at most after a failed connection
70 * attempt? This is the absolute maximum, regardless of what the calculation based on
71 * exponential back-off returns.
72 */
73#define GREYLIST_AFTER_ATTEMPT_MAX GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1)
74
75/**
76 * At what frequency do we sent HELLOs to a peer? 52 * At what frequency do we sent HELLOs to a peer?
77 */ 53 */
78#define HELLO_ADVERTISEMENT_MIN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) 54#define HELLO_ADVERTISEMENT_MIN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
@@ -111,12 +87,6 @@ struct Peer
111 struct GNUNET_CONTAINER_BloomFilter *filter; 87 struct GNUNET_CONTAINER_BloomFilter *filter;
112 88
113 /** 89 /**
114 * Until what time should we not try to connect again
115 * to this peer?
116 */
117 struct GNUNET_TIME_Absolute greylisted_until;
118
119 /**
120 * Next time we are allowed to transmit a HELLO to this peer? 90 * Next time we are allowed to transmit a HELLO to this peer?
121 */ 91 */
122 struct GNUNET_TIME_Absolute next_hello_allowed; 92 struct GNUNET_TIME_Absolute next_hello_allowed;
@@ -127,30 +97,20 @@ struct Peer
127 struct GNUNET_TIME_Absolute filter_expiration; 97 struct GNUNET_TIME_Absolute filter_expiration;
128 98
129 /** 99 /**
130 * When should try next connection attempt?
131 */
132 struct GNUNET_TIME_Absolute next_connect_attempt;
133
134 /**
135 * ID of task we use to wait for the time to send the next HELLO 100 * ID of task we use to wait for the time to send the next HELLO
136 * to this peer. 101 * to this peer.
137 */ 102 */
138 struct GNUNET_SCHEDULER_Task * hello_delay_task; 103 struct GNUNET_SCHEDULER_Task *hello_delay_task;
139 104
140 /** 105 /**
141 * Task for issuing GNUNET_TRANSPORT_try_connect for this peer. 106 * Handle for our connectivity suggestion for this peer.
142 */ 107 */
143 struct GNUNET_SCHEDULER_Task * attempt_connect_task; 108 struct GNUNET_ATS_ConnectivitySuggestHandle *sh;
144 109
145 /** 110 /**
146 * ID of task we use to clear peers from the greylist. 111 * How much would we like to connect to this peer?
147 */ 112 */
148 struct GNUNET_SCHEDULER_Task * greylist_clean_task; 113 uint32_t strength;
149
150 /**
151 * How often have we tried so far?
152 */
153 unsigned int connect_attempts;
154 114
155 /** 115 /**
156 * Is this peer listed here because he is a friend? 116 * Is this peer listed here because he is a friend?
@@ -177,16 +137,21 @@ static struct GNUNET_PEERINFO_NotifyContext *peerinfo_notify;
177static const struct GNUNET_CONFIGURATION_Handle *cfg; 137static const struct GNUNET_CONFIGURATION_Handle *cfg;
178 138
179/** 139/**
180 * Handle to the core API. 140 * Handle to the CORE service.
181 */ 141 */
182static struct GNUNET_CORE_Handle *handle; 142static struct GNUNET_CORE_Handle *handle;
183 143
184/** 144/**
185 * Handle to the transport API. 145 * Handle to the TRANSPORT service.
186 */ 146 */
187static struct GNUNET_TRANSPORT_Handle *transport; 147static struct GNUNET_TRANSPORT_Handle *transport;
188 148
189/** 149/**
150 * Handle to the ATS service.
151 */
152static struct GNUNET_ATS_ConnectivityHandle *ats;
153
154/**
190 * Identity of this peer. 155 * Identity of this peer.
191 */ 156 */
192static struct GNUNET_PeerIdentity my_identity; 157static struct GNUNET_PeerIdentity my_identity;
@@ -194,7 +159,7 @@ static struct GNUNET_PeerIdentity my_identity;
194/** 159/**
195 * All of our friends, all of our current neighbours and all peers for 160 * All of our friends, all of our current neighbours and all peers for
196 * which we have HELLOs. So pretty much everyone. Maps peer identities 161 * which we have HELLOs. So pretty much everyone. Maps peer identities
197 * to 'struct Peer *' values. 162 * to `struct Peer *` values.
198 */ 163 */
199static struct GNUNET_CONTAINER_MultiPeerMap *peers; 164static struct GNUNET_CONTAINER_MultiPeerMap *peers;
200 165
@@ -209,14 +174,10 @@ static struct GNUNET_STATISTICS_Handle *stats;
209static struct GNUNET_TRANSPORT_Blacklist *blacklist; 174static struct GNUNET_TRANSPORT_Blacklist *blacklist;
210 175
211/** 176/**
212 * When can we next ask transport to create a connection? 177 * Task scheduled to asynchronously reconsider adding/removing
213 */ 178 * peer connectivity suggestions.
214static struct GNUNET_TIME_Absolute next_connect_attempt;
215
216/**
217 * Task scheduled to try to add peers.
218 */ 179 */
219static struct GNUNET_SCHEDULER_Task * add_task; 180static struct GNUNET_SCHEDULER_Task *add_task;
220 181
221/** 182/**
222 * Flag to disallow non-friend connections (pure F2F mode). 183 * Flag to disallow non-friend connections (pure F2F mode).
@@ -252,17 +213,22 @@ static unsigned int friend_count;
252 * 213 *
253 * @param cls closure 214 * @param cls closure
254 * @param pid peer to approve or disapprove 215 * @param pid peer to approve or disapprove
255 * @return GNUNET_OK if the connection is allowed 216 * @return #GNUNET_OK if the connection is allowed
256 */ 217 */
257static int 218static int
258blacklist_check (void *cls, const struct GNUNET_PeerIdentity *pid) 219blacklist_check (void *cls,
220 const struct GNUNET_PeerIdentity *pid)
259{ 221{
260 struct Peer *pos; 222 struct Peer *pos;
261 223
262 pos = GNUNET_CONTAINER_multipeermap_get (peers, pid); 224 pos = GNUNET_CONTAINER_multipeermap_get (peers,
263 if ((pos != NULL) && (pos->is_friend == GNUNET_YES)) 225 pid);
226 if ( (NULL != pos) &&
227 (GNUNET_YES == pos->is_friend))
264 return GNUNET_OK; 228 return GNUNET_OK;
265 GNUNET_STATISTICS_update (stats, gettext_noop ("# peers blacklisted"), 1, 229 GNUNET_STATISTICS_update (stats,
230 gettext_noop ("# peers blacklisted"),
231 1,
266 GNUNET_NO); 232 GNUNET_NO);
267 return GNUNET_SYSERR; 233 return GNUNET_SYSERR;
268} 234}
@@ -275,7 +241,7 @@ blacklist_check (void *cls, const struct GNUNET_PeerIdentity *pid)
275static void 241static void
276whitelist_peers () 242whitelist_peers ()
277{ 243{
278 if (blacklist != NULL) 244 if (NULL != blacklist)
279 { 245 {
280 GNUNET_TRANSPORT_blacklist_cancel (blacklist); 246 GNUNET_TRANSPORT_blacklist_cancel (blacklist);
281 blacklist = NULL; 247 blacklist = NULL;
@@ -284,213 +250,108 @@ whitelist_peers ()
284 250
285 251
286/** 252/**
287 * Check if an additional connection from the given peer is allowed.
288 *
289 * @param peer connection to check
290 * @return GNUNET_OK if the connection is allowed
291 */
292static int
293is_connection_allowed (struct Peer *peer)
294{
295 if (0 ==
296 memcmp (&my_identity, &peer->pid, sizeof (struct GNUNET_PeerIdentity)))
297 return GNUNET_SYSERR; /* disallow connections to self */
298 if (peer->is_friend)
299 return GNUNET_OK;
300 if (GNUNET_YES == friends_only)
301 {
302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
303 "Determined that `%s' is not allowed to connect (not a friend)\n",
304 GNUNET_i2s (&peer->pid));
305 return GNUNET_SYSERR;
306 }
307 if (friend_count >= minimum_friend_count)
308 return GNUNET_OK;
309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
310 "Determined that `%s' is not allowed to connect (not enough connected friends)\n",
311 GNUNET_i2s (&peer->pid));
312 return GNUNET_SYSERR;
313}
314
315
316/**
317 * Free all resources associated with the given peer. 253 * Free all resources associated with the given peer.
318 * 254 *
319 * @param cls closure (not used) 255 * @param cls closure (not used)
320 * @param pid identity of the peer 256 * @param pid identity of the peer
321 * @param value peer to free 257 * @param value peer to free
322 * @return GNUNET_YES (always: continue to iterate) 258 * @return #GNUNET_YES (always: continue to iterate)
323 */ 259 */
324static int 260static int
325free_peer (void *cls, const struct GNUNET_PeerIdentity * pid, void *value) 261free_peer (void *cls,
262 const struct GNUNET_PeerIdentity * pid,
263 void *value)
326{ 264{
327 struct Peer *pos = value; 265 struct Peer *pos = value;
328 266
329 GNUNET_break (GNUNET_NO == pos->is_connected); 267 GNUNET_break (GNUNET_NO == pos->is_connected);
330 GNUNET_break (GNUNET_OK == 268 GNUNET_break (GNUNET_OK ==
331 GNUNET_CONTAINER_multipeermap_remove (peers, pid, pos)); 269 GNUNET_CONTAINER_multipeermap_remove (peers,
332 if (pos->hello_req != NULL) 270 pid,
271 pos));
272 if (NULL != pos->hello_req)
273 {
333 GNUNET_CORE_notify_transmit_ready_cancel (pos->hello_req); 274 GNUNET_CORE_notify_transmit_ready_cancel (pos->hello_req);
334 if (pos->hello_delay_task != NULL) 275 pos->hello_req = NULL;
276 }
277 if (NULL != pos->hello_delay_task)
278 {
335 GNUNET_SCHEDULER_cancel (pos->hello_delay_task); 279 GNUNET_SCHEDULER_cancel (pos->hello_delay_task);
336 if (pos->attempt_connect_task != NULL) 280 pos->hello_delay_task = NULL;
337 GNUNET_SCHEDULER_cancel (pos->attempt_connect_task); 281 }
338 if (pos->greylist_clean_task != NULL) 282 if (NULL != pos->sh)
339 GNUNET_SCHEDULER_cancel (pos->greylist_clean_task); 283 {
340 GNUNET_free_non_null (pos->hello); 284 GNUNET_ATS_connectivity_suggest_cancel (pos->sh);
341 if (pos->filter != NULL) 285 pos->sh = NULL;
286 }
287 if (NULL != pos->hello)
288 {
289 GNUNET_free_non_null (pos->hello);
290 pos->hello = NULL;
291 }
292 if (NULL != pos->filter)
293 {
342 GNUNET_CONTAINER_bloomfilter_free (pos->filter); 294 GNUNET_CONTAINER_bloomfilter_free (pos->filter);
295 pos->filter = NULL;
296 }
343 GNUNET_free (pos); 297 GNUNET_free (pos);
344 return GNUNET_YES; 298 return GNUNET_YES;
345} 299}
346 300
347 301
348/** 302/**
349 * Discard peer entries for greylisted peers 303 * Recalculate how much we want to be connected to the specified peer
350 * where the greylisting has expired. 304 * and let ATS know about the result.
351 * 305 *
352 * @param cls 'struct Peer' to greylist 306 * @param pos peer to consider connecting to
353 * @param tc scheduler context
354 */
355static void
356remove_from_greylist (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
357
358
359/**
360 * Try to connect to the specified peer.
361 *
362 * @param pos peer to connect to
363 */ 307 */
364static void 308static void
365attempt_connect (struct Peer *pos) 309attempt_connect (struct Peer *pos)
366{ 310{
367 struct GNUNET_TIME_Relative rem; 311 uint32_t strength;
368 312
369 if ((connection_count >= target_connection_count) && 313 if (0 ==
370 (friend_count >= minimum_friend_count)) 314 memcmp (&my_identity,
371 return; 315 &pos->pid,
372 if (GNUNET_YES == pos->is_connected) 316 sizeof (struct GNUNET_PeerIdentity)))
373 return; 317 return; /* This is myself, nothing to do. */
374 if (GNUNET_OK != is_connection_allowed (pos)) 318 if (connection_count < target_connection_count)
375 return; 319 strength = 1;
376 if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).rel_value_us > 0)
377 return;
378 if (GNUNET_YES == pos->is_friend)
379 rem = GREYLIST_AFTER_ATTEMPT_FRIEND;
380 else
381 rem = GREYLIST_AFTER_ATTEMPT;
382 rem = GNUNET_TIME_relative_multiply (rem, connection_count);
383 rem = GNUNET_TIME_relative_divide (rem, target_connection_count);
384 if (pos->connect_attempts > 30)
385 pos->connect_attempts = 30;
386 else 320 else
387 pos->connect_attempts ++; 321 strength = 0;
388 rem = GNUNET_TIME_relative_multiply (rem, 1 << pos->connect_attempts); 322 if ( (friend_count < minimum_friend_count) ||
389 rem = GNUNET_TIME_relative_max (rem, GREYLIST_AFTER_ATTEMPT_MIN); 323 (GNUNET_YES == friends_only) )
390 rem = GNUNET_TIME_relative_min (rem, GREYLIST_AFTER_ATTEMPT_MAX);
391 pos->greylisted_until = GNUNET_TIME_relative_to_absolute (rem);
392
393 pos->next_connect_attempt = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
394 GNUNET_TIME_relative_multiply (MAX_CONNECT_FREQUENCY_DELAY, pos->connect_attempts));
395 pos->next_connect_attempt = GNUNET_TIME_absolute_min (pos->next_connect_attempt,
396 GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), MIN_CONNECT_FREQUENCY_DELAY));
397
398 if (pos->greylist_clean_task != NULL)
399 GNUNET_SCHEDULER_cancel (pos->greylist_clean_task);
400 pos->greylist_clean_task =
401 GNUNET_SCHEDULER_add_delayed (rem, &remove_from_greylist, pos);
402 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking to connect to `%s'\n",
403 GNUNET_i2s (&pos->pid));
404 GNUNET_STATISTICS_update (stats,
405 gettext_noop
406 ("# connect requests issued to transport"), 1,
407 GNUNET_NO);
408 GNUNET_TRANSPORT_try_connect (transport, &pos->pid, NULL, NULL);
409}
410
411
412/**
413 * Try to connect to the specified peer.
414 *
415 * @param cls peer to connect to
416 * @param tc scheduler context
417 */
418static void
419do_attempt_connect (void *cls,
420 const struct GNUNET_SCHEDULER_TaskContext *tc)
421{
422 struct Peer *pos = cls;
423 struct GNUNET_TIME_Relative delay;
424
425 pos->attempt_connect_task = NULL;
426 if (GNUNET_YES == pos->is_connected)
427 return;
428
429 /* Try next connection attempt, when:
430 * - topology allows the next transport connection attempt
431 * and
432 * - the next connection event for this peer is allowed
433 */
434 delay = GNUNET_TIME_relative_max (GNUNET_TIME_absolute_get_remaining (next_connect_attempt),
435 GNUNET_TIME_absolute_get_remaining (pos->next_connect_attempt));
436
437 if (delay.rel_value_us > 0)
438 {
439 pos->attempt_connect_task = GNUNET_SCHEDULER_add_delayed (delay,
440 &do_attempt_connect,
441 pos);
442 return;
443 }
444 next_connect_attempt = GNUNET_TIME_relative_to_absolute (MAX_CONNECT_FREQUENCY_DELAY);
445 attempt_connect (pos);
446}
447
448
449/**
450 * Schedule a task to try to connect to the specified peer.
451 *
452 * @param pos peer to connect to
453 */
454static void
455schedule_attempt_connect (struct Peer *pos)
456{
457 if (NULL != pos->attempt_connect_task)
458 return;
459 pos->attempt_connect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (next_connect_attempt),
460 &do_attempt_connect,
461 pos);
462}
463
464
465/**
466 * Discard peer entries for greylisted peers
467 * where the greylisting has expired.
468 *
469 * @param cls 'struct Peer' to greylist
470 * @param tc scheduler context
471 */
472static void
473remove_from_greylist (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
474{
475 struct Peer *pos = cls;
476 struct GNUNET_TIME_Relative rem;
477
478 pos->greylist_clean_task = NULL;
479 rem = GNUNET_TIME_absolute_get_remaining (pos->greylisted_until);
480 if (0 == rem.rel_value_us)
481 { 324 {
482 schedule_attempt_connect (pos); 325 if (pos->is_friend)
326 strength += 10; /* urgently needed */
327 else
328 strength = 0; /* disallowed */
483 } 329 }
484 else 330 if (pos->is_friend)
331 strength *= 2; /* friends always count more */
332 if (pos->is_connected)
333 strength *= 2; /* existing connections preferred */
334 if (strength == pos->strength)
335 return; /* nothing to do */
336 if (NULL != pos->sh)
485 { 337 {
486 pos->greylist_clean_task = 338 GNUNET_ATS_connectivity_suggest_cancel (pos->sh);
487 GNUNET_SCHEDULER_add_delayed (rem, &remove_from_greylist, pos); 339 pos->sh = NULL;
488 } 340 }
489 if ((GNUNET_NO == pos->is_friend) && (GNUNET_NO == pos->is_connected) && 341 pos->strength = strength;
490 (NULL == pos->hello)) 342 if (0 != strength)
491 { 343 {
492 free_peer (NULL, &pos->pid, pos); 344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
493 return; 345 "Asking to connect to `%s' with strength %u\n",
346 GNUNET_i2s (&pos->pid),
347 (unsigned int) strength);
348 GNUNET_STATISTICS_update (stats,
349 gettext_noop ("# connect requests issued to ATS"),
350 1,
351 GNUNET_NO);
352 pos->sh = GNUNET_ATS_connectivity_suggest (ats,
353 &pos->pid,
354 strength);
494 } 355 }
495} 356}
496 357
@@ -505,21 +366,24 @@ remove_from_greylist (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
505 */ 366 */
506static struct Peer * 367static struct Peer *
507make_peer (const struct GNUNET_PeerIdentity *peer, 368make_peer (const struct GNUNET_PeerIdentity *peer,
508 const struct GNUNET_HELLO_Message *hello, int is_friend) 369 const struct GNUNET_HELLO_Message *hello,
370 int is_friend)
509{ 371{
510 struct Peer *ret; 372 struct Peer *ret;
511 373
512 ret = GNUNET_new (struct Peer); 374 ret = GNUNET_new (struct Peer);
513 ret->pid = *peer; 375 ret->pid = *peer;
514 ret->is_friend = is_friend; 376 ret->is_friend = is_friend;
515 ret->next_connect_attempt = GNUNET_TIME_absolute_get(); 377 if (NULL != hello)
516 if (hello != NULL)
517 { 378 {
518 ret->hello = GNUNET_malloc (GNUNET_HELLO_size (hello)); 379 ret->hello = GNUNET_malloc (GNUNET_HELLO_size (hello));
519 memcpy (ret->hello, hello, GNUNET_HELLO_size (hello)); 380 memcpy (ret->hello,
381 hello,
382 GNUNET_HELLO_size (hello));
520 } 383 }
521 GNUNET_break (GNUNET_OK == 384 GNUNET_break (GNUNET_OK ==
522 GNUNET_CONTAINER_multipeermap_put (peers, peer, 385 GNUNET_CONTAINER_multipeermap_put (peers,
386 peer,
523 ret, 387 ret,
524 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 388 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
525 return ret; 389 return ret;
@@ -548,7 +412,9 @@ setup_filter (struct Peer *peer)
548 GNUNET_TIME_relative_to_absolute 412 GNUNET_TIME_relative_to_absolute
549 (HELLO_ADVERTISEMENT_MIN_REPEAT_FREQUENCY); 413 (HELLO_ADVERTISEMENT_MIN_REPEAT_FREQUENCY);
550 /* never send a peer its own HELLO */ 414 /* never send a peer its own HELLO */
551 GNUNET_CRYPTO_hash (&peer->pid, sizeof (struct GNUNET_PeerIdentity), &hc); 415 GNUNET_CRYPTO_hash (&peer->pid,
416 sizeof (struct GNUNET_PeerIdentity),
417 &hc);
552 GNUNET_CONTAINER_bloomfilter_add (peer->filter, &hc); 418 GNUNET_CONTAINER_bloomfilter_add (peer->filter, &hc);
553} 419}
554 420
@@ -556,17 +422,19 @@ setup_filter (struct Peer *peer)
556/** 422/**
557 * Function to fill send buffer with HELLO. 423 * Function to fill send buffer with HELLO.
558 * 424 *
559 * @param cls 'struct Peer' of the target peer 425 * @param cls `struct Peer` of the target peer
560 * @param size number of bytes available in @a buf 426 * @param size number of bytes available in @a buf
561 * @param buf where the callee should write the message 427 * @param buf where the callee should write the message
562 * @return number of bytes written to @a buf 428 * @return number of bytes written to @a buf
563 */ 429 */
564static size_t 430static size_t
565hello_advertising_ready (void *cls, size_t size, void *buf); 431hello_advertising_ready (void *cls,
432 size_t size,
433 void *buf);
566 434
567 435
568/** 436/**
569 * Closure for 'find_advertisable_hello'. 437 * Closure for #find_advertisable_hello().
570 */ 438 */
571struct FindAdvHelloContext 439struct FindAdvHelloContext
572{ 440{
@@ -596,10 +464,12 @@ struct FindAdvHelloContext
596 * @param cls closure 464 * @param cls closure
597 * @param pid identity of a peer 465 * @param pid identity of a peer
598 * @param value 'struct Peer*' for the peer we are considering 466 * @param value 'struct Peer*' for the peer we are considering
599 * @return GNUNET_YES (continue iteration) 467 * @return #GNUNET_YES (continue iteration)
600 */ 468 */
601static int 469static int
602find_advertisable_hello (void *cls, const struct GNUNET_PeerIdentity * pid, void *value) 470find_advertisable_hello (void *cls,
471 const struct GNUNET_PeerIdentity *pid,
472 void *value)
603{ 473{
604 struct FindAdvHelloContext *fah = cls; 474 struct FindAdvHelloContext *fah = cls;
605 struct Peer *pos = value; 475 struct Peer *pos = value;
@@ -639,7 +509,8 @@ find_advertisable_hello (void *cls, const struct GNUNET_PeerIdentity * pid, void
639 * @param tc task context 509 * @param tc task context
640 */ 510 */
641static void 511static void
642schedule_next_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 512schedule_next_hello (void *cls,
513 const struct GNUNET_SCHEDULER_TaskContext *tc)
643{ 514{
644 struct Peer *pl = cls; 515 struct Peer *pl = cls;
645 struct FindAdvHelloContext fah; 516 struct FindAdvHelloContext fah;
@@ -657,9 +528,13 @@ schedule_next_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
657 fah.result = NULL; 528 fah.result = NULL;
658 fah.max_size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1; 529 fah.max_size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1;
659 fah.next_adv = GNUNET_TIME_UNIT_FOREVER_REL; 530 fah.next_adv = GNUNET_TIME_UNIT_FOREVER_REL;
660 GNUNET_CONTAINER_multipeermap_iterate (peers, &find_advertisable_hello, &fah); 531 GNUNET_CONTAINER_multipeermap_iterate (peers,
532 &find_advertisable_hello,
533 &fah);
661 pl->hello_delay_task = 534 pl->hello_delay_task =
662 GNUNET_SCHEDULER_add_delayed (fah.next_adv, &schedule_next_hello, pl); 535 GNUNET_SCHEDULER_add_delayed (fah.next_adv,
536 &schedule_next_hello,
537 pl);
663 if (fah.result == NULL) 538 if (fah.result == NULL)
664 return; 539 return;
665 next_want = GNUNET_HELLO_size (fah.result->hello); 540 next_want = GNUNET_HELLO_size (fah.result->hello);
@@ -682,13 +557,15 @@ schedule_next_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
682 * and recalculate when we should send HELLOs to it based 557 * and recalculate when we should send HELLOs to it based
683 * on our current state (something changed!). 558 * on our current state (something changed!).
684 * 559 *
685 * @param cls closure, 'struct Peer' to skip, or NULL 560 * @param cls closure `struct Peer` to skip, or NULL
686 * @param pid identity of a peer 561 * @param pid identity of a peer
687 * @param value 'struct Peer*' for the peer 562 * @param value `struct Peer *` for the peer
688 * @return GNUNET_YES (always) 563 * @return #GNUNET_YES (always)
689 */ 564 */
690static int 565static int
691reschedule_hellos (void *cls, const struct GNUNET_PeerIdentity * pid, void *value) 566reschedule_hellos (void *cls,
567 const struct GNUNET_PeerIdentity *pid,
568 void *value)
692{ 569{
693 struct Peer *peer = value; 570 struct Peer *peer = value;
694 struct Peer *skip = cls; 571 struct Peer *skip = cls;
@@ -720,43 +597,51 @@ reschedule_hellos (void *cls, const struct GNUNET_PeerIdentity * pid, void *valu
720 * @param peer peer identity this notification is about 597 * @param peer peer identity this notification is about
721 */ 598 */
722static void 599static void
723connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer) 600connect_notify (void *cls,
601 const struct GNUNET_PeerIdentity *peer)
724{ 602{
725 struct Peer *pos; 603 struct Peer *pos;
726 604
727 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 605 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
728 "Core told us that we are connecting to `%s'\n", 606 "Core told us that we are connecting to `%s'\n",
729 GNUNET_i2s (peer)); 607 GNUNET_i2s (peer));
730 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) 608 if (0 == memcmp (&my_identity,
609 peer,
610 sizeof (struct GNUNET_PeerIdentity)))
731 return; 611 return;
732 612
733 connection_count++; 613 connection_count++;
734 GNUNET_STATISTICS_set (stats, gettext_noop ("# peers connected"), 614 GNUNET_STATISTICS_set (stats,
735 connection_count, GNUNET_NO); 615 gettext_noop ("# peers connected"),
736 pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); 616 connection_count,
617 GNUNET_NO);
618 pos = GNUNET_CONTAINER_multipeermap_get (peers,
619 peer);
737 if (NULL == pos) 620 if (NULL == pos)
738 { 621 {
739 pos = make_peer (peer, NULL, GNUNET_NO); 622 pos = make_peer (peer,
740 GNUNET_break (GNUNET_OK == is_connection_allowed (pos)); 623 NULL,
624 GNUNET_NO);
741 } 625 }
742 else 626 else
743 { 627 {
744 GNUNET_assert (GNUNET_NO == pos->is_connected); 628 GNUNET_assert (GNUNET_NO == pos->is_connected);
745 pos->greylisted_until.abs_value_us = 0; /* remove greylisting */
746 } 629 }
747 pos->is_connected = GNUNET_YES; 630 pos->is_connected = GNUNET_YES;
748 pos->connect_attempts = 0; /* re-set back-off factor */
749 pos->next_connect_attempt = GNUNET_TIME_absolute_get(); /* re-set back-off factor */
750 if (pos->is_friend) 631 if (pos->is_friend)
751 { 632 {
752 if ((friend_count == minimum_friend_count - 1) &&
753 (GNUNET_YES != friends_only))
754 whitelist_peers ();
755 friend_count++; 633 friend_count++;
756 GNUNET_STATISTICS_set (stats, gettext_noop ("# friends connected"), 634 if ( (friend_count == minimum_friend_count) &&
757 friend_count, GNUNET_NO); 635 (GNUNET_YES != friends_only) )
636 whitelist_peers ();
637 GNUNET_STATISTICS_set (stats,
638 gettext_noop ("# friends connected"),
639 friend_count,
640 GNUNET_NO);
758 } 641 }
759 reschedule_hellos (NULL, peer, pos); 642 reschedule_hellos (NULL,
643 peer,
644 pos);
760} 645}
761 646
762 647
@@ -765,15 +650,17 @@ connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer)
765 * 650 *
766 * @param cls closure, not used 651 * @param cls closure, not used
767 * @param pid identity of a peer 652 * @param pid identity of a peer
768 * @param value 'struct Peer*' for the peer 653 * @param value `struct Peer *` for the peer
769 * @return GNUNET_YES (continue to iterate) 654 * @return #GNUNET_YES (continue to iterate)
770 */ 655 */
771static int 656static int
772try_add_peers (void *cls, const struct GNUNET_PeerIdentity * pid, void *value) 657try_add_peers (void *cls,
658 const struct GNUNET_PeerIdentity *pid,
659 void *value)
773{ 660{
774 struct Peer *pos = value; 661 struct Peer *pos = value;
775 662
776 schedule_attempt_connect (pos); 663 attempt_connect (pos);
777 return GNUNET_YES; 664 return GNUNET_YES;
778} 665}
779 666
@@ -785,11 +672,14 @@ try_add_peers (void *cls, const struct GNUNET_PeerIdentity * pid, void *value)
785 * @param tc scheduler context 672 * @param tc scheduler context
786 */ 673 */
787static void 674static void
788add_peer_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 675add_peer_task (void *cls,
676 const struct GNUNET_SCHEDULER_TaskContext *tc)
789{ 677{
790 add_task = NULL; 678 add_task = NULL;
791 679
792 GNUNET_CONTAINER_multipeermap_iterate (peers, &try_add_peers, NULL); 680 GNUNET_CONTAINER_multipeermap_iterate (peers,
681 &try_add_peers,
682 NULL);
793} 683}
794 684
795 685
@@ -800,11 +690,14 @@ add_peer_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
800 * @param peer peer identity this notification is about 690 * @param peer peer identity this notification is about
801 */ 691 */
802static void 692static void
803disconnect_notify (void *cls, const struct GNUNET_PeerIdentity *peer) 693disconnect_notify (void *cls,
694 const struct GNUNET_PeerIdentity *peer)
804{ 695{
805 struct Peer *pos; 696 struct Peer *pos;
806 697
807 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) 698 if (0 == memcmp (&my_identity,
699 peer,
700 sizeof (struct GNUNET_PeerIdentity)))
808 return; 701 return;
809 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 702 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
810 "Core told us that we disconnected from `%s'\n", 703 "Core told us that we disconnected from `%s'\n",
@@ -815,7 +708,7 @@ disconnect_notify (void *cls, const struct GNUNET_PeerIdentity *peer)
815 GNUNET_break (0); 708 GNUNET_break (0);
816 return; 709 return;
817 } 710 }
818 if (pos->is_connected != GNUNET_YES) 711 if (GNUNET_YES != pos->is_connected)
819 { 712 {
820 GNUNET_break (0); 713 GNUNET_break (0);
821 return; 714 return;
@@ -832,20 +725,28 @@ disconnect_notify (void *cls, const struct GNUNET_PeerIdentity *peer)
832 GNUNET_SCHEDULER_cancel (pos->hello_delay_task); 725 GNUNET_SCHEDULER_cancel (pos->hello_delay_task);
833 pos->hello_delay_task = NULL; 726 pos->hello_delay_task = NULL;
834 } 727 }
835 GNUNET_STATISTICS_set (stats, gettext_noop ("# peers connected"), 728 GNUNET_STATISTICS_set (stats,
836 connection_count, GNUNET_NO); 729 gettext_noop ("# peers connected"),
730 connection_count,
731 GNUNET_NO);
837 if (pos->is_friend) 732 if (pos->is_friend)
838 { 733 {
839 friend_count--; 734 friend_count--;
840 GNUNET_STATISTICS_set (stats, gettext_noop ("# friends connected"), 735 GNUNET_STATISTICS_set (stats,
841 friend_count, GNUNET_NO); 736 gettext_noop ("# friends connected"),
737 friend_count,
738 GNUNET_NO);
842 } 739 }
843 if (((connection_count < target_connection_count) || 740 if ( ( (connection_count < target_connection_count) ||
844 (friend_count < minimum_friend_count)) && 741 (friend_count < minimum_friend_count)) &&
845 (NULL == add_task)) 742 (NULL == add_task) )
846 add_task = GNUNET_SCHEDULER_add_now (&add_peer_task, NULL); 743 add_task = GNUNET_SCHEDULER_add_now (&add_peer_task,
847 if ((friend_count < minimum_friend_count) && (blacklist == NULL)) 744 NULL);
848 blacklist = GNUNET_TRANSPORT_blacklist (cfg, &blacklist_check, NULL); 745 if ( (friend_count < minimum_friend_count) &&
746 (NULL == blacklist))
747 blacklist = GNUNET_TRANSPORT_blacklist (cfg,
748 &blacklist_check,
749 NULL);
849} 750}
850 751
851 752
@@ -855,10 +756,11 @@ disconnect_notify (void *cls, const struct GNUNET_PeerIdentity *peer)
855 * @param cls flag that we will set if we see any addresses 756 * @param cls flag that we will set if we see any addresses
856 * @param address the address of the peer 757 * @param address the address of the peer
857 * @param expiration when will the given address expire 758 * @param expiration when will the given address expire
858 * @return GNUNET_SYSERR always, to terminate iteration 759 * @return #GNUNET_SYSERR always, to terminate iteration
859 */ 760 */
860static int 761static int
861address_iterator (void *cls, const struct GNUNET_HELLO_Address *address, 762address_iterator (void *cls,
763 const struct GNUNET_HELLO_Address *address,
862 struct GNUNET_TIME_Absolute expiration) 764 struct GNUNET_TIME_Absolute expiration)
863{ 765{
864 int *flag = cls; 766 int *flag = cls;
@@ -889,30 +791,39 @@ consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
889 GNUNET_break (0); 791 GNUNET_break (0);
890 return; 792 return;
891 } 793 }
892 if (0 == memcmp (&pid, &my_identity, sizeof (struct GNUNET_PeerIdentity))) 794 if (0 == memcmp (&pid,
795 &my_identity,
796 sizeof (struct GNUNET_PeerIdentity)))
893 return; /* that's me! */ 797 return; /* that's me! */
894 have_address = GNUNET_NO; 798 have_address = GNUNET_NO;
895 GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &address_iterator, 799 GNUNET_HELLO_iterate_addresses (hello,
800 GNUNET_NO,
801 &address_iterator,
896 &have_address); 802 &have_address);
897 if (GNUNET_NO == have_address) 803 if (GNUNET_NO == have_address)
898 return; /* no point in advertising this one... */ 804 return; /* no point in advertising this one... */
899 peer = GNUNET_CONTAINER_multipeermap_get (peers, &pid); 805 peer = GNUNET_CONTAINER_multipeermap_get (peers, &pid);
900 if (NULL == peer) 806 if (NULL == peer)
901 { 807 {
902 peer = make_peer (&pid, hello, GNUNET_NO); 808 peer = make_peer (&pid,
809 hello,
810 GNUNET_NO);
903 } 811 }
904 else if (peer->hello != NULL) 812 else if (NULL != peer->hello)
905 { 813 {
906 dt = GNUNET_HELLO_equals (peer->hello, hello, GNUNET_TIME_absolute_get ()); 814 dt = GNUNET_HELLO_equals (peer->hello,
815 hello,
816 GNUNET_TIME_absolute_get ());
907 if (dt.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) 817 if (dt.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
908 return; /* nothing new here */ 818 return; /* nothing new here */
909 } 819 }
910 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 820 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
911 "Found `%s' from peer `%s' for advertising\n", "HELLO", 821 "Found HELLO from peer `%s' for advertising\n",
912 GNUNET_i2s (&pid)); 822 GNUNET_i2s (&pid));
913 if (peer->hello != NULL) 823 if (NULL != peer->hello)
914 { 824 {
915 nh = GNUNET_HELLO_merge (peer->hello, hello); 825 nh = GNUNET_HELLO_merge (peer->hello,
826 hello);
916 GNUNET_free (peer->hello); 827 GNUNET_free (peer->hello);
917 peer->hello = nh; 828 peer->hello = nh;
918 } 829 }
@@ -920,14 +831,21 @@ consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
920 { 831 {
921 size = GNUNET_HELLO_size (hello); 832 size = GNUNET_HELLO_size (hello);
922 peer->hello = GNUNET_malloc (size); 833 peer->hello = GNUNET_malloc (size);
923 memcpy (peer->hello, hello, size); 834 memcpy (peer->hello,
835 hello,
836 size);
924 } 837 }
925 if (peer->filter != NULL) 838 if (NULL != peer->filter)
839 {
926 GNUNET_CONTAINER_bloomfilter_free (peer->filter); 840 GNUNET_CONTAINER_bloomfilter_free (peer->filter);
841 peer->filter = NULL;
842 }
927 setup_filter (peer); 843 setup_filter (peer);
928 /* since we have a new HELLO to pick from, re-schedule all 844 /* since we have a new HELLO to pick from, re-schedule all
929 * HELLO requests that are not bound by the HELLO send rate! */ 845 * HELLO requests that are not bound by the HELLO send rate! */
930 GNUNET_CONTAINER_multipeermap_iterate (peers, &reschedule_hellos, peer); 846 GNUNET_CONTAINER_multipeermap_iterate (peers,
847 &reschedule_hellos,
848 peer);
931} 849}
932 850
933 851
@@ -941,64 +859,60 @@ consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
941 * @param err_msg NULL if successful, otherwise contains error message 859 * @param err_msg NULL if successful, otherwise contains error message
942 */ 860 */
943static void 861static void
944process_peer (void *cls, const struct GNUNET_PeerIdentity *peer, 862process_peer (void *cls,
945 const struct GNUNET_HELLO_Message *hello, const char *err_msg) 863 const struct GNUNET_PeerIdentity *peer,
864 const struct GNUNET_HELLO_Message *hello,
865 const char *err_msg)
946{ 866{
947 struct Peer *pos; 867 struct Peer *pos;
948 868
949 if (err_msg != NULL) 869 if (NULL != err_msg)
950 { 870 {
951 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 871 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
952 _("Error in communication with PEERINFO service: %s\n"), 872 _("Error in communication with PEERINFO service: %s\n"),
953 err_msg); 873 err_msg);
954 GNUNET_PEERINFO_notify_cancel (peerinfo_notify); 874 GNUNET_PEERINFO_notify_cancel (peerinfo_notify);
955 peerinfo_notify = GNUNET_PEERINFO_notify (cfg, GNUNET_NO, &process_peer, NULL); 875 peerinfo_notify = GNUNET_PEERINFO_notify (cfg,
876 GNUNET_NO,
877 &process_peer,
878 NULL);
956 return; 879 return;
957 } 880 }
958 GNUNET_assert (peer != NULL); 881 GNUNET_assert (NULL != peer);
959 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) 882 if (0 == memcmp (&my_identity,
883 peer,
884 sizeof (struct GNUNET_PeerIdentity)))
960 return; /* that's me! */ 885 return; /* that's me! */
961 if (hello == NULL) 886 if (NULL == hello)
962 { 887 {
963 /* free existing HELLO, if any */ 888 /* free existing HELLO, if any */
964 pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); 889 pos = GNUNET_CONTAINER_multipeermap_get (peers,
890 peer);
965 if (NULL != pos) 891 if (NULL != pos)
966 { 892 {
967 GNUNET_free_non_null (pos->hello); 893 GNUNET_free_non_null (pos->hello);
968 pos->hello = NULL; 894 pos->hello = NULL;
969 if (pos->filter != NULL) 895 if (NULL != pos->filter)
970 { 896 {
971 GNUNET_CONTAINER_bloomfilter_free (pos->filter); 897 GNUNET_CONTAINER_bloomfilter_free (pos->filter);
972 pos->filter = NULL; 898 pos->filter = NULL;
973 } 899 }
974 if ((GNUNET_NO == pos->is_connected) && (GNUNET_NO == pos->is_friend) && 900 if ( (GNUNET_NO == pos->is_connected) &&
975 (0 == 901 (GNUNET_NO == pos->is_friend) )
976 GNUNET_TIME_absolute_get_remaining (pos-> 902 free_peer (NULL,
977 greylisted_until).rel_value_us)) 903 &pos->pid,
978 free_peer (NULL, &pos->pid, pos); 904 pos);
979 } 905 }
980 return; 906 return;
981 } 907 }
982 consider_for_advertising (hello); 908 consider_for_advertising (hello);
983 pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); 909 pos = GNUNET_CONTAINER_multipeermap_get (peers,
984 if (pos == NULL) 910 peer);
985 pos = make_peer (peer, hello, GNUNET_NO); 911 if (NULL == pos)
986 GNUNET_assert (NULL != pos); 912 pos = make_peer (peer,
987 if (GNUNET_YES == pos->is_connected) 913 hello,
988 { 914 GNUNET_NO);
989 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Already connected to peer `%s'\n", 915 attempt_connect (pos);
990 GNUNET_i2s (peer));
991 return;
992 }
993 if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).rel_value_us > 0)
994 {
995 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Already tried peer `%s' recently\n",
996 GNUNET_i2s (peer));
997 return; /* peer still greylisted */
998 }
999 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Considering connecting to peer `%s'\n",
1000 GNUNET_i2s (peer));
1001 schedule_attempt_connect (pos);
1002} 916}
1003 917
1004 918
@@ -1016,8 +930,7 @@ core_init (void *cls,
1016 if (NULL == my_id) 930 if (NULL == my_id)
1017 { 931 {
1018 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 932 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1019 _ 933 _("Failed to connect to core service, can not manage topology!\n"));
1020 ("Failed to connect to core service, can not manage topology!\n"));
1021 GNUNET_SCHEDULER_shutdown (); 934 GNUNET_SCHEDULER_shutdown ();
1022 return; 935 return;
1023 } 936 }
@@ -1025,8 +938,10 @@ core_init (void *cls,
1025 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 938 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1026 "I am peer `%s'\n", 939 "I am peer `%s'\n",
1027 GNUNET_i2s (my_id)); 940 GNUNET_i2s (my_id));
1028 peerinfo_notify = GNUNET_PEERINFO_notify (cfg, GNUNET_NO, 941 peerinfo_notify = GNUNET_PEERINFO_notify (cfg,
1029 &process_peer, NULL); 942 GNUNET_NO,
943 &process_peer,
944 NULL);
1030} 945}
1031 946
1032 947
@@ -1043,7 +958,9 @@ handle_friend (void *cls,
1043 unsigned int *entries_found = cls; 958 unsigned int *entries_found = cls;
1044 struct Peer *fl; 959 struct Peer *fl;
1045 960
1046 if (0 == memcmp (pid, &my_identity, sizeof (struct GNUNET_PeerIdentity))) 961 if (0 == memcmp (pid,
962 &my_identity,
963 sizeof (struct GNUNET_PeerIdentity)))
1047 { 964 {
1048 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 965 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1049 _("Found myself `%s' in friend list (useless, ignored)\n"), 966 _("Found myself `%s' in friend list (useless, ignored)\n"),
@@ -1072,19 +989,23 @@ read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
1072 &handle_friend, 989 &handle_friend,
1073 &entries_found)) 990 &entries_found))
1074 { 991 {
1075 if ((friends_only) || (minimum_friend_count > 0)) 992 if ( (GNUNET_YES == friends_only) ||
993 (minimum_friend_count > 0))
1076 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 994 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1077 _("Encountered errors parsing friends list!\n")); 995 _("Encountered errors parsing friends list!\n"));
1078 } 996 }
1079 GNUNET_STATISTICS_update (stats, gettext_noop ("# friends in configuration"), 997 GNUNET_STATISTICS_update (stats,
1080 entries_found, GNUNET_NO); 998 gettext_noop ("# friends in configuration"),
1081 if ((minimum_friend_count > entries_found) && (friends_only == GNUNET_NO)) 999 entries_found,
1000 GNUNET_NO);
1001 if ( (minimum_friend_count > entries_found) &&
1002 (GNUNET_NO == friends_only) )
1082 { 1003 {
1083 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1004 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1084 _("Fewer friends specified than required by minimum friend count. Will only connect to friends.\n")); 1005 _("Fewer friends specified than required by minimum friend count. Will only connect to friends.\n"));
1085 } 1006 }
1086 if ((minimum_friend_count > target_connection_count) && 1007 if ( (minimum_friend_count > target_connection_count) &&
1087 (friends_only == GNUNET_NO)) 1008 (GNUNET_NO == friends_only))
1088 { 1009 {
1089 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1010 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1090 _("More friendly connections required than target total number of connections.\n")); 1011 _("More friendly connections required than target total number of connections.\n"));
@@ -1100,42 +1021,51 @@ read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
1100 * @param other the other peer involved (sender or receiver, NULL 1021 * @param other the other peer involved (sender or receiver, NULL
1101 * for loopback messages where we are both sender and receiver) 1022 * for loopback messages where we are both sender and receiver)
1102 * @param message the actual HELLO message 1023 * @param message the actual HELLO message
1103 * @return GNUNET_OK to keep the connection open, 1024 * @return #GNUNET_OK to keep the connection open,
1104 * GNUNET_SYSERR to close it (signal serious error) 1025 * #GNUNET_SYSERR to close it (signal serious error)
1105 */ 1026 */
1106static int 1027static int
1107handle_encrypted_hello (void *cls, const struct GNUNET_PeerIdentity *other, 1028handle_encrypted_hello (void *cls,
1029 const struct GNUNET_PeerIdentity *other,
1108 const struct GNUNET_MessageHeader *message) 1030 const struct GNUNET_MessageHeader *message)
1109{ 1031{
1110 struct Peer *peer; 1032 struct Peer *peer;
1111 struct GNUNET_PeerIdentity pid; 1033 struct GNUNET_PeerIdentity pid;
1112 1034
1113 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received encrypted `%s' from peer `%s'", 1035 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1114 "HELLO", GNUNET_i2s (other)); 1036 "Received encrypted HELLO from peer `%s'",
1037 GNUNET_i2s (other));
1115 if (GNUNET_OK != 1038 if (GNUNET_OK !=
1116 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) message, &pid)) 1039 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) message, &pid))
1117 { 1040 {
1118 GNUNET_break_op (0); 1041 GNUNET_break_op (0);
1119 return GNUNET_SYSERR; 1042 return GNUNET_SYSERR;
1120 } 1043 }
1121 GNUNET_STATISTICS_update (stats, gettext_noop ("# HELLO messages received"), 1044 GNUNET_STATISTICS_update (stats,
1122 1, GNUNET_NO); 1045 gettext_noop ("# HELLO messages received"),
1046 1,
1047 GNUNET_NO);
1123 peer = GNUNET_CONTAINER_multipeermap_get (peers, &pid); 1048 peer = GNUNET_CONTAINER_multipeermap_get (peers, &pid);
1124 if (NULL == peer) 1049 if (NULL == peer)
1125 { 1050 {
1126 if ((GNUNET_YES == friends_only) || (friend_count < minimum_friend_count)) 1051 if ( (GNUNET_YES == friends_only) ||
1052 (friend_count < minimum_friend_count) )
1127 return GNUNET_OK; 1053 return GNUNET_OK;
1128 } 1054 }
1129 else 1055 else
1130 { 1056 {
1131 if ((GNUNET_YES != peer->is_friend) && (GNUNET_YES == friends_only)) 1057 if ( (GNUNET_YES != peer->is_friend) &&
1058 (GNUNET_YES == friends_only) )
1132 return GNUNET_OK; 1059 return GNUNET_OK;
1133 if ((GNUNET_YES != peer->is_friend) && 1060 if ((GNUNET_YES != peer->is_friend) &&
1134 (friend_count < minimum_friend_count)) 1061 (friend_count < minimum_friend_count))
1135 return GNUNET_OK; 1062 return GNUNET_OK;
1136 } 1063 }
1137 if (transport != NULL) 1064 if (NULL != transport)
1138 GNUNET_TRANSPORT_offer_hello (transport, message, NULL, NULL); 1065 GNUNET_TRANSPORT_offer_hello (transport,
1066 message,
1067 NULL,
1068 NULL);
1139 return GNUNET_OK; 1069 return GNUNET_OK;
1140} 1070}
1141 1071
@@ -1143,13 +1073,15 @@ handle_encrypted_hello (void *cls, const struct GNUNET_PeerIdentity *other,
1143/** 1073/**
1144 * Function to fill send buffer with HELLO. 1074 * Function to fill send buffer with HELLO.
1145 * 1075 *
1146 * @param cls 'struct Peer' of the target peer 1076 * @param cls `struct Peer` of the target peer
1147 * @param size number of bytes available in buf 1077 * @param size number of bytes available in buf
1148 * @param buf where the callee should write the message 1078 * @param buf where the callee should write the message
1149 * @return number of bytes written to buf 1079 * @return number of bytes written to buf
1150 */ 1080 */
1151static size_t 1081static size_t
1152hello_advertising_ready (void *cls, size_t size, void *buf) 1082hello_advertising_ready (void *cls,
1083 size_t size,
1084 void *buf)
1153{ 1085{
1154 struct Peer *pl = cls; 1086 struct Peer *pl = cls;
1155 struct FindAdvHelloContext fah; 1087 struct FindAdvHelloContext fah;
@@ -1163,16 +1095,24 @@ hello_advertising_ready (void *cls, size_t size, void *buf)
1163 fah.result = NULL; 1095 fah.result = NULL;
1164 fah.max_size = size; 1096 fah.max_size = size;
1165 fah.next_adv = GNUNET_TIME_UNIT_FOREVER_REL; 1097 fah.next_adv = GNUNET_TIME_UNIT_FOREVER_REL;
1166 GNUNET_CONTAINER_multipeermap_iterate (peers, &find_advertisable_hello, &fah); 1098 GNUNET_CONTAINER_multipeermap_iterate (peers,
1099 &find_advertisable_hello,
1100 &fah);
1167 want = 0; 1101 want = 0;
1168 if (fah.result != NULL) 1102 if (NULL != fah.result)
1169 { 1103 {
1170 want = GNUNET_HELLO_size (fah.result->hello); 1104 want = GNUNET_HELLO_size (fah.result->hello);
1171 GNUNET_assert (want <= size); 1105 GNUNET_assert (want <= size);
1172 memcpy (buf, fah.result->hello, want); 1106 memcpy (buf,
1173 GNUNET_CRYPTO_hash (&pl->pid, sizeof (struct GNUNET_PeerIdentity), &hc); 1107 fah.result->hello,
1174 GNUNET_CONTAINER_bloomfilter_add (fah.result->filter, &hc); 1108 want);
1175 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' with %u bytes", "HELLO", 1109 GNUNET_CRYPTO_hash (&pl->pid,
1110 sizeof (struct GNUNET_PeerIdentity),
1111 &hc);
1112 GNUNET_CONTAINER_bloomfilter_add (fah.result->filter,
1113 &hc);
1114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1115 "Sending HELLO with %u bytes",
1176 (unsigned int) want); 1116 (unsigned int) want);
1177 GNUNET_STATISTICS_update (stats, 1117 GNUNET_STATISTICS_update (stats,
1178 gettext_noop ("# HELLO messages gossipped"), 1, 1118 gettext_noop ("# HELLO messages gossipped"), 1,
@@ -1196,16 +1136,20 @@ hello_advertising_ready (void *cls, size_t size, void *buf)
1196 * @param tc scheduler context 1136 * @param tc scheduler context
1197 */ 1137 */
1198static void 1138static void
1199cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 1139cleaning_task (void *cls,
1140 const struct GNUNET_SCHEDULER_TaskContext *tc)
1200{ 1141{
1201 if (NULL != peerinfo_notify) 1142 if (NULL != peerinfo_notify)
1202 { 1143 {
1203 GNUNET_PEERINFO_notify_cancel (peerinfo_notify); 1144 GNUNET_PEERINFO_notify_cancel (peerinfo_notify);
1204 peerinfo_notify = NULL; 1145 peerinfo_notify = NULL;
1205 } 1146 }
1206 GNUNET_TRANSPORT_disconnect (transport); 1147 if (NULL != transport)
1207 transport = NULL; 1148 {
1208 if (handle != NULL) 1149 GNUNET_TRANSPORT_disconnect (transport);
1150 transport = NULL;
1151 }
1152 if (NULL != handle)
1209 { 1153 {
1210 GNUNET_CORE_disconnect (handle); 1154 GNUNET_CORE_disconnect (handle);
1211 handle = NULL; 1155 handle = NULL;
@@ -1216,10 +1160,17 @@ cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1216 GNUNET_SCHEDULER_cancel (add_task); 1160 GNUNET_SCHEDULER_cancel (add_task);
1217 add_task = NULL; 1161 add_task = NULL;
1218 } 1162 }
1219 GNUNET_CONTAINER_multipeermap_iterate (peers, &free_peer, NULL); 1163 GNUNET_CONTAINER_multipeermap_iterate (peers,
1164 &free_peer,
1165 NULL);
1220 GNUNET_CONTAINER_multipeermap_destroy (peers); 1166 GNUNET_CONTAINER_multipeermap_destroy (peers);
1221 peers = NULL; 1167 peers = NULL;
1222 if (stats != NULL) 1168 if (NULL != ats)
1169 {
1170 GNUNET_ATS_connectivity_done (ats);
1171 ats = NULL;
1172 }
1173 if (NULL != stats)
1223 { 1174 {
1224 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 1175 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
1225 stats = NULL; 1176 stats = NULL;
@@ -1250,27 +1201,42 @@ run (void *cls,
1250 cfg = c; 1201 cfg = c;
1251 stats = GNUNET_STATISTICS_create ("topology", cfg); 1202 stats = GNUNET_STATISTICS_create ("topology", cfg);
1252 friends_only = 1203 friends_only =
1253 GNUNET_CONFIGURATION_get_value_yesno (cfg, "TOPOLOGY", "FRIENDS-ONLY"); 1204 GNUNET_CONFIGURATION_get_value_yesno (cfg,
1205 "TOPOLOGY",
1206 "FRIENDS-ONLY");
1254 if (GNUNET_OK != 1207 if (GNUNET_OK !=
1255 GNUNET_CONFIGURATION_get_value_number (cfg, "TOPOLOGY", "MINIMUM-FRIENDS", 1208 GNUNET_CONFIGURATION_get_value_number (cfg,
1209 "TOPOLOGY",
1210 "MINIMUM-FRIENDS",
1256 &opt)) 1211 &opt))
1257 opt = 0; 1212 opt = 0;
1258 minimum_friend_count = (unsigned int) opt; 1213 minimum_friend_count = (unsigned int) opt;
1259 if (GNUNET_OK != 1214 if (GNUNET_OK !=
1260 GNUNET_CONFIGURATION_get_value_number (cfg, "TOPOLOGY", 1215 GNUNET_CONFIGURATION_get_value_number (cfg,
1261 "TARGET-CONNECTION-COUNT", &opt)) 1216 "TOPOLOGY",
1217 "TARGET-CONNECTION-COUNT",
1218 &opt))
1262 opt = 16; 1219 opt = 16;
1263 target_connection_count = (unsigned int) opt; 1220 target_connection_count = (unsigned int) opt;
1264 peers = GNUNET_CONTAINER_multipeermap_create (target_connection_count * 2, GNUNET_NO); 1221 peers = GNUNET_CONTAINER_multipeermap_create (target_connection_count * 2,
1265 1222 GNUNET_NO);
1266 if ((friends_only == GNUNET_YES) || (minimum_friend_count > 0)) 1223 read_friends_file (cfg);
1267 read_friends_file (cfg);
1268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1269 "Topology would like %u connections with at least %u friends\n", 1225 "Topology would like %u connections with at least %u friends\n",
1270 target_connection_count, minimum_friend_count); 1226 target_connection_count,
1271 if ((friend_count < minimum_friend_count) && (blacklist == NULL)) 1227 minimum_friend_count);
1272 blacklist = GNUNET_TRANSPORT_blacklist (cfg, &blacklist_check, NULL); 1228 if ( (friend_count < minimum_friend_count) &&
1273 transport = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, NULL, NULL, NULL); 1229 (NULL == blacklist))
1230 blacklist = GNUNET_TRANSPORT_blacklist (cfg,
1231 &blacklist_check,
1232 NULL);
1233 ats = GNUNET_ATS_connectivity_init (cfg);
1234 transport = GNUNET_TRANSPORT_connect (cfg,
1235 NULL,
1236 NULL,
1237 NULL,
1238 NULL,
1239 NULL);
1274 handle = 1240 handle =
1275 GNUNET_CORE_connect (cfg, NULL, 1241 GNUNET_CORE_connect (cfg, NULL,
1276 &core_init, 1242 &core_init,
@@ -1279,19 +1245,22 @@ run (void *cls,
1279 NULL, GNUNET_NO, 1245 NULL, GNUNET_NO,
1280 NULL, GNUNET_NO, 1246 NULL, GNUNET_NO,
1281 handlers); 1247 handlers);
1282 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleaning_task, 1248 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1249 &cleaning_task,
1283 NULL); 1250 NULL);
1284 if (NULL == transport) 1251 if (NULL == transport)
1285 { 1252 {
1286 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1253 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1287 _("Failed to connect to `%s' service.\n"), "transport"); 1254 _("Failed to connect to `%s' service.\n"),
1255 "transport");
1288 GNUNET_SCHEDULER_shutdown (); 1256 GNUNET_SCHEDULER_shutdown ();
1289 return; 1257 return;
1290 } 1258 }
1291 if (NULL == handle) 1259 if (NULL == handle)
1292 { 1260 {
1293 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1261 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1294 _("Failed to connect to `%s' service.\n"), "core"); 1262 _("Failed to connect to `%s' service.\n"),
1263 "core");
1295 GNUNET_SCHEDULER_shutdown (); 1264 GNUNET_SCHEDULER_shutdown ();
1296 return; 1265 return;
1297 } 1266 }
@@ -1318,9 +1287,9 @@ main (int argc, char *const *argv)
1318 1287
1319 ret = 1288 ret =
1320 (GNUNET_OK == 1289 (GNUNET_OK ==
1321 GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-topology", 1290 GNUNET_PROGRAM_run (argc, argv,
1322 _ 1291 "gnunet-daemon-topology",
1323 ("GNUnet topology control (maintaining P2P cadet and F2F constraints)"), 1292 _("GNUnet topology control"),
1324 options, &run, NULL)) ? 0 : 1; 1293 options, &run, NULL)) ? 0 : 1;
1325 GNUNET_free ((void*) argv); 1294 GNUNET_free ((void*) argv);
1326 return ret; 1295 return ret;