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