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