create matching connection objects for inbound connections
[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_connection.h"
39 #include "gnunet-service-cadet-new_dht.h"
40 #include "gnunet-service-cadet-new_peer.h"
41 #include "gnunet-service-cadet-new_paths.h"
42 #include "gnunet-service-cadet-new_tunnels.h"
43
44 /**
45  * How long do we wait until tearing down an idle peer?
46  */
47 #define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
48
49 /**
50  * How long do we keep paths around if we no longer care about the peer?
51  */
52 #define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
53
54
55
56
57 /**
58  * Data structure used to track whom we have to notify about changes
59  * to our message queue.
60  */
61 struct GCP_MessageQueueManager
62 {
63
64   /**
65    * Kept in a DLL.
66    */
67   struct GCP_MessageQueueManager *next;
68
69   /**
70    * Kept in a DLL.
71    */
72   struct GCP_MessageQueueManager *prev;
73
74   /**
75    * Function to call with updated message queue object.
76    */
77   GCP_MessageQueueNotificationCallback cb;
78
79   /**
80    * Closure for @e cb.
81    */
82   void *cb_cls;
83
84   /**
85    * The peer this is for.
86    */
87   struct CadetPeer *cp;
88
89 };
90
91
92 /**
93  * Struct containing all information regarding a given peer
94  */
95 struct CadetPeer
96 {
97   /**
98    * ID of the peer
99    */
100   struct GNUNET_PeerIdentity pid;
101
102   /**
103    * Last time we heard from this peer
104    */
105   struct GNUNET_TIME_Absolute last_contact;
106
107   /**
108    * Array of DLLs of paths traversing the peer, organized by the
109    * offset of the peer on the larger path.
110    */
111   struct CadetPeerPathEntry **path_heads;
112
113   /**
114    * Array of DLL of paths traversing the peer, organized by the
115    * offset of the peer on the larger path.
116    */
117   struct CadetPeerPathEntry **path_tails;
118
119   /**
120    * Notifications to call when @e core_mq changes.
121    */
122   struct GCP_MessageQueueManager *mqm_head;
123
124   /**
125    * Notifications to call when @e core_mq changes.
126    */
127   struct GCP_MessageQueueManager *mqm_tail;
128
129   /**
130    * MIN-heap of paths owned by this peer (they also end at this
131    * peer).  Ordered by desirability.
132    */
133   struct GNUNET_CONTAINER_Heap *path_heap;
134
135   /**
136    * Handle to stop the DHT search for paths to this peer
137    */
138   struct GCD_search_handle *search_h;
139
140   /**
141    * Task to stop the DHT search for paths to this peer
142    */
143   struct GNUNET_SCHEDULER_Task *search_delayedXXX;
144
145   /**
146    * Task to destroy this entry.
147    */
148   struct GNUNET_SCHEDULER_Task *destroy_task;
149
150   /**
151    * Tunnel to this peer, if any.
152    */
153   struct CadetTunnel *t;
154
155   /**
156    * Connections that go through this peer; indexed by tid.
157    */
158   struct GNUNET_CONTAINER_MultiShortmap *connections;
159
160   /**
161    * Handle for core transmissions.
162    */
163   struct GNUNET_MQ_Handle *core_mq;
164
165   /**
166    * Hello message of the peer.
167    */
168   struct GNUNET_HELLO_Message *hello;
169
170   /**
171    * Handle to us offering the HELLO to the transport.
172    */
173   struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
174
175   /**
176    * Handle to our ATS request asking ATS to suggest an address
177    * to TRANSPORT for this peer (to establish a direct link).
178    */
179   struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
180
181   /**
182    * How many messages are in the queue to this peer.
183    */
184   unsigned int queue_n;
185
186   /**
187    * How many paths do we have to this peer (in all @e path_heads DLLs combined).
188    */
189   unsigned int num_paths;
190
191   /**
192    * Current length of the @e path_heads and @path_tails arrays.
193    * The arrays should be grown as needed.
194    */
195   unsigned int path_dll_length;
196
197 };
198
199
200 /**
201  * Get the static string for a peer ID.
202  *
203  * @param peer Peer.
204  *
205  * @return Static string for it's ID.
206  */
207 const char *
208 GCP_2s (const struct CadetPeer *peer)
209 {
210   if (NULL == peer)
211     return "PEER(NULL)";
212   return GNUNET_i2s (&peer->pid);
213 }
214
215
216 /**
217  * This peer is no longer be needed, clean it up now.
218  *
219  * @param cls peer to clean up
220  */
221 static void
222 destroy_peer (void *cls)
223 {
224   struct CadetPeer *cp = cls;
225
226   cp->destroy_task = NULL;
227   GNUNET_assert (NULL == cp->t);
228   GNUNET_assert (NULL == cp->core_mq);
229   GNUNET_assert (0 == cp->path_dll_length);
230   GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
231   GNUNET_assert (GNUNET_YES ==
232                  GNUNET_CONTAINER_multipeermap_remove (peers,
233                                                        &cp->pid,
234                                                        cp));
235   GNUNET_free_non_null (cp->path_heads);
236   GNUNET_free_non_null (cp->path_tails);
237   cp->path_dll_length = 0;
238   if (NULL != cp->search_h)
239   {
240     GCD_search_stop (cp->search_h);
241     cp->search_h = NULL;
242   }
243   /* FIXME: clean up search_delayedXXX! */
244
245   if (NULL != cp->hello_offer)
246   {
247     GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
248     cp->hello_offer = NULL;
249   }
250   if (NULL != cp->connectivity_suggestion)
251   {
252     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
253     cp->connectivity_suggestion = NULL;
254   }
255   GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
256   GNUNET_CONTAINER_heap_destroy (cp->path_heap);
257   GNUNET_free_non_null (cp->hello);
258   /* Peer should not be freed if paths exist; if there are no paths,
259      there ought to be no connections, and without connections, no
260      notifications. Thus we can assert that mqm_head is empty at this
261      point. */
262   GNUNET_assert (NULL == cp->mqm_head);
263   GNUNET_free (cp);
264 }
265
266
267 /**
268  * Get the message queue for peer @a cp.
269  *
270  * @param cp peer to modify
271  * @return message queue (can be NULL)
272  */
273 struct GNUNET_MQ_Handle *
274 GCP_get_mq (struct CadetPeer *cp)
275 {
276   return cp->core_mq;
277 }
278
279
280 /**
281  * Set the message queue to @a mq for peer @a cp and notify watchers.
282  *
283  * @param cp peer to modify
284  * @param mq message queue to set (can be NULL)
285  */
286 void
287 GCP_set_mq (struct CadetPeer *cp,
288             struct GNUNET_MQ_Handle *mq)
289 {
290   cp->core_mq = mq;
291   for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
292        NULL != mqm;
293        mqm = mqm->next)
294     mqm->cb (mqm->cb_cls,
295              mq);
296 }
297
298
299 /**
300  * Send the message in @a env to @a cp.
301  *
302  * @param cp the peer
303  * @param env envelope with the message to send
304  */
305 void
306 GCP_send (struct CadetPeer *cp,
307           struct GNUNET_MQ_Envelope *env)
308 {
309   GNUNET_assert (NULL != cp->core_mq);
310   GNUNET_MQ_send (cp->core_mq,
311                   env);
312 }
313
314
315 /**
316  * Function called to destroy a peer now.
317  *
318  * @param cls NULL
319  * @param pid identity of the peer (unused)
320  * @param value the `struct CadetPeer` to clean up
321  * @return #GNUNET_OK (continue to iterate)
322  */
323 static int
324 destroy_iterator_cb (void *cls,
325                      const struct GNUNET_PeerIdentity *pid,
326                      void *value)
327 {
328   struct CadetPeer *cp = value;
329
330   if (NULL != cp->destroy_task)
331   {
332     GNUNET_SCHEDULER_cancel (cp->destroy_task);
333     cp->destroy_task = NULL;
334   }
335   destroy_peer (cp);
336   return GNUNET_OK;
337 }
338
339
340 /**
341  * Clean up all entries about all peers.
342  * Must only be called after all tunnels, CORE-connections and
343  * connections are down.
344  */
345 void
346 GCP_destroy_all_peers ()
347 {
348   GNUNET_CONTAINER_multipeermap_iterate (peers,
349                                          &destroy_iterator_cb,
350                                          NULL);
351 }
352
353
354 /**
355  * This peer may no longer be needed, consider cleaning it up.
356  *
357  * @param cp peer to clean up
358  */
359 static void
360 consider_peer_destroy (struct CadetPeer *cp);
361
362
363 /**
364  * We really no longere care about a peer, stop hogging memory with paths to it.
365  * Afterwards, see if there is more to be cleaned up about this peer.
366  *
367  * @param cls a `struct CadetPeer`.
368  */
369 static void
370 drop_paths (void *cls)
371 {
372   struct CadetPeer *cp = cls;
373   struct CadetPeerPath *path;
374
375   cp->destroy_task = NULL;
376   while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
377     GCPP_release (path);
378   consider_peer_destroy (cp);
379 }
380
381
382 /**
383  * This peer may no longer be needed, consider cleaning it up.
384  *
385  * @param cp peer to clean up
386  */
387 static void
388 consider_peer_destroy (struct CadetPeer *cp)
389 {
390   struct GNUNET_TIME_Relative exp;
391
392   if (NULL != cp->destroy_task)
393   {
394     GNUNET_SCHEDULER_cancel (cp->destroy_task);
395     cp->destroy_task = NULL;
396   }
397   if (NULL != cp->t)
398     return; /* still relevant! */
399   if (NULL != cp->core_mq)
400     return; /* still relevant! */
401   if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
402     return; /* still relevant! */
403   if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))
404   {
405     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
406                                                      &drop_paths,
407                                                      cp);
408     return;
409   }
410   if (0 < cp->path_dll_length)
411     return; /* still relevant! */
412   if (NULL != cp->hello)
413   {
414     /* relevant only until HELLO expires */
415     exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
416     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
417                                                      &destroy_peer,
418                                                      cp);
419     return;
420   }
421   cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
422                                                    &destroy_peer,
423                                                    cp);
424 }
425
426
427 /**
428  * Add an entry to the DLL of all of the paths that this peer is on.
429  *
430  * @param cp peer to modify
431  * @param entry an entry on a path
432  * @param off offset of this peer on the path
433  */
434 void
435 GCP_path_entry_add (struct CadetPeer *cp,
436                     struct CadetPeerPathEntry *entry,
437                     unsigned int off)
438 {
439   if (off >= cp->path_dll_length)
440   {
441     unsigned int len = cp->path_dll_length;
442
443     GNUNET_array_grow (cp->path_heads,
444                        len,
445                        off + 4);
446     GNUNET_array_grow (cp->path_tails,
447                        cp->path_dll_length,
448                        off + 4);
449   }
450   GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
451                                cp->path_tails[off],
452                                entry);
453   cp->num_paths++;
454
455   /* If we have a tunnel to this peer, tell the tunnel that there is a
456      new path available. */
457   if (NULL != cp->t)
458     GCT_consider_path (cp->t,
459                        entry->path,
460                        off);
461 }
462
463
464 /**
465  * Remove an entry from the DLL of all of the paths that this peer is on.
466  *
467  * @param cp peer to modify
468  * @param entry an entry on a path
469  * @param off offset of this peer on the path
470  */
471 void
472 GCP_path_entry_remove (struct CadetPeer *cp,
473                        struct CadetPeerPathEntry *entry,
474                        unsigned int off)
475 {
476   GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
477                                cp->path_tails[off],
478                                entry);
479   GNUNET_assert (0 < cp->num_paths);
480   cp->num_paths--;
481 }
482
483
484 /**
485  * Try adding a @a path to this @a peer.  If the peer already
486  * has plenty of paths, return NULL.
487  *
488  * @param cp peer to which the @a path leads to
489  * @param path a path looking for an owner; may not be fully initialized yet!
490  * @param off offset of @a cp in @a path
491  * @return NULL if this peer does not care to become a new owner,
492  *         otherwise the node in the peer's path heap for the @a path.
493  */
494 struct GNUNET_CONTAINER_HeapNode *
495 GCP_attach_path (struct CadetPeer *cp,
496                  struct CadetPeerPath *path,
497                  unsigned int off)
498 {
499   GNUNET_CONTAINER_HeapCostType desirability;
500   struct CadetPeerPath *root;
501   GNUNET_CONTAINER_HeapCostType root_desirability;
502   struct GNUNET_CONTAINER_HeapNode *hn;
503
504   /* FIXME: desirability is not yet initialized; tricky! */
505   desirability = GCPP_get_desirability (path);
506   if (GNUNET_NO ==
507       GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
508                                    (void **) &root,
509                                    &root_desirability))
510   {
511     root = NULL;
512     root_desirability = 0;
513   }
514
515   if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
516        (desirability < root_desirability) )
517     return NULL;
518
519   /* Yes, we'd like to add this path, add to our heap */
520   hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
521                                      (void *) cp,
522                                      desirability);
523
524   /* Consider maybe dropping other paths because of the new one */
525   if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
526       2 * DESIRED_CONNECTIONS_PER_TUNNEL)
527   {
528     /* Now we have way too many, drop least desirable UNLESS it is in use!
529        (Note that this intentionally keeps highly desireable, but currently
530        unused paths around in the hope that we might be able to switch, even
531        if the number of paths exceeds the threshold.) */
532     root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
533     if (NULL ==
534         GCPP_get_connection (root,
535                              cp,
536                              GCPP_get_length (root) - 1))
537     {
538       /* Got plenty of paths to this destination, and this is a low-quality
539          one that we don't care, allow it to die. */
540       GNUNET_assert (root ==
541                      GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
542       GCPP_release (root);
543     }
544   }
545   return hn;
546 }
547
548
549 /**
550  * This peer can no longer own @a path as the path
551  * has been extended and a peer further down the line
552  * is now the new owner.
553  *
554  * @param cp old owner of the @a path
555  * @param path path where the ownership is lost
556  * @param hn note in @a cp's path heap that must be deleted
557  */
558 void
559 GCP_detach_path (struct CadetPeer *cp,
560                  struct CadetPeerPath *path,
561                  struct GNUNET_CONTAINER_HeapNode *hn)
562 {
563   GNUNET_assert (path ==
564                  GNUNET_CONTAINER_heap_remove_node (hn));
565 }
566
567
568 /**
569  * Add a @a connection to this @a cp.
570  *
571  * @param cp peer via which the @a connection goes
572  * @param cc the connection to add
573  */
574 void
575 GCP_add_connection (struct CadetPeer *cp,
576                     struct CadetConnection *cc)
577 {
578   GNUNET_assert (GNUNET_OK ==
579                  GNUNET_CONTAINER_multishortmap_put (cp->connections,
580                                                      &GCC_get_id (cc)->connection_of_tunnel,
581                                                      cc,
582                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
583 }
584
585
586 /**
587  * Remove a @a connection that went via this @a cp.
588  *
589  * @param cp peer via which the @a connection went
590  * @param cc the connection to remove
591  */
592 void
593 GCP_remove_connection (struct CadetPeer *cp,
594                        struct CadetConnection *cc)
595 {
596   GNUNET_assert (GNUNET_YES ==
597                  GNUNET_CONTAINER_multishortmap_remove (cp->connections,
598                                                         &GCC_get_id (cc)->connection_of_tunnel,
599                                                         cc));
600 }
601
602
603 /**
604  * This peer is now on more "active" duty, activate processes related to it.
605  *
606  * @param cp the more-active peer
607  */
608 static void
609 consider_peer_activate (struct CadetPeer *cp)
610 {
611   uint32_t strength;
612
613   if (NULL != cp->destroy_task)
614   {
615     /* It's active, do not destory! */
616     GNUNET_SCHEDULER_cancel (cp->destroy_task);
617     cp->destroy_task = NULL;
618   }
619   if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
620        (NULL == cp->t) )
621   {
622     /* We're just on a path or directly connected; don't bother too much */
623     if (NULL != cp->connectivity_suggestion)
624     {
625       GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
626       cp->connectivity_suggestion = NULL;
627     }
628     if (NULL != cp->search_h)
629     {
630       GCD_search_stop (cp->search_h);
631       cp->search_h = NULL;
632     }
633     return;
634   }
635   if (NULL == cp->core_mq)
636   {
637     /* Lacks direct connection, try to create one by querying the DHT */
638     if ( (NULL == cp->search_h) &&
639          (DESIRED_CONNECTIONS_PER_TUNNEL < cp->num_paths) )
640       cp->search_h
641         = GCD_search (&cp->pid);
642   }
643   else
644   {
645     /* Have direct connection, stop DHT search if active */
646     if (NULL != cp->search_h)
647     {
648       GCD_search_stop (cp->search_h);
649       cp->search_h = NULL;
650     }
651   }
652
653   /* If we have a tunnel, our urge for connections is much bigger */
654   strength = (NULL != cp->t) ? 32 : 1;
655   if (NULL != cp->connectivity_suggestion)
656     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
657   cp->connectivity_suggestion
658     = GNUNET_ATS_connectivity_suggest (ats_ch,
659                                        &cp->pid,
660                                        strength);
661 }
662
663
664 /**
665  * Retrieve the CadetPeer stucture associated with the
666  * peer. Optionally create one and insert it in the appropriate
667  * structures if the peer is not known yet.
668  *
669  * @param peer_id Full identity of the peer.
670  * @param create #GNUNET_YES if a new peer should be created if unknown.
671  *               #GNUNET_NO to return NULL if peer is unknown.
672  * @return Existing or newly created peer structure.
673  *         NULL if unknown and not requested @a create
674  */
675 struct CadetPeer *
676 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
677          int create)
678 {
679   struct CadetPeer *cp;
680
681   cp = GNUNET_CONTAINER_multipeermap_get (peers,
682                                           peer_id);
683   if (NULL != cp)
684     return cp;
685   if (GNUNET_NO == create)
686     return NULL;
687   cp = GNUNET_new (struct CadetPeer);
688   cp->pid = *peer_id;
689   cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
690                                                            GNUNET_YES);
691   cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
692   GNUNET_assert (GNUNET_YES ==
693                  GNUNET_CONTAINER_multipeermap_put (peers,
694                                                     &cp->pid,
695                                                     cp,
696                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
697   return cp;
698 }
699
700
701 /**
702  * Obtain the peer identity for a `struct CadetPeer`.
703  *
704  * @param cp our peer handle
705  * @return the peer identity
706  */
707 const struct GNUNET_PeerIdentity *
708 GCP_get_id (struct CadetPeer *cp)
709 {
710   return &cp->pid;
711 }
712
713
714 /**
715  * Iterate over all known peers.
716  *
717  * @param iter Iterator.
718  * @param cls Closure for @c iter.
719  */
720 void
721 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
722                  void *cls)
723 {
724   GNUNET_CONTAINER_multipeermap_iterate (peers,
725                                          iter,
726                                          cls);
727 }
728
729
730 /**
731  * Count the number of known paths toward the peer.
732  *
733  * @param peer Peer to get path info.
734  * @return Number of known paths.
735  */
736 unsigned int
737 GCP_count_paths (const struct CadetPeer *peer)
738 {
739   return peer->num_paths;
740 }
741
742
743 /**
744  * Iterate over the paths to a peer.
745  *
746  * @param peer Peer to get path info.
747  * @param callback Function to call for every path.
748  * @param callback_cls Closure for @a callback.
749  * @return Number of iterated paths.
750  */
751 unsigned int
752 GCP_iterate_paths (struct CadetPeer *peer,
753                    GCP_PathIterator callback,
754                    void *callback_cls)
755 {
756   unsigned int ret = 0;
757
758   for (unsigned int i=0;i<peer->path_dll_length;i++)
759   {
760     for (struct CadetPeerPathEntry *pe = peer->path_heads[i];
761          NULL != pe;
762          pe = pe->next)
763     {
764       if (GNUNET_NO ==
765           callback (callback_cls,
766                     pe->path,
767                     i))
768         return ret;
769       ret++;
770     }
771   }
772   return ret;
773 }
774
775
776 /**
777  * Iterate over the paths to @a peer where
778  * @a peer is at distance @a dist from us.
779  *
780  * @param peer Peer to get path info.
781  * @param dist desired distance of @a peer to us on the path
782  * @param callback Function to call for every path.
783  * @param callback_cls Closure for @a callback.
784  * @return Number of iterated paths.
785  */
786 unsigned int
787 GCP_iterate_paths_at (struct CadetPeer *peer,
788                       unsigned int dist,
789                       GCP_PathIterator callback,
790                       void *callback_cls)
791 {
792   unsigned int ret = 0;
793
794   if (dist<peer->path_dll_length)
795     return 0;
796   for (struct CadetPeerPathEntry *pe = peer->path_heads[dist];
797        NULL != pe;
798        pe = pe->next)
799   {
800     if (GNUNET_NO ==
801         callback (callback_cls,
802                   pe->path,
803                   dist))
804       return ret;
805     ret++;
806   }
807   return ret;
808 }
809
810
811 /**
812  * Get the tunnel towards a peer.
813  *
814  * @param peer Peer to get from.
815  * @param create #GNUNET_YES to create a tunnel if we do not have one
816  * @return Tunnel towards peer.
817  */
818 struct CadetTunnel *
819 GCP_get_tunnel (struct CadetPeer *peer,
820                 int create)
821 {
822   if (NULL == peer)
823     return NULL;
824   if ( (NULL != peer->t) ||
825        (GNUNET_NO == create) )
826     return peer->t;
827   peer->t = GCT_create_tunnel (peer);
828   consider_peer_activate (peer);
829   return peer->t;
830 }
831
832
833 /**
834  * We got a HELLO for a @a peer, remember it, and possibly
835  * trigger adequate actions (like trying to connect).
836  *
837  * @param peer the peer we got a HELLO for
838  * @param hello the HELLO to remember
839  */
840 void
841 GCP_set_hello (struct CadetPeer *peer,
842                const struct GNUNET_HELLO_Message *hello)
843 {
844   /* FIXME: keep HELLO, possibly offer to TRANSPORT... */
845
846   consider_peer_destroy (peer);
847 }
848
849
850 /**
851  * The tunnel to the given peer no longer exists, remove it from our
852  * data structures, and possibly clean up the peer itself.
853  *
854  * @param peer the peer affected
855  * @param t the dead tunnel
856  */
857 void
858 GCP_drop_tunnel (struct CadetPeer *peer,
859                  struct CadetTunnel *t)
860 {
861   GNUNET_assert (peer->t == t);
862   peer->t = NULL;
863   consider_peer_destroy (peer);
864 }
865
866
867 /**
868  * Start message queue change notifications.
869  *
870  * @param cp peer to notify for
871  * @param cb function to call if mq becomes available or unavailable
872  * @param cb_cls closure for @a cb
873  * @return handle to cancel request
874  */
875 struct GCP_MessageQueueManager *
876 GCP_request_mq (struct CadetPeer *cp,
877                 GCP_MessageQueueNotificationCallback cb,
878                 void *cb_cls)
879 {
880   struct GCP_MessageQueueManager *mqm;
881
882   mqm = GNUNET_new (struct GCP_MessageQueueManager);
883   mqm->cb = cb;
884   mqm->cb_cls = cb_cls;
885   mqm->cp = cp;
886   GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
887                                cp->mqm_tail,
888                                mqm);
889   if (NULL != cp->core_mq)
890     cb (cb_cls,
891         cp->core_mq);
892   return mqm;
893 }
894
895
896 /**
897  * Stops message queue change notifications.
898  *
899  * @param mqm handle matching request to cancel
900  */
901 void
902 GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm)
903 {
904   struct CadetPeer *cp = mqm->cp;
905
906   GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
907                                cp->mqm_tail,
908                                mqm);
909   GNUNET_free (mqm);
910 }
911
912
913
914 /* end of gnunet-service-cadet-new_peer.c */