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