Don't pass NULL to destroy_route
[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   for (unsigned int i=0;i<cp->path_dll_length;i++)
331     GNUNET_assert (NULL == cp->path_heads[i]);
332   GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
333   GNUNET_assert (GNUNET_YES ==
334                  GNUNET_CONTAINER_multipeermap_remove (peers,
335                                                        &cp->pid,
336                                                        cp));
337   GNUNET_free_non_null (cp->path_heads);
338   GNUNET_free_non_null (cp->path_tails);
339   cp->path_dll_length = 0;
340   if (NULL != cp->search_h)
341   {
342     GCD_search_stop (cp->search_h);
343     cp->search_h = NULL;
344   }
345   /* FIXME: clean up search_delayedXXX! */
346
347   if (NULL != cp->hello_offer)
348   {
349     GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
350     cp->hello_offer = NULL;
351   }
352   if (NULL != cp->connectivity_suggestion)
353   {
354     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
355     cp->connectivity_suggestion = NULL;
356   }
357   GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
358   if (NULL != cp->path_heap)
359   {
360     GNUNET_CONTAINER_heap_destroy (cp->path_heap);
361     cp->path_heap = NULL;
362   }
363   GNUNET_free_non_null (cp->hello);
364   /* Peer should not be freed if paths exist; if there are no paths,
365      there ought to be no connections, and without connections, no
366      notifications. Thus we can assert that mqm_head is empty at this
367      point. */
368   GNUNET_assert (NULL == cp->mqm_head);
369   GNUNET_assert (NULL == cp->mqm_ready_ptr);
370   GNUNET_free (cp);
371 }
372
373
374 /**
375  * This peer is now on more "active" duty, activate processes related to it.
376  *
377  * @param cp the more-active peer
378  */
379 static void
380 consider_peer_activate (struct CadetPeer *cp)
381 {
382   uint32_t strength;
383
384   LOG (GNUNET_ERROR_TYPE_DEBUG,
385        "Updating peer %s activation state (%u connections)%s%s\n",
386        GCP_2s (cp),
387        GNUNET_CONTAINER_multishortmap_size (cp->connections),
388        (NULL == cp->t) ? "" : " with tunnel",
389        (NULL == cp->core_mq) ? "" : " with CORE link");
390   if (NULL != cp->destroy_task)
391   {
392     /* It's active, do not destory! */
393     GNUNET_SCHEDULER_cancel (cp->destroy_task);
394     cp->destroy_task = NULL;
395   }
396   if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
397        (NULL == cp->t) )
398   {
399     /* We're just on a path or directly connected; don't bother too much */
400     if (NULL != cp->connectivity_suggestion)
401     {
402       GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
403       cp->connectivity_suggestion = NULL;
404     }
405     if (NULL != cp->search_h)
406     {
407       GCD_search_stop (cp->search_h);
408       cp->search_h = NULL;
409     }
410     return;
411   }
412   if (NULL == cp->core_mq)
413   {
414     /* Lacks direct connection, try to create one by querying the DHT */
415     if ( (NULL == cp->search_h) &&
416          (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
417       cp->search_h
418         = GCD_search (&cp->pid);
419   }
420   else
421   {
422     /* Have direct connection, stop DHT search if active */
423     if (NULL != cp->search_h)
424     {
425       GCD_search_stop (cp->search_h);
426       cp->search_h = NULL;
427     }
428   }
429
430   /* If we have a tunnel, our urge for connections is much bigger */
431   strength = (NULL != cp->t) ? 32 : 1;
432   if (NULL != cp->connectivity_suggestion)
433     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
434   cp->connectivity_suggestion
435     = GNUNET_ATS_connectivity_suggest (ats_ch,
436                                        &cp->pid,
437                                        strength);
438 }
439
440
441 /**
442  * This peer may no longer be needed, consider cleaning it up.
443  *
444  * @param cp peer to clean up
445  */
446 static void
447 consider_peer_destroy (struct CadetPeer *cp);
448
449
450 /**
451  * We really no longere care about a peer, stop hogging memory with paths to it.
452  * Afterwards, see if there is more to be cleaned up about this peer.
453  *
454  * @param cls a `struct CadetPeer`.
455  */
456 static void
457 drop_paths (void *cls)
458 {
459   struct CadetPeer *cp = cls;
460   struct CadetPeerPath *path;
461
462   cp->destroy_task = NULL;
463   while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
464     GCPP_release (path);
465   consider_peer_destroy (cp);
466 }
467
468
469 /**
470  * This peer may no longer be needed, consider cleaning it up.
471  *
472  * @param cp peer to clean up
473  */
474 static void
475 consider_peer_destroy (struct CadetPeer *cp)
476 {
477   struct GNUNET_TIME_Relative exp;
478
479   if (NULL != cp->destroy_task)
480   {
481     GNUNET_SCHEDULER_cancel (cp->destroy_task);
482     cp->destroy_task = NULL;
483   }
484   if (NULL != cp->t)
485     return; /* still relevant! */
486   if (NULL != cp->core_mq)
487     return; /* still relevant! */
488   if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
489     return; /* still relevant! */
490   if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))
491   {
492     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
493                                                      &drop_paths,
494                                                      cp);
495     return;
496   }
497   for (unsigned int i=0;i<cp->path_dll_length;i++)
498     if (NULL != cp->path_heads[i])
499       return; /* still relevant! */
500   if (NULL != cp->hello)
501   {
502     /* relevant only until HELLO expires */
503     exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
504     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
505                                                      &destroy_peer,
506                                                      cp);
507     return;
508   }
509   cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
510                                                    &destroy_peer,
511                                                    cp);
512 }
513
514
515 /**
516  * Set the message queue to @a mq for peer @a cp and notify watchers.
517  *
518  * @param cp peer to modify
519  * @param mq message queue to set (can be NULL)
520  */
521 void
522 GCP_set_mq (struct CadetPeer *cp,
523             struct GNUNET_MQ_Handle *mq)
524 {
525   LOG (GNUNET_ERROR_TYPE_DEBUG,
526        "Message queue for peer %s is now %p\n",
527        GCP_2s (cp),
528        mq);
529   cp->core_mq = mq;
530   for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
531        NULL != mqm;
532        mqm = mqm->next)
533   {
534     if (NULL == mq)
535     {
536       if (NULL != mqm->env)
537       {
538         GNUNET_MQ_discard (mqm->env);
539         mqm->env = NULL;
540         mqm->cb (mqm->cb_cls,
541                  GNUNET_SYSERR);
542       }
543       else
544       {
545         mqm->cb (mqm->cb_cls,
546                  GNUNET_NO);
547       }
548     }
549     else
550     {
551       GNUNET_assert (NULL == mqm->env);
552       mqm->cb (mqm->cb_cls,
553                GNUNET_YES);
554     }
555   }
556   if ( (NULL != mq) ||
557        (NULL != cp->t) )
558     consider_peer_activate (cp);
559   else
560     consider_peer_destroy (cp);
561
562   if ( (NULL != mq) &&
563        (NULL != cp->t) )
564   {
565     /* have a new, direct path to the target, notify tunnel */
566     struct CadetPeerPath *path;
567
568     path = GCPP_get_path_from_route (1,
569                                      &cp->pid);
570     GCT_consider_path (cp->t,
571                        path,
572                        0);
573   }
574 }
575
576
577 /**
578  * Debug function should NEVER return true in production code, useful to
579  * simulate losses for testcases.
580  *
581  * @return #GNUNET_YES or #GNUNET_NO with the decision to drop.
582  */
583 static int
584 should_I_drop (void)
585 {
586   if (0 == drop_percent)
587     return GNUNET_NO;
588   if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
589                                 101) < drop_percent)
590     return GNUNET_YES;
591   return GNUNET_NO;
592 }
593
594
595 /**
596  * Function called when CORE took one of the messages from
597  * a message queue manager and transmitted it.
598  *
599  * @param cls the `struct CadetPeeer` where we made progress
600  */
601 static void
602 mqm_send_done (void *cls);
603
604
605 /**
606  * Transmit current envelope from this @a mqm.
607  *
608  * @param mqm mqm to transmit message for now
609  */
610 static void
611 mqm_execute (struct GCP_MessageQueueManager *mqm)
612 {
613   struct CadetPeer *cp = mqm->cp;
614
615   /* Move ready pointer to the next entry that might be ready. */
616   if ( (mqm == cp->mqm_ready_ptr) &&
617        (NULL != mqm->next) )
618     cp->mqm_ready_ptr = mqm->next;
619   /* Move entry to the end of the DLL, to be fair. */
620   if (mqm != cp->mqm_tail)
621   {
622     GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
623                                  cp->mqm_tail,
624                                  mqm);
625     GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
626                                       cp->mqm_tail,
627                                       mqm);
628   }
629   cp->mqm_ready_counter--;
630   if (GNUNET_YES == should_I_drop ())
631   {
632     LOG (GNUNET_ERROR_TYPE_DEBUG,
633          "DROPPING message to peer %s from MQM %p\n",
634          GCP_2s (cp),
635          mqm);
636     GNUNET_MQ_discard (mqm->env);
637     mqm->env = NULL;
638     mqm_send_done (cp);
639   }
640   else
641   {
642     LOG (GNUNET_ERROR_TYPE_DEBUG,
643          "Sending to peer %s from MQM %p\n",
644          GCP_2s (cp),
645          mqm);
646     GNUNET_MQ_send (cp->core_mq,
647                     mqm->env);
648     mqm->env = NULL;
649   }
650   mqm->cb (mqm->cb_cls,
651            GNUNET_YES);
652 }
653
654
655 /**
656  * Find the next ready message in the queue (starting
657  * the search from the `cp->mqm_ready_ptr`) and if possible
658  * execute the transmission.
659  *
660  * @param cp peer to try to send the next ready message to
661  */
662 static void
663 send_next_ready (struct CadetPeer *cp)
664 {
665   struct GCP_MessageQueueManager *mqm;
666
667   if (0 == cp->mqm_ready_counter)
668     return;
669   while ( (NULL != (mqm = cp->mqm_ready_ptr)) &&
670           (NULL == mqm->env) )
671     cp->mqm_ready_ptr = mqm->next;
672   if (NULL == mqm)
673     return; /* nothing to do */
674   mqm_execute (mqm);
675 }
676
677
678 /**
679  * Function called when CORE took one of the messages from
680  * a message queue manager and transmitted it.
681  *
682  * @param cls the `struct CadetPeeer` where we made progress
683  */
684 static void
685 mqm_send_done (void *cls)
686 {
687   struct CadetPeer *cp = cls;
688
689   LOG (GNUNET_ERROR_TYPE_DEBUG,
690        "Sending to peer %s completed\n",
691        GCP_2s (cp));
692   send_next_ready (cp);
693 }
694
695
696 /**
697  * Send the message in @a env to @a cp.
698  *
699  * @param mqm the message queue manager to use for transmission
700  * @param env envelope with the message to send; must NOT
701  *            yet have a #GNUNET_MQ_notify_sent() callback attached to it
702  */
703 void
704 GCP_send (struct GCP_MessageQueueManager *mqm,
705           struct GNUNET_MQ_Envelope *env)
706 {
707   struct CadetPeer *cp = mqm->cp;
708
709   GNUNET_assert (NULL != env);
710   LOG (GNUNET_ERROR_TYPE_DEBUG,
711        "Queueing message to peer %s in MQM %p\n",
712        GCP_2s (cp),
713        mqm);
714   GNUNET_assert (NULL != cp->core_mq);
715   GNUNET_assert (NULL == mqm->env);
716   GNUNET_MQ_notify_sent (env,
717                          &mqm_send_done,
718                          cp);
719   mqm->env = env;
720   cp->mqm_ready_counter++;
721   if (mqm != cp->mqm_ready_ptr)
722     cp->mqm_ready_ptr = cp->mqm_head;
723   if (1 == cp->mqm_ready_counter)
724     cp->mqm_ready_ptr = mqm;
725   if (0 != GNUNET_MQ_get_length (cp->core_mq))
726     return;
727   send_next_ready (cp);
728 }
729
730
731 /**
732  * Function called to destroy a peer now.
733  *
734  * @param cls NULL
735  * @param pid identity of the peer (unused)
736  * @param value the `struct CadetPeer` to clean up
737  * @return #GNUNET_OK (continue to iterate)
738  */
739 static int
740 destroy_iterator_cb (void *cls,
741                      const struct GNUNET_PeerIdentity *pid,
742                      void *value)
743 {
744   struct CadetPeer *cp = value;
745
746   if (NULL != cp->destroy_task)
747   {
748     GNUNET_SCHEDULER_cancel (cp->destroy_task);
749     cp->destroy_task = NULL;
750   }
751   destroy_peer (cp);
752   return GNUNET_OK;
753 }
754
755
756 /**
757  * Clean up all entries about all peers.
758  * Must only be called after all tunnels, CORE-connections and
759  * connections are down.
760  */
761 void
762 GCP_destroy_all_peers ()
763 {
764   LOG (GNUNET_ERROR_TYPE_DEBUG,
765        "Destroying all peers now\n");
766   GNUNET_CONTAINER_multipeermap_iterate (peers,
767                                          &destroy_iterator_cb,
768                                          NULL);
769 }
770
771
772 /**
773  * Drop all paths owned by this peer, and do not
774  * allow new ones to be added: We are shutting down.
775  *
776  * @param cp peer to drop paths to
777  */
778 void
779 GCP_drop_owned_paths (struct CadetPeer *cp)
780 {
781   struct CadetPeerPath *path;
782
783   LOG (GNUNET_ERROR_TYPE_DEBUG,
784        "Destroying all paths to %s\n",
785        GCP_2s (cp));
786   while (NULL != (path =
787                   GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
788     GCPP_release (path);
789   GNUNET_CONTAINER_heap_destroy (cp->path_heap);
790   cp->path_heap = NULL;
791 }
792
793
794 /**
795  * Add an entry to the DLL of all of the paths that this peer is on.
796  *
797  * @param cp peer to modify
798  * @param entry an entry on a path
799  * @param off offset of this peer on the path
800  */
801 void
802 GCP_path_entry_add (struct CadetPeer *cp,
803                     struct CadetPeerPathEntry *entry,
804                     unsigned int off)
805 {
806   GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path,
807                                                 off));
808   LOG (GNUNET_ERROR_TYPE_DEBUG,
809        "Discovered that peer %s is on path %s at offset %u\n",
810        GCP_2s (cp),
811        GCPP_2s (entry->path),
812        off);
813   if (off >= cp->path_dll_length)
814   {
815     unsigned int len = cp->path_dll_length;
816
817     GNUNET_array_grow (cp->path_heads,
818                        len,
819                        off + 4);
820     GNUNET_array_grow (cp->path_tails,
821                        cp->path_dll_length,
822                        off + 4);
823   }
824   GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
825                                cp->path_tails[off],
826                                entry);
827   cp->off_sum += off;
828   cp->num_paths++;
829
830   /* If we have a tunnel to this peer, tell the tunnel that there is a
831      new path available. */
832   if (NULL != cp->t)
833     GCT_consider_path (cp->t,
834                        entry->path,
835                        off);
836
837   if ( (NULL != cp->search_h) &&
838        (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths) )
839   {
840     /* Now I have enough paths, stop search */
841     GCD_search_stop (cp->search_h);
842     cp->search_h = NULL;
843   }
844 }
845
846
847 /**
848  * Remove an entry from the DLL of all of the paths that this peer is on.
849  *
850  * @param cp peer to modify
851  * @param entry an entry on a path
852  * @param off offset of this peer on the path
853  */
854 void
855 GCP_path_entry_remove (struct CadetPeer *cp,
856                        struct CadetPeerPathEntry *entry,
857                        unsigned int off)
858 {
859   LOG (GNUNET_ERROR_TYPE_DEBUG,
860        "Removing knowledge about peer %s beging on path %s at offset %u\n",
861        GCP_2s (cp),
862        GCPP_2s (entry->path),
863        off);
864   GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
865                                cp->path_tails[off],
866                                entry);
867   GNUNET_assert (0 < cp->num_paths);
868   cp->off_sum -= off;
869   cp->num_paths--;
870   if ( (NULL == cp->core_mq) &&
871        (NULL != cp->t) &&
872        (NULL == cp->search_h) &&
873        (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
874     cp->search_h
875       = GCD_search (&cp->pid);
876 }
877
878
879 /**
880  * Try adding a @a path to this @a peer.  If the peer already
881  * has plenty of paths, return NULL.
882  *
883  * @param cp peer to which the @a path leads to
884  * @param path a path looking for an owner; may not be fully initialized yet!
885  * @param off offset of @a cp in @a path
886  * @param force force attaching the path
887  * @return NULL if this peer does not care to become a new owner,
888  *         otherwise the node in the peer's path heap for the @a path.
889  */
890 struct GNUNET_CONTAINER_HeapNode *
891 GCP_attach_path (struct CadetPeer *cp,
892                  struct CadetPeerPath *path,
893                  unsigned int off,
894                  int force)
895 {
896   GNUNET_CONTAINER_HeapCostType desirability;
897   struct CadetPeerPath *root;
898   GNUNET_CONTAINER_HeapCostType root_desirability;
899   struct GNUNET_CONTAINER_HeapNode *hn;
900
901   GNUNET_assert (cp == GCPP_get_peer_at_offset (path,
902                                                 off));
903   if (NULL == cp->path_heap)
904   {
905     /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */
906     GNUNET_assert (GNUNET_NO == force);
907     return NULL;
908   }
909   desirability = GCPP_get_desirability (path);
910   if (GNUNET_NO == force)
911   {
912     /* FIXME: desirability is not yet initialized; tricky! */
913     if (GNUNET_NO ==
914         GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
915                                      (void **) &root,
916                                      &root_desirability))
917     {
918       root = NULL;
919       root_desirability = 0;
920     }
921
922     if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
923          (desirability < root_desirability) )
924     {
925       LOG (GNUNET_ERROR_TYPE_DEBUG,
926            "Decided to not attach path %p to peer %s due to undesirability\n",
927            GCPP_2s (path),
928            GCP_2s (cp));
929       return NULL;
930     }
931   }
932
933   LOG (GNUNET_ERROR_TYPE_DEBUG,
934        "Attaching path %s to peer %s (%s)\n",
935        GCPP_2s (path),
936        GCP_2s (cp),
937        (GNUNET_NO == force) ? "desirable" : "forced");
938
939   /* Yes, we'd like to add this path, add to our heap */
940   hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
941                                      path,
942                                      desirability);
943
944   /* Consider maybe dropping other paths because of the new one */
945   if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
946       2 * DESIRED_CONNECTIONS_PER_TUNNEL)
947   {
948     /* Now we have way too many, drop least desirable UNLESS it is in use!
949        (Note that this intentionally keeps highly desireable, but currently
950        unused paths around in the hope that we might be able to switch, even
951        if the number of paths exceeds the threshold.) */
952     root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
953     if ( (path != root) &&
954          (NULL ==
955           GCPP_get_connection (root,
956                                cp,
957                                GCPP_get_length (root) - 1)) )
958     {
959       /* Got plenty of paths to this destination, and this is a low-quality
960          one that we don't care, allow it to die. */
961       GNUNET_assert (root ==
962                      GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
963       GCPP_release (root);
964     }
965   }
966   return hn;
967 }
968
969
970 /**
971  * This peer can no longer own @a path as the path
972  * has been extended and a peer further down the line
973  * is now the new owner.
974  *
975  * @param cp old owner of the @a path
976  * @param path path where the ownership is lost
977  * @param hn note in @a cp's path heap that must be deleted
978  */
979 void
980 GCP_detach_path (struct CadetPeer *cp,
981                  struct CadetPeerPath *path,
982                  struct GNUNET_CONTAINER_HeapNode *hn)
983 {
984   LOG (GNUNET_ERROR_TYPE_DEBUG,
985        "Detatching path %s from peer %s\n",
986        GCPP_2s (path),
987        GCP_2s (cp));
988   GNUNET_assert (path ==
989                  GNUNET_CONTAINER_heap_remove_node (hn));
990 }
991
992
993 /**
994  * Add a @a connection to this @a cp.
995  *
996  * @param cp peer via which the @a connection goes
997  * @param cc the connection to add
998  */
999 void
1000 GCP_add_connection (struct CadetPeer *cp,
1001                     struct CadetConnection *cc)
1002 {
1003   LOG (GNUNET_ERROR_TYPE_DEBUG,
1004        "Adding connection %s to peer %s\n",
1005        GCC_2s (cc),
1006        GCP_2s (cp));
1007   GNUNET_assert (GNUNET_OK ==
1008                  GNUNET_CONTAINER_multishortmap_put (cp->connections,
1009                                                      &GCC_get_id (cc)->connection_of_tunnel,
1010                                                      cc,
1011                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1012 }
1013
1014
1015 /**
1016  * Remove a @a connection that went via this @a cp.
1017  *
1018  * @param cp peer via which the @a connection went
1019  * @param cc the connection to remove
1020  */
1021 void
1022 GCP_remove_connection (struct CadetPeer *cp,
1023                        struct CadetConnection *cc)
1024 {
1025   LOG (GNUNET_ERROR_TYPE_DEBUG,
1026        "Removing connection %s from peer %s\n",
1027        GCC_2s (cc),
1028        GCP_2s (cp));
1029   GNUNET_assert (GNUNET_YES ==
1030                  GNUNET_CONTAINER_multishortmap_remove (cp->connections,
1031                                                         &GCC_get_id (cc)->connection_of_tunnel,
1032                                                         cc));
1033 }
1034
1035
1036 /**
1037  * Retrieve the CadetPeer stucture associated with the
1038  * peer. Optionally create one and insert it in the appropriate
1039  * structures if the peer is not known yet.
1040  *
1041  * @param peer_id Full identity of the peer.
1042  * @param create #GNUNET_YES if a new peer should be created if unknown.
1043  *               #GNUNET_NO to return NULL if peer is unknown.
1044  * @return Existing or newly created peer structure.
1045  *         NULL if unknown and not requested @a create
1046  */
1047 struct CadetPeer *
1048 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
1049          int create)
1050 {
1051   struct CadetPeer *cp;
1052
1053   cp = GNUNET_CONTAINER_multipeermap_get (peers,
1054                                           peer_id);
1055   if (NULL != cp)
1056     return cp;
1057   if (GNUNET_NO == create)
1058     return NULL;
1059   cp = GNUNET_new (struct CadetPeer);
1060   cp->pid = *peer_id;
1061   cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
1062                                                            GNUNET_YES);
1063   cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1064   GNUNET_assert (GNUNET_YES ==
1065                  GNUNET_CONTAINER_multipeermap_put (peers,
1066                                                     &cp->pid,
1067                                                     cp,
1068                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1069   LOG (GNUNET_ERROR_TYPE_DEBUG,
1070        "Creating peer %s\n",
1071        GCP_2s (cp));
1072   return cp;
1073 }
1074
1075
1076 /**
1077  * Obtain the peer identity for a `struct CadetPeer`.
1078  *
1079  * @param cp our peer handle
1080  * @return the peer identity
1081  */
1082 const struct GNUNET_PeerIdentity *
1083 GCP_get_id (struct CadetPeer *cp)
1084 {
1085   return &cp->pid;
1086 }
1087
1088
1089 /**
1090  * Iterate over all known peers.
1091  *
1092  * @param iter Iterator.
1093  * @param cls Closure for @c iter.
1094  */
1095 void
1096 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
1097                  void *cls)
1098 {
1099   GNUNET_CONTAINER_multipeermap_iterate (peers,
1100                                          iter,
1101                                          cls);
1102 }
1103
1104
1105 /**
1106  * Count the number of known paths toward the peer.
1107  *
1108  * @param cp Peer to get path info.
1109  * @return Number of known paths.
1110  */
1111 unsigned int
1112 GCP_count_paths (const struct CadetPeer *cp)
1113 {
1114   return cp->num_paths;
1115 }
1116
1117
1118 /**
1119  * Iterate over the paths to a peer.
1120  *
1121  * @param cp Peer to get path info.
1122  * @param callback Function to call for every path.
1123  * @param callback_cls Closure for @a callback.
1124  * @return Number of iterated paths.
1125  */
1126 unsigned int
1127 GCP_iterate_paths (struct CadetPeer *cp,
1128                    GCP_PathIterator callback,
1129                    void *callback_cls)
1130 {
1131   unsigned int ret = 0;
1132
1133   LOG (GNUNET_ERROR_TYPE_DEBUG,
1134        "Iterating over paths to peer %s%s\n",
1135        GCP_2s (cp),
1136        (NULL == cp->core_mq) ? "" : " including direct link");
1137   if (NULL != cp->core_mq)
1138   {
1139     struct CadetPeerPath *path;
1140
1141     path = GCPP_get_path_from_route (1,
1142                                      &cp->pid);
1143     ret++;
1144     if (GNUNET_NO ==
1145         callback (callback_cls,
1146                   path,
1147                   1))
1148       return ret;
1149   }
1150   for (unsigned int i=0;i<cp->path_dll_length;i++)
1151   {
1152     for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1153          NULL != pe;
1154          pe = pe->next)
1155     {
1156       ret++;
1157       if (GNUNET_NO ==
1158           callback (callback_cls,
1159                     pe->path,
1160                     i))
1161         return ret;
1162     }
1163   }
1164   return ret;
1165 }
1166
1167
1168 /**
1169  * Iterate over the paths to @a cp where
1170  * @a cp is at distance @a dist from us.
1171  *
1172  * @param cp Peer to get path info.
1173  * @param dist desired distance of @a cp to us on the path
1174  * @param callback Function to call for every path.
1175  * @param callback_cls Closure for @a callback.
1176  * @return Number of iterated paths.
1177  */
1178 unsigned int
1179 GCP_iterate_paths_at (struct CadetPeer *cp,
1180                       unsigned int dist,
1181                       GCP_PathIterator callback,
1182                       void *callback_cls)
1183 {
1184   unsigned int ret = 0;
1185
1186   if (dist >= cp->path_dll_length)
1187   {
1188     LOG (GNUNET_ERROR_TYPE_DEBUG,
1189          "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1190          dist,
1191          cp->path_dll_length);
1192     return 0;
1193   }
1194   for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1195        NULL != pe;
1196        pe = pe->next)
1197   {
1198     if (GNUNET_NO ==
1199         callback (callback_cls,
1200                   pe->path,
1201                   dist))
1202       return ret;
1203     ret++;
1204   }
1205   return ret;
1206 }
1207
1208
1209 /**
1210  * Get the tunnel towards a peer.
1211  *
1212  * @param cp Peer to get from.
1213  * @param create #GNUNET_YES to create a tunnel if we do not have one
1214  * @return Tunnel towards peer.
1215  */
1216 struct CadetTunnel *
1217 GCP_get_tunnel (struct CadetPeer *cp,
1218                 int create)
1219 {
1220   if (NULL == cp)
1221     return NULL;
1222   if ( (NULL != cp->t) ||
1223        (GNUNET_NO == create) )
1224     return cp->t;
1225   cp->t = GCT_create_tunnel (cp);
1226   consider_peer_activate (cp);
1227   return cp->t;
1228 }
1229
1230
1231 /**
1232  * Hello offer was passed to the transport service. Mark it
1233  * as done.
1234  *
1235  * @param cls the `struct CadetPeer` where the offer completed
1236  */
1237 static void
1238 hello_offer_done (void *cls)
1239 {
1240   struct CadetPeer *cp = cls;
1241
1242   cp->hello_offer = NULL;
1243 }
1244
1245
1246 /**
1247  * We got a HELLO for a @a peer, remember it, and possibly
1248  * trigger adequate actions (like trying to connect).
1249  *
1250  * @param cp the peer we got a HELLO for
1251  * @param hello the HELLO to remember
1252  */
1253 void
1254 GCP_set_hello (struct CadetPeer *cp,
1255                const struct GNUNET_HELLO_Message *hello)
1256 {
1257   struct GNUNET_HELLO_Message *mrg;
1258
1259   LOG (GNUNET_ERROR_TYPE_DEBUG,
1260        "Got %u byte HELLO for peer %s\n",
1261        (unsigned int) GNUNET_HELLO_size (hello),
1262        GCP_2s (cp));
1263   if (NULL != cp->hello_offer)
1264   {
1265     GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
1266     cp->hello_offer = NULL;
1267   }
1268   if (NULL != cp->hello)
1269   {
1270     mrg = GNUNET_HELLO_merge (hello,
1271                               cp->hello);
1272     GNUNET_free (cp->hello);
1273     cp->hello = mrg;
1274   }
1275   else
1276   {
1277     cp->hello = GNUNET_memdup (hello,
1278                                GNUNET_HELLO_size (hello));
1279   }
1280   cp->hello_offer
1281     = GNUNET_TRANSPORT_offer_hello (cfg,
1282                                     GNUNET_HELLO_get_header (cp->hello) ,
1283                                     &hello_offer_done,
1284                                     cp);
1285   /* New HELLO means cp's destruction time may change... */
1286   consider_peer_destroy (cp);
1287 }
1288
1289
1290 /**
1291  * The tunnel to the given peer no longer exists, remove it from our
1292  * data structures, and possibly clean up the peer itself.
1293  *
1294  * @param cp the peer affected
1295  * @param t the dead tunnel
1296  */
1297 void
1298 GCP_drop_tunnel (struct CadetPeer *cp,
1299                  struct CadetTunnel *t)
1300 {
1301   LOG (GNUNET_ERROR_TYPE_DEBUG,
1302        "Dropping tunnel %s to peer %s\n",
1303        GCT_2s (t),
1304        GCP_2s (cp));
1305   GNUNET_assert (cp->t == t);
1306   cp->t = NULL;
1307   consider_peer_destroy (cp);
1308 }
1309
1310
1311 /**
1312  * Test if @a cp has a core-level connection
1313  *
1314  * @param cp peer to test
1315  * @return #GNUNET_YES if @a cp has a core-level connection
1316  */
1317 int
1318 GCP_has_core_connection (struct CadetPeer *cp)
1319 {
1320   return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1321 }
1322
1323
1324 /**
1325  * Start message queue change notifications.
1326  *
1327  * @param cp peer to notify for
1328  * @param cb function to call if mq becomes available or unavailable
1329  * @param cb_cls closure for @a cb
1330  * @return handle to cancel request
1331  */
1332 struct GCP_MessageQueueManager *
1333 GCP_request_mq (struct CadetPeer *cp,
1334                 GCP_MessageQueueNotificationCallback cb,
1335                 void *cb_cls)
1336 {
1337   struct GCP_MessageQueueManager *mqm;
1338
1339   mqm = GNUNET_new (struct GCP_MessageQueueManager);
1340   mqm->cb = cb;
1341   mqm->cb_cls = cb_cls;
1342   mqm->cp = cp;
1343   GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1344                                cp->mqm_tail,
1345                                mqm);
1346   LOG (GNUNET_ERROR_TYPE_DEBUG,
1347        "Creating MQM %p for peer %s\n",
1348        mqm,
1349        GCP_2s (cp));
1350   if (NULL != cp->core_mq)
1351     cb (cb_cls,
1352         GNUNET_YES);
1353   return mqm;
1354 }
1355
1356
1357 /**
1358  * Stops message queue change notifications.
1359  *
1360  * @param mqm handle matching request to cancel
1361  * @param last_env final message to transmit, or NULL
1362  */
1363 void
1364 GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1365                        struct GNUNET_MQ_Envelope *last_env)
1366 {
1367   struct CadetPeer *cp = mqm->cp;
1368
1369   LOG (GNUNET_ERROR_TYPE_DEBUG,
1370        "Destroying MQM %p for peer %s%s\n",
1371        mqm,
1372        GCP_2s (cp),
1373        (NULL == last_env) ? "" : " with last ditch transmission");
1374   if (NULL != mqm->env)
1375     GNUNET_MQ_discard (mqm->env);
1376   if (NULL != last_env)
1377   {
1378     if (NULL != cp->core_mq)
1379       GNUNET_MQ_send (cp->core_mq,
1380                       last_env);
1381     else
1382       GNUNET_MQ_discard (last_env);
1383   }
1384   if (cp->mqm_ready_ptr == mqm)
1385     cp->mqm_ready_ptr = mqm->next;
1386   GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1387                                cp->mqm_tail,
1388                                mqm);
1389   GNUNET_free (mqm);
1390 }
1391
1392
1393 /**
1394  * Send the message in @a env to @a cp, overriding queueing logic.
1395  * This function should only be used to send error messages outside
1396  * of flow and congestion control, similar to ICMP.  Note that
1397  * the envelope may be silently discarded as well.
1398  *
1399  * @param cp peer to send the message to
1400  * @param env envelope with the message to send
1401  */
1402 void
1403 GCP_send_ooo (struct CadetPeer *cp,
1404               struct GNUNET_MQ_Envelope *env)
1405 {
1406   LOG (GNUNET_ERROR_TYPE_DEBUG,
1407        "Sending message to %s out of management\n",
1408        GCP_2s (cp));
1409   if (NULL == cp->core_mq)
1410   {
1411     GNUNET_MQ_discard (env);
1412     return;
1413   }
1414   GNUNET_MQ_send (cp->core_mq,
1415                   env);
1416 }
1417
1418
1419
1420
1421 /* end of gnunet-service-cadet-new_peer.c */