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