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