2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
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.
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.
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.
22 * @file cadet/gnunet-service-cadet-new_peer.c
23 * @brief Information we track per peer.
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
28 * - timeout for routes
29 * - optimize stopping/restarting DHT search to situations
30 * where we actually need it (i.e. not if we have a direct connection,
31 * or if we already have plenty of good short ones, or maybe even
32 * to take a break if we have some connections and have searched a lot (?))
33 * - optimize MQM ready scans (O(n) -> O(1))
36 #include "gnunet_util_lib.h"
37 #include "gnunet_hello_lib.h"
38 #include "gnunet_signatures.h"
39 #include "gnunet_transport_service.h"
40 #include "gnunet_ats_service.h"
41 #include "gnunet_core_service.h"
42 #include "gnunet_statistics_service.h"
43 #include "cadet_protocol.h"
44 #include "gnunet-service-cadet-new.h"
45 #include "gnunet-service-cadet-new_connection.h"
46 #include "gnunet-service-cadet-new_dht.h"
47 #include "gnunet-service-cadet-new_peer.h"
48 #include "gnunet-service-cadet-new_paths.h"
49 #include "gnunet-service-cadet-new_tunnels.h"
52 #define LOG(level, ...) GNUNET_log_from(level,"cadet-per",__VA_ARGS__)
56 * How long do we wait until tearing down an idle peer?
58 #define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
61 * How long do we keep paths around if we no longer care about the peer?
63 #define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
69 * Data structure used to track whom we have to notify about changes
70 * to our message queue.
72 struct GCP_MessageQueueManager
78 struct GCP_MessageQueueManager *next;
83 struct GCP_MessageQueueManager *prev;
86 * Function to call with updated message queue object.
88 GCP_MessageQueueNotificationCallback cb;
96 * The peer this is for.
101 * Envelope this manager would like to transmit once it is its turn.
103 struct GNUNET_MQ_Envelope *env;
109 * Struct containing all information regarding a given peer
116 struct GNUNET_PeerIdentity pid;
119 * Last time we heard from this peer
121 struct GNUNET_TIME_Absolute last_contact;
124 * Array of DLLs of paths traversing the peer, organized by the
125 * offset of the peer on the larger path.
127 struct CadetPeerPathEntry **path_heads;
130 * Array of DLL of paths traversing the peer, organized by the
131 * offset of the peer on the larger path.
133 struct CadetPeerPathEntry **path_tails;
136 * Notifications to call when @e core_mq changes.
138 struct GCP_MessageQueueManager *mqm_head;
141 * Notifications to call when @e core_mq changes.
143 struct GCP_MessageQueueManager *mqm_tail;
146 * MIN-heap of paths owned by this peer (they also end at this
147 * peer). Ordered by desirability.
149 struct GNUNET_CONTAINER_Heap *path_heap;
152 * Handle to stop the DHT search for paths to this peer
154 struct GCD_search_handle *search_h;
157 * Task to stop the DHT search for paths to this peer
159 struct GNUNET_SCHEDULER_Task *search_delayedXXX;
162 * Task to destroy this entry.
164 struct GNUNET_SCHEDULER_Task *destroy_task;
167 * Tunnel to this peer, if any.
169 struct CadetTunnel *t;
172 * Connections that go through this peer; indexed by tid.
174 struct GNUNET_CONTAINER_MultiShortmap *connections;
177 * Handle for core transmissions.
179 struct GNUNET_MQ_Handle *core_mq;
182 * Hello message of the peer.
184 struct GNUNET_HELLO_Message *hello;
187 * Handle to us offering the HELLO to the transport.
189 struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
192 * Handle to our ATS request asking ATS to suggest an address
193 * to TRANSPORT for this peer (to establish a direct link).
195 struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
198 * How many messages are in the queue to this peer.
200 unsigned int queue_n;
203 * How many paths do we have to this peer (in all @e path_heads DLLs combined).
205 unsigned int num_paths;
208 * Number of message queue managers of this peer that have a message in waiting.
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!
214 unsigned int mqm_ready_counter;
217 * Current length of the @e path_heads and @path_tails arrays.
218 * The arrays should be grown as needed.
220 unsigned int path_dll_length;
226 * Get the static string for a peer ID.
229 * @return Static string for it's ID.
232 GCP_2s (const struct CadetPeer *cp)
236 GNUNET_snprintf (buf,
239 GNUNET_i2s (&cp->pid));
245 * This peer is no longer be needed, clean it up now.
247 * @param cls peer to clean up
250 destroy_peer (void *cls)
252 struct CadetPeer *cp = cls;
254 LOG (GNUNET_ERROR_TYPE_DEBUG,
255 "Destroying state about peer %s\n",
257 cp->destroy_task = NULL;
258 GNUNET_assert (NULL == cp->t);
259 GNUNET_assert (NULL == cp->core_mq);
260 for (unsigned int i=0;i<cp->path_dll_length;i++)
261 GNUNET_assert (NULL == cp->path_heads[i]);
262 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
263 GNUNET_assert (GNUNET_YES ==
264 GNUNET_CONTAINER_multipeermap_remove (peers,
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)
272 GCD_search_stop (cp->search_h);
275 /* FIXME: clean up search_delayedXXX! */
277 if (NULL != cp->hello_offer)
279 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
280 cp->hello_offer = NULL;
282 if (NULL != cp->connectivity_suggestion)
284 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
285 cp->connectivity_suggestion = NULL;
287 GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
288 if (NULL != cp->path_heap)
290 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
291 cp->path_heap = NULL;
293 GNUNET_free_non_null (cp->hello);
294 /* Peer should not be freed if paths exist; if there are no paths,
295 there ought to be no connections, and without connections, no
296 notifications. Thus we can assert that mqm_head is empty at this
298 GNUNET_assert (NULL == cp->mqm_head);
304 * This peer is now on more "active" duty, activate processes related to it.
306 * @param cp the more-active peer
309 consider_peer_activate (struct CadetPeer *cp)
313 LOG (GNUNET_ERROR_TYPE_DEBUG,
314 "Updating peer %s activation state (%u connections)%s%s\n",
316 GNUNET_CONTAINER_multishortmap_size (cp->connections),
317 (NULL == cp->t) ? "" : " with tunnel",
318 (NULL == cp->core_mq) ? "" : " with CORE link");
319 if (NULL != cp->destroy_task)
321 /* It's active, do not destory! */
322 GNUNET_SCHEDULER_cancel (cp->destroy_task);
323 cp->destroy_task = NULL;
325 if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
328 /* We're just on a path or directly connected; don't bother too much */
329 if (NULL != cp->connectivity_suggestion)
331 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
332 cp->connectivity_suggestion = NULL;
334 if (NULL != cp->search_h)
336 GCD_search_stop (cp->search_h);
341 if (NULL == cp->core_mq)
343 /* Lacks direct connection, try to create one by querying the DHT */
344 if ( (NULL == cp->search_h) &&
345 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
347 = GCD_search (&cp->pid);
351 /* Have direct connection, stop DHT search if active */
352 if (NULL != cp->search_h)
354 GCD_search_stop (cp->search_h);
359 /* If we have a tunnel, our urge for connections is much bigger */
360 strength = (NULL != cp->t) ? 32 : 1;
361 if (NULL != cp->connectivity_suggestion)
362 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
363 cp->connectivity_suggestion
364 = GNUNET_ATS_connectivity_suggest (ats_ch,
371 * This peer may no longer be needed, consider cleaning it up.
373 * @param cp peer to clean up
376 consider_peer_destroy (struct CadetPeer *cp);
380 * We really no longere care about a peer, stop hogging memory with paths to it.
381 * Afterwards, see if there is more to be cleaned up about this peer.
383 * @param cls a `struct CadetPeer`.
386 drop_paths (void *cls)
388 struct CadetPeer *cp = cls;
389 struct CadetPeerPath *path;
391 cp->destroy_task = NULL;
392 while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
394 consider_peer_destroy (cp);
399 * This peer may no longer be needed, consider cleaning it up.
401 * @param cp peer to clean up
404 consider_peer_destroy (struct CadetPeer *cp)
406 struct GNUNET_TIME_Relative exp;
408 if (NULL != cp->destroy_task)
410 GNUNET_SCHEDULER_cancel (cp->destroy_task);
411 cp->destroy_task = NULL;
414 return; /* still relevant! */
415 if (NULL != cp->core_mq)
416 return; /* still relevant! */
417 if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
418 return; /* still relevant! */
419 if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))
421 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
426 for (unsigned int i=0;i<cp->path_dll_length;i++)
427 if (NULL != cp->path_heads[i])
428 return; /* still relevant! */
429 if (NULL != cp->hello)
431 /* relevant only until HELLO expires */
432 exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
433 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
438 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
445 * Set the message queue to @a mq for peer @a cp and notify watchers.
447 * @param cp peer to modify
448 * @param mq message queue to set (can be NULL)
451 GCP_set_mq (struct CadetPeer *cp,
452 struct GNUNET_MQ_Handle *mq)
454 LOG (GNUNET_ERROR_TYPE_DEBUG,
455 "Message queue for peer %s is now %p\n",
459 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
465 if (NULL != mqm->env)
467 GNUNET_MQ_discard (mqm->env);
469 mqm->cb (mqm->cb_cls,
474 mqm->cb (mqm->cb_cls,
480 GNUNET_assert (NULL == mqm->env);
481 mqm->cb (mqm->cb_cls,
487 consider_peer_activate (cp);
489 consider_peer_destroy (cp);
494 /* have a new, direct path to the target, notify tunnel */
495 struct CadetPeerPath *path;
497 path = GCPP_get_path_from_route (1,
499 GCT_consider_path (cp->t,
507 * Debug function should NEVER return true in production code, useful to
508 * simulate losses for testcases.
510 * @return #GNUNET_YES or #GNUNET_NO with the decision to drop.
515 if (0 == drop_percent)
517 if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
525 * Function called when CORE took one of the messages from
526 * a message queue manager and transmitted it.
528 * @param cls the `struct CadetPeeer` where we made progress
531 mqm_send_done (void *cls);
535 * Transmit current envelope from this @a mqm.
537 * @param mqm mqm to transmit message for now
540 mqm_execute (struct GCP_MessageQueueManager *mqm)
542 struct CadetPeer *cp = mqm->cp;
544 /* Move entry to the end of the DLL, to be fair. */
545 if (mqm != cp->mqm_tail)
547 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
550 GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
554 cp->mqm_ready_counter--;
555 if (GNUNET_YES == should_I_drop ())
557 LOG (GNUNET_ERROR_TYPE_DEBUG,
558 "DROPPING message to peer %s from MQM %p\n",
561 GNUNET_MQ_discard (mqm->env);
567 LOG (GNUNET_ERROR_TYPE_DEBUG,
568 "Sending to peer %s from MQM %p\n",
571 GNUNET_MQ_send (cp->core_mq,
575 mqm->cb (mqm->cb_cls,
581 * Function called when CORE took one of the messages from
582 * a message queue manager and transmitted it.
584 * @param cls the `struct CadetPeeer` where we made progress
587 mqm_send_done (void *cls)
589 struct CadetPeer *cp = cls;
591 LOG (GNUNET_ERROR_TYPE_DEBUG,
592 "Sending to peer %s completed\n",
594 if (0 == cp->mqm_ready_counter)
595 return; /* nothing to do */
596 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
600 if (NULL == mqm->env)
609 * Send the message in @a env to @a cp.
611 * @param mqm the message queue manager to use for transmission
612 * @param env envelope with the message to send; must NOT
613 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
616 GCP_send (struct GCP_MessageQueueManager *mqm,
617 struct GNUNET_MQ_Envelope *env)
619 struct CadetPeer *cp = mqm->cp;
621 LOG (GNUNET_ERROR_TYPE_DEBUG,
622 "Queueing message to peer %s in MQM %p\n",
625 GNUNET_assert (NULL != cp->core_mq);
626 GNUNET_assert (NULL == mqm->env);
627 GNUNET_MQ_notify_sent (env,
631 cp->mqm_ready_counter++;
632 if (0 != GNUNET_MQ_get_length (cp->core_mq))
639 * Function called to destroy a peer now.
642 * @param pid identity of the peer (unused)
643 * @param value the `struct CadetPeer` to clean up
644 * @return #GNUNET_OK (continue to iterate)
647 destroy_iterator_cb (void *cls,
648 const struct GNUNET_PeerIdentity *pid,
651 struct CadetPeer *cp = value;
653 if (NULL != cp->destroy_task)
655 GNUNET_SCHEDULER_cancel (cp->destroy_task);
656 cp->destroy_task = NULL;
664 * Clean up all entries about all peers.
665 * Must only be called after all tunnels, CORE-connections and
666 * connections are down.
669 GCP_destroy_all_peers ()
671 LOG (GNUNET_ERROR_TYPE_DEBUG,
672 "Destroying all peers now\n");
673 GNUNET_CONTAINER_multipeermap_iterate (peers,
674 &destroy_iterator_cb,
680 * Drop all paths owned by this peer, and do not
681 * allow new ones to be added: We are shutting down.
683 * @param cp peer to drop paths to
686 GCP_drop_owned_paths (struct CadetPeer *cp)
688 struct CadetPeerPath *path;
690 LOG (GNUNET_ERROR_TYPE_DEBUG,
691 "Destroying all paths to %s\n",
693 while (NULL != (path =
694 GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
696 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
697 cp->path_heap = NULL;
702 * Add an entry to the DLL of all of the paths that this peer is on.
704 * @param cp peer to modify
705 * @param entry an entry on a path
706 * @param off offset of this peer on the path
709 GCP_path_entry_add (struct CadetPeer *cp,
710 struct CadetPeerPathEntry *entry,
713 GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path,
715 LOG (GNUNET_ERROR_TYPE_DEBUG,
716 "Discovered that peer %s is on path %s at offset %u\n",
718 GCPP_2s (entry->path),
720 if (off >= cp->path_dll_length)
722 unsigned int len = cp->path_dll_length;
724 GNUNET_array_grow (cp->path_heads,
727 GNUNET_array_grow (cp->path_tails,
731 GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
736 /* If we have a tunnel to this peer, tell the tunnel that there is a
737 new path available. */
739 GCT_consider_path (cp->t,
743 if ( (NULL != cp->search_h) &&
744 (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths) )
746 /* Now I have enough paths, stop search */
747 GCD_search_stop (cp->search_h);
754 * Remove an entry from the DLL of all of the paths that this peer is on.
756 * @param cp peer to modify
757 * @param entry an entry on a path
758 * @param off offset of this peer on the path
761 GCP_path_entry_remove (struct CadetPeer *cp,
762 struct CadetPeerPathEntry *entry,
765 LOG (GNUNET_ERROR_TYPE_DEBUG,
766 "Removing knowledge about peer %s beging on path %s at offset %u\n",
768 GCPP_2s (entry->path),
770 GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
773 GNUNET_assert (0 < cp->num_paths);
775 if ( (NULL == cp->core_mq) &&
777 (NULL == cp->search_h) &&
778 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
780 = GCD_search (&cp->pid);
785 * Try adding a @a path to this @a peer. If the peer already
786 * has plenty of paths, return NULL.
788 * @param cp peer to which the @a path leads to
789 * @param path a path looking for an owner; may not be fully initialized yet!
790 * @param off offset of @a cp in @a path
791 * @param force force attaching the path
792 * @return NULL if this peer does not care to become a new owner,
793 * otherwise the node in the peer's path heap for the @a path.
795 struct GNUNET_CONTAINER_HeapNode *
796 GCP_attach_path (struct CadetPeer *cp,
797 struct CadetPeerPath *path,
801 GNUNET_CONTAINER_HeapCostType desirability;
802 struct CadetPeerPath *root;
803 GNUNET_CONTAINER_HeapCostType root_desirability;
804 struct GNUNET_CONTAINER_HeapNode *hn;
806 GNUNET_assert (cp == GCPP_get_peer_at_offset (path,
808 if (NULL == cp->path_heap)
810 /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */
811 GNUNET_assert (GNUNET_NO == force);
814 desirability = GCPP_get_desirability (path);
815 if (GNUNET_NO == force)
817 /* FIXME: desirability is not yet initialized; tricky! */
819 GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
824 root_desirability = 0;
827 if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
828 (desirability < root_desirability) )
830 LOG (GNUNET_ERROR_TYPE_DEBUG,
831 "Decided to not attach path %p to peer %s due to undesirability\n",
838 LOG (GNUNET_ERROR_TYPE_DEBUG,
839 "Attaching path %s to peer %s (%s)\n",
842 (GNUNET_NO == force) ? "desirable" : "forced");
844 /* Yes, we'd like to add this path, add to our heap */
845 hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
849 /* Consider maybe dropping other paths because of the new one */
850 if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
851 2 * DESIRED_CONNECTIONS_PER_TUNNEL)
853 /* Now we have way too many, drop least desirable UNLESS it is in use!
854 (Note that this intentionally keeps highly desireable, but currently
855 unused paths around in the hope that we might be able to switch, even
856 if the number of paths exceeds the threshold.) */
857 root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
858 if ( (path != root) &&
860 GCPP_get_connection (root,
862 GCPP_get_length (root) - 1)) )
864 /* Got plenty of paths to this destination, and this is a low-quality
865 one that we don't care, allow it to die. */
866 GNUNET_assert (root ==
867 GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
876 * This peer can no longer own @a path as the path
877 * has been extended and a peer further down the line
878 * is now the new owner.
880 * @param cp old owner of the @a path
881 * @param path path where the ownership is lost
882 * @param hn note in @a cp's path heap that must be deleted
885 GCP_detach_path (struct CadetPeer *cp,
886 struct CadetPeerPath *path,
887 struct GNUNET_CONTAINER_HeapNode *hn)
889 LOG (GNUNET_ERROR_TYPE_DEBUG,
890 "Detatching path %s from peer %s\n",
893 GNUNET_assert (path ==
894 GNUNET_CONTAINER_heap_remove_node (hn));
899 * Add a @a connection to this @a cp.
901 * @param cp peer via which the @a connection goes
902 * @param cc the connection to add
905 GCP_add_connection (struct CadetPeer *cp,
906 struct CadetConnection *cc)
908 LOG (GNUNET_ERROR_TYPE_DEBUG,
909 "Adding connection %s to peer %s\n",
912 GNUNET_assert (GNUNET_OK ==
913 GNUNET_CONTAINER_multishortmap_put (cp->connections,
914 &GCC_get_id (cc)->connection_of_tunnel,
916 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
921 * Remove a @a connection that went via this @a cp.
923 * @param cp peer via which the @a connection went
924 * @param cc the connection to remove
927 GCP_remove_connection (struct CadetPeer *cp,
928 struct CadetConnection *cc)
930 LOG (GNUNET_ERROR_TYPE_DEBUG,
931 "Removing connection %s from peer %s\n",
934 GNUNET_assert (GNUNET_YES ==
935 GNUNET_CONTAINER_multishortmap_remove (cp->connections,
936 &GCC_get_id (cc)->connection_of_tunnel,
942 * Retrieve the CadetPeer stucture associated with the
943 * peer. Optionally create one and insert it in the appropriate
944 * structures if the peer is not known yet.
946 * @param peer_id Full identity of the peer.
947 * @param create #GNUNET_YES if a new peer should be created if unknown.
948 * #GNUNET_NO to return NULL if peer is unknown.
949 * @return Existing or newly created peer structure.
950 * NULL if unknown and not requested @a create
953 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
956 struct CadetPeer *cp;
958 cp = GNUNET_CONTAINER_multipeermap_get (peers,
962 if (GNUNET_NO == create)
964 cp = GNUNET_new (struct CadetPeer);
966 cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
968 cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
969 GNUNET_assert (GNUNET_YES ==
970 GNUNET_CONTAINER_multipeermap_put (peers,
973 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
974 LOG (GNUNET_ERROR_TYPE_DEBUG,
975 "Creating peer %s\n",
982 * Obtain the peer identity for a `struct CadetPeer`.
984 * @param cp our peer handle
985 * @return the peer identity
987 const struct GNUNET_PeerIdentity *
988 GCP_get_id (struct CadetPeer *cp)
995 * Iterate over all known peers.
997 * @param iter Iterator.
998 * @param cls Closure for @c iter.
1001 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
1004 GNUNET_CONTAINER_multipeermap_iterate (peers,
1011 * Count the number of known paths toward the peer.
1013 * @param cp Peer to get path info.
1014 * @return Number of known paths.
1017 GCP_count_paths (const struct CadetPeer *cp)
1019 return cp->num_paths;
1024 * Iterate over the paths to a peer.
1026 * @param cp Peer to get path info.
1027 * @param callback Function to call for every path.
1028 * @param callback_cls Closure for @a callback.
1029 * @return Number of iterated paths.
1032 GCP_iterate_paths (struct CadetPeer *cp,
1033 GCP_PathIterator callback,
1036 unsigned int ret = 0;
1038 LOG (GNUNET_ERROR_TYPE_DEBUG,
1039 "Iterating over paths to peer %s%s\n",
1041 (NULL == cp->core_mq) ? "" : " including direct link");
1042 if (NULL != cp->core_mq)
1044 struct CadetPeerPath *path;
1046 path = GCPP_get_path_from_route (1,
1050 callback (callback_cls,
1055 for (unsigned int i=0;i<cp->path_dll_length;i++)
1057 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1063 callback (callback_cls,
1074 * Iterate over the paths to @a cp where
1075 * @a cp is at distance @a dist from us.
1077 * @param cp Peer to get path info.
1078 * @param dist desired distance of @a cp to us on the path
1079 * @param callback Function to call for every path.
1080 * @param callback_cls Closure for @a callback.
1081 * @return Number of iterated paths.
1084 GCP_iterate_paths_at (struct CadetPeer *cp,
1086 GCP_PathIterator callback,
1089 unsigned int ret = 0;
1091 if (dist >= cp->path_dll_length)
1093 LOG (GNUNET_ERROR_TYPE_DEBUG,
1094 "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1096 cp->path_dll_length);
1099 for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1104 callback (callback_cls,
1115 * Get the tunnel towards a peer.
1117 * @param cp Peer to get from.
1118 * @param create #GNUNET_YES to create a tunnel if we do not have one
1119 * @return Tunnel towards peer.
1121 struct CadetTunnel *
1122 GCP_get_tunnel (struct CadetPeer *cp,
1127 if ( (NULL != cp->t) ||
1128 (GNUNET_NO == create) )
1130 cp->t = GCT_create_tunnel (cp);
1131 consider_peer_activate (cp);
1137 * Hello offer was passed to the transport service. Mark it
1140 * @param cls the `struct CadetPeer` where the offer completed
1143 hello_offer_done (void *cls)
1145 struct CadetPeer *cp = cls;
1147 cp->hello_offer = NULL;
1152 * We got a HELLO for a @a peer, remember it, and possibly
1153 * trigger adequate actions (like trying to connect).
1155 * @param cp the peer we got a HELLO for
1156 * @param hello the HELLO to remember
1159 GCP_set_hello (struct CadetPeer *cp,
1160 const struct GNUNET_HELLO_Message *hello)
1162 struct GNUNET_HELLO_Message *mrg;
1164 LOG (GNUNET_ERROR_TYPE_DEBUG,
1165 "Got %u byte HELLO for peer %s\n",
1166 (unsigned int) GNUNET_HELLO_size (hello),
1168 if (NULL != cp->hello_offer)
1170 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
1171 cp->hello_offer = NULL;
1173 if (NULL != cp->hello)
1175 mrg = GNUNET_HELLO_merge (hello,
1177 GNUNET_free (cp->hello);
1182 cp->hello = GNUNET_memdup (hello,
1183 GNUNET_HELLO_size (hello));
1186 = GNUNET_TRANSPORT_offer_hello (cfg,
1187 GNUNET_HELLO_get_header (cp->hello) ,
1190 /* New HELLO means cp's destruction time may change... */
1191 consider_peer_destroy (cp);
1196 * The tunnel to the given peer no longer exists, remove it from our
1197 * data structures, and possibly clean up the peer itself.
1199 * @param cp the peer affected
1200 * @param t the dead tunnel
1203 GCP_drop_tunnel (struct CadetPeer *cp,
1204 struct CadetTunnel *t)
1206 LOG (GNUNET_ERROR_TYPE_DEBUG,
1207 "Dropping tunnel %s to peer %s\n",
1210 GNUNET_assert (cp->t == t);
1212 consider_peer_destroy (cp);
1217 * Test if @a cp has a core-level connection
1219 * @param cp peer to test
1220 * @return #GNUNET_YES if @a cp has a core-level connection
1223 GCP_has_core_connection (struct CadetPeer *cp)
1225 return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1230 * Start message queue change notifications.
1232 * @param cp peer to notify for
1233 * @param cb function to call if mq becomes available or unavailable
1234 * @param cb_cls closure for @a cb
1235 * @return handle to cancel request
1237 struct GCP_MessageQueueManager *
1238 GCP_request_mq (struct CadetPeer *cp,
1239 GCP_MessageQueueNotificationCallback cb,
1242 struct GCP_MessageQueueManager *mqm;
1244 mqm = GNUNET_new (struct GCP_MessageQueueManager);
1246 mqm->cb_cls = cb_cls;
1248 GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1251 LOG (GNUNET_ERROR_TYPE_DEBUG,
1252 "Creating MQM %p for peer %s\n",
1255 if (NULL != cp->core_mq)
1263 * Stops message queue change notifications.
1265 * @param mqm handle matching request to cancel
1266 * @param last_env final message to transmit, or NULL
1269 GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1270 struct GNUNET_MQ_Envelope *last_env)
1272 struct CadetPeer *cp = mqm->cp;
1274 LOG (GNUNET_ERROR_TYPE_DEBUG,
1275 "Destroying MQM %p for peer %s%s\n",
1278 (NULL == last_env) ? "" : " with last ditch transmission");
1279 if (NULL != mqm->env)
1280 GNUNET_MQ_discard (mqm->env);
1281 if (NULL != last_env)
1283 if (NULL != cp->core_mq)
1284 GNUNET_MQ_send (cp->core_mq,
1287 GNUNET_MQ_discard (last_env);
1289 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1297 * Send the message in @a env to @a cp, overriding queueing logic.
1298 * This function should only be used to send error messages outside
1299 * of flow and congestion control, similar to ICMP. Note that
1300 * the envelope may be silently discarded as well.
1302 * @param cp peer to send the message to
1303 * @param env envelope with the message to send
1306 GCP_send_ooo (struct CadetPeer *cp,
1307 struct GNUNET_MQ_Envelope *env)
1309 LOG (GNUNET_ERROR_TYPE_DEBUG,
1310 "Sending message to %s out of management\n",
1312 if (NULL == cp->core_mq)
1314 GNUNET_MQ_discard (env);
1317 GNUNET_MQ_send (cp->core_mq,
1324 /* end of gnunet-service-cadet-new_peer.c */