towards actual routing...
[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_MultiHashMap *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_multihashmap_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_multihashmap_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  * Set the message queue to @a mq for peer @a cp and notify watchers.
269  *
270  * @param cp peer to modify
271  * @param mq message queue to set (can be NULL)
272  */
273 void
274 GCP_set_mq (struct CadetPeer *cp,
275             struct GNUNET_MQ_Handle *mq)
276 {
277   cp->core_mq = mq;
278   for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
279        NULL != mqm;
280        mqm = mqm->next)
281     mqm->cb (mqm->cb_cls,
282              mq);
283 }
284
285
286 /**
287  * Send the message in @a env to @a cp.
288  *
289  * @param cp the peer
290  * @param env envelope with the message to send
291  */
292 void
293 GCP_send (struct CadetPeer *cp,
294           struct GNUNET_MQ_Envelope *env)
295 {
296   GNUNET_assert (NULL != cp->core_mq);
297   GNUNET_MQ_send (cp->core_mq,
298                   env);
299 }
300
301
302 /**
303  * Function called to destroy a peer now.
304  *
305  * @param cls NULL
306  * @param pid identity of the peer (unused)
307  * @param value the `struct CadetPeer` to clean up
308  * @return #GNUNET_OK (continue to iterate)
309  */
310 static int
311 destroy_iterator_cb (void *cls,
312                      const struct GNUNET_PeerIdentity *pid,
313                      void *value)
314 {
315   struct CadetPeer *cp = value;
316
317   if (NULL != cp->destroy_task)
318   {
319     GNUNET_SCHEDULER_cancel (cp->destroy_task);
320     cp->destroy_task = NULL;
321   }
322   destroy_peer (cp);
323   return GNUNET_OK;
324 }
325
326
327 /**
328  * Clean up all entries about all peers.
329  * Must only be called after all tunnels, CORE-connections and
330  * connections are down.
331  */
332 void
333 GCP_destroy_all_peers ()
334 {
335   GNUNET_CONTAINER_multipeermap_iterate (peers,
336                                          &destroy_iterator_cb,
337                                          NULL);
338 }
339
340
341 /**
342  * This peer may no longer be needed, consider cleaning it up.
343  *
344  * @param cp peer to clean up
345  */
346 static void
347 consider_peer_destroy (struct CadetPeer *cp);
348
349
350 /**
351  * We really no longere care about a peer, stop hogging memory with paths to it.
352  * Afterwards, see if there is more to be cleaned up about this peer.
353  *
354  * @param cls a `struct CadetPeer`.
355  */
356 static void
357 drop_paths (void *cls)
358 {
359   struct CadetPeer *cp = cls;
360   struct CadetPeerPath *path;
361
362   cp->destroy_task = NULL;
363   while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
364     GCPP_release (path);
365   consider_peer_destroy (cp);
366 }
367
368
369 /**
370  * This peer may no longer be needed, consider cleaning it up.
371  *
372  * @param cp peer to clean up
373  */
374 static void
375 consider_peer_destroy (struct CadetPeer *cp)
376 {
377   struct GNUNET_TIME_Relative exp;
378
379   if (NULL != cp->destroy_task)
380   {
381     GNUNET_SCHEDULER_cancel (cp->destroy_task);
382     cp->destroy_task = NULL;
383   }
384   if (NULL != cp->t)
385     return; /* still relevant! */
386   if (NULL != cp->core_mq)
387     return; /* still relevant! */
388   if (0 != GNUNET_CONTAINER_multihashmap_size (cp->connections))
389     return; /* still relevant! */
390   if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))
391   {
392     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
393                                                      &drop_paths,
394                                                      cp);
395     return;
396   }
397   if (0 < cp->path_dll_length)
398     return; /* still relevant! */
399   if (NULL != cp->hello)
400   {
401     /* relevant only until HELLO expires */
402     exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
403     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
404                                                      &destroy_peer,
405                                                      cp);
406     return;
407   }
408   cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
409                                                    &destroy_peer,
410                                                    cp);
411 }
412
413
414 /**
415  * Add an entry to the DLL of all of the paths that this peer is on.
416  *
417  * @param cp peer to modify
418  * @param entry an entry on a path
419  * @param off offset of this peer on the path
420  */
421 void
422 GCP_path_entry_add (struct CadetPeer *cp,
423                     struct CadetPeerPathEntry *entry,
424                     unsigned int off)
425 {
426   if (off >= cp->path_dll_length)
427   {
428     unsigned int len = cp->path_dll_length;
429
430     GNUNET_array_grow (cp->path_heads,
431                        len,
432                        off + 4);
433     GNUNET_array_grow (cp->path_tails,
434                        cp->path_dll_length,
435                        off + 4);
436   }
437   GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
438                                cp->path_tails[off],
439                                entry);
440   cp->num_paths++;
441
442   /* If we have a tunnel to this peer, tell the tunnel that there is a
443      new path available. */
444   if (NULL != cp->t)
445     GCT_consider_path (cp->t,
446                        entry->path,
447                        off);
448 }
449
450
451 /**
452  * Remove an entry from the DLL of all of the paths that this peer is on.
453  *
454  * @param cp peer to modify
455  * @param entry an entry on a path
456  * @param off offset of this peer on the path
457  */
458 void
459 GCP_path_entry_remove (struct CadetPeer *cp,
460                        struct CadetPeerPathEntry *entry,
461                        unsigned int off)
462 {
463   GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
464                                cp->path_tails[off],
465                                entry);
466   GNUNET_assert (0 < cp->num_paths);
467   cp->num_paths--;
468 }
469
470
471 /**
472  * Try adding a @a path to this @a peer.  If the peer already
473  * has plenty of paths, return NULL.
474  *
475  * @param cp peer to which the @a path leads to
476  * @param path a path looking for an owner; may not be fully initialized yet!
477  * @param off offset of @a cp in @a path
478  * @return NULL if this peer does not care to become a new owner,
479  *         otherwise the node in the peer's path heap for the @a path.
480  */
481 struct GNUNET_CONTAINER_HeapNode *
482 GCP_attach_path (struct CadetPeer *cp,
483                  struct CadetPeerPath *path,
484                  unsigned int off)
485 {
486   GNUNET_CONTAINER_HeapCostType desirability;
487   struct CadetPeerPath *root;
488   GNUNET_CONTAINER_HeapCostType root_desirability;
489   struct GNUNET_CONTAINER_HeapNode *hn;
490
491   /* FIXME: desirability is not yet initialized; tricky! */
492   desirability = GCPP_get_desirability (path);
493   if (GNUNET_NO ==
494       GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
495                                    (void **) &root,
496                                    &root_desirability))
497   {
498     root = NULL;
499     root_desirability = 0;
500   }
501
502   if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
503        (desirability < root_desirability) )
504     return NULL;
505
506   /* Yes, we'd like to add this path, add to our heap */
507   hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
508                                      (void *) cp,
509                                      desirability);
510
511   /* Consider maybe dropping other paths because of the new one */
512   if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
513       2 * DESIRED_CONNECTIONS_PER_TUNNEL)
514   {
515     /* Now we have way too many, drop least desirable UNLESS it is in use!
516        (Note that this intentionally keeps highly desireable, but currently
517        unused paths around in the hope that we might be able to switch, even
518        if the number of paths exceeds the threshold.) */
519     root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
520     if (NULL ==
521         GCPP_get_connection (root,
522                              cp,
523                              GCPP_get_length (root) - 1))
524     {
525       /* Got plenty of paths to this destination, and this is a low-quality
526          one that we don't care, allow it to die. */
527       GNUNET_assert (root ==
528                      GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
529       GCPP_release (root);
530     }
531   }
532   return hn;
533 }
534
535
536 /**
537  * This peer can no longer own @a path as the path
538  * has been extended and a peer further down the line
539  * is now the new owner.
540  *
541  * @param cp old owner of the @a path
542  * @param path path where the ownership is lost
543  * @param hn note in @a cp's path heap that must be deleted
544  */
545 void
546 GCP_detach_path (struct CadetPeer *cp,
547                  struct CadetPeerPath *path,
548                  struct GNUNET_CONTAINER_HeapNode *hn)
549 {
550   GNUNET_assert (path ==
551                  GNUNET_CONTAINER_heap_remove_node (hn));
552 }
553
554
555 /**
556  * Add a @a connection to this @a cp.
557  *
558  * @param cp peer via which the @a connection goes
559  * @param cc the connection to add
560  */
561 void
562 GCP_add_connection (struct CadetPeer *cp,
563                     struct CadetConnection *cc)
564 {
565   GNUNET_assert (GNUNET_OK ==
566                  GNUNET_CONTAINER_multihashmap_put (cp->connections,
567                                                     GCC_get_h (cc),
568                                                     cc,
569                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
570 }
571
572
573 /**
574  * Remove a @a connection that went via this @a cp.
575  *
576  * @param cp peer via which the @a connection went
577  * @param cc the connection to remove
578  */
579 void
580 GCP_remove_connection (struct CadetPeer *cp,
581                        struct CadetConnection *cc)
582 {
583   GNUNET_assert (GNUNET_YES ==
584                  GNUNET_CONTAINER_multihashmap_remove (cp->connections,
585                                                        GCC_get_h (cc),
586                                                        cc));
587 }
588
589
590 /**
591  * This peer is now on more "active" duty, activate processes related to it.
592  *
593  * @param cp the more-active peer
594  */
595 static void
596 consider_peer_activate (struct CadetPeer *cp)
597 {
598   uint32_t strength;
599
600   if (NULL != cp->destroy_task)
601   {
602     /* It's active, do not destory! */
603     GNUNET_SCHEDULER_cancel (cp->destroy_task);
604     cp->destroy_task = NULL;
605   }
606   if ( (0 == GNUNET_CONTAINER_multihashmap_size (cp->connections)) &&
607        (NULL == cp->t) )
608   {
609     /* We're just on a path or directly connected; don't bother too much */
610     if (NULL != cp->connectivity_suggestion)
611     {
612       GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
613       cp->connectivity_suggestion = NULL;
614     }
615     if (NULL != cp->search_h)
616     {
617       GCD_search_stop (cp->search_h);
618       cp->search_h = NULL;
619     }
620     return;
621   }
622   if (NULL == cp->core_mq)
623   {
624     /* Lacks direct connection, try to create one by querying the DHT */
625     if ( (NULL == cp->search_h) &&
626          (DESIRED_CONNECTIONS_PER_TUNNEL < cp->num_paths) )
627       cp->search_h
628         = GCD_search (&cp->pid);
629   }
630   else
631   {
632     /* Have direct connection, stop DHT search if active */
633     if (NULL != cp->search_h)
634     {
635       GCD_search_stop (cp->search_h);
636       cp->search_h = NULL;
637     }
638   }
639
640   /* If we have a tunnel, our urge for connections is much bigger */
641   strength = (NULL != cp->t) ? 32 : 1;
642   if (NULL != cp->connectivity_suggestion)
643     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
644   cp->connectivity_suggestion
645     = GNUNET_ATS_connectivity_suggest (ats_ch,
646                                        &cp->pid,
647                                        strength);
648 }
649
650
651 /**
652  * Retrieve the CadetPeer stucture associated with the
653  * peer. Optionally create one and insert it in the appropriate
654  * structures if the peer is not known yet.
655  *
656  * @param peer_id Full identity of the peer.
657  * @param create #GNUNET_YES if a new peer should be created if unknown.
658  *               #GNUNET_NO to return NULL if peer is unknown.
659  * @return Existing or newly created peer structure.
660  *         NULL if unknown and not requested @a create
661  */
662 struct CadetPeer *
663 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
664          int create)
665 {
666   struct CadetPeer *cp;
667
668   cp = GNUNET_CONTAINER_multipeermap_get (peers,
669                                           peer_id);
670   if (NULL != cp)
671     return cp;
672   if (GNUNET_NO == create)
673     return NULL;
674   cp = GNUNET_new (struct CadetPeer);
675   cp->pid = *peer_id;
676   cp->connections = GNUNET_CONTAINER_multihashmap_create (32,
677                                                           GNUNET_YES);
678   cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
679   GNUNET_assert (GNUNET_YES ==
680                  GNUNET_CONTAINER_multipeermap_put (peers,
681                                                     &cp->pid,
682                                                     cp,
683                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
684   return cp;
685 }
686
687
688 /**
689  * Obtain the peer identity for a `struct CadetPeer`.
690  *
691  * @param cp our peer handle
692  * @return the peer identity
693  */
694 const struct GNUNET_PeerIdentity *
695 GCP_get_id (struct CadetPeer *cp)
696 {
697   return &cp->pid;
698 }
699
700
701 /**
702  * Iterate over all known peers.
703  *
704  * @param iter Iterator.
705  * @param cls Closure for @c iter.
706  */
707 void
708 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
709                  void *cls)
710 {
711   GNUNET_CONTAINER_multipeermap_iterate (peers,
712                                          iter,
713                                          cls);
714 }
715
716
717 /**
718  * Count the number of known paths toward the peer.
719  *
720  * @param peer Peer to get path info.
721  * @return Number of known paths.
722  */
723 unsigned int
724 GCP_count_paths (const struct CadetPeer *peer)
725 {
726   return peer->num_paths;
727 }
728
729
730 /**
731  * Iterate over the paths to a peer.
732  *
733  * @param peer Peer to get path info.
734  * @param callback Function to call for every path.
735  * @param callback_cls Closure for @a callback.
736  * @return Number of iterated paths.
737  */
738 unsigned int
739 GCP_iterate_paths (struct CadetPeer *peer,
740                    GCP_PathIterator callback,
741                    void *callback_cls)
742 {
743   unsigned int ret = 0;
744
745   for (unsigned int i=0;i<peer->path_dll_length;i++)
746   {
747     for (struct CadetPeerPathEntry *pe = peer->path_heads[i];
748          NULL != pe;
749          pe = pe->next)
750     {
751       if (GNUNET_NO ==
752           callback (callback_cls,
753                     pe->path,
754                     i))
755         return ret;
756       ret++;
757     }
758   }
759   return ret;
760 }
761
762
763 /**
764  * Iterate over the paths to @a peer where
765  * @a peer is at distance @a dist from us.
766  *
767  * @param peer Peer to get path info.
768  * @param dist desired distance of @a peer to us on the path
769  * @param callback Function to call for every path.
770  * @param callback_cls Closure for @a callback.
771  * @return Number of iterated paths.
772  */
773 unsigned int
774 GCP_iterate_paths_at (struct CadetPeer *peer,
775                       unsigned int dist,
776                       GCP_PathIterator callback,
777                       void *callback_cls)
778 {
779   unsigned int ret = 0;
780
781   if (dist<peer->path_dll_length)
782     return 0;
783   for (struct CadetPeerPathEntry *pe = peer->path_heads[dist];
784        NULL != pe;
785        pe = pe->next)
786   {
787     if (GNUNET_NO ==
788         callback (callback_cls,
789                   pe->path,
790                   dist))
791       return ret;
792     ret++;
793   }
794   return ret;
795 }
796
797
798 /**
799  * Get the tunnel towards a peer.
800  *
801  * @param peer Peer to get from.
802  * @param create #GNUNET_YES to create a tunnel if we do not have one
803  * @return Tunnel towards peer.
804  */
805 struct CadetTunnel *
806 GCP_get_tunnel (struct CadetPeer *peer,
807                 int create)
808 {
809   if (NULL == peer)
810     return NULL;
811   if ( (NULL != peer->t) ||
812        (GNUNET_NO == create) )
813     return peer->t;
814   peer->t = GCT_create_tunnel (peer);
815   consider_peer_activate (peer);
816   return peer->t;
817 }
818
819
820 /**
821  * We got a HELLO for a @a peer, remember it, and possibly
822  * trigger adequate actions (like trying to connect).
823  *
824  * @param peer the peer we got a HELLO for
825  * @param hello the HELLO to remember
826  */
827 void
828 GCP_set_hello (struct CadetPeer *peer,
829                const struct GNUNET_HELLO_Message *hello)
830 {
831   /* FIXME: keep HELLO, possibly offer to TRANSPORT... */
832
833   consider_peer_destroy (peer);
834 }
835
836
837 /**
838  * The tunnel to the given peer no longer exists, remove it from our
839  * data structures, and possibly clean up the peer itself.
840  *
841  * @param peer the peer affected
842  * @param t the dead tunnel
843  */
844 void
845 GCP_drop_tunnel (struct CadetPeer *peer,
846                  struct CadetTunnel *t)
847 {
848   GNUNET_assert (peer->t == t);
849   peer->t = NULL;
850   consider_peer_destroy (peer);
851 }
852
853
854 /**
855  * Start message queue change notifications.
856  *
857  * @param cp peer to notify for
858  * @param cb function to call if mq becomes available or unavailable
859  * @param cb_cls closure for @a cb
860  * @return handle to cancel request
861  */
862 struct GCP_MessageQueueManager *
863 GCP_request_mq (struct CadetPeer *cp,
864                 GCP_MessageQueueNotificationCallback cb,
865                 void *cb_cls)
866 {
867   struct GCP_MessageQueueManager *mqm;
868
869   mqm = GNUNET_new (struct GCP_MessageQueueManager);
870   mqm->cb = cb;
871   mqm->cb_cls = cb_cls;
872   mqm->cp = cp;
873   GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
874                                cp->mqm_tail,
875                                mqm);
876   if (NULL != cp->core_mq)
877     cb (cb_cls,
878         cp->core_mq);
879   return mqm;
880 }
881
882
883 /**
884  * Stops message queue change notifications.
885  *
886  * @param mqm handle matching request to cancel
887  */
888 void
889 GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm)
890 {
891   struct CadetPeer *cp = mqm->cp;
892
893   GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
894                                cp->mqm_tail,
895                                mqm);
896   GNUNET_free (mqm);
897 }
898
899
900
901 /* end of gnunet-service-cadet-new_peer.c */