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 "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"
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 GNUNET_assert (0 == cp->path_dll_length);
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 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
288 GNUNET_free_non_null (cp->hello);
289 /* Peer should not be freed if paths exist; if there are no paths,
290 there ought to be no connections, and without connections, no
291 notifications. Thus we can assert that mqm_head is empty at this
293 GNUNET_assert (NULL == cp->mqm_head);
299 * This peer is now on more "active" duty, activate processes related to it.
301 * @param cp the more-active peer
304 consider_peer_activate (struct CadetPeer *cp)
308 LOG (GNUNET_ERROR_TYPE_DEBUG,
309 "Updating peer %s activation state (%u connections)%s%s\n",
311 GNUNET_CONTAINER_multishortmap_size (cp->connections),
312 (NULL == cp->t) ? "" : " with tunnel",
313 (NULL == cp->core_mq) ? "" : " with CORE link");
314 if (NULL != cp->destroy_task)
316 /* It's active, do not destory! */
317 GNUNET_SCHEDULER_cancel (cp->destroy_task);
318 cp->destroy_task = NULL;
320 if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
323 /* We're just on a path or directly connected; don't bother too much */
324 if (NULL != cp->connectivity_suggestion)
326 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
327 cp->connectivity_suggestion = NULL;
329 if (NULL != cp->search_h)
331 GCD_search_stop (cp->search_h);
336 if (NULL == cp->core_mq)
338 /* Lacks direct connection, try to create one by querying the DHT */
339 if ( (NULL == cp->search_h) &&
340 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
342 = GCD_search (&cp->pid);
346 /* Have direct connection, stop DHT search if active */
347 if (NULL != cp->search_h)
349 GCD_search_stop (cp->search_h);
354 /* If we have a tunnel, our urge for connections is much bigger */
355 strength = (NULL != cp->t) ? 32 : 1;
356 if (NULL != cp->connectivity_suggestion)
357 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
358 cp->connectivity_suggestion
359 = GNUNET_ATS_connectivity_suggest (ats_ch,
366 * This peer may no longer be needed, consider cleaning it up.
368 * @param cp peer to clean up
371 consider_peer_destroy (struct CadetPeer *cp);
375 * We really no longere care about a peer, stop hogging memory with paths to it.
376 * Afterwards, see if there is more to be cleaned up about this peer.
378 * @param cls a `struct CadetPeer`.
381 drop_paths (void *cls)
383 struct CadetPeer *cp = cls;
384 struct CadetPeerPath *path;
386 cp->destroy_task = NULL;
387 while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
389 consider_peer_destroy (cp);
394 * This peer may no longer be needed, consider cleaning it up.
396 * @param cp peer to clean up
399 consider_peer_destroy (struct CadetPeer *cp)
401 struct GNUNET_TIME_Relative exp;
403 if (NULL != cp->destroy_task)
405 GNUNET_SCHEDULER_cancel (cp->destroy_task);
406 cp->destroy_task = NULL;
409 return; /* still relevant! */
410 if (NULL != cp->core_mq)
411 return; /* still relevant! */
412 if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
413 return; /* still relevant! */
414 if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))
416 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
421 if (0 < cp->path_dll_length)
422 return; /* still relevant! */
423 if (NULL != cp->hello)
425 /* relevant only until HELLO expires */
426 exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
427 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
432 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
439 * Set the message queue to @a mq for peer @a cp and notify watchers.
441 * @param cp peer to modify
442 * @param mq message queue to set (can be NULL)
445 GCP_set_mq (struct CadetPeer *cp,
446 struct GNUNET_MQ_Handle *mq)
448 LOG (GNUNET_ERROR_TYPE_DEBUG,
449 "Message queue for peer %s is now %p\n",
453 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
459 if (NULL != mqm->env)
461 GNUNET_MQ_discard (mqm->env);
463 mqm->cb (mqm->cb_cls,
468 mqm->cb (mqm->cb_cls,
474 GNUNET_assert (NULL == mqm->env);
475 mqm->cb (mqm->cb_cls,
481 consider_peer_activate (cp);
483 consider_peer_destroy (cp);
488 /* have a new, direct path to the target, notify tunnel */
489 struct CadetPeerPath *path;
491 path = GCPP_get_path_from_route (1,
493 GCT_consider_path (cp->t,
501 * Transmit current envelope from this @a mqm.
503 * @param mqm mqm to transmit message for now
506 mqm_execute (struct GCP_MessageQueueManager *mqm)
508 struct CadetPeer *cp = mqm->cp;
510 LOG (GNUNET_ERROR_TYPE_DEBUG,
511 "Sending to peer %s from MQM %p\n",
514 /* Move entry to the end of the DLL, to be fair. */
515 if (mqm != cp->mqm_tail)
517 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
520 GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
524 GNUNET_MQ_send (cp->core_mq,
527 cp->mqm_ready_counter--;
532 * Function called when CORE took one of the messages from
533 * a message queue manager and transmitted it.
535 * @param cls the `struct CadetPeeer` where we made progress
538 mqm_send_done (void *cls)
540 struct CadetPeer *cp = cls;
542 LOG (GNUNET_ERROR_TYPE_DEBUG,
543 "Sending to peer %s completed\n",
545 if (0 == cp->mqm_ready_counter)
546 return; /* nothing to do */
547 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
551 if (NULL == mqm->env)
560 * Send the message in @a env to @a cp.
562 * @param mqm the message queue manager to use for transmission
563 * @param env envelope with the message to send; must NOT
564 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
567 GCP_send (struct GCP_MessageQueueManager *mqm,
568 struct GNUNET_MQ_Envelope *env)
570 struct CadetPeer *cp = mqm->cp;
572 LOG (GNUNET_ERROR_TYPE_DEBUG,
573 "Queueing message to peer %s in MQM %p\n",
576 GNUNET_assert (NULL != cp->core_mq);
577 GNUNET_assert (NULL == mqm->env);
578 GNUNET_MQ_notify_sent (env,
582 cp->mqm_ready_counter++;
583 if (0 != GNUNET_MQ_get_length (cp->core_mq))
590 * Function called to destroy a peer now.
593 * @param pid identity of the peer (unused)
594 * @param value the `struct CadetPeer` to clean up
595 * @return #GNUNET_OK (continue to iterate)
598 destroy_iterator_cb (void *cls,
599 const struct GNUNET_PeerIdentity *pid,
602 struct CadetPeer *cp = value;
604 if (NULL != cp->destroy_task)
606 GNUNET_SCHEDULER_cancel (cp->destroy_task);
607 cp->destroy_task = NULL;
615 * Clean up all entries about all peers.
616 * Must only be called after all tunnels, CORE-connections and
617 * connections are down.
620 GCP_destroy_all_peers ()
622 LOG (GNUNET_ERROR_TYPE_DEBUG,
623 "Destroying all peers now\n");
624 GNUNET_CONTAINER_multipeermap_iterate (peers,
625 &destroy_iterator_cb,
631 * Add an entry to the DLL of all of the paths that this peer is on.
633 * @param cp peer to modify
634 * @param entry an entry on a path
635 * @param off offset of this peer on the path
638 GCP_path_entry_add (struct CadetPeer *cp,
639 struct CadetPeerPathEntry *entry,
642 LOG (GNUNET_ERROR_TYPE_DEBUG,
643 "Discovered that peer %s is on path %s at offset %u\n",
645 GCPP_2s (entry->path),
647 if (off >= cp->path_dll_length)
649 unsigned int len = cp->path_dll_length;
651 GNUNET_array_grow (cp->path_heads,
654 GNUNET_array_grow (cp->path_tails,
658 GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
663 /* If we have a tunnel to this peer, tell the tunnel that there is a
664 new path available. */
666 GCT_consider_path (cp->t,
670 if ( (NULL != cp->search_h) &&
671 (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths) )
673 /* Now I have enough paths, stop search */
674 GCD_search_stop (cp->search_h);
681 * Remove an entry from the DLL of all of the paths that this peer is on.
683 * @param cp peer to modify
684 * @param entry an entry on a path
685 * @param off offset of this peer on the path
688 GCP_path_entry_remove (struct CadetPeer *cp,
689 struct CadetPeerPathEntry *entry,
692 LOG (GNUNET_ERROR_TYPE_DEBUG,
693 "Removing knowledge about peer %s beging on path %s at offset %u\n",
695 GCPP_2s (entry->path),
697 GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
700 GNUNET_assert (0 < cp->num_paths);
702 if ( (NULL == cp->core_mq) &&
704 (NULL == cp->search_h) &&
705 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
707 = GCD_search (&cp->pid);
712 * Try adding a @a path to this @a peer. If the peer already
713 * has plenty of paths, return NULL.
715 * @param cp peer to which the @a path leads to
716 * @param path a path looking for an owner; may not be fully initialized yet!
717 * @param off offset of @a cp in @a path
718 * @param force force attaching the path
719 * @return NULL if this peer does not care to become a new owner,
720 * otherwise the node in the peer's path heap for the @a path.
722 struct GNUNET_CONTAINER_HeapNode *
723 GCP_attach_path (struct CadetPeer *cp,
724 struct CadetPeerPath *path,
728 GNUNET_CONTAINER_HeapCostType desirability;
729 struct CadetPeerPath *root;
730 GNUNET_CONTAINER_HeapCostType root_desirability;
731 struct GNUNET_CONTAINER_HeapNode *hn;
733 desirability = GCPP_get_desirability (path);
734 if (GNUNET_NO == force)
736 /* FIXME: desirability is not yet initialized; tricky! */
738 GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
743 root_desirability = 0;
746 if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
747 (desirability < root_desirability) )
749 LOG (GNUNET_ERROR_TYPE_DEBUG,
750 "Decided to not attach path %p to peer %s due to undesirability\n",
757 LOG (GNUNET_ERROR_TYPE_DEBUG,
758 "Attaching path %s to peer %s (%s)\n",
761 (GNUNET_NO == force) ? "desirable" : "forced");
763 /* Yes, we'd like to add this path, add to our heap */
764 hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
768 /* Consider maybe dropping other paths because of the new one */
769 if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
770 2 * DESIRED_CONNECTIONS_PER_TUNNEL)
772 /* Now we have way too many, drop least desirable UNLESS it is in use!
773 (Note that this intentionally keeps highly desireable, but currently
774 unused paths around in the hope that we might be able to switch, even
775 if the number of paths exceeds the threshold.) */
776 root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
777 if ( (path != root) &&
779 GCPP_get_connection (root,
781 GCPP_get_length (root) - 1)) )
783 /* Got plenty of paths to this destination, and this is a low-quality
784 one that we don't care, allow it to die. */
785 GNUNET_assert (root ==
786 GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
795 * This peer can no longer own @a path as the path
796 * has been extended and a peer further down the line
797 * is now the new owner.
799 * @param cp old owner of the @a path
800 * @param path path where the ownership is lost
801 * @param hn note in @a cp's path heap that must be deleted
804 GCP_detach_path (struct CadetPeer *cp,
805 struct CadetPeerPath *path,
806 struct GNUNET_CONTAINER_HeapNode *hn)
808 LOG (GNUNET_ERROR_TYPE_DEBUG,
809 "Detatching path %s from peer %s\n",
812 GNUNET_assert (path ==
813 GNUNET_CONTAINER_heap_remove_node (hn));
818 * Add a @a connection to this @a cp.
820 * @param cp peer via which the @a connection goes
821 * @param cc the connection to add
824 GCP_add_connection (struct CadetPeer *cp,
825 struct CadetConnection *cc)
827 LOG (GNUNET_ERROR_TYPE_DEBUG,
828 "Adding connection %s to peer %s\n",
831 GNUNET_assert (GNUNET_OK ==
832 GNUNET_CONTAINER_multishortmap_put (cp->connections,
833 &GCC_get_id (cc)->connection_of_tunnel,
835 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
840 * Remove a @a connection that went via this @a cp.
842 * @param cp peer via which the @a connection went
843 * @param cc the connection to remove
846 GCP_remove_connection (struct CadetPeer *cp,
847 struct CadetConnection *cc)
849 LOG (GNUNET_ERROR_TYPE_DEBUG,
850 "Removing connection %s from peer %s\n",
853 GNUNET_assert (GNUNET_YES ==
854 GNUNET_CONTAINER_multishortmap_remove (cp->connections,
855 &GCC_get_id (cc)->connection_of_tunnel,
861 * Retrieve the CadetPeer stucture associated with the
862 * peer. Optionally create one and insert it in the appropriate
863 * structures if the peer is not known yet.
865 * @param peer_id Full identity of the peer.
866 * @param create #GNUNET_YES if a new peer should be created if unknown.
867 * #GNUNET_NO to return NULL if peer is unknown.
868 * @return Existing or newly created peer structure.
869 * NULL if unknown and not requested @a create
872 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
875 struct CadetPeer *cp;
877 cp = GNUNET_CONTAINER_multipeermap_get (peers,
881 if (GNUNET_NO == create)
883 cp = GNUNET_new (struct CadetPeer);
885 cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
887 cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
888 GNUNET_assert (GNUNET_YES ==
889 GNUNET_CONTAINER_multipeermap_put (peers,
892 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
893 LOG (GNUNET_ERROR_TYPE_DEBUG,
894 "Creating peer %s\n",
901 * Obtain the peer identity for a `struct CadetPeer`.
903 * @param cp our peer handle
904 * @return the peer identity
906 const struct GNUNET_PeerIdentity *
907 GCP_get_id (struct CadetPeer *cp)
914 * Iterate over all known peers.
916 * @param iter Iterator.
917 * @param cls Closure for @c iter.
920 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
923 GNUNET_CONTAINER_multipeermap_iterate (peers,
930 * Count the number of known paths toward the peer.
932 * @param cp Peer to get path info.
933 * @return Number of known paths.
936 GCP_count_paths (const struct CadetPeer *cp)
938 return cp->num_paths;
943 * Iterate over the paths to a peer.
945 * @param cp Peer to get path info.
946 * @param callback Function to call for every path.
947 * @param callback_cls Closure for @a callback.
948 * @return Number of iterated paths.
951 GCP_iterate_paths (struct CadetPeer *cp,
952 GCP_PathIterator callback,
955 unsigned int ret = 0;
957 LOG (GNUNET_ERROR_TYPE_DEBUG,
958 "Iterating over paths to peer %s%s\n",
960 (NULL == cp->core_mq) ? "" : " including direct link");
961 if (NULL != cp->core_mq)
963 struct CadetPeerPath *path;
965 path = GCPP_get_path_from_route (1,
969 callback (callback_cls,
974 for (unsigned int i=0;i<cp->path_dll_length;i++)
976 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
982 callback (callback_cls,
993 * Iterate over the paths to @a cp where
994 * @a cp is at distance @a dist from us.
996 * @param cp Peer to get path info.
997 * @param dist desired distance of @a cp to us on the path
998 * @param callback Function to call for every path.
999 * @param callback_cls Closure for @a callback.
1000 * @return Number of iterated paths.
1003 GCP_iterate_paths_at (struct CadetPeer *cp,
1005 GCP_PathIterator callback,
1008 unsigned int ret = 0;
1010 if (dist >= cp->path_dll_length)
1012 LOG (GNUNET_ERROR_TYPE_DEBUG,
1013 "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1015 cp->path_dll_length);
1018 for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1023 callback (callback_cls,
1034 * Get the tunnel towards a peer.
1036 * @param cp Peer to get from.
1037 * @param create #GNUNET_YES to create a tunnel if we do not have one
1038 * @return Tunnel towards peer.
1040 struct CadetTunnel *
1041 GCP_get_tunnel (struct CadetPeer *cp,
1046 if ( (NULL != cp->t) ||
1047 (GNUNET_NO == create) )
1049 cp->t = GCT_create_tunnel (cp);
1050 consider_peer_activate (cp);
1056 * Hello offer was passed to the transport service. Mark it
1059 * @param cls the `struct CadetPeer` where the offer completed
1062 hello_offer_done (void *cls)
1064 struct CadetPeer *cp = cls;
1066 cp->hello_offer = NULL;
1071 * We got a HELLO for a @a peer, remember it, and possibly
1072 * trigger adequate actions (like trying to connect).
1074 * @param cp the peer we got a HELLO for
1075 * @param hello the HELLO to remember
1078 GCP_set_hello (struct CadetPeer *cp,
1079 const struct GNUNET_HELLO_Message *hello)
1081 struct GNUNET_HELLO_Message *mrg;
1083 LOG (GNUNET_ERROR_TYPE_DEBUG,
1084 "Got %u byte HELLO for peer %s\n",
1085 (unsigned int) GNUNET_HELLO_size (hello),
1087 if (NULL != cp->hello_offer)
1089 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
1090 cp->hello_offer = NULL;
1092 if (NULL != cp->hello)
1094 mrg = GNUNET_HELLO_merge (hello,
1096 GNUNET_free (cp->hello);
1101 cp->hello = GNUNET_memdup (hello,
1102 GNUNET_HELLO_size (hello));
1105 = GNUNET_TRANSPORT_offer_hello (cfg,
1106 GNUNET_HELLO_get_header (cp->hello) ,
1109 /* New HELLO means cp's destruction time may change... */
1110 consider_peer_destroy (cp);
1115 * The tunnel to the given peer no longer exists, remove it from our
1116 * data structures, and possibly clean up the peer itself.
1118 * @param cp the peer affected
1119 * @param t the dead tunnel
1122 GCP_drop_tunnel (struct CadetPeer *cp,
1123 struct CadetTunnel *t)
1125 LOG (GNUNET_ERROR_TYPE_DEBUG,
1126 "Dropping tunnel %s to peer %s\n",
1129 GNUNET_assert (cp->t == t);
1131 consider_peer_destroy (cp);
1136 * Test if @a cp has a core-level connection
1138 * @param cp peer to test
1139 * @return #GNUNET_YES if @a cp has a core-level connection
1142 GCP_has_core_connection (struct CadetPeer *cp)
1144 return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1149 * Start message queue change notifications.
1151 * @param cp peer to notify for
1152 * @param cb function to call if mq becomes available or unavailable
1153 * @param cb_cls closure for @a cb
1154 * @return handle to cancel request
1156 struct GCP_MessageQueueManager *
1157 GCP_request_mq (struct CadetPeer *cp,
1158 GCP_MessageQueueNotificationCallback cb,
1161 struct GCP_MessageQueueManager *mqm;
1163 mqm = GNUNET_new (struct GCP_MessageQueueManager);
1165 mqm->cb_cls = cb_cls;
1167 GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1170 LOG (GNUNET_ERROR_TYPE_DEBUG,
1171 "Creating MQM %p for peer %s\n",
1174 if (NULL != cp->core_mq)
1182 * Stops message queue change notifications.
1184 * @param mqm handle matching request to cancel
1185 * @param last_env final message to transmit, or NULL
1188 GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1189 struct GNUNET_MQ_Envelope *last_env)
1191 struct CadetPeer *cp = mqm->cp;
1193 LOG (GNUNET_ERROR_TYPE_DEBUG,
1194 "Destroying MQM %p for peer %s%s\n",
1197 (NULL == last_env) ? "" : " with last ditch transmission");
1198 if (NULL != mqm->env)
1199 GNUNET_MQ_discard (mqm->env);
1200 if (NULL != last_env)
1202 if (NULL != cp->core_mq)
1203 GNUNET_MQ_send (cp->core_mq,
1206 GNUNET_MQ_discard (last_env);
1208 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1216 * Send the message in @a env to @a cp, overriding queueing logic.
1217 * This function should only be used to send error messages outside
1218 * of flow and congestion control, similar to ICMP. Note that
1219 * the envelope may be silently discarded as well.
1221 * @param cp peer to send the message to
1222 * @param env envelope with the message to send
1225 GCP_send_ooo (struct CadetPeer *cp,
1226 struct GNUNET_MQ_Envelope *env)
1228 LOG (GNUNET_ERROR_TYPE_DEBUG,
1229 "Sending message to %s out of management\n",
1231 if (NULL == cp->core_mq)
1233 GNUNET_MQ_discard (env);
1236 GNUNET_MQ_send (cp->core_mq,
1243 /* end of gnunet-service-cadet-new_peer.c */