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)
49 * Struct containing all information regarding a given peer
56 struct GNUNET_PeerIdentity pid;
59 * Last time we heard from this peer
61 struct GNUNET_TIME_Absolute last_contact;
64 * Paths to reach the peer, ordered by ascending hop count
66 struct CadetPeerPath *path_head;
69 * Paths to reach the peer, ordered by ascending hop count
71 struct CadetPeerPath *path_tail;
74 * Handle to stop the DHT search for paths to this peer
76 struct GCD_search_handle *search_h;
79 * Task to stop the DHT search for paths to this peer
81 struct GNUNET_SCHEDULER_Task *search_delayed;
84 * Task to destroy this entry.
86 struct GNUNET_SCHEDULER_Task *destroy_task;
89 * Tunnel to this peer, if any.
91 struct CadetTunnel *t;
94 * Connections that go through this peer; indexed by tid.
96 struct GNUNET_CONTAINER_MultiHashMap *connections;
99 * Handle for core transmissions.
101 struct GNUNET_MQ_Handle *core_mq;
104 * Hello message of the peer.
106 struct GNUNET_HELLO_Message *hello;
109 * Handle to us offering the HELLO to the transport.
111 struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
114 * Handle to our ATS request asking ATS to suggest an address
115 * to TRANSPORT for this peer (to establish a direct link).
117 struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
120 * How many messages are in the queue to this peer.
122 unsigned int queue_n;
125 * How many paths do we have to this peer (in the @e path_head DLL).
127 unsigned int num_paths;
133 * Get the static string for a peer ID.
137 * @return Static string for it's ID.
140 GCP_2s (const struct CadetPeer *peer)
144 return GNUNET_i2s (&peer->pid);
149 * This peer is no longer be needed, clean it up now.
151 * @param cls peer to clean up
154 destroy_peer (void *cls)
156 struct CadetPeer *cp = cls;
158 cp->destroy_task = NULL;
159 GNUNET_assert (NULL == cp->t);
160 GNUNET_assert (NULL == cp->core_mq);
161 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (cp->connections));
162 GNUNET_assert (GNUNET_YES ==
163 GNUNET_CONTAINER_multipeermap_remove (peers,
166 /* FIXME: clean up paths! */
167 /* FIXME: clean up search_h! */
168 /* FIXME: clean up search_delayed! */
170 GNUNET_CONTAINER_multihashmap_destroy (cp->connections);
171 GNUNET_free_non_null (cp->hello);
172 if (NULL != cp->hello_offer)
174 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
175 cp->hello_offer = NULL;
177 if (NULL != cp->connectivity_suggestion)
179 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
180 cp->connectivity_suggestion = NULL;
187 * Function called to destroy a peer now.
190 * @param pid identity of the peer (unused)
191 * @param value the `struct CadetPeer` to clean up
192 * @return #GNUNET_OK (continue to iterate)
195 destroy_iterator_cb (void *cls,
196 const struct GNUNET_PeerIdentity *pid,
199 struct CadetPeer *cp = value;
201 if (NULL != cp->destroy_task)
202 GNUNET_SCHEDULER_cancel (cp->destroy_task);
209 * Clean up all entries about all peers.
210 * Must only be called after all tunnels, CORE-connections and
211 * connections are down.
214 GCP_destroy_all_peers ()
216 GNUNET_CONTAINER_multipeermap_iterate (peers,
217 &destroy_iterator_cb,
223 * This peer may no longer be needed, consider cleaning it up.
225 * @param peer peer to clean up
228 consider_peer_destroy (struct CadetPeer *peer)
230 struct GNUNET_TIME_Relative exp;
232 if (NULL != peer->destroy_task)
234 GNUNET_SCHEDULER_cancel (peer->destroy_task);
235 peer->destroy_task = NULL;
238 return; /* still relevant! */
239 if (NULL != peer->core_mq)
240 return; /* still relevant! */
241 if (0 != GNUNET_CONTAINER_multihashmap_size (peer->connections))
242 return; /* still relevant! */
243 if (NULL != peer->hello)
245 /* relevant only until HELLO expires */
246 exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (peer->hello));
247 peer->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
252 peer->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
259 * Function called when the DHT finds a @a path to the peer (@a cls).
261 * @param cls the `struct CadetPeer`
262 * @param path the path that was found
265 dht_result_cb (void *cls,
266 const struct CadetPeerPath *path)
268 struct CadetPeer *peer = cls;
270 // FIXME: handle path!
275 * This peer is now on more "active" duty, activate processes related to it.
277 * @param peer the more-active peer
280 consider_peer_activate (struct CadetPeer *peer)
284 if (NULL != peer->destroy_task)
286 /* It's active, do not destory! */
287 GNUNET_SCHEDULER_cancel (peer->destroy_task);
288 peer->destroy_task = NULL;
290 if (NULL == peer->core_mq)
292 /* Lacks direct connection, try to create one by querying the DHT */
293 if ( (NULL == peer->search_h) &&
294 (DESIRED_CONNECTIONS_PER_TUNNEL < peer->num_paths) )
296 = GCD_search (&peer->pid,
302 /* Have direct connection, stop DHT search if active */
303 if (NULL != peer->search_h)
305 GCD_search_stop (peer->search_h);
306 peer->search_h = NULL;
310 /* If we have a tunnel, our urge for connections is much bigger */
311 strength = (NULL != peer->t) ? 32 : 1;
312 if (NULL != peer->connectivity_suggestion)
313 GNUNET_ATS_connectivity_suggest_cancel (peer->connectivity_suggestion);
314 peer->connectivity_suggestion
315 = GNUNET_ATS_connectivity_suggest (ats_ch,
322 * Retrieve the CadetPeer stucture associated with the
323 * peer. Optionally create one and insert it in the appropriate
324 * structures if the peer is not known yet.
326 * @param peer_id Full identity of the peer.
327 * @param create #GNUNET_YES if a new peer should be created if unknown.
328 * #GNUNET_NO to return NULL if peer is unknown.
329 * @return Existing or newly created peer structure.
330 * NULL if unknown and not requested @a create
333 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
336 struct CadetPeer *cp;
338 cp = GNUNET_CONTAINER_multipeermap_get (peers,
342 if (GNUNET_NO == create)
344 cp = GNUNET_new (struct CadetPeer);
346 cp->connections = GNUNET_CONTAINER_multihashmap_create (32,
348 cp->search_h = NULL; // FIXME: start search immediately!?
349 cp->connectivity_suggestion = NULL; // FIXME: request with ATS!?
351 GNUNET_assert (GNUNET_YES ==
352 GNUNET_CONTAINER_multipeermap_put (peers,
355 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
361 * Obtain the peer identity for a `struct CadetPeer`.
363 * @param cp our peer handle
364 * @param[out] peer_id where to write the peer identity
367 GCP_id (struct CadetPeer *cp,
368 struct GNUNET_PeerIdentity *peer_id)
375 * Create a peer path based on the result of a DHT lookup.
377 * @param get_path path of the get request
378 * @param get_path_length lenght of @a get_path
379 * @param put_path path of the put request
380 * @param put_path_length length of the @a put_path
381 * @return a path through the network
383 struct CadetPeerPath *
384 GCP_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
385 unsigned int get_path_length,
386 const struct GNUNET_PeerIdentity *put_path,
387 unsigned int put_path_length)
389 GNUNET_assert (0); // FIXME: implement!
395 * Iterate over all known peers.
397 * @param iter Iterator.
398 * @param cls Closure for @c iter.
401 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
404 GNUNET_CONTAINER_multipeermap_iterate (peers,
411 * Count the number of known paths toward the peer.
413 * @param peer Peer to get path info.
414 * @return Number of known paths.
417 GCP_count_paths (const struct CadetPeer *peer)
419 return peer->num_paths;
424 * Iterate over the paths to a peer.
426 * @param peer Peer to get path info.
427 * @param callback Function to call for every path.
428 * @param callback_cls Closure for @a callback.
429 * @return Number of iterated paths.
432 GCP_iterate_paths (struct CadetPeer *peer,
433 GCP_PathIterator callback,
436 unsigned int ret = 0;
438 for (struct CadetPeerPath *path = peer->path_head;
443 callback (callback_cls,
454 * Get the tunnel towards a peer.
456 * @param peer Peer to get from.
457 * @param create #GNUNET_YES to create a tunnel if we do not have one
458 * @return Tunnel towards peer.
461 GCP_get_tunnel (struct CadetPeer *peer,
466 if ( (NULL != peer->t) ||
467 (GNUNET_NO == create) )
469 peer->t = GCT_create_tunnel (peer);
470 consider_peer_activate (peer);
476 * We got a HELLO for a @a peer, remember it, and possibly
477 * trigger adequate actions (like trying to connect).
479 * @param peer the peer we got a HELLO for
480 * @param hello the HELLO to remember
483 GCP_set_hello (struct CadetPeer *peer,
484 const struct GNUNET_HELLO_Message *hello)
488 consider_peer_destroy (peer);
493 * The tunnel to the given peer no longer exists, remove it from our
494 * data structures, and possibly clean up the peer itself.
496 * @param peer the peer affected
497 * @param t the dead tunnel
500 GCP_drop_tunnel (struct CadetPeer *peer,
501 struct CadetTunnel *t)
503 GNUNET_assert (peer->t == t);
505 consider_peer_destroy (peer);
509 /* end of gnunet-service-cadet-new_peer.c */