fix comparisson
[oweals/gnunet.git] / src / cadet / gnunet-service-cadet-new_peer.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2001-2017 GNUnet e.V.
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file cadet/gnunet-service-cadet-new_peer.c
23  * @brief Information we track per peer.
24  * @author Bartlomiej Polot
25  * @author Christian Grothoff
26  *
27  * TODO:
28  * - optimize stopping/restarting DHT search to situations
29  *   where we actually need it (i.e. not if we have a direct connection,
30  *   or if we already have plenty of good short ones, or maybe even
31  *   to take a break if we have some connections and have searched a lot (?))
32  * - optimize MQM ready scans (O(n) -> O(1))
33  */
34 #include "platform.h"
35 #include "gnunet_util_lib.h"
36 #include "gnunet_hello_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 cp Peer.
229  * @return Static string for it's ID.
230  */
231 const char *
232 GCP_2s (const struct CadetPeer *cp)
233 {
234   static char buf[32];
235
236   GNUNET_snprintf (buf,
237                    sizeof (buf),
238                    "P(%s)",
239                    GNUNET_i2s (&cp->pid));
240   return buf;
241 }
242
243
244 /**
245  * This peer is no longer be needed, clean it up now.
246  *
247  * @param cls peer to clean up
248  */
249 static void
250 destroy_peer (void *cls)
251 {
252   struct CadetPeer *cp = cls;
253
254   LOG (GNUNET_ERROR_TYPE_DEBUG,
255        "Destroying state about peer %s\n",
256        GCP_2s (cp));
257   cp->destroy_task = NULL;
258   GNUNET_assert (NULL == cp->t);
259   GNUNET_assert (NULL == cp->core_mq);
260   GNUNET_assert (0 == cp->path_dll_length);
261   GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
262   GNUNET_assert (GNUNET_YES ==
263                  GNUNET_CONTAINER_multipeermap_remove (peers,
264                                                        &cp->pid,
265                                                        cp));
266   GNUNET_free_non_null (cp->path_heads);
267   GNUNET_free_non_null (cp->path_tails);
268   cp->path_dll_length = 0;
269   if (NULL != cp->search_h)
270   {
271     GCD_search_stop (cp->search_h);
272     cp->search_h = NULL;
273   }
274   /* FIXME: clean up search_delayedXXX! */
275
276   if (NULL != cp->hello_offer)
277   {
278     GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
279     cp->hello_offer = NULL;
280   }
281   if (NULL != cp->connectivity_suggestion)
282   {
283     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
284     cp->connectivity_suggestion = NULL;
285   }
286   GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
287   GNUNET_CONTAINER_heap_destroy (cp->path_heap);
288   GNUNET_free_non_null (cp->hello);
289   /* Peer should not be freed if paths exist; if there are no paths,
290      there ought to be no connections, and without connections, no
291      notifications. Thus we can assert that mqm_head is empty at this
292      point. */
293   GNUNET_assert (NULL == cp->mqm_head);
294   GNUNET_free (cp);
295 }
296
297
298 /**
299  * This peer is now on more "active" duty, activate processes related to it.
300  *
301  * @param cp the more-active peer
302  */
303 static void
304 consider_peer_activate (struct CadetPeer *cp)
305 {
306   uint32_t strength;
307
308   LOG (GNUNET_ERROR_TYPE_DEBUG,
309        "Updating peer %s activation state (%u connections)%s%s\n",
310        GCP_2s (cp),
311        GNUNET_CONTAINER_multishortmap_size (cp->connections),
312        (NULL == cp->t) ? "" : " with tunnel",
313        (NULL == cp->core_mq) ? "" : " with CORE link");
314   if (NULL != cp->destroy_task)
315   {
316     /* It's active, do not destory! */
317     GNUNET_SCHEDULER_cancel (cp->destroy_task);
318     cp->destroy_task = NULL;
319   }
320   if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
321        (NULL == cp->t) )
322   {
323     /* We're just on a path or directly connected; don't bother too much */
324     if (NULL != cp->connectivity_suggestion)
325     {
326       GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
327       cp->connectivity_suggestion = NULL;
328     }
329     if (NULL != cp->search_h)
330     {
331       GCD_search_stop (cp->search_h);
332       cp->search_h = NULL;
333     }
334     return;
335   }
336   if (NULL == cp->core_mq)
337   {
338     /* Lacks direct connection, try to create one by querying the DHT */
339     if ( (NULL == cp->search_h) &&
340          (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
341       cp->search_h
342         = GCD_search (&cp->pid);
343   }
344   else
345   {
346     /* Have direct connection, stop DHT search if active */
347     if (NULL != cp->search_h)
348     {
349       GCD_search_stop (cp->search_h);
350       cp->search_h = NULL;
351     }
352   }
353
354   /* If we have a tunnel, our urge for connections is much bigger */
355   strength = (NULL != cp->t) ? 32 : 1;
356   if (NULL != cp->connectivity_suggestion)
357     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
358   cp->connectivity_suggestion
359     = GNUNET_ATS_connectivity_suggest (ats_ch,
360                                        &cp->pid,
361                                        strength);
362 }
363
364
365 /**
366  * This peer may no longer be needed, consider cleaning it up.
367  *
368  * @param cp peer to clean up
369  */
370 static void
371 consider_peer_destroy (struct CadetPeer *cp);
372
373
374 /**
375  * We really no longere care about a peer, stop hogging memory with paths to it.
376  * Afterwards, see if there is more to be cleaned up about this peer.
377  *
378  * @param cls a `struct CadetPeer`.
379  */
380 static void
381 drop_paths (void *cls)
382 {
383   struct CadetPeer *cp = cls;
384   struct CadetPeerPath *path;
385
386   cp->destroy_task = NULL;
387   while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
388     GCPP_release (path);
389   consider_peer_destroy (cp);
390 }
391
392
393 /**
394  * This peer may no longer be needed, consider cleaning it up.
395  *
396  * @param cp peer to clean up
397  */
398 static void
399 consider_peer_destroy (struct CadetPeer *cp)
400 {
401   struct GNUNET_TIME_Relative exp;
402
403   if (NULL != cp->destroy_task)
404   {
405     GNUNET_SCHEDULER_cancel (cp->destroy_task);
406     cp->destroy_task = NULL;
407   }
408   if (NULL != cp->t)
409     return; /* still relevant! */
410   if (NULL != cp->core_mq)
411     return; /* still relevant! */
412   if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
413     return; /* still relevant! */
414   if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))
415   {
416     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
417                                                      &drop_paths,
418                                                      cp);
419     return;
420   }
421   if (0 < cp->path_dll_length)
422     return; /* still relevant! */
423   if (NULL != cp->hello)
424   {
425     /* relevant only until HELLO expires */
426     exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
427     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
428                                                      &destroy_peer,
429                                                      cp);
430     return;
431   }
432   cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
433                                                    &destroy_peer,
434                                                    cp);
435 }
436
437
438 /**
439  * Set the message queue to @a mq for peer @a cp and notify watchers.
440  *
441  * @param cp peer to modify
442  * @param mq message queue to set (can be NULL)
443  */
444 void
445 GCP_set_mq (struct CadetPeer *cp,
446             struct GNUNET_MQ_Handle *mq)
447 {
448   LOG (GNUNET_ERROR_TYPE_DEBUG,
449        "Message queue for peer %s is now %p\n",
450        GCP_2s (cp),
451        mq);
452   cp->core_mq = mq;
453   for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
454        NULL != mqm;
455        mqm = mqm->next)
456   {
457     if (NULL == mq)
458     {
459       if (NULL != mqm->env)
460       {
461         GNUNET_MQ_discard (mqm->env);
462         mqm->env = NULL;
463         mqm->cb (mqm->cb_cls,
464                  GNUNET_SYSERR);
465       }
466       else
467       {
468         mqm->cb (mqm->cb_cls,
469                  GNUNET_NO);
470       }
471     }
472     else
473     {
474       GNUNET_assert (NULL == mqm->env);
475       mqm->cb (mqm->cb_cls,
476                GNUNET_YES);
477     }
478   }
479   if ( (NULL != mq) ||
480        (NULL != cp->t) )
481     consider_peer_activate (cp);
482   else
483     consider_peer_destroy (cp);
484
485   if ( (NULL != mq) &&
486        (NULL != cp->t) )
487   {
488     /* have a new, direct path to the target, notify tunnel */
489     struct CadetPeerPath *path;
490
491     path = GCPP_get_path_from_route (1,
492                                      &cp->pid);
493     GCT_consider_path (cp->t,
494                        path,
495                        0);
496   }
497 }
498
499
500 /**
501  * Transmit current envelope from this @a mqm.
502  *
503  * @param mqm mqm to transmit message for now
504  */
505 static void
506 mqm_execute (struct GCP_MessageQueueManager *mqm)
507 {
508   struct CadetPeer *cp = mqm->cp;
509
510   LOG (GNUNET_ERROR_TYPE_DEBUG,
511        "Sending to peer %s from MQM %p\n",
512        GCP_2s (cp),
513        mqm);
514   /* Move entry to the end of the DLL, to be fair. */
515   if (mqm != cp->mqm_tail)
516   {
517     GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
518                                  cp->mqm_tail,
519                                  mqm);
520     GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
521                                       cp->mqm_tail,
522                                       mqm);
523   }
524   GNUNET_MQ_send (cp->core_mq,
525                   mqm->env);
526   mqm->env = NULL;
527   cp->mqm_ready_counter--;
528 }
529
530
531 /**
532  * Function called when CORE took one of the messages from
533  * a message queue manager and transmitted it.
534  *
535  * @param cls the `struct CadetPeeer` where we made progress
536  */
537 static void
538 mqm_send_done (void *cls)
539 {
540   struct CadetPeer *cp = cls;
541
542   LOG (GNUNET_ERROR_TYPE_DEBUG,
543        "Sending to peer %s completed\n",
544        GCP_2s (cp));
545   if (0 == cp->mqm_ready_counter)
546     return; /* nothing to do */
547   for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
548        NULL != mqm;
549        mqm = mqm->next)
550   {
551     if (NULL == mqm->env)
552       continue;
553     mqm_execute (mqm);
554     return;
555   }
556 }
557
558
559 /**
560  * Send the message in @a env to @a cp.
561  *
562  * @param mqm the message queue manager to use for transmission
563  * @param env envelope with the message to send; must NOT
564  *            yet have a #GNUNET_MQ_notify_sent() callback attached to it
565  */
566 void
567 GCP_send (struct GCP_MessageQueueManager *mqm,
568           struct GNUNET_MQ_Envelope *env)
569 {
570   struct CadetPeer *cp = mqm->cp;
571
572   LOG (GNUNET_ERROR_TYPE_DEBUG,
573        "Queueing message to peer %s in MQM %p\n",
574        GCP_2s (cp),
575        mqm);
576   GNUNET_assert (NULL != cp->core_mq);
577   GNUNET_assert (NULL == mqm->env);
578   GNUNET_MQ_notify_sent (env,
579                          &mqm_send_done,
580                          cp);
581   mqm->env = env;
582   cp->mqm_ready_counter++;
583   if (0 != GNUNET_MQ_get_length (cp->core_mq))
584     return;
585   mqm_execute (mqm);
586 }
587
588
589 /**
590  * Function called to destroy a peer now.
591  *
592  * @param cls NULL
593  * @param pid identity of the peer (unused)
594  * @param value the `struct CadetPeer` to clean up
595  * @return #GNUNET_OK (continue to iterate)
596  */
597 static int
598 destroy_iterator_cb (void *cls,
599                      const struct GNUNET_PeerIdentity *pid,
600                      void *value)
601 {
602   struct CadetPeer *cp = value;
603
604   if (NULL != cp->destroy_task)
605   {
606     GNUNET_SCHEDULER_cancel (cp->destroy_task);
607     cp->destroy_task = NULL;
608   }
609   destroy_peer (cp);
610   return GNUNET_OK;
611 }
612
613
614 /**
615  * Clean up all entries about all peers.
616  * Must only be called after all tunnels, CORE-connections and
617  * connections are down.
618  */
619 void
620 GCP_destroy_all_peers ()
621 {
622   LOG (GNUNET_ERROR_TYPE_DEBUG,
623        "Destroying all peers now\n");
624   GNUNET_CONTAINER_multipeermap_iterate (peers,
625                                          &destroy_iterator_cb,
626                                          NULL);
627 }
628
629
630 /**
631  * Add an entry to the DLL of all of the paths that this peer is on.
632  *
633  * @param cp peer to modify
634  * @param entry an entry on a path
635  * @param off offset of this peer on the path
636  */
637 void
638 GCP_path_entry_add (struct CadetPeer *cp,
639                     struct CadetPeerPathEntry *entry,
640                     unsigned int off)
641 {
642   LOG (GNUNET_ERROR_TYPE_DEBUG,
643        "Discovered that peer %s is on path %s at offset %u\n",
644        GCP_2s (cp),
645        GCPP_2s (entry->path),
646        off);
647   if (off >= cp->path_dll_length)
648   {
649     unsigned int len = cp->path_dll_length;
650
651     GNUNET_array_grow (cp->path_heads,
652                        len,
653                        off + 4);
654     GNUNET_array_grow (cp->path_tails,
655                        cp->path_dll_length,
656                        off + 4);
657   }
658   GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
659                                cp->path_tails[off],
660                                entry);
661   cp->num_paths++;
662
663   /* If we have a tunnel to this peer, tell the tunnel that there is a
664      new path available. */
665   if (NULL != cp->t)
666     GCT_consider_path (cp->t,
667                        entry->path,
668                        off);
669
670   if ( (NULL != cp->search_h) &&
671        (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths) )
672   {
673     /* Now I have enough paths, stop search */
674     GCD_search_stop (cp->search_h);
675     cp->search_h = NULL;
676   }
677 }
678
679
680 /**
681  * Remove an entry from the DLL of all of the paths that this peer is on.
682  *
683  * @param cp peer to modify
684  * @param entry an entry on a path
685  * @param off offset of this peer on the path
686  */
687 void
688 GCP_path_entry_remove (struct CadetPeer *cp,
689                        struct CadetPeerPathEntry *entry,
690                        unsigned int off)
691 {
692   LOG (GNUNET_ERROR_TYPE_DEBUG,
693        "Removing knowledge about peer %s beging on path %s at offset %u\n",
694        GCP_2s (cp),
695        GCPP_2s (entry->path),
696        off);
697   GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
698                                cp->path_tails[off],
699                                entry);
700   GNUNET_assert (0 < cp->num_paths);
701   cp->num_paths--;
702   if ( (NULL == cp->core_mq) &&
703        (NULL != cp->t) &&
704        (NULL == cp->search_h) &&
705        (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
706     cp->search_h
707       = GCD_search (&cp->pid);
708 }
709
710
711 /**
712  * Try adding a @a path to this @a peer.  If the peer already
713  * has plenty of paths, return NULL.
714  *
715  * @param cp peer to which the @a path leads to
716  * @param path a path looking for an owner; may not be fully initialized yet!
717  * @param off offset of @a cp in @a path
718  * @param force force attaching the path
719  * @return NULL if this peer does not care to become a new owner,
720  *         otherwise the node in the peer's path heap for the @a path.
721  */
722 struct GNUNET_CONTAINER_HeapNode *
723 GCP_attach_path (struct CadetPeer *cp,
724                  struct CadetPeerPath *path,
725                  unsigned int off,
726                  int force)
727 {
728   GNUNET_CONTAINER_HeapCostType desirability;
729   struct CadetPeerPath *root;
730   GNUNET_CONTAINER_HeapCostType root_desirability;
731   struct GNUNET_CONTAINER_HeapNode *hn;
732
733   desirability = GCPP_get_desirability (path);
734   if (GNUNET_NO == force)
735   {
736     /* FIXME: desirability is not yet initialized; tricky! */
737     if (GNUNET_NO ==
738         GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
739                                      (void **) &root,
740                                      &root_desirability))
741     {
742       root = NULL;
743       root_desirability = 0;
744     }
745
746     if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
747          (desirability < root_desirability) )
748     {
749       LOG (GNUNET_ERROR_TYPE_DEBUG,
750            "Decided to not attach path %p to peer %s due to undesirability\n",
751            GCPP_2s (path),
752            GCP_2s (cp));
753       return NULL;
754     }
755   }
756
757   LOG (GNUNET_ERROR_TYPE_DEBUG,
758        "Attaching path %s to peer %s (%s)\n",
759        GCPP_2s (path),
760        GCP_2s (cp),
761        (GNUNET_NO == force) ? "desirable" : "forced");
762
763   /* Yes, we'd like to add this path, add to our heap */
764   hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
765                                      path,
766                                      desirability);
767
768   /* Consider maybe dropping other paths because of the new one */
769   if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
770       2 * DESIRED_CONNECTIONS_PER_TUNNEL)
771   {
772     /* Now we have way too many, drop least desirable UNLESS it is in use!
773        (Note that this intentionally keeps highly desireable, but currently
774        unused paths around in the hope that we might be able to switch, even
775        if the number of paths exceeds the threshold.) */
776     root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
777     if ( (path != root) &&
778          (NULL ==
779           GCPP_get_connection (root,
780                                cp,
781                                GCPP_get_length (root) - 1)) )
782     {
783       /* Got plenty of paths to this destination, and this is a low-quality
784          one that we don't care, allow it to die. */
785       GNUNET_assert (root ==
786                      GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
787       GCPP_release (root);
788     }
789   }
790   return hn;
791 }
792
793
794 /**
795  * This peer can no longer own @a path as the path
796  * has been extended and a peer further down the line
797  * is now the new owner.
798  *
799  * @param cp old owner of the @a path
800  * @param path path where the ownership is lost
801  * @param hn note in @a cp's path heap that must be deleted
802  */
803 void
804 GCP_detach_path (struct CadetPeer *cp,
805                  struct CadetPeerPath *path,
806                  struct GNUNET_CONTAINER_HeapNode *hn)
807 {
808   LOG (GNUNET_ERROR_TYPE_DEBUG,
809        "Detatching path %s from peer %s\n",
810        GCPP_2s (path),
811        GCP_2s (cp));
812   GNUNET_assert (path ==
813                  GNUNET_CONTAINER_heap_remove_node (hn));
814 }
815
816
817 /**
818  * Add a @a connection to this @a cp.
819  *
820  * @param cp peer via which the @a connection goes
821  * @param cc the connection to add
822  */
823 void
824 GCP_add_connection (struct CadetPeer *cp,
825                     struct CadetConnection *cc)
826 {
827   LOG (GNUNET_ERROR_TYPE_DEBUG,
828        "Adding connection %s to peer %s\n",
829        GCC_2s (cc),
830        GCP_2s (cp));
831   GNUNET_assert (GNUNET_OK ==
832                  GNUNET_CONTAINER_multishortmap_put (cp->connections,
833                                                      &GCC_get_id (cc)->connection_of_tunnel,
834                                                      cc,
835                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
836 }
837
838
839 /**
840  * Remove a @a connection that went via this @a cp.
841  *
842  * @param cp peer via which the @a connection went
843  * @param cc the connection to remove
844  */
845 void
846 GCP_remove_connection (struct CadetPeer *cp,
847                        struct CadetConnection *cc)
848 {
849   LOG (GNUNET_ERROR_TYPE_DEBUG,
850        "Removing connection %s from peer %s\n",
851        GCC_2s (cc),
852        GCP_2s (cp));
853   GNUNET_assert (GNUNET_YES ==
854                  GNUNET_CONTAINER_multishortmap_remove (cp->connections,
855                                                         &GCC_get_id (cc)->connection_of_tunnel,
856                                                         cc));
857 }
858
859
860 /**
861  * Retrieve the CadetPeer stucture associated with the
862  * peer. Optionally create one and insert it in the appropriate
863  * structures if the peer is not known yet.
864  *
865  * @param peer_id Full identity of the peer.
866  * @param create #GNUNET_YES if a new peer should be created if unknown.
867  *               #GNUNET_NO to return NULL if peer is unknown.
868  * @return Existing or newly created peer structure.
869  *         NULL if unknown and not requested @a create
870  */
871 struct CadetPeer *
872 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
873          int create)
874 {
875   struct CadetPeer *cp;
876
877   cp = GNUNET_CONTAINER_multipeermap_get (peers,
878                                           peer_id);
879   if (NULL != cp)
880     return cp;
881   if (GNUNET_NO == create)
882     return NULL;
883   cp = GNUNET_new (struct CadetPeer);
884   cp->pid = *peer_id;
885   cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
886                                                            GNUNET_YES);
887   cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
888   GNUNET_assert (GNUNET_YES ==
889                  GNUNET_CONTAINER_multipeermap_put (peers,
890                                                     &cp->pid,
891                                                     cp,
892                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
893   LOG (GNUNET_ERROR_TYPE_DEBUG,
894        "Creating peer %s\n",
895        GCP_2s (cp));
896   return cp;
897 }
898
899
900 /**
901  * Obtain the peer identity for a `struct CadetPeer`.
902  *
903  * @param cp our peer handle
904  * @return the peer identity
905  */
906 const struct GNUNET_PeerIdentity *
907 GCP_get_id (struct CadetPeer *cp)
908 {
909   return &cp->pid;
910 }
911
912
913 /**
914  * Iterate over all known peers.
915  *
916  * @param iter Iterator.
917  * @param cls Closure for @c iter.
918  */
919 void
920 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
921                  void *cls)
922 {
923   GNUNET_CONTAINER_multipeermap_iterate (peers,
924                                          iter,
925                                          cls);
926 }
927
928
929 /**
930  * Count the number of known paths toward the peer.
931  *
932  * @param cp Peer to get path info.
933  * @return Number of known paths.
934  */
935 unsigned int
936 GCP_count_paths (const struct CadetPeer *cp)
937 {
938   return cp->num_paths;
939 }
940
941
942 /**
943  * Iterate over the paths to a peer.
944  *
945  * @param cp Peer to get path info.
946  * @param callback Function to call for every path.
947  * @param callback_cls Closure for @a callback.
948  * @return Number of iterated paths.
949  */
950 unsigned int
951 GCP_iterate_paths (struct CadetPeer *cp,
952                    GCP_PathIterator callback,
953                    void *callback_cls)
954 {
955   unsigned int ret = 0;
956
957   LOG (GNUNET_ERROR_TYPE_DEBUG,
958        "Iterating over paths to peer %s%s\n",
959        GCP_2s (cp),
960        (NULL == cp->core_mq) ? "" : " including direct link");
961   if (NULL != cp->core_mq)
962   {
963     struct CadetPeerPath *path;
964
965     path = GCPP_get_path_from_route (1,
966                                      &cp->pid);
967     ret++;
968     if (GNUNET_NO ==
969         callback (callback_cls,
970                   path,
971                   1))
972       return ret;
973   }
974   for (unsigned int i=0;i<cp->path_dll_length;i++)
975   {
976     for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
977          NULL != pe;
978          pe = pe->next)
979     {
980       ret++;
981       if (GNUNET_NO ==
982           callback (callback_cls,
983                     pe->path,
984                     i))
985         return ret;
986     }
987   }
988   return ret;
989 }
990
991
992 /**
993  * Iterate over the paths to @a cp where
994  * @a cp is at distance @a dist from us.
995  *
996  * @param cp Peer to get path info.
997  * @param dist desired distance of @a cp to us on the path
998  * @param callback Function to call for every path.
999  * @param callback_cls Closure for @a callback.
1000  * @return Number of iterated paths.
1001  */
1002 unsigned int
1003 GCP_iterate_paths_at (struct CadetPeer *cp,
1004                       unsigned int dist,
1005                       GCP_PathIterator callback,
1006                       void *callback_cls)
1007 {
1008   unsigned int ret = 0;
1009
1010   if (dist >= cp->path_dll_length)
1011   {
1012     LOG (GNUNET_ERROR_TYPE_DEBUG,
1013          "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1014          dist,
1015          cp->path_dll_length);
1016     return 0;
1017   }
1018   for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1019        NULL != pe;
1020        pe = pe->next)
1021   {
1022     if (GNUNET_NO ==
1023         callback (callback_cls,
1024                   pe->path,
1025                   dist))
1026       return ret;
1027     ret++;
1028   }
1029   return ret;
1030 }
1031
1032
1033 /**
1034  * Get the tunnel towards a peer.
1035  *
1036  * @param cp Peer to get from.
1037  * @param create #GNUNET_YES to create a tunnel if we do not have one
1038  * @return Tunnel towards peer.
1039  */
1040 struct CadetTunnel *
1041 GCP_get_tunnel (struct CadetPeer *cp,
1042                 int create)
1043 {
1044   if (NULL == cp)
1045     return NULL;
1046   if ( (NULL != cp->t) ||
1047        (GNUNET_NO == create) )
1048     return cp->t;
1049   cp->t = GCT_create_tunnel (cp);
1050   consider_peer_activate (cp);
1051   return cp->t;
1052 }
1053
1054
1055 /**
1056  * Hello offer was passed to the transport service. Mark it
1057  * as done.
1058  *
1059  * @param cls the `struct CadetPeer` where the offer completed
1060  */
1061 static void
1062 hello_offer_done (void *cls)
1063 {
1064   struct CadetPeer *cp = cls;
1065
1066   cp->hello_offer = NULL;
1067 }
1068
1069
1070 /**
1071  * We got a HELLO for a @a peer, remember it, and possibly
1072  * trigger adequate actions (like trying to connect).
1073  *
1074  * @param cp the peer we got a HELLO for
1075  * @param hello the HELLO to remember
1076  */
1077 void
1078 GCP_set_hello (struct CadetPeer *cp,
1079                const struct GNUNET_HELLO_Message *hello)
1080 {
1081   struct GNUNET_HELLO_Message *mrg;
1082
1083   LOG (GNUNET_ERROR_TYPE_DEBUG,
1084        "Got %u byte HELLO for peer %s\n",
1085        (unsigned int) GNUNET_HELLO_size (hello),
1086        GCP_2s (cp));
1087   if (NULL != cp->hello_offer)
1088   {
1089     GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
1090     cp->hello_offer = NULL;
1091   }
1092   if (NULL != cp->hello)
1093   {
1094     mrg = GNUNET_HELLO_merge (hello,
1095                               cp->hello);
1096     GNUNET_free (cp->hello);
1097     cp->hello = mrg;
1098   }
1099   else
1100   {
1101     cp->hello = GNUNET_memdup (hello,
1102                                GNUNET_HELLO_size (hello));
1103   }
1104   cp->hello_offer
1105     = GNUNET_TRANSPORT_offer_hello (cfg,
1106                                     GNUNET_HELLO_get_header (cp->hello) ,
1107                                     &hello_offer_done,
1108                                     cp);
1109   /* New HELLO means cp's destruction time may change... */
1110   consider_peer_destroy (cp);
1111 }
1112
1113
1114 /**
1115  * The tunnel to the given peer no longer exists, remove it from our
1116  * data structures, and possibly clean up the peer itself.
1117  *
1118  * @param cp the peer affected
1119  * @param t the dead tunnel
1120  */
1121 void
1122 GCP_drop_tunnel (struct CadetPeer *cp,
1123                  struct CadetTunnel *t)
1124 {
1125   LOG (GNUNET_ERROR_TYPE_DEBUG,
1126        "Dropping tunnel %s to peer %s\n",
1127        GCT_2s (t),
1128        GCP_2s (cp));
1129   GNUNET_assert (cp->t == t);
1130   cp->t = NULL;
1131   consider_peer_destroy (cp);
1132 }
1133
1134
1135 /**
1136  * Test if @a cp has a core-level connection
1137  *
1138  * @param cp peer to test
1139  * @return #GNUNET_YES if @a cp has a core-level connection
1140  */
1141 int
1142 GCP_has_core_connection (struct CadetPeer *cp)
1143 {
1144   return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1145 }
1146
1147
1148 /**
1149  * Start message queue change notifications.
1150  *
1151  * @param cp peer to notify for
1152  * @param cb function to call if mq becomes available or unavailable
1153  * @param cb_cls closure for @a cb
1154  * @return handle to cancel request
1155  */
1156 struct GCP_MessageQueueManager *
1157 GCP_request_mq (struct CadetPeer *cp,
1158                 GCP_MessageQueueNotificationCallback cb,
1159                 void *cb_cls)
1160 {
1161   struct GCP_MessageQueueManager *mqm;
1162
1163   mqm = GNUNET_new (struct GCP_MessageQueueManager);
1164   mqm->cb = cb;
1165   mqm->cb_cls = cb_cls;
1166   mqm->cp = cp;
1167   GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1168                                cp->mqm_tail,
1169                                mqm);
1170   LOG (GNUNET_ERROR_TYPE_DEBUG,
1171        "Creating MQM %p for peer %s\n",
1172        mqm,
1173        GCP_2s (cp));
1174   if (NULL != cp->core_mq)
1175     cb (cb_cls,
1176         GNUNET_YES);
1177   return mqm;
1178 }
1179
1180
1181 /**
1182  * Stops message queue change notifications.
1183  *
1184  * @param mqm handle matching request to cancel
1185  * @param last_env final message to transmit, or NULL
1186  */
1187 void
1188 GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1189                        struct GNUNET_MQ_Envelope *last_env)
1190 {
1191   struct CadetPeer *cp = mqm->cp;
1192
1193   LOG (GNUNET_ERROR_TYPE_DEBUG,
1194        "Destroying MQM %p for peer %s%s\n",
1195        mqm,
1196        GCP_2s (cp),
1197        (NULL == last_env) ? "" : " with last ditch transmission");
1198   if (NULL != mqm->env)
1199     GNUNET_MQ_discard (mqm->env);
1200   if (NULL != last_env)
1201   {
1202     if (NULL != cp->core_mq)
1203       GNUNET_MQ_send (cp->core_mq,
1204                       last_env);
1205     else
1206       GNUNET_MQ_discard (last_env);
1207   }
1208   GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1209                                cp->mqm_tail,
1210                                mqm);
1211   GNUNET_free (mqm);
1212 }
1213
1214
1215 /**
1216  * Send the message in @a env to @a cp, overriding queueing logic.
1217  * This function should only be used to send error messages outside
1218  * of flow and congestion control, similar to ICMP.  Note that
1219  * the envelope may be silently discarded as well.
1220  *
1221  * @param cp peer to send the message to
1222  * @param env envelope with the message to send
1223  */
1224 void
1225 GCP_send_ooo (struct CadetPeer *cp,
1226               struct GNUNET_MQ_Envelope *env)
1227 {
1228   LOG (GNUNET_ERROR_TYPE_DEBUG,
1229        "Sending message to %s out of management\n",
1230        GCP_2s (cp));
1231   if (NULL == cp->core_mq)
1232   {
1233     GNUNET_MQ_discard (env);
1234     return;
1235   }
1236   GNUNET_MQ_send (cp->core_mq,
1237                   env);
1238 }
1239
1240
1241
1242
1243 /* end of gnunet-service-cadet-new_peer.c */