remaing remaining mandatory functions for basic operation
[oweals/gnunet.git] / src / cadet / gnunet-service-cadet-new_peer.c
1
2 /*
3      This file is part of GNUnet.
4      Copyright (C) 2001-2017 GNUnet e.V.
5
6      GNUnet is free software; you can redistribute it and/or modify
7      it under the terms of the GNU General Public License as published
8      by the Free Software Foundation; either version 3, or (at your
9      option) any later version.
10
11      GNUnet is distributed in the hope that it will be useful, but
12      WITHOUT ANY WARRANTY; without even the implied warranty of
13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14      General Public License for more details.
15
16      You should have received a copy of the GNU General Public License
17      along with GNUnet; see the file COPYING.  If not, write to the
18      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19      Boston, MA 02110-1301, USA.
20 */
21
22 /**
23  * @file cadet/gnunet-service-cadet-new_peer.c
24  * @brief Information we track per peer.
25  * @author Bartlomiej Polot
26  * @author Christian Grothoff
27  *
28  * TODO:
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_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  * How long do we wait until tearing down an idle peer?
53  */
54 #define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
55
56 /**
57  * How long do we keep paths around if we no longer care about the peer?
58  */
59 #define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
60
61
62
63
64 /**
65  * Data structure used to track whom we have to notify about changes
66  * to our message queue.
67  */
68 struct GCP_MessageQueueManager
69 {
70
71   /**
72    * Kept in a DLL.
73    */
74   struct GCP_MessageQueueManager *next;
75
76   /**
77    * Kept in a DLL.
78    */
79   struct GCP_MessageQueueManager *prev;
80
81   /**
82    * Function to call with updated message queue object.
83    */
84   GCP_MessageQueueNotificationCallback cb;
85
86   /**
87    * Closure for @e cb.
88    */
89   void *cb_cls;
90
91   /**
92    * The peer this is for.
93    */
94   struct CadetPeer *cp;
95
96   /**
97    * Envelope this manager would like to transmit once it is its turn.
98    */
99   struct GNUNET_MQ_Envelope *env;
100
101 };
102
103
104 /**
105  * Struct containing all information regarding a given peer
106  */
107 struct CadetPeer
108 {
109   /**
110    * ID of the peer
111    */
112   struct GNUNET_PeerIdentity pid;
113
114   /**
115    * Last time we heard from this peer
116    */
117   struct GNUNET_TIME_Absolute last_contact;
118
119   /**
120    * Array of DLLs of paths traversing the peer, organized by the
121    * offset of the peer on the larger path.
122    */
123   struct CadetPeerPathEntry **path_heads;
124
125   /**
126    * Array of DLL of paths traversing the peer, organized by the
127    * offset of the peer on the larger path.
128    */
129   struct CadetPeerPathEntry **path_tails;
130
131   /**
132    * Notifications to call when @e core_mq changes.
133    */
134   struct GCP_MessageQueueManager *mqm_head;
135
136   /**
137    * Notifications to call when @e core_mq changes.
138    */
139   struct GCP_MessageQueueManager *mqm_tail;
140
141   /**
142    * MIN-heap of paths owned by this peer (they also end at this
143    * peer).  Ordered by desirability.
144    */
145   struct GNUNET_CONTAINER_Heap *path_heap;
146
147   /**
148    * Handle to stop the DHT search for paths to this peer
149    */
150   struct GCD_search_handle *search_h;
151
152   /**
153    * Task to stop the DHT search for paths to this peer
154    */
155   struct GNUNET_SCHEDULER_Task *search_delayedXXX;
156
157   /**
158    * Task to destroy this entry.
159    */
160   struct GNUNET_SCHEDULER_Task *destroy_task;
161
162   /**
163    * Tunnel to this peer, if any.
164    */
165   struct CadetTunnel *t;
166
167   /**
168    * Connections that go through this peer; indexed by tid.
169    */
170   struct GNUNET_CONTAINER_MultiShortmap *connections;
171
172   /**
173    * Handle for core transmissions.
174    */
175   struct GNUNET_MQ_Handle *core_mq;
176
177   /**
178    * Hello message of the peer.
179    */
180   struct GNUNET_HELLO_Message *hello;
181
182   /**
183    * Handle to us offering the HELLO to the transport.
184    */
185   struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
186
187   /**
188    * Handle to our ATS request asking ATS to suggest an address
189    * to TRANSPORT for this peer (to establish a direct link).
190    */
191   struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
192
193   /**
194    * How many messages are in the queue to this peer.
195    */
196   unsigned int queue_n;
197
198   /**
199    * How many paths do we have to this peer (in all @e path_heads DLLs combined).
200    */
201   unsigned int num_paths;
202
203   /**
204    * Number of message queue managers of this peer that have a message in waiting.
205    *
206    * Used to quickly see if we need to bother scanning the @e msm_head DLL.
207    * TODO: could be replaced by another DLL that would then allow us to avoid
208    * the O(n)-scan of the DLL for ready entries!
209    */
210   unsigned int mqm_ready_counter;
211
212   /**
213    * Current length of the @e path_heads and @path_tails arrays.
214    * The arrays should be grown as needed.
215    */
216   unsigned int path_dll_length;
217
218 };
219
220
221 /**
222  * Get the static string for a peer ID.
223  *
224  * @param peer Peer.
225  *
226  * @return Static string for it's ID.
227  */
228 const char *
229 GCP_2s (const struct CadetPeer *peer)
230 {
231   if (NULL == peer)
232     return "PEER(NULL)";
233   return GNUNET_i2s (&peer->pid);
234 }
235
236
237 /**
238  * This peer is no longer be needed, clean it up now.
239  *
240  * @param cls peer to clean up
241  */
242 static void
243 destroy_peer (void *cls)
244 {
245   struct CadetPeer *cp = cls;
246
247   cp->destroy_task = NULL;
248   GNUNET_assert (NULL == cp->t);
249   GNUNET_assert (NULL == cp->core_mq);
250   GNUNET_assert (0 == cp->path_dll_length);
251   GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
252   GNUNET_assert (GNUNET_YES ==
253                  GNUNET_CONTAINER_multipeermap_remove (peers,
254                                                        &cp->pid,
255                                                        cp));
256   GNUNET_free_non_null (cp->path_heads);
257   GNUNET_free_non_null (cp->path_tails);
258   cp->path_dll_length = 0;
259   if (NULL != cp->search_h)
260   {
261     GCD_search_stop (cp->search_h);
262     cp->search_h = NULL;
263   }
264   /* FIXME: clean up search_delayedXXX! */
265
266   if (NULL != cp->hello_offer)
267   {
268     GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
269     cp->hello_offer = NULL;
270   }
271   if (NULL != cp->connectivity_suggestion)
272   {
273     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
274     cp->connectivity_suggestion = NULL;
275   }
276   GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
277   GNUNET_CONTAINER_heap_destroy (cp->path_heap);
278   GNUNET_free_non_null (cp->hello);
279   /* Peer should not be freed if paths exist; if there are no paths,
280      there ought to be no connections, and without connections, no
281      notifications. Thus we can assert that mqm_head is empty at this
282      point. */
283   GNUNET_assert (NULL == cp->mqm_head);
284   GNUNET_free (cp);
285 }
286
287
288 /**
289  * Set the message queue to @a mq for peer @a cp and notify watchers.
290  *
291  * @param cp peer to modify
292  * @param mq message queue to set (can be NULL)
293  */
294 void
295 GCP_set_mq (struct CadetPeer *cp,
296             struct GNUNET_MQ_Handle *mq)
297 {
298   cp->core_mq = mq;
299
300   for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
301        NULL != mqm;
302        mqm = mqm->next)
303   {
304     if (NULL == mq)
305     {
306       if (NULL != mqm->env)
307       {
308         GNUNET_MQ_discard (mqm->env);
309         mqm->env = NULL;
310         mqm->cb (mqm->cb_cls,
311                  GNUNET_SYSERR);
312       }
313       else
314       {
315         mqm->cb (mqm->cb_cls,
316                  GNUNET_NO);
317       }
318     }
319     else
320     {
321       GNUNET_assert (NULL == mqm->env);
322       mqm->cb (mqm->cb_cls,
323                GNUNET_YES);
324     }
325   }
326 }
327
328
329 /**
330  * Transmit current envelope from this @a mqm.
331  *
332  * @param mqm mqm to transmit message for now
333  */
334 static void
335 mqm_execute (struct GCP_MessageQueueManager *mqm)
336 {
337   struct CadetPeer *cp = mqm->cp;
338
339   /* Move entry to the end of the DLL, to be fair. */
340   if (mqm != cp->mqm_tail)
341   {
342     GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
343                                  cp->mqm_tail,
344                                  mqm);
345     GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
346                                       cp->mqm_tail,
347                                       mqm);
348   }
349   GNUNET_MQ_send (cp->core_mq,
350                   mqm->env);
351   mqm->env = NULL;
352   cp->mqm_ready_counter--;
353 }
354
355
356 /**
357  * Function called when CORE took one of the messages from
358  * a message queue manager and transmitted it.
359  *
360  * @param cls the `struct CadetPeeer` where we made progress
361  */
362 static void
363 mqm_send_done (void *cls)
364 {
365   struct CadetPeer *cp = cls;
366
367   if (0 == cp->mqm_ready_counter)
368     return; /* nothing to do */
369   for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
370        NULL != mqm;
371        mqm = mqm->next)
372   {
373     if (NULL == mqm->env)
374       continue;
375     mqm_execute (mqm);
376     return;
377   }
378 }
379
380
381 /**
382  * Send the message in @a env to @a cp.
383  *
384  * @param mqm the message queue manager to use for transmission
385  * @param env envelope with the message to send; must NOT
386  *            yet have a #GNUNET_MQ_notify_sent() callback attached to it
387  */
388 void
389 GCP_send (struct GCP_MessageQueueManager *mqm,
390           struct GNUNET_MQ_Envelope *env)
391 {
392   struct CadetPeer *cp = mqm->cp;
393
394   GNUNET_assert (NULL != cp->core_mq);
395   GNUNET_assert (NULL == mqm->env);
396   GNUNET_MQ_notify_sent (env,
397                          &mqm_send_done,
398                          cp);
399   mqm->env = env;
400   cp->mqm_ready_counter++;
401   if (0 != GNUNET_MQ_get_length (cp->core_mq))
402     return;
403   mqm_execute (mqm);
404 }
405
406
407 /**
408  * Function called to destroy a peer now.
409  *
410  * @param cls NULL
411  * @param pid identity of the peer (unused)
412  * @param value the `struct CadetPeer` to clean up
413  * @return #GNUNET_OK (continue to iterate)
414  */
415 static int
416 destroy_iterator_cb (void *cls,
417                      const struct GNUNET_PeerIdentity *pid,
418                      void *value)
419 {
420   struct CadetPeer *cp = value;
421
422   if (NULL != cp->destroy_task)
423   {
424     GNUNET_SCHEDULER_cancel (cp->destroy_task);
425     cp->destroy_task = NULL;
426   }
427   destroy_peer (cp);
428   return GNUNET_OK;
429 }
430
431
432 /**
433  * Clean up all entries about all peers.
434  * Must only be called after all tunnels, CORE-connections and
435  * connections are down.
436  */
437 void
438 GCP_destroy_all_peers ()
439 {
440   GNUNET_CONTAINER_multipeermap_iterate (peers,
441                                          &destroy_iterator_cb,
442                                          NULL);
443 }
444
445
446 /**
447  * This peer may no longer be needed, consider cleaning it up.
448  *
449  * @param cp peer to clean up
450  */
451 static void
452 consider_peer_destroy (struct CadetPeer *cp);
453
454
455 /**
456  * We really no longere care about a peer, stop hogging memory with paths to it.
457  * Afterwards, see if there is more to be cleaned up about this peer.
458  *
459  * @param cls a `struct CadetPeer`.
460  */
461 static void
462 drop_paths (void *cls)
463 {
464   struct CadetPeer *cp = cls;
465   struct CadetPeerPath *path;
466
467   cp->destroy_task = NULL;
468   while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
469     GCPP_release (path);
470   consider_peer_destroy (cp);
471 }
472
473
474 /**
475  * This peer may no longer be needed, consider cleaning it up.
476  *
477  * @param cp peer to clean up
478  */
479 static void
480 consider_peer_destroy (struct CadetPeer *cp)
481 {
482   struct GNUNET_TIME_Relative exp;
483
484   if (NULL != cp->destroy_task)
485   {
486     GNUNET_SCHEDULER_cancel (cp->destroy_task);
487     cp->destroy_task = NULL;
488   }
489   if (NULL != cp->t)
490     return; /* still relevant! */
491   if (NULL != cp->core_mq)
492     return; /* still relevant! */
493   if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
494     return; /* still relevant! */
495   if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))
496   {
497     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
498                                                      &drop_paths,
499                                                      cp);
500     return;
501   }
502   if (0 < cp->path_dll_length)
503     return; /* still relevant! */
504   if (NULL != cp->hello)
505   {
506     /* relevant only until HELLO expires */
507     exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
508     cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
509                                                      &destroy_peer,
510                                                      cp);
511     return;
512   }
513   cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
514                                                    &destroy_peer,
515                                                    cp);
516 }
517
518
519 /**
520  * Add an entry to the DLL of all of the paths that this peer is on.
521  *
522  * @param cp peer to modify
523  * @param entry an entry on a path
524  * @param off offset of this peer on the path
525  */
526 void
527 GCP_path_entry_add (struct CadetPeer *cp,
528                     struct CadetPeerPathEntry *entry,
529                     unsigned int off)
530 {
531   if (off >= cp->path_dll_length)
532   {
533     unsigned int len = cp->path_dll_length;
534
535     GNUNET_array_grow (cp->path_heads,
536                        len,
537                        off + 4);
538     GNUNET_array_grow (cp->path_tails,
539                        cp->path_dll_length,
540                        off + 4);
541   }
542   GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
543                                cp->path_tails[off],
544                                entry);
545   cp->num_paths++;
546
547   /* If we have a tunnel to this peer, tell the tunnel that there is a
548      new path available. */
549   if (NULL != cp->t)
550     GCT_consider_path (cp->t,
551                        entry->path,
552                        off);
553 }
554
555
556 /**
557  * Remove an entry from the DLL of all of the paths that this peer is on.
558  *
559  * @param cp peer to modify
560  * @param entry an entry on a path
561  * @param off offset of this peer on the path
562  */
563 void
564 GCP_path_entry_remove (struct CadetPeer *cp,
565                        struct CadetPeerPathEntry *entry,
566                        unsigned int off)
567 {
568   GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
569                                cp->path_tails[off],
570                                entry);
571   GNUNET_assert (0 < cp->num_paths);
572   cp->num_paths--;
573 }
574
575
576 /**
577  * Try adding a @a path to this @a peer.  If the peer already
578  * has plenty of paths, return NULL.
579  *
580  * @param cp peer to which the @a path leads to
581  * @param path a path looking for an owner; may not be fully initialized yet!
582  * @param off offset of @a cp in @a path
583  * @return NULL if this peer does not care to become a new owner,
584  *         otherwise the node in the peer's path heap for the @a path.
585  */
586 struct GNUNET_CONTAINER_HeapNode *
587 GCP_attach_path (struct CadetPeer *cp,
588                  struct CadetPeerPath *path,
589                  unsigned int off)
590 {
591   GNUNET_CONTAINER_HeapCostType desirability;
592   struct CadetPeerPath *root;
593   GNUNET_CONTAINER_HeapCostType root_desirability;
594   struct GNUNET_CONTAINER_HeapNode *hn;
595
596   /* FIXME: desirability is not yet initialized; tricky! */
597   desirability = GCPP_get_desirability (path);
598   if (GNUNET_NO ==
599       GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
600                                    (void **) &root,
601                                    &root_desirability))
602   {
603     root = NULL;
604     root_desirability = 0;
605   }
606
607   if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
608        (desirability < root_desirability) )
609     return NULL;
610
611   /* Yes, we'd like to add this path, add to our heap */
612   hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
613                                      (void *) cp,
614                                      desirability);
615
616   /* Consider maybe dropping other paths because of the new one */
617   if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
618       2 * DESIRED_CONNECTIONS_PER_TUNNEL)
619   {
620     /* Now we have way too many, drop least desirable UNLESS it is in use!
621        (Note that this intentionally keeps highly desireable, but currently
622        unused paths around in the hope that we might be able to switch, even
623        if the number of paths exceeds the threshold.) */
624     root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
625     if (NULL ==
626         GCPP_get_connection (root,
627                              cp,
628                              GCPP_get_length (root) - 1))
629     {
630       /* Got plenty of paths to this destination, and this is a low-quality
631          one that we don't care, allow it to die. */
632       GNUNET_assert (root ==
633                      GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
634       GCPP_release (root);
635     }
636   }
637   return hn;
638 }
639
640
641 /**
642  * This peer can no longer own @a path as the path
643  * has been extended and a peer further down the line
644  * is now the new owner.
645  *
646  * @param cp old owner of the @a path
647  * @param path path where the ownership is lost
648  * @param hn note in @a cp's path heap that must be deleted
649  */
650 void
651 GCP_detach_path (struct CadetPeer *cp,
652                  struct CadetPeerPath *path,
653                  struct GNUNET_CONTAINER_HeapNode *hn)
654 {
655   GNUNET_assert (path ==
656                  GNUNET_CONTAINER_heap_remove_node (hn));
657 }
658
659
660 /**
661  * Add a @a connection to this @a cp.
662  *
663  * @param cp peer via which the @a connection goes
664  * @param cc the connection to add
665  */
666 void
667 GCP_add_connection (struct CadetPeer *cp,
668                     struct CadetConnection *cc)
669 {
670   GNUNET_assert (GNUNET_OK ==
671                  GNUNET_CONTAINER_multishortmap_put (cp->connections,
672                                                      &GCC_get_id (cc)->connection_of_tunnel,
673                                                      cc,
674                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
675 }
676
677
678 /**
679  * Remove a @a connection that went via this @a cp.
680  *
681  * @param cp peer via which the @a connection went
682  * @param cc the connection to remove
683  */
684 void
685 GCP_remove_connection (struct CadetPeer *cp,
686                        struct CadetConnection *cc)
687 {
688   GNUNET_assert (GNUNET_YES ==
689                  GNUNET_CONTAINER_multishortmap_remove (cp->connections,
690                                                         &GCC_get_id (cc)->connection_of_tunnel,
691                                                         cc));
692 }
693
694
695 /**
696  * This peer is now on more "active" duty, activate processes related to it.
697  *
698  * @param cp the more-active peer
699  */
700 static void
701 consider_peer_activate (struct CadetPeer *cp)
702 {
703   uint32_t strength;
704
705   if (NULL != cp->destroy_task)
706   {
707     /* It's active, do not destory! */
708     GNUNET_SCHEDULER_cancel (cp->destroy_task);
709     cp->destroy_task = NULL;
710   }
711   if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
712        (NULL == cp->t) )
713   {
714     /* We're just on a path or directly connected; don't bother too much */
715     if (NULL != cp->connectivity_suggestion)
716     {
717       GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
718       cp->connectivity_suggestion = NULL;
719     }
720     if (NULL != cp->search_h)
721     {
722       GCD_search_stop (cp->search_h);
723       cp->search_h = NULL;
724     }
725     return;
726   }
727   if (NULL == cp->core_mq)
728   {
729     /* Lacks direct connection, try to create one by querying the DHT */
730     if ( (NULL == cp->search_h) &&
731          (DESIRED_CONNECTIONS_PER_TUNNEL < cp->num_paths) )
732       cp->search_h
733         = GCD_search (&cp->pid);
734   }
735   else
736   {
737     /* Have direct connection, stop DHT search if active */
738     if (NULL != cp->search_h)
739     {
740       GCD_search_stop (cp->search_h);
741       cp->search_h = NULL;
742     }
743   }
744
745   /* If we have a tunnel, our urge for connections is much bigger */
746   strength = (NULL != cp->t) ? 32 : 1;
747   if (NULL != cp->connectivity_suggestion)
748     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
749   cp->connectivity_suggestion
750     = GNUNET_ATS_connectivity_suggest (ats_ch,
751                                        &cp->pid,
752                                        strength);
753 }
754
755
756 /**
757  * Retrieve the CadetPeer stucture associated with the
758  * peer. Optionally create one and insert it in the appropriate
759  * structures if the peer is not known yet.
760  *
761  * @param peer_id Full identity of the peer.
762  * @param create #GNUNET_YES if a new peer should be created if unknown.
763  *               #GNUNET_NO to return NULL if peer is unknown.
764  * @return Existing or newly created peer structure.
765  *         NULL if unknown and not requested @a create
766  */
767 struct CadetPeer *
768 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
769          int create)
770 {
771   struct CadetPeer *cp;
772
773   cp = GNUNET_CONTAINER_multipeermap_get (peers,
774                                           peer_id);
775   if (NULL != cp)
776     return cp;
777   if (GNUNET_NO == create)
778     return NULL;
779   cp = GNUNET_new (struct CadetPeer);
780   cp->pid = *peer_id;
781   cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
782                                                            GNUNET_YES);
783   cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
784   GNUNET_assert (GNUNET_YES ==
785                  GNUNET_CONTAINER_multipeermap_put (peers,
786                                                     &cp->pid,
787                                                     cp,
788                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
789   return cp;
790 }
791
792
793 /**
794  * Obtain the peer identity for a `struct CadetPeer`.
795  *
796  * @param cp our peer handle
797  * @return the peer identity
798  */
799 const struct GNUNET_PeerIdentity *
800 GCP_get_id (struct CadetPeer *cp)
801 {
802   return &cp->pid;
803 }
804
805
806 /**
807  * Iterate over all known peers.
808  *
809  * @param iter Iterator.
810  * @param cls Closure for @c iter.
811  */
812 void
813 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
814                  void *cls)
815 {
816   GNUNET_CONTAINER_multipeermap_iterate (peers,
817                                          iter,
818                                          cls);
819 }
820
821
822 /**
823  * Count the number of known paths toward the peer.
824  *
825  * @param peer Peer to get path info.
826  * @return Number of known paths.
827  */
828 unsigned int
829 GCP_count_paths (const struct CadetPeer *peer)
830 {
831   return peer->num_paths;
832 }
833
834
835 /**
836  * Iterate over the paths to a peer.
837  *
838  * @param peer Peer to get path info.
839  * @param callback Function to call for every path.
840  * @param callback_cls Closure for @a callback.
841  * @return Number of iterated paths.
842  */
843 unsigned int
844 GCP_iterate_paths (struct CadetPeer *peer,
845                    GCP_PathIterator callback,
846                    void *callback_cls)
847 {
848   unsigned int ret = 0;
849
850   for (unsigned int i=0;i<peer->path_dll_length;i++)
851   {
852     for (struct CadetPeerPathEntry *pe = peer->path_heads[i];
853          NULL != pe;
854          pe = pe->next)
855     {
856       if (GNUNET_NO ==
857           callback (callback_cls,
858                     pe->path,
859                     i))
860         return ret;
861       ret++;
862     }
863   }
864   return ret;
865 }
866
867
868 /**
869  * Iterate over the paths to @a peer where
870  * @a peer is at distance @a dist from us.
871  *
872  * @param peer Peer to get path info.
873  * @param dist desired distance of @a peer to us on the path
874  * @param callback Function to call for every path.
875  * @param callback_cls Closure for @a callback.
876  * @return Number of iterated paths.
877  */
878 unsigned int
879 GCP_iterate_paths_at (struct CadetPeer *peer,
880                       unsigned int dist,
881                       GCP_PathIterator callback,
882                       void *callback_cls)
883 {
884   unsigned int ret = 0;
885
886   if (dist<peer->path_dll_length)
887     return 0;
888   for (struct CadetPeerPathEntry *pe = peer->path_heads[dist];
889        NULL != pe;
890        pe = pe->next)
891   {
892     if (GNUNET_NO ==
893         callback (callback_cls,
894                   pe->path,
895                   dist))
896       return ret;
897     ret++;
898   }
899   return ret;
900 }
901
902
903 /**
904  * Get the tunnel towards a peer.
905  *
906  * @param cp Peer to get from.
907  * @param create #GNUNET_YES to create a tunnel if we do not have one
908  * @return Tunnel towards peer.
909  */
910 struct CadetTunnel *
911 GCP_get_tunnel (struct CadetPeer *cp,
912                 int create)
913 {
914   if (NULL == cp)
915     return NULL;
916   if ( (NULL != cp->t) ||
917        (GNUNET_NO == create) )
918     return cp->t;
919   cp->t = GCT_create_tunnel (cp);
920   consider_peer_activate (cp);
921   return cp->t;
922 }
923
924
925 /**
926  * Hello offer was passed to the transport service. Mark it
927  * as done.
928  *
929  * @param cls the `struct CadetPeer` where the offer completed
930  */
931 static void
932 hello_offer_done (void *cls)
933 {
934   struct CadetPeer *cp = cls;
935
936   cp->hello_offer = NULL;
937 }
938
939
940 /**
941  * We got a HELLO for a @a peer, remember it, and possibly
942  * trigger adequate actions (like trying to connect).
943  *
944  * @param cp the peer we got a HELLO for
945  * @param hello the HELLO to remember
946  */
947 void
948 GCP_set_hello (struct CadetPeer *cp,
949                const struct GNUNET_HELLO_Message *hello)
950 {
951   struct GNUNET_HELLO_Message *mrg;
952
953   if (NULL != cp->hello_offer)
954   {
955     GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
956     cp->hello_offer = NULL;
957   }
958   if (NULL != cp->hello)
959   {
960     mrg = GNUNET_HELLO_merge (hello,
961                               cp->hello);
962     GNUNET_free (cp->hello);
963     cp->hello = mrg;
964   }
965   else
966   {
967     cp->hello = GNUNET_memdup (hello,
968                                GNUNET_HELLO_size (hello));
969   }
970   cp->hello_offer
971     = GNUNET_TRANSPORT_offer_hello (cfg,
972                                     GNUNET_HELLO_get_header (cp->hello) ,
973                                     &hello_offer_done,
974                                     cp);
975   /* New HELLO means cp's destruction time may change... */
976   consider_peer_destroy (cp);
977 }
978
979
980 /**
981  * The tunnel to the given peer no longer exists, remove it from our
982  * data structures, and possibly clean up the peer itself.
983  *
984  * @param cp the peer affected
985  * @param t the dead tunnel
986  */
987 void
988 GCP_drop_tunnel (struct CadetPeer *cp,
989                  struct CadetTunnel *t)
990 {
991   GNUNET_assert (cp->t == t);
992   cp->t = NULL;
993   consider_peer_destroy (cp);
994 }
995
996
997 /**
998  * Test if @a cp has a core-level connection
999  *
1000  * @param cp peer to test
1001  * @return #GNUNET_YES if @a cp has a core-level connection
1002  */
1003 int
1004 GCP_has_core_connection (struct CadetPeer *cp)
1005 {
1006   return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1007 }
1008
1009
1010 /**
1011  * Start message queue change notifications.
1012  *
1013  * @param cp peer to notify for
1014  * @param cb function to call if mq becomes available or unavailable
1015  * @param cb_cls closure for @a cb
1016  * @return handle to cancel request
1017  */
1018 struct GCP_MessageQueueManager *
1019 GCP_request_mq (struct CadetPeer *cp,
1020                 GCP_MessageQueueNotificationCallback cb,
1021                 void *cb_cls)
1022 {
1023   struct GCP_MessageQueueManager *mqm;
1024
1025   mqm = GNUNET_new (struct GCP_MessageQueueManager);
1026   mqm->cb = cb;
1027   mqm->cb_cls = cb_cls;
1028   mqm->cp = cp;
1029   GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1030                                cp->mqm_tail,
1031                                mqm);
1032   if (NULL != cp->core_mq)
1033     cb (cb_cls,
1034         GNUNET_YES);
1035   return mqm;
1036 }
1037
1038
1039 /**
1040  * Stops message queue change notifications.
1041  *
1042  * @param mqm handle matching request to cancel
1043  * @param last_env final message to transmit, or NULL
1044  */
1045 void
1046 GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1047                        struct GNUNET_MQ_Envelope *last_env)
1048 {
1049   struct CadetPeer *cp = mqm->cp;
1050
1051   if (NULL != mqm->env)
1052     GNUNET_MQ_discard (mqm->env);
1053   if (NULL != last_env)
1054   {
1055     if (NULL != cp->core_mq)
1056       GNUNET_MQ_send (cp->core_mq,
1057                       last_env);
1058     else
1059       GNUNET_MQ_discard (last_env);
1060   }
1061   GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1062                                cp->mqm_tail,
1063                                mqm);
1064   GNUNET_free (mqm);
1065 }
1066
1067
1068 /**
1069  * Send the message in @a env to @a cp, overriding queueing logic.
1070  * This function should only be used to send error messages outside
1071  * of flow and congestion control, similar to ICMP.  Note that
1072  * the envelope may be silently discarded as well.
1073  *
1074  * @param cp peer to send the message to
1075  * @param env envelope with the message to send
1076  */
1077 void
1078 GCP_send_ooo (struct CadetPeer *cp,
1079               struct GNUNET_MQ_Envelope *env)
1080 {
1081   if (NULL == cp->core_mq)
1082   {
1083     GNUNET_MQ_discard (env);
1084     return;
1085   }
1086   GNUNET_MQ_send (cp->core_mq,
1087                   env);
1088 }
1089
1090
1091
1092
1093 /* end of gnunet-service-cadet-new_peer.c */