3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
23 * @file cadet/gnunet-service-cadet-new_peer.c
24 * @brief Information we track per peer.
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
29 #include "gnunet_util_lib.h"
30 #include "gnunet_signatures.h"
31 #include "gnunet_transport_service.h"
32 #include "gnunet_ats_service.h"
33 #include "gnunet_core_service.h"
34 #include "gnunet_statistics_service.h"
35 #include "cadet_protocol.h"
36 #include "cadet_path.h"
37 #include "gnunet-service-cadet-new.h"
38 #include "gnunet-service-cadet-new_dht.h"
39 #include "gnunet-service-cadet-new_peer.h"
40 #include "gnunet-service-cadet-new_tunnels.h"
43 * How long do we wait until tearing down an idle peer?
45 #define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
48 * Struct containing all information regarding a given peer
55 struct GNUNET_PeerIdentity pid;
58 * Last time we heard from this peer
60 struct GNUNET_TIME_Absolute last_contact;
63 * Array of DLLs of paths traversing the peer, organized by the
64 * offset of the peer on the larger path.
66 struct CadetPeerPathEntry **path_heads;
69 * Array of DLL of paths traversing the peer, organized by the
70 * offset of the peer on the larger path.
72 struct CadetPeerPathEntry **path_tails;
75 * MIN-heap of paths ending at this peer. Ordered by desirability.
77 struct GNUNET_CONTAINER_Heap *path_heap;
80 * Handle to stop the DHT search for paths to this peer
82 struct GCD_search_handle *search_h;
85 * Task to stop the DHT search for paths to this peer
87 struct GNUNET_SCHEDULER_Task *search_delayedXXX;
90 * Task to destroy this entry.
92 struct GNUNET_SCHEDULER_Task *destroy_task;
95 * Tunnel to this peer, if any.
97 struct CadetTunnel *t;
100 * Connections that go through this peer; indexed by tid.
102 struct GNUNET_CONTAINER_MultiHashMap *connections;
105 * Handle for core transmissions.
107 struct GNUNET_MQ_Handle *core_mq;
110 * Hello message of the peer.
112 struct GNUNET_HELLO_Message *hello;
115 * Handle to us offering the HELLO to the transport.
117 struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
120 * Handle to our ATS request asking ATS to suggest an address
121 * to TRANSPORT for this peer (to establish a direct link).
123 struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
126 * How many messages are in the queue to this peer.
128 unsigned int queue_n;
131 * How many paths do we have to this peer (in all @e path_heads DLLs combined).
133 unsigned int num_paths;
136 * Current length of the @e path_heads and @path_tails arrays.
137 * The arrays should be grown as needed.
139 unsigned int path_dll_length;
145 * Get the static string for a peer ID.
149 * @return Static string for it's ID.
152 GCP_2s (const struct CadetPeer *peer)
156 return GNUNET_i2s (&peer->pid);
161 * This peer is no longer be needed, clean it up now.
163 * @param cls peer to clean up
166 destroy_peer (void *cls)
168 struct CadetPeer *cp = cls;
170 cp->destroy_task = NULL;
171 GNUNET_assert (NULL == cp->t);
172 GNUNET_assert (NULL == cp->core_mq);
173 GNUNET_assert (0 == cp->path_dll_length);
174 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (cp->connections));
175 GNUNET_assert (GNUNET_YES ==
176 GNUNET_CONTAINER_multipeermap_remove (peers,
179 GNUNET_free_non_null (cp->path_heads);
180 GNUNET_free_non_null (cp->path_tails);
181 cp->path_dll_length = 0;
182 if (NULL != cp->search_h)
184 GCD_search_stop (cp->search_h);
187 /* FIXME: clean up search_delayedXXX! */
189 GNUNET_CONTAINER_multihashmap_destroy (cp->connections);
190 GNUNET_free_non_null (cp->hello);
191 if (NULL != cp->hello_offer)
193 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
194 cp->hello_offer = NULL;
196 if (NULL != cp->connectivity_suggestion)
198 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
199 cp->connectivity_suggestion = NULL;
206 * Function called to destroy a peer now.
209 * @param pid identity of the peer (unused)
210 * @param value the `struct CadetPeer` to clean up
211 * @return #GNUNET_OK (continue to iterate)
214 destroy_iterator_cb (void *cls,
215 const struct GNUNET_PeerIdentity *pid,
218 struct CadetPeer *cp = value;
220 if (NULL != cp->destroy_task)
222 GNUNET_SCHEDULER_cancel (cp->destroy_task);
223 cp->destroy_task = NULL;
231 * Clean up all entries about all peers.
232 * Must only be called after all tunnels, CORE-connections and
233 * connections are down.
236 GCP_destroy_all_peers ()
238 GNUNET_CONTAINER_multipeermap_iterate (peers,
239 &destroy_iterator_cb,
245 * This peer may no longer be needed, consider cleaning it up.
247 * @param cp peer to clean up
250 consider_peer_destroy (struct CadetPeer *cp)
252 struct GNUNET_TIME_Relative exp;
254 if (NULL != cp->destroy_task)
256 GNUNET_SCHEDULER_cancel (cp->destroy_task);
257 cp->destroy_task = NULL;
260 return; /* still relevant! */
261 if (NULL != cp->core_mq)
262 return; /* still relevant! */
263 if (0 != cp->path_dll_length)
264 return; /* still relevant! */
265 if (0 != GNUNET_CONTAINER_multihashmap_size (cp->connections))
266 return; /* still relevant! */
267 if (NULL != cp->hello)
269 /* relevant only until HELLO expires */
270 exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
271 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
276 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
283 * Add an entry to the DLL of all of the paths that this peer is on.
285 * @param cp peer to modify
286 * @param entry an entry on a path
287 * @param off offset of this peer on the path
290 GCP_path_entry_add (struct CadetPeer *cp,
291 struct CadetPeerPathEntry *entry,
294 if (off >= cp->path_dll_length)
296 unsigned int len = cp->path_dll_length;
298 GNUNET_array_grow (cp->path_heads,
301 GNUNET_array_grow (cp->path_tails,
305 GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
313 * Remove an entry from the DLL of all of the paths that this peer is on.
315 * @param cp peer to modify
316 * @param entry an entry on a path
317 * @param off offset of this peer on the path
320 GCP_path_entry_remove (struct CadetPeer *cp,
321 struct CadetPeerPathEntry *entry,
324 GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
327 GNUNET_assert (0 < cp->num_paths);
333 * Function called when the DHT finds a @a path to the peer (@a cls).
335 * @param cls the `struct CadetPeer`
336 * @param path the path that was found
339 dht_result_cb (void *cls,
340 const struct CadetPeerPath *path)
342 struct CadetPeer *cp = cls;
343 GNUNET_CONTAINER_HeapCostType desirability;
344 struct CadetPeerPath *root;
345 GNUNET_CONTAINER_HeapCostType root_desirability;
347 desirability = GCPP_get_desirability (path);
349 GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
354 root_desirability = 0;
356 if ( (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths) ||
357 (desirability >= root_desirability) )
359 /* Yes, we'd like to add this path, add to our heap */
362 GNUNET_CONTAINER_heap_insert (cp->path_heap,
366 if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
367 2 * DESIRED_CONNECTIONS_PER_TUNNEL)
369 /* Now we have way too many, drop least desirable */
370 root = GNUNET_CONTAINER_heap_remove_root (cp->path_heap);
378 * This peer is now on more "active" duty, activate processes related to it.
380 * @param cp the more-active peer
383 consider_peer_activate (struct CadetPeer *cp)
387 if (NULL != cp->destroy_task)
389 /* It's active, do not destory! */
390 GNUNET_SCHEDULER_cancel (cp->destroy_task);
391 cp->destroy_task = NULL;
393 if ( (0 == GNUNET_CONTAINER_multihashmap_size (cp->connections)) &&
396 /* We're just on a path or directly connected; don't bother too much */
397 if (NULL != cp->connectivity_suggestion)
399 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
400 cp->connectivity_suggestion = NULL;
402 if (NULL != cp->search_h)
404 GCD_search_stop (cp->search_h);
409 if (NULL == cp->core_mq)
411 /* Lacks direct connection, try to create one by querying the DHT */
412 if ( (NULL == cp->search_h) &&
413 (DESIRED_CONNECTIONS_PER_TUNNEL < cp->num_paths) )
415 = GCD_search (&cp->pid,
421 /* Have direct connection, stop DHT search if active */
422 if (NULL != cp->search_h)
424 GCD_search_stop (cp->search_h);
429 /* If we have a tunnel, our urge for connections is much bigger */
430 strength = (NULL != cp->t) ? 32 : 1;
431 if (NULL != cp->connectivity_suggestion)
432 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
433 cp->connectivity_suggestion
434 = GNUNET_ATS_connectivity_suggest (ats_ch,
441 * Retrieve the CadetPeer stucture associated with the
442 * peer. Optionally create one and insert it in the appropriate
443 * structures if the peer is not known yet.
445 * @param peer_id Full identity of the peer.
446 * @param create #GNUNET_YES if a new peer should be created if unknown.
447 * #GNUNET_NO to return NULL if peer is unknown.
448 * @return Existing or newly created peer structure.
449 * NULL if unknown and not requested @a create
452 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
455 struct CadetPeer *cp;
457 cp = GNUNET_CONTAINER_multipeermap_get (peers,
461 if (GNUNET_NO == create)
463 cp = GNUNET_new (struct CadetPeer);
465 cp->connections = GNUNET_CONTAINER_multihashmap_create (32,
467 cp->search_h = NULL; // FIXME: start search immediately!?
468 cp->connectivity_suggestion = NULL; // FIXME: request with ATS!?
470 GNUNET_assert (GNUNET_YES ==
471 GNUNET_CONTAINER_multipeermap_put (peers,
474 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
480 * Obtain the peer identity for a `struct CadetPeer`.
482 * @param cp our peer handle
483 * @param[out] peer_id where to write the peer identity
486 GCP_id (struct CadetPeer *cp,
487 struct GNUNET_PeerIdentity *peer_id)
494 * Iterate over all known peers.
496 * @param iter Iterator.
497 * @param cls Closure for @c iter.
500 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
503 GNUNET_CONTAINER_multipeermap_iterate (peers,
510 * Count the number of known paths toward the peer.
512 * @param peer Peer to get path info.
513 * @return Number of known paths.
516 GCP_count_paths (const struct CadetPeer *peer)
518 return peer->num_paths;
523 * Iterate over the paths to a peer.
525 * @param peer Peer to get path info.
526 * @param callback Function to call for every path.
527 * @param callback_cls Closure for @a callback.
528 * @return Number of iterated paths.
531 GCP_iterate_paths (struct CadetPeer *peer,
532 GCP_PathIterator callback,
535 unsigned int ret = 0;
537 for (unsigned int i=0;i<peer->path_dll_length;i++)
539 for (struct CadetPeerPathEntry *pe = peer->path_heads[i];
544 callback (callback_cls,
556 * Get the tunnel towards a peer.
558 * @param peer Peer to get from.
559 * @param create #GNUNET_YES to create a tunnel if we do not have one
560 * @return Tunnel towards peer.
563 GCP_get_tunnel (struct CadetPeer *peer,
568 if ( (NULL != peer->t) ||
569 (GNUNET_NO == create) )
571 peer->t = GCT_create_tunnel (peer);
572 consider_peer_activate (peer);
578 * We got a HELLO for a @a peer, remember it, and possibly
579 * trigger adequate actions (like trying to connect).
581 * @param peer the peer we got a HELLO for
582 * @param hello the HELLO to remember
585 GCP_set_hello (struct CadetPeer *peer,
586 const struct GNUNET_HELLO_Message *hello)
590 consider_peer_destroy (peer);
595 * The tunnel to the given peer no longer exists, remove it from our
596 * data structures, and possibly clean up the peer itself.
598 * @param peer the peer affected
599 * @param t the dead tunnel
602 GCP_drop_tunnel (struct CadetPeer *peer,
603 struct CadetTunnel *t)
605 GNUNET_assert (peer->t == t);
607 consider_peer_destroy (peer);
611 /* end of gnunet-service-cadet-new_peer.c */