more work on peers, paths and tunnels
[oweals/gnunet.git] / src / cadet / gnunet-service-cadet-new_peer.c
1
2 /*
3      This file is part of GNUnet.
4      Copyright (C) 2001-2017 GNUnet e.V.
5
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.
10
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.
15
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.
20 */
21
22 /**
23  * @file cadet/gnunet-service-cadet-new_peer.c
24  * @brief Information we track per peer.
25  * @author Bartlomiej Polot
26  * @author Christian Grothoff
27  */
28 #include "platform.h"
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_paths.h"
41 #include "gnunet-service-cadet-new_tunnels.h"
42
43 /**
44  * How long do we wait until tearing down an idle peer?
45  */
46 #define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
47
48 /**
49  * How long do we keep paths around if we no longer care about the peer?
50  */
51 #define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
52
53
54 /**
55  * Struct containing all information regarding a given peer
56  */
57 struct CadetPeer
58 {
59   /**
60    * ID of the peer
61    */
62   struct GNUNET_PeerIdentity pid;
63
64   /**
65    * Last time we heard from this peer
66    */
67   struct GNUNET_TIME_Absolute last_contact;
68
69   /**
70    * Array of DLLs of paths traversing the peer, organized by the
71    * offset of the peer on the larger path.
72    */
73   struct CadetPeerPathEntry **path_heads;
74
75   /**
76    * Array of DLL of paths traversing the peer, organized by the
77    * offset of the peer on the larger path.
78    */
79   struct CadetPeerPathEntry **path_tails;
80
81   /**
82    * MIN-heap of paths owned by this peer (they also end at this
83    * peer).  Ordered by desirability.
84    */
85   struct GNUNET_CONTAINER_Heap *path_heap;
86
87   /**
88    * Handle to stop the DHT search for paths to this peer
89    */
90   struct GCD_search_handle *search_h;
91
92   /**
93    * Task to stop the DHT search for paths to this peer
94    */
95   struct GNUNET_SCHEDULER_Task *search_delayedXXX;
96
97   /**
98    * Task to destroy this entry.
99    */
100   struct GNUNET_SCHEDULER_Task *destroy_task;
101
102   /**
103    * Tunnel to this peer, if any.
104    */
105   struct CadetTunnel *t;
106
107   /**
108    * Connections that go through this peer; indexed by tid.
109    */
110   struct GNUNET_CONTAINER_MultiHashMap *connections;
111
112   /**
113    * Handle for core transmissions.
114    */
115   struct GNUNET_MQ_Handle *core_mq;
116
117   /**
118    * Hello message of the peer.
119    */
120   struct GNUNET_HELLO_Message *hello;
121
122   /**
123    * Handle to us offering the HELLO to the transport.
124    */
125   struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
126
127   /**
128    * Handle to our ATS request asking ATS to suggest an address
129    * to TRANSPORT for this peer (to establish a direct link).
130    */
131   struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
132
133   /**
134    * How many messages are in the queue to this peer.
135    */
136   unsigned int queue_n;
137
138   /**
139    * How many paths do we have to this peer (in all @e path_heads DLLs combined).
140    */
141   unsigned int num_paths;
142
143   /**
144    * Current length of the @e path_heads and @path_tails arrays.
145    * The arrays should be grown as needed.
146    */
147   unsigned int path_dll_length;
148
149 };
150
151
152 /**
153  * Get the static string for a peer ID.
154  *
155  * @param peer Peer.
156  *
157  * @return Static string for it's ID.
158  */
159 const char *
160 GCP_2s (const struct CadetPeer *peer)
161 {
162   if (NULL == peer)
163     return "PEER(NULL)";
164   return GNUNET_i2s (&peer->pid);
165 }
166
167
168 /**
169  * This peer is no longer be needed, clean it up now.
170  *
171  * @param cls peer to clean up
172  */
173 static void
174 destroy_peer (void *cls)
175 {
176   struct CadetPeer *cp = cls;
177
178   cp->destroy_task = NULL;
179   GNUNET_assert (NULL == cp->t);
180   GNUNET_assert (NULL == cp->core_mq);
181   GNUNET_assert (0 == cp->path_dll_length);
182   GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (cp->connections));
183   GNUNET_assert (GNUNET_YES ==
184                  GNUNET_CONTAINER_multipeermap_remove (peers,
185                                                        &cp->pid,
186                                                        cp));
187   GNUNET_free_non_null (cp->path_heads);
188   GNUNET_free_non_null (cp->path_tails);
189   cp->path_dll_length = 0;
190   if (NULL != cp->search_h)
191   {
192     GCD_search_stop (cp->search_h);
193     cp->search_h = NULL;
194   }
195   /* FIXME: clean up search_delayedXXX! */
196
197   if (NULL != cp->hello_offer)
198   {
199     GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
200     cp->hello_offer = NULL;
201   }
202   if (NULL != cp->connectivity_suggestion)
203   {
204     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
205     cp->connectivity_suggestion = NULL;
206   }
207   GNUNET_CONTAINER_multihashmap_destroy (cp->connections);
208   GNUNET_CONTAINER_heap_destroy (cp->path_heap);
209   GNUNET_free_non_null (cp->hello);
210   GNUNET_free (cp);
211 }
212
213
214 /**
215  * Function called to destroy a peer now.
216  *
217  * @param cls NULL
218  * @param pid identity of the peer (unused)
219  * @param value the `struct CadetPeer` to clean up
220  * @return #GNUNET_OK (continue to iterate)
221  */
222 static int
223 destroy_iterator_cb (void *cls,
224                      const struct GNUNET_PeerIdentity *pid,
225                      void *value)
226 {
227   struct CadetPeer *cp = value;
228
229   if (NULL != cp->destroy_task)
230   {
231     GNUNET_SCHEDULER_cancel (cp->destroy_task);
232     cp->destroy_task = NULL;
233   }
234   destroy_peer (cp);
235   return GNUNET_OK;
236 }
237
238
239 /**
240  * Clean up all entries about all peers.
241  * Must only be called after all tunnels, CORE-connections and
242  * connections are down.
243  */
244 void
245 GCP_destroy_all_peers ()
246 {
247   GNUNET_CONTAINER_multipeermap_iterate (peers,
248                                          &destroy_iterator_cb,
249                                          NULL);
250 }
251
252
253 /**
254  * This peer may no longer be needed, consider cleaning it up.
255  *
256  * @param cp peer to clean up
257  */
258 static void
259 consider_peer_destroy (struct CadetPeer *cp);
260
261
262 /**
263  * We really no longere care about a peer, stop hogging memory with paths to it.
264  * Afterwards, see if there is more to be cleaned up about this peer.
265  *
266  * @param cls a `struct CadetPeer`.
267  */
268 static void
269 drop_paths (void *cls)
270 {
271   struct CadetPeer *cp = cls;
272   struct CadetPeerPath *path;
273
274   cp->destroy_task = NULL;
275   while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
276     GCPP_release (path);
277   consider_peer_destroy (cp);
278 }
279
280
281 /**
282  * This peer may no longer be needed, consider cleaning it up.
283  *
284  * @param cp peer to clean up
285  */
286 static void
287 consider_peer_destroy (struct CadetPeer *cp)
288 {
289   struct GNUNET_TIME_Relative exp;
290
291   if (NULL != cp->destroy_task)
292   {
293     GNUNET_SCHEDULER_cancel (cp->destroy_task);
294     cp->destroy_task = NULL;
295   }
296   if (NULL != cp->t)
297     return; /* still relevant! */
298   if (NULL != cp->core_mq)
299     return; /* still relevant! */
300   if (0 != GNUNET_CONTAINER_multihashmap_size (cp->connections))
301     return; /* still relevant! */
302   if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))
303   {
304     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
305                                                      &drop_paths,
306                                                      cp);
307     return;
308   }
309   if (0 < cp->path_dll_length)
310     return; /* still relevant! */
311   if (NULL != cp->hello)
312   {
313     /* relevant only until HELLO expires */
314     exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
315     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
316                                                      &destroy_peer,
317                                                      cp);
318     return;
319   }
320   cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
321                                                    &destroy_peer,
322                                                    cp);
323 }
324
325
326 /**
327  * Add an entry to the DLL of all of the paths that this peer is on.
328  *
329  * @param cp peer to modify
330  * @param entry an entry on a path
331  * @param off offset of this peer on the path
332  */
333 void
334 GCP_path_entry_add (struct CadetPeer *cp,
335                     struct CadetPeerPathEntry *entry,
336                     unsigned int off)
337 {
338   if (off >= cp->path_dll_length)
339   {
340     unsigned int len = cp->path_dll_length;
341
342     GNUNET_array_grow (cp->path_heads,
343                        len,
344                        off + 4);
345     GNUNET_array_grow (cp->path_tails,
346                        cp->path_dll_length,
347                        off + 4);
348   }
349   GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
350                                cp->path_tails[off],
351                                entry);
352   cp->num_paths++;
353
354   /* If we have a tunnel to this peer, tell the tunnel that there is a
355      new path available. */
356   if (NULL != cp->t)
357     GCT_consider_path (cp->t,
358                        entry->path,
359                        off);
360 }
361
362
363 /**
364  * Remove an entry from the DLL of all of the paths that this peer is on.
365  *
366  * @param cp peer to modify
367  * @param entry an entry on a path
368  * @param off offset of this peer on the path
369  */
370 void
371 GCP_path_entry_remove (struct CadetPeer *cp,
372                        struct CadetPeerPathEntry *entry,
373                        unsigned int off)
374 {
375   GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
376                                cp->path_tails[off],
377                                entry);
378   GNUNET_assert (0 < cp->num_paths);
379   cp->num_paths--;
380 }
381
382
383 /**
384  * Try adding a @a path to this @a peer.  If the peer already
385  * has plenty of paths, return NULL.
386  *
387  * @param cp peer to which the @a path leads to
388  * @param path a path looking for an owner
389  * @return NULL if this peer does not care to become a new owner,
390  *         otherwise the node in the peer's path heap for the @a path.
391  */
392 struct GNUNET_CONTAINER_HeapNode *
393 GCP_attach_path (struct CadetPeer *cp,
394                  struct CadetPeerPath *path)
395 {
396   GNUNET_CONTAINER_HeapCostType desirability;
397   struct CadetPeerPath *root;
398   GNUNET_CONTAINER_HeapCostType root_desirability;
399   struct GNUNET_CONTAINER_HeapNode *hn;
400
401   desirability = GCPP_get_desirability (path);
402   if (GNUNET_NO ==
403       GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
404                                    (void **) &root,
405                                    &root_desirability))
406   {
407     root = NULL;
408     root_desirability = 0;
409   }
410
411   if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
412        (desirability < root_desirability) )
413     return NULL;
414
415   /* Yes, we'd like to add this path, add to our heap */
416   hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
417                                      (void *) cp,
418                                      desirability);
419
420   /* Consider maybe dropping other paths because of the new one */
421   if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
422       2 * DESIRED_CONNECTIONS_PER_TUNNEL)
423   {
424     /* Now we have way too many, drop least desirable UNLESS it is in use!
425        (Note that this intentionally keeps highly desireable, but currently
426        unused paths around in the hope that we might be able to switch, even
427        if the number of paths exceeds the threshold.) */
428     root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
429     if (NULL ==
430         GCPP_get_connection (root,
431                              cp,
432                              GCPP_get_length (root) - 1))
433     {
434       /* Got plenty of paths to this destination, and this is a low-quality
435          one that we don't care, allow it to die. */
436       GNUNET_assert (root ==
437                      GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
438       GCPP_release (root);
439     }
440   }
441   return hn;
442 }
443
444
445 /**
446  * Function called when the DHT finds a @a path to the peer (@a cls).
447  *
448  * @param cls the `struct CadetPeer`
449  * @param path the path that was found
450  */
451 static void
452 dht_result_cb (void *cls,
453                struct CadetPeerPath *path)
454 {
455   struct CadetPeer *cp = cls;
456   struct GNUNET_CONTAINER_HeapNode *hn;
457
458   hn = GCP_attach_path (cp,
459                         path);
460   if (NULL == hn)
461     return;
462   GCPP_acquire (path,
463                 hn);
464 }
465
466
467 /**
468  * This peer is now on more "active" duty, activate processes related to it.
469  *
470  * @param cp the more-active peer
471  */
472 static void
473 consider_peer_activate (struct CadetPeer *cp)
474 {
475   uint32_t strength;
476
477   if (NULL != cp->destroy_task)
478   {
479     /* It's active, do not destory! */
480     GNUNET_SCHEDULER_cancel (cp->destroy_task);
481     cp->destroy_task = NULL;
482   }
483   if ( (0 == GNUNET_CONTAINER_multihashmap_size (cp->connections)) &&
484        (NULL == cp->t) )
485   {
486     /* We're just on a path or directly connected; don't bother too much */
487     if (NULL != cp->connectivity_suggestion)
488     {
489       GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
490       cp->connectivity_suggestion = NULL;
491     }
492     if (NULL != cp->search_h)
493     {
494       GCD_search_stop (cp->search_h);
495       cp->search_h = NULL;
496     }
497     return;
498   }
499   if (NULL == cp->core_mq)
500   {
501     /* Lacks direct connection, try to create one by querying the DHT */
502     if ( (NULL == cp->search_h) &&
503          (DESIRED_CONNECTIONS_PER_TUNNEL < cp->num_paths) )
504       cp->search_h
505         = GCD_search (&cp->pid,
506                       &dht_result_cb,
507                       cp);
508   }
509   else
510   {
511     /* Have direct connection, stop DHT search if active */
512     if (NULL != cp->search_h)
513     {
514       GCD_search_stop (cp->search_h);
515       cp->search_h = NULL;
516     }
517   }
518
519   /* If we have a tunnel, our urge for connections is much bigger */
520   strength = (NULL != cp->t) ? 32 : 1;
521   if (NULL != cp->connectivity_suggestion)
522     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
523   cp->connectivity_suggestion
524     = GNUNET_ATS_connectivity_suggest (ats_ch,
525                                        &cp->pid,
526                                        strength);
527 }
528
529
530 /**
531  * Retrieve the CadetPeer stucture associated with the
532  * peer. Optionally create one and insert it in the appropriate
533  * structures if the peer is not known yet.
534  *
535  * @param peer_id Full identity of the peer.
536  * @param create #GNUNET_YES if a new peer should be created if unknown.
537  *               #GNUNET_NO to return NULL if peer is unknown.
538  * @return Existing or newly created peer structure.
539  *         NULL if unknown and not requested @a create
540  */
541 struct CadetPeer *
542 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
543          int create)
544 {
545   struct CadetPeer *cp;
546
547   cp = GNUNET_CONTAINER_multipeermap_get (peers,
548                                           peer_id);
549   if (NULL != cp)
550     return cp;
551   if (GNUNET_NO == create)
552     return NULL;
553   cp = GNUNET_new (struct CadetPeer);
554   cp->pid = *peer_id;
555   cp->connections = GNUNET_CONTAINER_multihashmap_create (32,
556                                                           GNUNET_YES);
557   cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
558   GNUNET_assert (GNUNET_YES ==
559                  GNUNET_CONTAINER_multipeermap_put (peers,
560                                                     &cp->pid,
561                                                     cp,
562                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
563   return cp;
564 }
565
566
567 /**
568  * Obtain the peer identity for a `struct CadetPeer`.
569  *
570  * @param cp our peer handle
571  * @return the peer identity
572  */
573 const struct GNUNET_PeerIdentity *
574 GCP_get_id (struct CadetPeer *cp)
575 {
576   return &cp->pid;
577 }
578
579
580 /**
581  * Iterate over all known peers.
582  *
583  * @param iter Iterator.
584  * @param cls Closure for @c iter.
585  */
586 void
587 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
588                  void *cls)
589 {
590   GNUNET_CONTAINER_multipeermap_iterate (peers,
591                                          iter,
592                                          cls);
593 }
594
595
596 /**
597  * Count the number of known paths toward the peer.
598  *
599  * @param peer Peer to get path info.
600  * @return Number of known paths.
601  */
602 unsigned int
603 GCP_count_paths (const struct CadetPeer *peer)
604 {
605   return peer->num_paths;
606 }
607
608
609 /**
610  * Iterate over the paths to a peer.
611  *
612  * @param peer Peer to get path info.
613  * @param callback Function to call for every path.
614  * @param callback_cls Closure for @a callback.
615  * @return Number of iterated paths.
616  */
617 unsigned int
618 GCP_iterate_paths (struct CadetPeer *peer,
619                    GCP_PathIterator callback,
620                    void *callback_cls)
621 {
622   unsigned int ret = 0;
623
624   for (unsigned int i=0;i<peer->path_dll_length;i++)
625   {
626     for (struct CadetPeerPathEntry *pe = peer->path_heads[i];
627          NULL != pe;
628          pe = pe->next)
629     {
630       if (GNUNET_NO ==
631           callback (callback_cls,
632                     pe->path,
633                     i))
634         return ret;
635       ret++;
636     }
637   }
638   return ret;
639 }
640
641
642 /**
643  * Get the tunnel towards a peer.
644  *
645  * @param peer Peer to get from.
646  * @param create #GNUNET_YES to create a tunnel if we do not have one
647  * @return Tunnel towards peer.
648  */
649 struct CadetTunnel *
650 GCP_get_tunnel (struct CadetPeer *peer,
651                 int create)
652 {
653   if (NULL == peer)
654     return NULL;
655   if ( (NULL != peer->t) ||
656        (GNUNET_NO == create) )
657     return peer->t;
658   peer->t = GCT_create_tunnel (peer);
659   consider_peer_activate (peer);
660   return peer->t;
661 }
662
663
664 /**
665  * We got a HELLO for a @a peer, remember it, and possibly
666  * trigger adequate actions (like trying to connect).
667  *
668  * @param peer the peer we got a HELLO for
669  * @param hello the HELLO to remember
670  */
671 void
672 GCP_set_hello (struct CadetPeer *peer,
673                const struct GNUNET_HELLO_Message *hello)
674 {
675   /* FIXME: keep HELLO, possibly offer to TRANSPORT... */
676
677   consider_peer_destroy (peer);
678 }
679
680
681 /**
682  * The tunnel to the given peer no longer exists, remove it from our
683  * data structures, and possibly clean up the peer itself.
684  *
685  * @param peer the peer affected
686  * @param t the dead tunnel
687  */
688 void
689 GCP_drop_tunnel (struct CadetPeer *peer,
690                  struct CadetTunnel *t)
691 {
692   GNUNET_assert (peer->t == t);
693   peer->t = NULL;
694   consider_peer_destroy (peer);
695 }
696
697
698 /* end of gnunet-service-cadet-new_peer.c */