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 * - 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))
35 #include "gnunet_util_lib.h"
36 #include "gnunet_hello_lib.h"
37 #include "gnunet_signatures.h"
38 #include "gnunet_transport_service.h"
39 #include "gnunet_ats_service.h"
40 #include "gnunet_core_service.h"
41 #include "gnunet_statistics_service.h"
42 #include "cadet_protocol.h"
43 #include "gnunet-service-cadet-new.h"
44 #include "gnunet-service-cadet-new_connection.h"
45 #include "gnunet-service-cadet-new_dht.h"
46 #include "gnunet-service-cadet-new_peer.h"
47 #include "gnunet-service-cadet-new_paths.h"
48 #include "gnunet-service-cadet-new_tunnels.h"
51 #define LOG(level, ...) GNUNET_log_from(level,"cadet-per",__VA_ARGS__)
55 * How long do we wait until tearing down an idle peer?
57 #define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
60 * How long do we keep paths around if we no longer care about the peer?
62 #define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
68 * Data structure used to track whom we have to notify about changes
69 * to our message queue.
71 struct GCP_MessageQueueManager
77 struct GCP_MessageQueueManager *next;
82 struct GCP_MessageQueueManager *prev;
85 * Function to call with updated message queue object.
87 GCP_MessageQueueNotificationCallback cb;
95 * The peer this is for.
100 * Envelope this manager would like to transmit once it is its turn.
102 struct GNUNET_MQ_Envelope *env;
108 * Struct containing all information regarding a given peer
115 struct GNUNET_PeerIdentity pid;
118 * Last time we heard from this peer
120 struct GNUNET_TIME_Absolute last_contact;
123 * Array of DLLs of paths traversing the peer, organized by the
124 * offset of the peer on the larger path.
126 struct CadetPeerPathEntry **path_heads;
129 * Array of DLL of paths traversing the peer, organized by the
130 * offset of the peer on the larger path.
132 struct CadetPeerPathEntry **path_tails;
135 * Notifications to call when @e core_mq changes.
137 struct GCP_MessageQueueManager *mqm_head;
140 * Notifications to call when @e core_mq changes.
142 struct GCP_MessageQueueManager *mqm_tail;
145 * MIN-heap of paths owned by this peer (they also end at this
146 * peer). Ordered by desirability.
148 struct GNUNET_CONTAINER_Heap *path_heap;
151 * Handle to stop the DHT search for paths to this peer
153 struct GCD_search_handle *search_h;
156 * Task to stop the DHT search for paths to this peer
158 struct GNUNET_SCHEDULER_Task *search_delayedXXX;
161 * Task to destroy this entry.
163 struct GNUNET_SCHEDULER_Task *destroy_task;
166 * Tunnel to this peer, if any.
168 struct CadetTunnel *t;
171 * Connections that go through this peer; indexed by tid.
173 struct GNUNET_CONTAINER_MultiShortmap *connections;
176 * Handle for core transmissions.
178 struct GNUNET_MQ_Handle *core_mq;
181 * Hello message of the peer.
183 struct GNUNET_HELLO_Message *hello;
186 * Handle to us offering the HELLO to the transport.
188 struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
191 * Handle to our ATS request asking ATS to suggest an address
192 * to TRANSPORT for this peer (to establish a direct link).
194 struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
197 * How many messages are in the queue to this peer.
199 unsigned int queue_n;
202 * How many paths do we have to this peer (in all @e path_heads DLLs combined).
204 unsigned int num_paths;
207 * Number of message queue managers of this peer that have a message in waiting.
209 * Used to quickly see if we need to bother scanning the @e msm_head DLL.
210 * TODO: could be replaced by another DLL that would then allow us to avoid
211 * the O(n)-scan of the DLL for ready entries!
213 unsigned int mqm_ready_counter;
216 * Current length of the @e path_heads and @path_tails arrays.
217 * The arrays should be grown as needed.
219 unsigned int path_dll_length;
225 * Get the static string for a peer ID.
228 * @return Static string for it's ID.
231 GCP_2s (const struct CadetPeer *cp)
235 GNUNET_snprintf (buf,
238 GNUNET_i2s (&cp->pid));
244 * This peer is no longer be needed, clean it up now.
246 * @param cls peer to clean up
249 destroy_peer (void *cls)
251 struct CadetPeer *cp = cls;
253 LOG (GNUNET_ERROR_TYPE_DEBUG,
254 "Destroying state about peer %s\n",
256 cp->destroy_task = NULL;
257 GNUNET_assert (NULL == cp->t);
258 GNUNET_assert (NULL == cp->core_mq);
259 for (unsigned int i=0;i<cp->path_dll_length;i++)
260 GNUNET_assert (NULL == cp->path_heads[i]);
261 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
262 GNUNET_assert (GNUNET_YES ==
263 GNUNET_CONTAINER_multipeermap_remove (peers,
266 GNUNET_free_non_null (cp->path_heads);
267 GNUNET_free_non_null (cp->path_tails);
268 cp->path_dll_length = 0;
269 if (NULL != cp->search_h)
271 GCD_search_stop (cp->search_h);
274 /* FIXME: clean up search_delayedXXX! */
276 if (NULL != cp->hello_offer)
278 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
279 cp->hello_offer = NULL;
281 if (NULL != cp->connectivity_suggestion)
283 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
284 cp->connectivity_suggestion = NULL;
286 GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
287 if (NULL != cp->path_heap)
289 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
290 cp->path_heap = NULL;
292 GNUNET_free_non_null (cp->hello);
293 /* Peer should not be freed if paths exist; if there are no paths,
294 there ought to be no connections, and without connections, no
295 notifications. Thus we can assert that mqm_head is empty at this
297 GNUNET_assert (NULL == cp->mqm_head);
303 * This peer is now on more "active" duty, activate processes related to it.
305 * @param cp the more-active peer
308 consider_peer_activate (struct CadetPeer *cp)
312 LOG (GNUNET_ERROR_TYPE_DEBUG,
313 "Updating peer %s activation state (%u connections)%s%s\n",
315 GNUNET_CONTAINER_multishortmap_size (cp->connections),
316 (NULL == cp->t) ? "" : " with tunnel",
317 (NULL == cp->core_mq) ? "" : " with CORE link");
318 if (NULL != cp->destroy_task)
320 /* It's active, do not destory! */
321 GNUNET_SCHEDULER_cancel (cp->destroy_task);
322 cp->destroy_task = NULL;
324 if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
327 /* We're just on a path or directly connected; don't bother too much */
328 if (NULL != cp->connectivity_suggestion)
330 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
331 cp->connectivity_suggestion = NULL;
333 if (NULL != cp->search_h)
335 GCD_search_stop (cp->search_h);
340 if (NULL == cp->core_mq)
342 /* Lacks direct connection, try to create one by querying the DHT */
343 if ( (NULL == cp->search_h) &&
344 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
346 = GCD_search (&cp->pid);
350 /* Have direct connection, stop DHT search if active */
351 if (NULL != cp->search_h)
353 GCD_search_stop (cp->search_h);
358 /* If we have a tunnel, our urge for connections is much bigger */
359 strength = (NULL != cp->t) ? 32 : 1;
360 if (NULL != cp->connectivity_suggestion)
361 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
362 cp->connectivity_suggestion
363 = GNUNET_ATS_connectivity_suggest (ats_ch,
370 * This peer may no longer be needed, consider cleaning it up.
372 * @param cp peer to clean up
375 consider_peer_destroy (struct CadetPeer *cp);
379 * We really no longere care about a peer, stop hogging memory with paths to it.
380 * Afterwards, see if there is more to be cleaned up about this peer.
382 * @param cls a `struct CadetPeer`.
385 drop_paths (void *cls)
387 struct CadetPeer *cp = cls;
388 struct CadetPeerPath *path;
390 cp->destroy_task = NULL;
391 while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
393 consider_peer_destroy (cp);
398 * This peer may no longer be needed, consider cleaning it up.
400 * @param cp peer to clean up
403 consider_peer_destroy (struct CadetPeer *cp)
405 struct GNUNET_TIME_Relative exp;
407 if (NULL != cp->destroy_task)
409 GNUNET_SCHEDULER_cancel (cp->destroy_task);
410 cp->destroy_task = NULL;
413 return; /* still relevant! */
414 if (NULL != cp->core_mq)
415 return; /* still relevant! */
416 if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
417 return; /* still relevant! */
418 if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))
420 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
425 for (unsigned int i=0;i<cp->path_dll_length;i++)
426 if (NULL != cp->path_heads[i])
427 return; /* still relevant! */
428 if (NULL != cp->hello)
430 /* relevant only until HELLO expires */
431 exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
432 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
437 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
444 * Set the message queue to @a mq for peer @a cp and notify watchers.
446 * @param cp peer to modify
447 * @param mq message queue to set (can be NULL)
450 GCP_set_mq (struct CadetPeer *cp,
451 struct GNUNET_MQ_Handle *mq)
453 LOG (GNUNET_ERROR_TYPE_DEBUG,
454 "Message queue for peer %s is now %p\n",
458 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
464 if (NULL != mqm->env)
466 GNUNET_MQ_discard (mqm->env);
468 mqm->cb (mqm->cb_cls,
473 mqm->cb (mqm->cb_cls,
479 GNUNET_assert (NULL == mqm->env);
480 mqm->cb (mqm->cb_cls,
486 consider_peer_activate (cp);
488 consider_peer_destroy (cp);
493 /* have a new, direct path to the target, notify tunnel */
494 struct CadetPeerPath *path;
496 path = GCPP_get_path_from_route (1,
498 GCT_consider_path (cp->t,
506 * Debug function should NEVER return true in production code, useful to
507 * simulate losses for testcases.
509 * @return #GNUNET_YES or #GNUNET_NO with the decision to drop.
514 if (0 == drop_percent)
516 if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
524 * Function called when CORE took one of the messages from
525 * a message queue manager and transmitted it.
527 * @param cls the `struct CadetPeeer` where we made progress
530 mqm_send_done (void *cls);
534 * Transmit current envelope from this @a mqm.
536 * @param mqm mqm to transmit message for now
539 mqm_execute (struct GCP_MessageQueueManager *mqm)
541 struct CadetPeer *cp = mqm->cp;
543 /* Move entry to the end of the DLL, to be fair. */
544 if (mqm != cp->mqm_tail)
546 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
549 GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
553 cp->mqm_ready_counter--;
554 if (GNUNET_YES == should_I_drop ())
556 LOG (GNUNET_ERROR_TYPE_DEBUG,
557 "DROPPING message to peer %s from MQM %p\n",
560 GNUNET_MQ_discard (mqm->env);
566 LOG (GNUNET_ERROR_TYPE_DEBUG,
567 "Sending to peer %s from MQM %p\n",
570 GNUNET_MQ_send (cp->core_mq,
574 mqm->cb (mqm->cb_cls,
580 * Function called when CORE took one of the messages from
581 * a message queue manager and transmitted it.
583 * @param cls the `struct CadetPeeer` where we made progress
586 mqm_send_done (void *cls)
588 struct CadetPeer *cp = cls;
590 LOG (GNUNET_ERROR_TYPE_DEBUG,
591 "Sending to peer %s completed\n",
593 if (0 == cp->mqm_ready_counter)
594 return; /* nothing to do */
595 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
599 if (NULL == mqm->env)
608 * Send the message in @a env to @a cp.
610 * @param mqm the message queue manager to use for transmission
611 * @param env envelope with the message to send; must NOT
612 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
615 GCP_send (struct GCP_MessageQueueManager *mqm,
616 struct GNUNET_MQ_Envelope *env)
618 struct CadetPeer *cp = mqm->cp;
620 LOG (GNUNET_ERROR_TYPE_DEBUG,
621 "Queueing message to peer %s in MQM %p\n",
624 GNUNET_assert (NULL != cp->core_mq);
625 GNUNET_assert (NULL == mqm->env);
626 GNUNET_MQ_notify_sent (env,
630 cp->mqm_ready_counter++;
631 if (0 != GNUNET_MQ_get_length (cp->core_mq))
638 * Function called to destroy a peer now.
641 * @param pid identity of the peer (unused)
642 * @param value the `struct CadetPeer` to clean up
643 * @return #GNUNET_OK (continue to iterate)
646 destroy_iterator_cb (void *cls,
647 const struct GNUNET_PeerIdentity *pid,
650 struct CadetPeer *cp = value;
652 if (NULL != cp->destroy_task)
654 GNUNET_SCHEDULER_cancel (cp->destroy_task);
655 cp->destroy_task = NULL;
663 * Clean up all entries about all peers.
664 * Must only be called after all tunnels, CORE-connections and
665 * connections are down.
668 GCP_destroy_all_peers ()
670 LOG (GNUNET_ERROR_TYPE_DEBUG,
671 "Destroying all peers now\n");
672 GNUNET_CONTAINER_multipeermap_iterate (peers,
673 &destroy_iterator_cb,
679 * Drop all paths owned by this peer, and do not
680 * allow new ones to be added: We are shutting down.
682 * @param cp peer to drop paths to
685 GCP_drop_owned_paths (struct CadetPeer *cp)
687 struct CadetPeerPath *path;
689 LOG (GNUNET_ERROR_TYPE_DEBUG,
690 "Destroying all paths to %s\n",
692 while (NULL != (path =
693 GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
695 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
696 cp->path_heap = NULL;
701 * Add an entry to the DLL of all of the paths that this peer is on.
703 * @param cp peer to modify
704 * @param entry an entry on a path
705 * @param off offset of this peer on the path
708 GCP_path_entry_add (struct CadetPeer *cp,
709 struct CadetPeerPathEntry *entry,
712 GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path,
714 LOG (GNUNET_ERROR_TYPE_DEBUG,
715 "Discovered that peer %s is on path %s at offset %u\n",
717 GCPP_2s (entry->path),
719 if (off >= cp->path_dll_length)
721 unsigned int len = cp->path_dll_length;
723 GNUNET_array_grow (cp->path_heads,
726 GNUNET_array_grow (cp->path_tails,
730 GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
735 /* If we have a tunnel to this peer, tell the tunnel that there is a
736 new path available. */
738 GCT_consider_path (cp->t,
742 if ( (NULL != cp->search_h) &&
743 (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths) )
745 /* Now I have enough paths, stop search */
746 GCD_search_stop (cp->search_h);
753 * Remove an entry from the DLL of all of the paths that this peer is on.
755 * @param cp peer to modify
756 * @param entry an entry on a path
757 * @param off offset of this peer on the path
760 GCP_path_entry_remove (struct CadetPeer *cp,
761 struct CadetPeerPathEntry *entry,
764 LOG (GNUNET_ERROR_TYPE_DEBUG,
765 "Removing knowledge about peer %s beging on path %s at offset %u\n",
767 GCPP_2s (entry->path),
769 GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
772 GNUNET_assert (0 < cp->num_paths);
774 if ( (NULL == cp->core_mq) &&
776 (NULL == cp->search_h) &&
777 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
779 = GCD_search (&cp->pid);
784 * Try adding a @a path to this @a peer. If the peer already
785 * has plenty of paths, return NULL.
787 * @param cp peer to which the @a path leads to
788 * @param path a path looking for an owner; may not be fully initialized yet!
789 * @param off offset of @a cp in @a path
790 * @param force force attaching the path
791 * @return NULL if this peer does not care to become a new owner,
792 * otherwise the node in the peer's path heap for the @a path.
794 struct GNUNET_CONTAINER_HeapNode *
795 GCP_attach_path (struct CadetPeer *cp,
796 struct CadetPeerPath *path,
800 GNUNET_CONTAINER_HeapCostType desirability;
801 struct CadetPeerPath *root;
802 GNUNET_CONTAINER_HeapCostType root_desirability;
803 struct GNUNET_CONTAINER_HeapNode *hn;
805 GNUNET_assert (cp == GCPP_get_peer_at_offset (path,
807 if (NULL == cp->path_heap)
809 /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */
810 GNUNET_assert (GNUNET_NO == force);
813 desirability = GCPP_get_desirability (path);
814 if (GNUNET_NO == force)
816 /* FIXME: desirability is not yet initialized; tricky! */
818 GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
823 root_desirability = 0;
826 if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
827 (desirability < root_desirability) )
829 LOG (GNUNET_ERROR_TYPE_DEBUG,
830 "Decided to not attach path %p to peer %s due to undesirability\n",
837 LOG (GNUNET_ERROR_TYPE_DEBUG,
838 "Attaching path %s to peer %s (%s)\n",
841 (GNUNET_NO == force) ? "desirable" : "forced");
843 /* Yes, we'd like to add this path, add to our heap */
844 hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
848 /* Consider maybe dropping other paths because of the new one */
849 if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
850 2 * DESIRED_CONNECTIONS_PER_TUNNEL)
852 /* Now we have way too many, drop least desirable UNLESS it is in use!
853 (Note that this intentionally keeps highly desireable, but currently
854 unused paths around in the hope that we might be able to switch, even
855 if the number of paths exceeds the threshold.) */
856 root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
857 if ( (path != root) &&
859 GCPP_get_connection (root,
861 GCPP_get_length (root) - 1)) )
863 /* Got plenty of paths to this destination, and this is a low-quality
864 one that we don't care, allow it to die. */
865 GNUNET_assert (root ==
866 GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
875 * This peer can no longer own @a path as the path
876 * has been extended and a peer further down the line
877 * is now the new owner.
879 * @param cp old owner of the @a path
880 * @param path path where the ownership is lost
881 * @param hn note in @a cp's path heap that must be deleted
884 GCP_detach_path (struct CadetPeer *cp,
885 struct CadetPeerPath *path,
886 struct GNUNET_CONTAINER_HeapNode *hn)
888 LOG (GNUNET_ERROR_TYPE_DEBUG,
889 "Detatching path %s from peer %s\n",
892 GNUNET_assert (path ==
893 GNUNET_CONTAINER_heap_remove_node (hn));
898 * Add a @a connection to this @a cp.
900 * @param cp peer via which the @a connection goes
901 * @param cc the connection to add
904 GCP_add_connection (struct CadetPeer *cp,
905 struct CadetConnection *cc)
907 LOG (GNUNET_ERROR_TYPE_DEBUG,
908 "Adding connection %s to peer %s\n",
911 GNUNET_assert (GNUNET_OK ==
912 GNUNET_CONTAINER_multishortmap_put (cp->connections,
913 &GCC_get_id (cc)->connection_of_tunnel,
915 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
920 * Remove a @a connection that went via this @a cp.
922 * @param cp peer via which the @a connection went
923 * @param cc the connection to remove
926 GCP_remove_connection (struct CadetPeer *cp,
927 struct CadetConnection *cc)
929 LOG (GNUNET_ERROR_TYPE_DEBUG,
930 "Removing connection %s from peer %s\n",
933 GNUNET_assert (GNUNET_YES ==
934 GNUNET_CONTAINER_multishortmap_remove (cp->connections,
935 &GCC_get_id (cc)->connection_of_tunnel,
941 * Retrieve the CadetPeer stucture associated with the
942 * peer. Optionally create one and insert it in the appropriate
943 * structures if the peer is not known yet.
945 * @param peer_id Full identity of the peer.
946 * @param create #GNUNET_YES if a new peer should be created if unknown.
947 * #GNUNET_NO to return NULL if peer is unknown.
948 * @return Existing or newly created peer structure.
949 * NULL if unknown and not requested @a create
952 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
955 struct CadetPeer *cp;
957 cp = GNUNET_CONTAINER_multipeermap_get (peers,
961 if (GNUNET_NO == create)
963 cp = GNUNET_new (struct CadetPeer);
965 cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
967 cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
968 GNUNET_assert (GNUNET_YES ==
969 GNUNET_CONTAINER_multipeermap_put (peers,
972 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
973 LOG (GNUNET_ERROR_TYPE_DEBUG,
974 "Creating peer %s\n",
981 * Obtain the peer identity for a `struct CadetPeer`.
983 * @param cp our peer handle
984 * @return the peer identity
986 const struct GNUNET_PeerIdentity *
987 GCP_get_id (struct CadetPeer *cp)
994 * Iterate over all known peers.
996 * @param iter Iterator.
997 * @param cls Closure for @c iter.
1000 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
1003 GNUNET_CONTAINER_multipeermap_iterate (peers,
1010 * Count the number of known paths toward the peer.
1012 * @param cp Peer to get path info.
1013 * @return Number of known paths.
1016 GCP_count_paths (const struct CadetPeer *cp)
1018 return cp->num_paths;
1023 * Iterate over the paths to a peer.
1025 * @param cp Peer to get path info.
1026 * @param callback Function to call for every path.
1027 * @param callback_cls Closure for @a callback.
1028 * @return Number of iterated paths.
1031 GCP_iterate_paths (struct CadetPeer *cp,
1032 GCP_PathIterator callback,
1035 unsigned int ret = 0;
1037 LOG (GNUNET_ERROR_TYPE_DEBUG,
1038 "Iterating over paths to peer %s%s\n",
1040 (NULL == cp->core_mq) ? "" : " including direct link");
1041 if (NULL != cp->core_mq)
1043 struct CadetPeerPath *path;
1045 path = GCPP_get_path_from_route (1,
1049 callback (callback_cls,
1054 for (unsigned int i=0;i<cp->path_dll_length;i++)
1056 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1062 callback (callback_cls,
1073 * Iterate over the paths to @a cp where
1074 * @a cp is at distance @a dist from us.
1076 * @param cp Peer to get path info.
1077 * @param dist desired distance of @a cp to us on the path
1078 * @param callback Function to call for every path.
1079 * @param callback_cls Closure for @a callback.
1080 * @return Number of iterated paths.
1083 GCP_iterate_paths_at (struct CadetPeer *cp,
1085 GCP_PathIterator callback,
1088 unsigned int ret = 0;
1090 if (dist >= cp->path_dll_length)
1092 LOG (GNUNET_ERROR_TYPE_DEBUG,
1093 "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1095 cp->path_dll_length);
1098 for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1103 callback (callback_cls,
1114 * Get the tunnel towards a peer.
1116 * @param cp Peer to get from.
1117 * @param create #GNUNET_YES to create a tunnel if we do not have one
1118 * @return Tunnel towards peer.
1120 struct CadetTunnel *
1121 GCP_get_tunnel (struct CadetPeer *cp,
1126 if ( (NULL != cp->t) ||
1127 (GNUNET_NO == create) )
1129 cp->t = GCT_create_tunnel (cp);
1130 consider_peer_activate (cp);
1136 * Hello offer was passed to the transport service. Mark it
1139 * @param cls the `struct CadetPeer` where the offer completed
1142 hello_offer_done (void *cls)
1144 struct CadetPeer *cp = cls;
1146 cp->hello_offer = NULL;
1151 * We got a HELLO for a @a peer, remember it, and possibly
1152 * trigger adequate actions (like trying to connect).
1154 * @param cp the peer we got a HELLO for
1155 * @param hello the HELLO to remember
1158 GCP_set_hello (struct CadetPeer *cp,
1159 const struct GNUNET_HELLO_Message *hello)
1161 struct GNUNET_HELLO_Message *mrg;
1163 LOG (GNUNET_ERROR_TYPE_DEBUG,
1164 "Got %u byte HELLO for peer %s\n",
1165 (unsigned int) GNUNET_HELLO_size (hello),
1167 if (NULL != cp->hello_offer)
1169 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
1170 cp->hello_offer = NULL;
1172 if (NULL != cp->hello)
1174 mrg = GNUNET_HELLO_merge (hello,
1176 GNUNET_free (cp->hello);
1181 cp->hello = GNUNET_memdup (hello,
1182 GNUNET_HELLO_size (hello));
1185 = GNUNET_TRANSPORT_offer_hello (cfg,
1186 GNUNET_HELLO_get_header (cp->hello) ,
1189 /* New HELLO means cp's destruction time may change... */
1190 consider_peer_destroy (cp);
1195 * The tunnel to the given peer no longer exists, remove it from our
1196 * data structures, and possibly clean up the peer itself.
1198 * @param cp the peer affected
1199 * @param t the dead tunnel
1202 GCP_drop_tunnel (struct CadetPeer *cp,
1203 struct CadetTunnel *t)
1205 LOG (GNUNET_ERROR_TYPE_DEBUG,
1206 "Dropping tunnel %s to peer %s\n",
1209 GNUNET_assert (cp->t == t);
1211 consider_peer_destroy (cp);
1216 * Test if @a cp has a core-level connection
1218 * @param cp peer to test
1219 * @return #GNUNET_YES if @a cp has a core-level connection
1222 GCP_has_core_connection (struct CadetPeer *cp)
1224 return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1229 * Start message queue change notifications.
1231 * @param cp peer to notify for
1232 * @param cb function to call if mq becomes available or unavailable
1233 * @param cb_cls closure for @a cb
1234 * @return handle to cancel request
1236 struct GCP_MessageQueueManager *
1237 GCP_request_mq (struct CadetPeer *cp,
1238 GCP_MessageQueueNotificationCallback cb,
1241 struct GCP_MessageQueueManager *mqm;
1243 mqm = GNUNET_new (struct GCP_MessageQueueManager);
1245 mqm->cb_cls = cb_cls;
1247 GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1250 LOG (GNUNET_ERROR_TYPE_DEBUG,
1251 "Creating MQM %p for peer %s\n",
1254 if (NULL != cp->core_mq)
1262 * Stops message queue change notifications.
1264 * @param mqm handle matching request to cancel
1265 * @param last_env final message to transmit, or NULL
1268 GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1269 struct GNUNET_MQ_Envelope *last_env)
1271 struct CadetPeer *cp = mqm->cp;
1273 LOG (GNUNET_ERROR_TYPE_DEBUG,
1274 "Destroying MQM %p for peer %s%s\n",
1277 (NULL == last_env) ? "" : " with last ditch transmission");
1278 if (NULL != mqm->env)
1279 GNUNET_MQ_discard (mqm->env);
1280 if (NULL != last_env)
1282 if (NULL != cp->core_mq)
1283 GNUNET_MQ_send (cp->core_mq,
1286 GNUNET_MQ_discard (last_env);
1288 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1296 * Send the message in @a env to @a cp, overriding queueing logic.
1297 * This function should only be used to send error messages outside
1298 * of flow and congestion control, similar to ICMP. Note that
1299 * the envelope may be silently discarded as well.
1301 * @param cp peer to send the message to
1302 * @param env envelope with the message to send
1305 GCP_send_ooo (struct CadetPeer *cp,
1306 struct GNUNET_MQ_Envelope *env)
1308 LOG (GNUNET_ERROR_TYPE_DEBUG,
1309 "Sending message to %s out of management\n",
1311 if (NULL == cp->core_mq)
1313 GNUNET_MQ_discard (env);
1316 GNUNET_MQ_send (cp->core_mq,
1323 /* end of gnunet-service-cadet-new_peer.c */