implement get_path_from_route
[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  * @param force force attaching the path
588  * @return NULL if this peer does not care to become a new owner,
589  *         otherwise the node in the peer's path heap for the @a path.
590  */
591 struct GNUNET_CONTAINER_HeapNode *
592 GCP_attach_path (struct CadetPeer *cp,
593                  struct CadetPeerPath *path,
594                  unsigned int off,
595                  int force)
596 {
597   GNUNET_CONTAINER_HeapCostType desirability;
598   struct CadetPeerPath *root;
599   GNUNET_CONTAINER_HeapCostType root_desirability;
600   struct GNUNET_CONTAINER_HeapNode *hn;
601
602   if (GNUNET_NO == force)
603   {
604     /* FIXME: desirability is not yet initialized; tricky! */
605     desirability = GCPP_get_desirability (path);
606     if (GNUNET_NO ==
607         GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
608                                      (void **) &root,
609                                      &root_desirability))
610     {
611       root = NULL;
612       root_desirability = 0;
613     }
614
615     if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
616          (desirability < root_desirability) )
617       return NULL;
618   }
619
620   /* Yes, we'd like to add this path, add to our heap */
621   hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
622                                      (void *) cp,
623                                      desirability);
624
625   /* Consider maybe dropping other paths because of the new one */
626   if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
627       2 * DESIRED_CONNECTIONS_PER_TUNNEL)
628   {
629     /* Now we have way too many, drop least desirable UNLESS it is in use!
630        (Note that this intentionally keeps highly desireable, but currently
631        unused paths around in the hope that we might be able to switch, even
632        if the number of paths exceeds the threshold.) */
633     root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
634     if ( (path != root) &&
635          (NULL ==
636           GCPP_get_connection (root,
637                                cp,
638                                GCPP_get_length (root) - 1)) )
639     {
640       /* Got plenty of paths to this destination, and this is a low-quality
641          one that we don't care, allow it to die. */
642       GNUNET_assert (root ==
643                      GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
644       GCPP_release (root);
645     }
646   }
647   return hn;
648 }
649
650
651 /**
652  * This peer can no longer own @a path as the path
653  * has been extended and a peer further down the line
654  * is now the new owner.
655  *
656  * @param cp old owner of the @a path
657  * @param path path where the ownership is lost
658  * @param hn note in @a cp's path heap that must be deleted
659  */
660 void
661 GCP_detach_path (struct CadetPeer *cp,
662                  struct CadetPeerPath *path,
663                  struct GNUNET_CONTAINER_HeapNode *hn)
664 {
665   GNUNET_assert (path ==
666                  GNUNET_CONTAINER_heap_remove_node (hn));
667 }
668
669
670 /**
671  * Add a @a connection to this @a cp.
672  *
673  * @param cp peer via which the @a connection goes
674  * @param cc the connection to add
675  */
676 void
677 GCP_add_connection (struct CadetPeer *cp,
678                     struct CadetConnection *cc)
679 {
680   GNUNET_assert (GNUNET_OK ==
681                  GNUNET_CONTAINER_multishortmap_put (cp->connections,
682                                                      &GCC_get_id (cc)->connection_of_tunnel,
683                                                      cc,
684                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
685 }
686
687
688 /**
689  * Remove a @a connection that went via this @a cp.
690  *
691  * @param cp peer via which the @a connection went
692  * @param cc the connection to remove
693  */
694 void
695 GCP_remove_connection (struct CadetPeer *cp,
696                        struct CadetConnection *cc)
697 {
698   GNUNET_assert (GNUNET_YES ==
699                  GNUNET_CONTAINER_multishortmap_remove (cp->connections,
700                                                         &GCC_get_id (cc)->connection_of_tunnel,
701                                                         cc));
702 }
703
704
705 /**
706  * This peer is now on more "active" duty, activate processes related to it.
707  *
708  * @param cp the more-active peer
709  */
710 static void
711 consider_peer_activate (struct CadetPeer *cp)
712 {
713   uint32_t strength;
714
715   if (NULL != cp->destroy_task)
716   {
717     /* It's active, do not destory! */
718     GNUNET_SCHEDULER_cancel (cp->destroy_task);
719     cp->destroy_task = NULL;
720   }
721   if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
722        (NULL == cp->t) )
723   {
724     /* We're just on a path or directly connected; don't bother too much */
725     if (NULL != cp->connectivity_suggestion)
726     {
727       GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
728       cp->connectivity_suggestion = NULL;
729     }
730     if (NULL != cp->search_h)
731     {
732       GCD_search_stop (cp->search_h);
733       cp->search_h = NULL;
734     }
735     return;
736   }
737   if (NULL == cp->core_mq)
738   {
739     /* Lacks direct connection, try to create one by querying the DHT */
740     if ( (NULL == cp->search_h) &&
741          (DESIRED_CONNECTIONS_PER_TUNNEL < cp->num_paths) )
742       cp->search_h
743         = GCD_search (&cp->pid);
744   }
745   else
746   {
747     /* Have direct connection, stop DHT search if active */
748     if (NULL != cp->search_h)
749     {
750       GCD_search_stop (cp->search_h);
751       cp->search_h = NULL;
752     }
753   }
754
755   /* If we have a tunnel, our urge for connections is much bigger */
756   strength = (NULL != cp->t) ? 32 : 1;
757   if (NULL != cp->connectivity_suggestion)
758     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
759   cp->connectivity_suggestion
760     = GNUNET_ATS_connectivity_suggest (ats_ch,
761                                        &cp->pid,
762                                        strength);
763 }
764
765
766 /**
767  * Retrieve the CadetPeer stucture associated with the
768  * peer. Optionally create one and insert it in the appropriate
769  * structures if the peer is not known yet.
770  *
771  * @param peer_id Full identity of the peer.
772  * @param create #GNUNET_YES if a new peer should be created if unknown.
773  *               #GNUNET_NO to return NULL if peer is unknown.
774  * @return Existing or newly created peer structure.
775  *         NULL if unknown and not requested @a create
776  */
777 struct CadetPeer *
778 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
779          int create)
780 {
781   struct CadetPeer *cp;
782
783   cp = GNUNET_CONTAINER_multipeermap_get (peers,
784                                           peer_id);
785   if (NULL != cp)
786     return cp;
787   if (GNUNET_NO == create)
788     return NULL;
789   cp = GNUNET_new (struct CadetPeer);
790   cp->pid = *peer_id;
791   cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
792                                                            GNUNET_YES);
793   cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
794   GNUNET_assert (GNUNET_YES ==
795                  GNUNET_CONTAINER_multipeermap_put (peers,
796                                                     &cp->pid,
797                                                     cp,
798                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
799   return cp;
800 }
801
802
803 /**
804  * Obtain the peer identity for a `struct CadetPeer`.
805  *
806  * @param cp our peer handle
807  * @return the peer identity
808  */
809 const struct GNUNET_PeerIdentity *
810 GCP_get_id (struct CadetPeer *cp)
811 {
812   return &cp->pid;
813 }
814
815
816 /**
817  * Iterate over all known peers.
818  *
819  * @param iter Iterator.
820  * @param cls Closure for @c iter.
821  */
822 void
823 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
824                  void *cls)
825 {
826   GNUNET_CONTAINER_multipeermap_iterate (peers,
827                                          iter,
828                                          cls);
829 }
830
831
832 /**
833  * Count the number of known paths toward the peer.
834  *
835  * @param peer Peer to get path info.
836  * @return Number of known paths.
837  */
838 unsigned int
839 GCP_count_paths (const struct CadetPeer *peer)
840 {
841   return peer->num_paths;
842 }
843
844
845 /**
846  * Iterate over the paths to a peer.
847  *
848  * @param peer Peer to get path info.
849  * @param callback Function to call for every path.
850  * @param callback_cls Closure for @a callback.
851  * @return Number of iterated paths.
852  */
853 unsigned int
854 GCP_iterate_paths (struct CadetPeer *peer,
855                    GCP_PathIterator callback,
856                    void *callback_cls)
857 {
858   unsigned int ret = 0;
859
860   for (unsigned int i=0;i<peer->path_dll_length;i++)
861   {
862     for (struct CadetPeerPathEntry *pe = peer->path_heads[i];
863          NULL != pe;
864          pe = pe->next)
865     {
866       if (GNUNET_NO ==
867           callback (callback_cls,
868                     pe->path,
869                     i))
870         return ret;
871       ret++;
872     }
873   }
874   return ret;
875 }
876
877
878 /**
879  * Iterate over the paths to @a peer where
880  * @a peer is at distance @a dist from us.
881  *
882  * @param peer Peer to get path info.
883  * @param dist desired distance of @a peer to us on the path
884  * @param callback Function to call for every path.
885  * @param callback_cls Closure for @a callback.
886  * @return Number of iterated paths.
887  */
888 unsigned int
889 GCP_iterate_paths_at (struct CadetPeer *peer,
890                       unsigned int dist,
891                       GCP_PathIterator callback,
892                       void *callback_cls)
893 {
894   unsigned int ret = 0;
895
896   if (dist<peer->path_dll_length)
897     return 0;
898   for (struct CadetPeerPathEntry *pe = peer->path_heads[dist];
899        NULL != pe;
900        pe = pe->next)
901   {
902     if (GNUNET_NO ==
903         callback (callback_cls,
904                   pe->path,
905                   dist))
906       return ret;
907     ret++;
908   }
909   return ret;
910 }
911
912
913 /**
914  * Get the tunnel towards a peer.
915  *
916  * @param cp Peer to get from.
917  * @param create #GNUNET_YES to create a tunnel if we do not have one
918  * @return Tunnel towards peer.
919  */
920 struct CadetTunnel *
921 GCP_get_tunnel (struct CadetPeer *cp,
922                 int create)
923 {
924   if (NULL == cp)
925     return NULL;
926   if ( (NULL != cp->t) ||
927        (GNUNET_NO == create) )
928     return cp->t;
929   cp->t = GCT_create_tunnel (cp);
930   consider_peer_activate (cp);
931   return cp->t;
932 }
933
934
935 /**
936  * Hello offer was passed to the transport service. Mark it
937  * as done.
938  *
939  * @param cls the `struct CadetPeer` where the offer completed
940  */
941 static void
942 hello_offer_done (void *cls)
943 {
944   struct CadetPeer *cp = cls;
945
946   cp->hello_offer = NULL;
947 }
948
949
950 /**
951  * We got a HELLO for a @a peer, remember it, and possibly
952  * trigger adequate actions (like trying to connect).
953  *
954  * @param cp the peer we got a HELLO for
955  * @param hello the HELLO to remember
956  */
957 void
958 GCP_set_hello (struct CadetPeer *cp,
959                const struct GNUNET_HELLO_Message *hello)
960 {
961   struct GNUNET_HELLO_Message *mrg;
962
963   if (NULL != cp->hello_offer)
964   {
965     GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
966     cp->hello_offer = NULL;
967   }
968   if (NULL != cp->hello)
969   {
970     mrg = GNUNET_HELLO_merge (hello,
971                               cp->hello);
972     GNUNET_free (cp->hello);
973     cp->hello = mrg;
974   }
975   else
976   {
977     cp->hello = GNUNET_memdup (hello,
978                                GNUNET_HELLO_size (hello));
979   }
980   cp->hello_offer
981     = GNUNET_TRANSPORT_offer_hello (cfg,
982                                     GNUNET_HELLO_get_header (cp->hello) ,
983                                     &hello_offer_done,
984                                     cp);
985   /* New HELLO means cp's destruction time may change... */
986   consider_peer_destroy (cp);
987 }
988
989
990 /**
991  * The tunnel to the given peer no longer exists, remove it from our
992  * data structures, and possibly clean up the peer itself.
993  *
994  * @param cp the peer affected
995  * @param t the dead tunnel
996  */
997 void
998 GCP_drop_tunnel (struct CadetPeer *cp,
999                  struct CadetTunnel *t)
1000 {
1001   GNUNET_assert (cp->t == t);
1002   cp->t = NULL;
1003   consider_peer_destroy (cp);
1004 }
1005
1006
1007 /**
1008  * Test if @a cp has a core-level connection
1009  *
1010  * @param cp peer to test
1011  * @return #GNUNET_YES if @a cp has a core-level connection
1012  */
1013 int
1014 GCP_has_core_connection (struct CadetPeer *cp)
1015 {
1016   return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1017 }
1018
1019
1020 /**
1021  * Start message queue change notifications.
1022  *
1023  * @param cp peer to notify for
1024  * @param cb function to call if mq becomes available or unavailable
1025  * @param cb_cls closure for @a cb
1026  * @return handle to cancel request
1027  */
1028 struct GCP_MessageQueueManager *
1029 GCP_request_mq (struct CadetPeer *cp,
1030                 GCP_MessageQueueNotificationCallback cb,
1031                 void *cb_cls)
1032 {
1033   struct GCP_MessageQueueManager *mqm;
1034
1035   mqm = GNUNET_new (struct GCP_MessageQueueManager);
1036   mqm->cb = cb;
1037   mqm->cb_cls = cb_cls;
1038   mqm->cp = cp;
1039   GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1040                                cp->mqm_tail,
1041                                mqm);
1042   if (NULL != cp->core_mq)
1043     cb (cb_cls,
1044         GNUNET_YES);
1045   return mqm;
1046 }
1047
1048
1049 /**
1050  * Stops message queue change notifications.
1051  *
1052  * @param mqm handle matching request to cancel
1053  * @param last_env final message to transmit, or NULL
1054  */
1055 void
1056 GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1057                        struct GNUNET_MQ_Envelope *last_env)
1058 {
1059   struct CadetPeer *cp = mqm->cp;
1060
1061   if (NULL != mqm->env)
1062     GNUNET_MQ_discard (mqm->env);
1063   if (NULL != last_env)
1064   {
1065     if (NULL != cp->core_mq)
1066       GNUNET_MQ_send (cp->core_mq,
1067                       last_env);
1068     else
1069       GNUNET_MQ_discard (last_env);
1070   }
1071   GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1072                                cp->mqm_tail,
1073                                mqm);
1074   GNUNET_free (mqm);
1075 }
1076
1077
1078 /**
1079  * Send the message in @a env to @a cp, overriding queueing logic.
1080  * This function should only be used to send error messages outside
1081  * of flow and congestion control, similar to ICMP.  Note that
1082  * the envelope may be silently discarded as well.
1083  *
1084  * @param cp peer to send the message to
1085  * @param env envelope with the message to send
1086  */
1087 void
1088 GCP_send_ooo (struct CadetPeer *cp,
1089               struct GNUNET_MQ_Envelope *env)
1090 {
1091   if (NULL == cp->core_mq)
1092   {
1093     GNUNET_MQ_discard (env);
1094     return;
1095   }
1096   GNUNET_MQ_send (cp->core_mq,
1097                   env);
1098 }
1099
1100
1101
1102
1103 /* end of gnunet-service-cadet-new_peer.c */