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