improving logging
[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 "cadet_path.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 peer Peer.
229  *
230  * @return Static string for it's ID.
231  */
232 const char *
233 GCP_2s (const struct CadetPeer *peer)
234 {
235   static char buf[64];
236
237   GNUNET_snprintf (buf,
238                    sizeof (buf),
239                    "P(%s)",
240                    GNUNET_i2s (&peer->pid));
241   return buf;
242 }
243
244
245 /**
246  * This peer is no longer be needed, clean it up now.
247  *
248  * @param cls peer to clean up
249  */
250 static void
251 destroy_peer (void *cls)
252 {
253   struct CadetPeer *cp = cls;
254
255   LOG (GNUNET_ERROR_TYPE_DEBUG,
256        "Destroying state about peer %s\n",
257        GCP_2s (cp));
258   cp->destroy_task = NULL;
259   GNUNET_assert (NULL == cp->t);
260   GNUNET_assert (NULL == cp->core_mq);
261   GNUNET_assert (0 == cp->path_dll_length);
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   GNUNET_CONTAINER_heap_destroy (cp->path_heap);
289   GNUNET_free_non_null (cp->hello);
290   /* Peer should not be freed if paths exist; if there are no paths,
291      there ought to be no connections, and without connections, no
292      notifications. Thus we can assert that mqm_head is empty at this
293      point. */
294   GNUNET_assert (NULL == cp->mqm_head);
295   GNUNET_free (cp);
296 }
297
298
299 /**
300  * Set the message queue to @a mq for peer @a cp and notify watchers.
301  *
302  * @param cp peer to modify
303  * @param mq message queue to set (can be NULL)
304  */
305 void
306 GCP_set_mq (struct CadetPeer *cp,
307             struct GNUNET_MQ_Handle *mq)
308 {
309   LOG (GNUNET_ERROR_TYPE_DEBUG,
310        "Message queue for peer %s is now %p\n",
311        GCP_2s (cp),
312        mq);
313   cp->core_mq = mq;
314
315   for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
316        NULL != mqm;
317        mqm = mqm->next)
318   {
319     if (NULL == mq)
320     {
321       if (NULL != mqm->env)
322       {
323         GNUNET_MQ_discard (mqm->env);
324         mqm->env = NULL;
325         mqm->cb (mqm->cb_cls,
326                  GNUNET_SYSERR);
327       }
328       else
329       {
330         mqm->cb (mqm->cb_cls,
331                  GNUNET_NO);
332       }
333     }
334     else
335     {
336       GNUNET_assert (NULL == mqm->env);
337       mqm->cb (mqm->cb_cls,
338                GNUNET_YES);
339     }
340   }
341 }
342
343
344 /**
345  * Transmit current envelope from this @a mqm.
346  *
347  * @param mqm mqm to transmit message for now
348  */
349 static void
350 mqm_execute (struct GCP_MessageQueueManager *mqm)
351 {
352   struct CadetPeer *cp = mqm->cp;
353
354   LOG (GNUNET_ERROR_TYPE_DEBUG,
355        "Sending to peer %s from MQM %p\n",
356        GCP_2s (cp),
357        mqm);
358   /* Move entry to the end of the DLL, to be fair. */
359   if (mqm != cp->mqm_tail)
360   {
361     GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
362                                  cp->mqm_tail,
363                                  mqm);
364     GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
365                                       cp->mqm_tail,
366                                       mqm);
367   }
368   GNUNET_MQ_send (cp->core_mq,
369                   mqm->env);
370   mqm->env = NULL;
371   cp->mqm_ready_counter--;
372 }
373
374
375 /**
376  * Function called when CORE took one of the messages from
377  * a message queue manager and transmitted it.
378  *
379  * @param cls the `struct CadetPeeer` where we made progress
380  */
381 static void
382 mqm_send_done (void *cls)
383 {
384   struct CadetPeer *cp = cls;
385
386   LOG (GNUNET_ERROR_TYPE_DEBUG,
387        "Sending to peer %s completed\n",
388        GCP_2s (cp));
389   if (0 == cp->mqm_ready_counter)
390     return; /* nothing to do */
391   for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
392        NULL != mqm;
393        mqm = mqm->next)
394   {
395     if (NULL == mqm->env)
396       continue;
397     mqm_execute (mqm);
398     return;
399   }
400 }
401
402
403 /**
404  * Send the message in @a env to @a cp.
405  *
406  * @param mqm the message queue manager to use for transmission
407  * @param env envelope with the message to send; must NOT
408  *            yet have a #GNUNET_MQ_notify_sent() callback attached to it
409  */
410 void
411 GCP_send (struct GCP_MessageQueueManager *mqm,
412           struct GNUNET_MQ_Envelope *env)
413 {
414   struct CadetPeer *cp = mqm->cp;
415
416   LOG (GNUNET_ERROR_TYPE_DEBUG,
417        "Queueing message to peer %s in MQM %p\n",
418        GCP_2s (cp),
419        mqm);
420   GNUNET_assert (NULL != cp->core_mq);
421   GNUNET_assert (NULL == mqm->env);
422   GNUNET_MQ_notify_sent (env,
423                          &mqm_send_done,
424                          cp);
425   mqm->env = env;
426   cp->mqm_ready_counter++;
427   if (0 != GNUNET_MQ_get_length (cp->core_mq))
428     return;
429   mqm_execute (mqm);
430 }
431
432
433 /**
434  * Function called to destroy a peer now.
435  *
436  * @param cls NULL
437  * @param pid identity of the peer (unused)
438  * @param value the `struct CadetPeer` to clean up
439  * @return #GNUNET_OK (continue to iterate)
440  */
441 static int
442 destroy_iterator_cb (void *cls,
443                      const struct GNUNET_PeerIdentity *pid,
444                      void *value)
445 {
446   struct CadetPeer *cp = value;
447
448   if (NULL != cp->destroy_task)
449   {
450     GNUNET_SCHEDULER_cancel (cp->destroy_task);
451     cp->destroy_task = NULL;
452   }
453   destroy_peer (cp);
454   return GNUNET_OK;
455 }
456
457
458 /**
459  * Clean up all entries about all peers.
460  * Must only be called after all tunnels, CORE-connections and
461  * connections are down.
462  */
463 void
464 GCP_destroy_all_peers ()
465 {
466   LOG (GNUNET_ERROR_TYPE_DEBUG,
467        "Destroying all peers now\n");
468   GNUNET_CONTAINER_multipeermap_iterate (peers,
469                                          &destroy_iterator_cb,
470                                          NULL);
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
483 /**
484  * We really no longere care about a peer, stop hogging memory with paths to it.
485  * Afterwards, see if there is more to be cleaned up about this peer.
486  *
487  * @param cls a `struct CadetPeer`.
488  */
489 static void
490 drop_paths (void *cls)
491 {
492   struct CadetPeer *cp = cls;
493   struct CadetPeerPath *path;
494
495   cp->destroy_task = NULL;
496   while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
497     GCPP_release (path);
498   consider_peer_destroy (cp);
499 }
500
501
502 /**
503  * This peer may no longer be needed, consider cleaning it up.
504  *
505  * @param cp peer to clean up
506  */
507 static void
508 consider_peer_destroy (struct CadetPeer *cp)
509 {
510   struct GNUNET_TIME_Relative exp;
511
512   if (NULL != cp->destroy_task)
513   {
514     GNUNET_SCHEDULER_cancel (cp->destroy_task);
515     cp->destroy_task = NULL;
516   }
517   if (NULL != cp->t)
518     return; /* still relevant! */
519   if (NULL != cp->core_mq)
520     return; /* still relevant! */
521   if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
522     return; /* still relevant! */
523   if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))
524   {
525     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
526                                                      &drop_paths,
527                                                      cp);
528     return;
529   }
530   if (0 < cp->path_dll_length)
531     return; /* still relevant! */
532   if (NULL != cp->hello)
533   {
534     /* relevant only until HELLO expires */
535     exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
536     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
537                                                      &destroy_peer,
538                                                      cp);
539     return;
540   }
541   cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
542                                                    &destroy_peer,
543                                                    cp);
544 }
545
546
547 /**
548  * Add an entry to the DLL of all of the paths that this peer is on.
549  *
550  * @param cp peer to modify
551  * @param entry an entry on a path
552  * @param off offset of this peer on the path
553  */
554 void
555 GCP_path_entry_add (struct CadetPeer *cp,
556                     struct CadetPeerPathEntry *entry,
557                     unsigned int off)
558 {
559   LOG (GNUNET_ERROR_TYPE_DEBUG,
560        "Discovered that peer %s is on path %s at offset %u\n",
561        GCP_2s (cp),
562        GCPP_2s (entry->path),
563        off);
564   if (off >= cp->path_dll_length)
565   {
566     unsigned int len = cp->path_dll_length;
567
568     GNUNET_array_grow (cp->path_heads,
569                        len,
570                        off + 4);
571     GNUNET_array_grow (cp->path_tails,
572                        cp->path_dll_length,
573                        off + 4);
574   }
575   GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
576                                cp->path_tails[off],
577                                entry);
578   cp->num_paths++;
579
580   /* If we have a tunnel to this peer, tell the tunnel that there is a
581      new path available. */
582   if (NULL != cp->t)
583     GCT_consider_path (cp->t,
584                        entry->path,
585                        off);
586 }
587
588
589 /**
590  * Remove an entry from the DLL of all of the paths that this peer is on.
591  *
592  * @param cp peer to modify
593  * @param entry an entry on a path
594  * @param off offset of this peer on the path
595  */
596 void
597 GCP_path_entry_remove (struct CadetPeer *cp,
598                        struct CadetPeerPathEntry *entry,
599                        unsigned int off)
600 {
601   LOG (GNUNET_ERROR_TYPE_DEBUG,
602        "Removing knowledge about peer %s beging on path %s at offset %u\n",
603        GCP_2s (cp),
604        GCPP_2s (entry->path),
605        off);
606   GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
607                                cp->path_tails[off],
608                                entry);
609   GNUNET_assert (0 < cp->num_paths);
610   cp->num_paths--;
611 }
612
613
614 /**
615  * Try adding a @a path to this @a peer.  If the peer already
616  * has plenty of paths, return NULL.
617  *
618  * @param cp peer to which the @a path leads to
619  * @param path a path looking for an owner; may not be fully initialized yet!
620  * @param off offset of @a cp in @a path
621  * @param force force attaching the path
622  * @return NULL if this peer does not care to become a new owner,
623  *         otherwise the node in the peer's path heap for the @a path.
624  */
625 struct GNUNET_CONTAINER_HeapNode *
626 GCP_attach_path (struct CadetPeer *cp,
627                  struct CadetPeerPath *path,
628                  unsigned int off,
629                  int force)
630 {
631   GNUNET_CONTAINER_HeapCostType desirability;
632   struct CadetPeerPath *root;
633   GNUNET_CONTAINER_HeapCostType root_desirability;
634   struct GNUNET_CONTAINER_HeapNode *hn;
635
636   if (GNUNET_NO == force)
637   {
638     /* FIXME: desirability is not yet initialized; tricky! */
639     desirability = GCPP_get_desirability (path);
640     if (GNUNET_NO ==
641         GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
642                                      (void **) &root,
643                                      &root_desirability))
644     {
645       root = NULL;
646       root_desirability = 0;
647     }
648
649     if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
650          (desirability < root_desirability) )
651     {
652       LOG (GNUNET_ERROR_TYPE_DEBUG,
653            "Decided to not attach path %p to peer %s due to undesirability\n",
654            GCPP_2s (path),
655            GCP_2s (cp));
656       return NULL;
657     }
658   }
659
660   LOG (GNUNET_ERROR_TYPE_DEBUG,
661        "Attaching path %p to peer %s (%s)\n",
662        GCPP_2s (path),
663        GCP_2s (cp),
664        (GNUNET_NO == force) ? "desirable" : "forced");
665
666   /* Yes, we'd like to add this path, add to our heap */
667   hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
668                                      (void *) cp,
669                                      desirability);
670
671   /* Consider maybe dropping other paths because of the new one */
672   if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
673       2 * DESIRED_CONNECTIONS_PER_TUNNEL)
674   {
675     /* Now we have way too many, drop least desirable UNLESS it is in use!
676        (Note that this intentionally keeps highly desireable, but currently
677        unused paths around in the hope that we might be able to switch, even
678        if the number of paths exceeds the threshold.) */
679     root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
680     if ( (path != root) &&
681          (NULL ==
682           GCPP_get_connection (root,
683                                cp,
684                                GCPP_get_length (root) - 1)) )
685     {
686       /* Got plenty of paths to this destination, and this is a low-quality
687          one that we don't care, allow it to die. */
688       GNUNET_assert (root ==
689                      GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
690       GCPP_release (root);
691     }
692   }
693   return hn;
694 }
695
696
697 /**
698  * This peer can no longer own @a path as the path
699  * has been extended and a peer further down the line
700  * is now the new owner.
701  *
702  * @param cp old owner of the @a path
703  * @param path path where the ownership is lost
704  * @param hn note in @a cp's path heap that must be deleted
705  */
706 void
707 GCP_detach_path (struct CadetPeer *cp,
708                  struct CadetPeerPath *path,
709                  struct GNUNET_CONTAINER_HeapNode *hn)
710 {
711   LOG (GNUNET_ERROR_TYPE_DEBUG,
712        "Detatching path %p from peer %s\n",
713        GCPP_2s (path),
714        GCP_2s (cp));
715   GNUNET_assert (path ==
716                  GNUNET_CONTAINER_heap_remove_node (hn));
717 }
718
719
720 /**
721  * Add a @a connection to this @a cp.
722  *
723  * @param cp peer via which the @a connection goes
724  * @param cc the connection to add
725  */
726 void
727 GCP_add_connection (struct CadetPeer *cp,
728                     struct CadetConnection *cc)
729 {
730   LOG (GNUNET_ERROR_TYPE_DEBUG,
731        "Adding connection %s to peer %s\n",
732        GCC_2s (cc),
733        GCP_2s (cp));
734   GNUNET_assert (GNUNET_OK ==
735                  GNUNET_CONTAINER_multishortmap_put (cp->connections,
736                                                      &GCC_get_id (cc)->connection_of_tunnel,
737                                                      cc,
738                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
739 }
740
741
742 /**
743  * Remove a @a connection that went via this @a cp.
744  *
745  * @param cp peer via which the @a connection went
746  * @param cc the connection to remove
747  */
748 void
749 GCP_remove_connection (struct CadetPeer *cp,
750                        struct CadetConnection *cc)
751 {
752   LOG (GNUNET_ERROR_TYPE_DEBUG,
753        "Removing connection %s from peer %s\n",
754        GCC_2s (cc),
755        GCP_2s (cp));
756   GNUNET_assert (GNUNET_YES ==
757                  GNUNET_CONTAINER_multishortmap_remove (cp->connections,
758                                                         &GCC_get_id (cc)->connection_of_tunnel,
759                                                         cc));
760 }
761
762
763 /**
764  * This peer is now on more "active" duty, activate processes related to it.
765  *
766  * @param cp the more-active peer
767  */
768 static void
769 consider_peer_activate (struct CadetPeer *cp)
770 {
771   uint32_t strength;
772
773   LOG (GNUNET_ERROR_TYPE_DEBUG,
774        "Updating peer %s activation state (%u connections)%s%s\n",
775        GCP_2s (cp),
776        GNUNET_CONTAINER_multishortmap_size (cp->connections),
777        (NULL == cp->t) ? "" : " with tunnel",
778        (NULL == cp->core_mq) ? "" : " with CORE link");
779   if (NULL != cp->destroy_task)
780   {
781     /* It's active, do not destory! */
782     GNUNET_SCHEDULER_cancel (cp->destroy_task);
783     cp->destroy_task = NULL;
784   }
785   if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
786        (NULL == cp->t) )
787   {
788     /* We're just on a path or directly connected; don't bother too much */
789     if (NULL != cp->connectivity_suggestion)
790     {
791       GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
792       cp->connectivity_suggestion = NULL;
793     }
794     if (NULL != cp->search_h)
795     {
796       GCD_search_stop (cp->search_h);
797       cp->search_h = NULL;
798     }
799     return;
800   }
801   if (NULL == cp->core_mq)
802   {
803     /* Lacks direct connection, try to create one by querying the DHT */
804     if ( (NULL == cp->search_h) &&
805          (DESIRED_CONNECTIONS_PER_TUNNEL < cp->num_paths) )
806       cp->search_h
807         = GCD_search (&cp->pid);
808   }
809   else
810   {
811     /* Have direct connection, stop DHT search if active */
812     if (NULL != cp->search_h)
813     {
814       GCD_search_stop (cp->search_h);
815       cp->search_h = NULL;
816     }
817   }
818
819   /* If we have a tunnel, our urge for connections is much bigger */
820   strength = (NULL != cp->t) ? 32 : 1;
821   if (NULL != cp->connectivity_suggestion)
822     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
823   cp->connectivity_suggestion
824     = GNUNET_ATS_connectivity_suggest (ats_ch,
825                                        &cp->pid,
826                                        strength);
827 }
828
829
830 /**
831  * Retrieve the CadetPeer stucture associated with the
832  * peer. Optionally create one and insert it in the appropriate
833  * structures if the peer is not known yet.
834  *
835  * @param peer_id Full identity of the peer.
836  * @param create #GNUNET_YES if a new peer should be created if unknown.
837  *               #GNUNET_NO to return NULL if peer is unknown.
838  * @return Existing or newly created peer structure.
839  *         NULL if unknown and not requested @a create
840  */
841 struct CadetPeer *
842 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
843          int create)
844 {
845   struct CadetPeer *cp;
846
847   cp = GNUNET_CONTAINER_multipeermap_get (peers,
848                                           peer_id);
849   if (NULL != cp)
850     return cp;
851   if (GNUNET_NO == create)
852     return NULL;
853   cp = GNUNET_new (struct CadetPeer);
854   cp->pid = *peer_id;
855   cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
856                                                            GNUNET_YES);
857   cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
858   GNUNET_assert (GNUNET_YES ==
859                  GNUNET_CONTAINER_multipeermap_put (peers,
860                                                     &cp->pid,
861                                                     cp,
862                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
863   LOG (GNUNET_ERROR_TYPE_DEBUG,
864        "Creating peer %s\n",
865        GCP_2s (cp));
866   return cp;
867 }
868
869
870 /**
871  * Obtain the peer identity for a `struct CadetPeer`.
872  *
873  * @param cp our peer handle
874  * @return the peer identity
875  */
876 const struct GNUNET_PeerIdentity *
877 GCP_get_id (struct CadetPeer *cp)
878 {
879   return &cp->pid;
880 }
881
882
883 /**
884  * Iterate over all known peers.
885  *
886  * @param iter Iterator.
887  * @param cls Closure for @c iter.
888  */
889 void
890 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
891                  void *cls)
892 {
893   GNUNET_CONTAINER_multipeermap_iterate (peers,
894                                          iter,
895                                          cls);
896 }
897
898
899 /**
900  * Count the number of known paths toward the peer.
901  *
902  * @param peer Peer to get path info.
903  * @return Number of known paths.
904  */
905 unsigned int
906 GCP_count_paths (const struct CadetPeer *peer)
907 {
908   return peer->num_paths;
909 }
910
911
912 /**
913  * Iterate over the paths to a peer.
914  *
915  * @param peer Peer to get path info.
916  * @param callback Function to call for every path.
917  * @param callback_cls Closure for @a callback.
918  * @return Number of iterated paths.
919  */
920 unsigned int
921 GCP_iterate_paths (struct CadetPeer *peer,
922                    GCP_PathIterator callback,
923                    void *callback_cls)
924 {
925   unsigned int ret = 0;
926
927   for (unsigned int i=0;i<peer->path_dll_length;i++)
928   {
929     for (struct CadetPeerPathEntry *pe = peer->path_heads[i];
930          NULL != pe;
931          pe = pe->next)
932     {
933       if (GNUNET_NO ==
934           callback (callback_cls,
935                     pe->path,
936                     i))
937         return ret;
938       ret++;
939     }
940   }
941   return ret;
942 }
943
944
945 /**
946  * Iterate over the paths to @a peer where
947  * @a peer is at distance @a dist from us.
948  *
949  * @param peer Peer to get path info.
950  * @param dist desired distance of @a peer to us on the path
951  * @param callback Function to call for every path.
952  * @param callback_cls Closure for @a callback.
953  * @return Number of iterated paths.
954  */
955 unsigned int
956 GCP_iterate_paths_at (struct CadetPeer *peer,
957                       unsigned int dist,
958                       GCP_PathIterator callback,
959                       void *callback_cls)
960 {
961   unsigned int ret = 0;
962
963   if (dist<peer->path_dll_length)
964     return 0;
965   for (struct CadetPeerPathEntry *pe = peer->path_heads[dist];
966        NULL != pe;
967        pe = pe->next)
968   {
969     if (GNUNET_NO ==
970         callback (callback_cls,
971                   pe->path,
972                   dist))
973       return ret;
974     ret++;
975   }
976   return ret;
977 }
978
979
980 /**
981  * Get the tunnel towards a peer.
982  *
983  * @param cp Peer to get from.
984  * @param create #GNUNET_YES to create a tunnel if we do not have one
985  * @return Tunnel towards peer.
986  */
987 struct CadetTunnel *
988 GCP_get_tunnel (struct CadetPeer *cp,
989                 int create)
990 {
991   if (NULL == cp)
992     return NULL;
993   if ( (NULL != cp->t) ||
994        (GNUNET_NO == create) )
995     return cp->t;
996   cp->t = GCT_create_tunnel (cp);
997   consider_peer_activate (cp);
998   return cp->t;
999 }
1000
1001
1002 /**
1003  * Hello offer was passed to the transport service. Mark it
1004  * as done.
1005  *
1006  * @param cls the `struct CadetPeer` where the offer completed
1007  */
1008 static void
1009 hello_offer_done (void *cls)
1010 {
1011   struct CadetPeer *cp = cls;
1012
1013   cp->hello_offer = NULL;
1014 }
1015
1016
1017 /**
1018  * We got a HELLO for a @a peer, remember it, and possibly
1019  * trigger adequate actions (like trying to connect).
1020  *
1021  * @param cp the peer we got a HELLO for
1022  * @param hello the HELLO to remember
1023  */
1024 void
1025 GCP_set_hello (struct CadetPeer *cp,
1026                const struct GNUNET_HELLO_Message *hello)
1027 {
1028   struct GNUNET_HELLO_Message *mrg;
1029
1030   LOG (GNUNET_ERROR_TYPE_DEBUG,
1031        "Got %u byte HELLO for peer %s\n",
1032        (unsigned int) GNUNET_HELLO_size (hello),
1033        GCP_2s (cp));
1034   if (NULL != cp->hello_offer)
1035   {
1036     GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
1037     cp->hello_offer = NULL;
1038   }
1039   if (NULL != cp->hello)
1040   {
1041     mrg = GNUNET_HELLO_merge (hello,
1042                               cp->hello);
1043     GNUNET_free (cp->hello);
1044     cp->hello = mrg;
1045   }
1046   else
1047   {
1048     cp->hello = GNUNET_memdup (hello,
1049                                GNUNET_HELLO_size (hello));
1050   }
1051   cp->hello_offer
1052     = GNUNET_TRANSPORT_offer_hello (cfg,
1053                                     GNUNET_HELLO_get_header (cp->hello) ,
1054                                     &hello_offer_done,
1055                                     cp);
1056   /* New HELLO means cp's destruction time may change... */
1057   consider_peer_destroy (cp);
1058 }
1059
1060
1061 /**
1062  * The tunnel to the given peer no longer exists, remove it from our
1063  * data structures, and possibly clean up the peer itself.
1064  *
1065  * @param cp the peer affected
1066  * @param t the dead tunnel
1067  */
1068 void
1069 GCP_drop_tunnel (struct CadetPeer *cp,
1070                  struct CadetTunnel *t)
1071 {
1072   LOG (GNUNET_ERROR_TYPE_DEBUG,
1073        "Dropping tunnel %s to peer %s\n",
1074        GCT_2s (t),
1075        GCP_2s (cp));
1076   GNUNET_assert (cp->t == t);
1077   cp->t = NULL;
1078   consider_peer_destroy (cp);
1079 }
1080
1081
1082 /**
1083  * Test if @a cp has a core-level connection
1084  *
1085  * @param cp peer to test
1086  * @return #GNUNET_YES if @a cp has a core-level connection
1087  */
1088 int
1089 GCP_has_core_connection (struct CadetPeer *cp)
1090 {
1091   return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1092 }
1093
1094
1095 /**
1096  * Start message queue change notifications.
1097  *
1098  * @param cp peer to notify for
1099  * @param cb function to call if mq becomes available or unavailable
1100  * @param cb_cls closure for @a cb
1101  * @return handle to cancel request
1102  */
1103 struct GCP_MessageQueueManager *
1104 GCP_request_mq (struct CadetPeer *cp,
1105                 GCP_MessageQueueNotificationCallback cb,
1106                 void *cb_cls)
1107 {
1108   struct GCP_MessageQueueManager *mqm;
1109
1110   mqm = GNUNET_new (struct GCP_MessageQueueManager);
1111   mqm->cb = cb;
1112   mqm->cb_cls = cb_cls;
1113   mqm->cp = cp;
1114   GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1115                                cp->mqm_tail,
1116                                mqm);
1117   LOG (GNUNET_ERROR_TYPE_DEBUG,
1118        "Creating MQM %p for peer %s\n",
1119        mqm,
1120        GCP_2s (cp));
1121   if (NULL != cp->core_mq)
1122     cb (cb_cls,
1123         GNUNET_YES);
1124   return mqm;
1125 }
1126
1127
1128 /**
1129  * Stops message queue change notifications.
1130  *
1131  * @param mqm handle matching request to cancel
1132  * @param last_env final message to transmit, or NULL
1133  */
1134 void
1135 GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1136                        struct GNUNET_MQ_Envelope *last_env)
1137 {
1138   struct CadetPeer *cp = mqm->cp;
1139
1140   LOG (GNUNET_ERROR_TYPE_DEBUG,
1141        "Destroying MQM %p for peer %s%s\n",
1142        mqm,
1143        GCP_2s (cp),
1144        (NULL == last_env) ? "" : " with last ditch transmission");
1145   if (NULL != mqm->env)
1146     GNUNET_MQ_discard (mqm->env);
1147   if (NULL != last_env)
1148   {
1149     if (NULL != cp->core_mq)
1150       GNUNET_MQ_send (cp->core_mq,
1151                       last_env);
1152     else
1153       GNUNET_MQ_discard (last_env);
1154   }
1155   GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1156                                cp->mqm_tail,
1157                                mqm);
1158   GNUNET_free (mqm);
1159 }
1160
1161
1162 /**
1163  * Send the message in @a env to @a cp, overriding queueing logic.
1164  * This function should only be used to send error messages outside
1165  * of flow and congestion control, similar to ICMP.  Note that
1166  * the envelope may be silently discarded as well.
1167  *
1168  * @param cp peer to send the message to
1169  * @param env envelope with the message to send
1170  */
1171 void
1172 GCP_send_ooo (struct CadetPeer *cp,
1173               struct GNUNET_MQ_Envelope *env)
1174 {
1175   LOG (GNUNET_ERROR_TYPE_DEBUG,
1176        "Sending message to %s out of management\n",
1177        GCP_2s (cp));
1178   if (NULL == cp->core_mq)
1179   {
1180     GNUNET_MQ_discard (env);
1181     return;
1182   }
1183   GNUNET_MQ_send (cp->core_mq,
1184                   env);
1185 }
1186
1187
1188
1189
1190 /* end of gnunet-service-cadet-new_peer.c */