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