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.
230 * @return Static string for it's ID.
233 GCP_2s (const struct CadetPeer *peer)
237 GNUNET_snprintf (buf,
240 GNUNET_i2s (&peer->pid));
246 * This peer is no longer be needed, clean it up now.
248 * @param cls peer to clean up
251 destroy_peer (void *cls)
253 struct CadetPeer *cp = cls;
255 LOG (GNUNET_ERROR_TYPE_DEBUG,
256 "Destroying state about peer %s\n",
258 cp->destroy_task = NULL;
259 GNUNET_assert (NULL == cp->t);
260 GNUNET_assert (NULL == cp->core_mq);
261 GNUNET_assert (0 == cp->path_dll_length);
262 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
263 GNUNET_assert (GNUNET_YES ==
264 GNUNET_CONTAINER_multipeermap_remove (peers,
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 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
289 GNUNET_free_non_null (cp->hello);
290 /* Peer should not be freed if paths exist; if there are no paths,
291 there ought to be no connections, and without connections, no
292 notifications. Thus we can assert that mqm_head is empty at this
294 GNUNET_assert (NULL == cp->mqm_head);
300 * Set the message queue to @a mq for peer @a cp and notify watchers.
302 * @param cp peer to modify
303 * @param mq message queue to set (can be NULL)
306 GCP_set_mq (struct CadetPeer *cp,
307 struct GNUNET_MQ_Handle *mq)
309 LOG (GNUNET_ERROR_TYPE_DEBUG,
310 "Message queue for peer %s is now %p\n",
315 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
321 if (NULL != mqm->env)
323 GNUNET_MQ_discard (mqm->env);
325 mqm->cb (mqm->cb_cls,
330 mqm->cb (mqm->cb_cls,
336 GNUNET_assert (NULL == mqm->env);
337 mqm->cb (mqm->cb_cls,
345 * Transmit current envelope from this @a mqm.
347 * @param mqm mqm to transmit message for now
350 mqm_execute (struct GCP_MessageQueueManager *mqm)
352 struct CadetPeer *cp = mqm->cp;
354 LOG (GNUNET_ERROR_TYPE_DEBUG,
355 "Sending to peer %s from MQM %p\n",
358 /* Move entry to the end of the DLL, to be fair. */
359 if (mqm != cp->mqm_tail)
361 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
364 GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
368 GNUNET_MQ_send (cp->core_mq,
371 cp->mqm_ready_counter--;
376 * Function called when CORE took one of the messages from
377 * a message queue manager and transmitted it.
379 * @param cls the `struct CadetPeeer` where we made progress
382 mqm_send_done (void *cls)
384 struct CadetPeer *cp = cls;
386 LOG (GNUNET_ERROR_TYPE_DEBUG,
387 "Sending to peer %s completed\n",
389 if (0 == cp->mqm_ready_counter)
390 return; /* nothing to do */
391 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head;
395 if (NULL == mqm->env)
404 * Send the message in @a env to @a cp.
406 * @param mqm the message queue manager to use for transmission
407 * @param env envelope with the message to send; must NOT
408 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
411 GCP_send (struct GCP_MessageQueueManager *mqm,
412 struct GNUNET_MQ_Envelope *env)
414 struct CadetPeer *cp = mqm->cp;
416 LOG (GNUNET_ERROR_TYPE_DEBUG,
417 "Queueing message to peer %s in MQM %p\n",
420 GNUNET_assert (NULL != cp->core_mq);
421 GNUNET_assert (NULL == mqm->env);
422 GNUNET_MQ_notify_sent (env,
426 cp->mqm_ready_counter++;
427 if (0 != GNUNET_MQ_get_length (cp->core_mq))
434 * Function called to destroy a peer now.
437 * @param pid identity of the peer (unused)
438 * @param value the `struct CadetPeer` to clean up
439 * @return #GNUNET_OK (continue to iterate)
442 destroy_iterator_cb (void *cls,
443 const struct GNUNET_PeerIdentity *pid,
446 struct CadetPeer *cp = value;
448 if (NULL != cp->destroy_task)
450 GNUNET_SCHEDULER_cancel (cp->destroy_task);
451 cp->destroy_task = NULL;
459 * Clean up all entries about all peers.
460 * Must only be called after all tunnels, CORE-connections and
461 * connections are down.
464 GCP_destroy_all_peers ()
466 LOG (GNUNET_ERROR_TYPE_DEBUG,
467 "Destroying all peers now\n");
468 GNUNET_CONTAINER_multipeermap_iterate (peers,
469 &destroy_iterator_cb,
475 * This peer may no longer be needed, consider cleaning it up.
477 * @param cp peer to clean up
480 consider_peer_destroy (struct CadetPeer *cp);
484 * We really no longere care about a peer, stop hogging memory with paths to it.
485 * Afterwards, see if there is more to be cleaned up about this peer.
487 * @param cls a `struct CadetPeer`.
490 drop_paths (void *cls)
492 struct CadetPeer *cp = cls;
493 struct CadetPeerPath *path;
495 cp->destroy_task = NULL;
496 while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
498 consider_peer_destroy (cp);
503 * This peer may no longer be needed, consider cleaning it up.
505 * @param cp peer to clean up
508 consider_peer_destroy (struct CadetPeer *cp)
510 struct GNUNET_TIME_Relative exp;
512 if (NULL != cp->destroy_task)
514 GNUNET_SCHEDULER_cancel (cp->destroy_task);
515 cp->destroy_task = NULL;
518 return; /* still relevant! */
519 if (NULL != cp->core_mq)
520 return; /* still relevant! */
521 if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
522 return; /* still relevant! */
523 if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))
525 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
530 if (0 < cp->path_dll_length)
531 return; /* still relevant! */
532 if (NULL != cp->hello)
534 /* relevant only until HELLO expires */
535 exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
536 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
541 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
548 * Add an entry to the DLL of all of the paths that this peer is on.
550 * @param cp peer to modify
551 * @param entry an entry on a path
552 * @param off offset of this peer on the path
555 GCP_path_entry_add (struct CadetPeer *cp,
556 struct CadetPeerPathEntry *entry,
559 LOG (GNUNET_ERROR_TYPE_DEBUG,
560 "Discovered that peer %s is on path %s at offset %u\n",
562 GCPP_2s (entry->path),
564 if (off >= cp->path_dll_length)
566 unsigned int len = cp->path_dll_length;
568 GNUNET_array_grow (cp->path_heads,
571 GNUNET_array_grow (cp->path_tails,
575 GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
580 /* If we have a tunnel to this peer, tell the tunnel that there is a
581 new path available. */
583 GCT_consider_path (cp->t,
590 * Remove an entry from the DLL of all of the paths that this peer is on.
592 * @param cp peer to modify
593 * @param entry an entry on a path
594 * @param off offset of this peer on the path
597 GCP_path_entry_remove (struct CadetPeer *cp,
598 struct CadetPeerPathEntry *entry,
601 LOG (GNUNET_ERROR_TYPE_DEBUG,
602 "Removing knowledge about peer %s beging on path %s at offset %u\n",
604 GCPP_2s (entry->path),
606 GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
609 GNUNET_assert (0 < cp->num_paths);
615 * Try adding a @a path to this @a peer. If the peer already
616 * has plenty of paths, return NULL.
618 * @param cp peer to which the @a path leads to
619 * @param path a path looking for an owner; may not be fully initialized yet!
620 * @param off offset of @a cp in @a path
621 * @param force force attaching the path
622 * @return NULL if this peer does not care to become a new owner,
623 * otherwise the node in the peer's path heap for the @a path.
625 struct GNUNET_CONTAINER_HeapNode *
626 GCP_attach_path (struct CadetPeer *cp,
627 struct CadetPeerPath *path,
631 GNUNET_CONTAINER_HeapCostType desirability;
632 struct CadetPeerPath *root;
633 GNUNET_CONTAINER_HeapCostType root_desirability;
634 struct GNUNET_CONTAINER_HeapNode *hn;
636 if (GNUNET_NO == force)
638 /* FIXME: desirability is not yet initialized; tricky! */
639 desirability = GCPP_get_desirability (path);
641 GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
646 root_desirability = 0;
649 if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
650 (desirability < root_desirability) )
652 LOG (GNUNET_ERROR_TYPE_DEBUG,
653 "Decided to not attach path %p to peer %s due to undesirability\n",
660 LOG (GNUNET_ERROR_TYPE_DEBUG,
661 "Attaching path %p to peer %s (%s)\n",
664 (GNUNET_NO == force) ? "desirable" : "forced");
666 /* Yes, we'd like to add this path, add to our heap */
667 hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
671 /* Consider maybe dropping other paths because of the new one */
672 if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
673 2 * DESIRED_CONNECTIONS_PER_TUNNEL)
675 /* Now we have way too many, drop least desirable UNLESS it is in use!
676 (Note that this intentionally keeps highly desireable, but currently
677 unused paths around in the hope that we might be able to switch, even
678 if the number of paths exceeds the threshold.) */
679 root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
680 if ( (path != root) &&
682 GCPP_get_connection (root,
684 GCPP_get_length (root) - 1)) )
686 /* Got plenty of paths to this destination, and this is a low-quality
687 one that we don't care, allow it to die. */
688 GNUNET_assert (root ==
689 GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
698 * This peer can no longer own @a path as the path
699 * has been extended and a peer further down the line
700 * is now the new owner.
702 * @param cp old owner of the @a path
703 * @param path path where the ownership is lost
704 * @param hn note in @a cp's path heap that must be deleted
707 GCP_detach_path (struct CadetPeer *cp,
708 struct CadetPeerPath *path,
709 struct GNUNET_CONTAINER_HeapNode *hn)
711 LOG (GNUNET_ERROR_TYPE_DEBUG,
712 "Detatching path %p from peer %s\n",
715 GNUNET_assert (path ==
716 GNUNET_CONTAINER_heap_remove_node (hn));
721 * Add a @a connection to this @a cp.
723 * @param cp peer via which the @a connection goes
724 * @param cc the connection to add
727 GCP_add_connection (struct CadetPeer *cp,
728 struct CadetConnection *cc)
730 LOG (GNUNET_ERROR_TYPE_DEBUG,
731 "Adding connection %s to peer %s\n",
734 GNUNET_assert (GNUNET_OK ==
735 GNUNET_CONTAINER_multishortmap_put (cp->connections,
736 &GCC_get_id (cc)->connection_of_tunnel,
738 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
743 * Remove a @a connection that went via this @a cp.
745 * @param cp peer via which the @a connection went
746 * @param cc the connection to remove
749 GCP_remove_connection (struct CadetPeer *cp,
750 struct CadetConnection *cc)
752 LOG (GNUNET_ERROR_TYPE_DEBUG,
753 "Removing connection %s from peer %s\n",
756 GNUNET_assert (GNUNET_YES ==
757 GNUNET_CONTAINER_multishortmap_remove (cp->connections,
758 &GCC_get_id (cc)->connection_of_tunnel,
764 * This peer is now on more "active" duty, activate processes related to it.
766 * @param cp the more-active peer
769 consider_peer_activate (struct CadetPeer *cp)
773 LOG (GNUNET_ERROR_TYPE_DEBUG,
774 "Updating peer %s activation state (%u connections)%s%s\n",
776 GNUNET_CONTAINER_multishortmap_size (cp->connections),
777 (NULL == cp->t) ? "" : " with tunnel",
778 (NULL == cp->core_mq) ? "" : " with CORE link");
779 if (NULL != cp->destroy_task)
781 /* It's active, do not destory! */
782 GNUNET_SCHEDULER_cancel (cp->destroy_task);
783 cp->destroy_task = NULL;
785 if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
788 /* We're just on a path or directly connected; don't bother too much */
789 if (NULL != cp->connectivity_suggestion)
791 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
792 cp->connectivity_suggestion = NULL;
794 if (NULL != cp->search_h)
796 GCD_search_stop (cp->search_h);
801 if (NULL == cp->core_mq)
803 /* Lacks direct connection, try to create one by querying the DHT */
804 if ( (NULL == cp->search_h) &&
805 (DESIRED_CONNECTIONS_PER_TUNNEL < cp->num_paths) )
807 = GCD_search (&cp->pid);
811 /* Have direct connection, stop DHT search if active */
812 if (NULL != cp->search_h)
814 GCD_search_stop (cp->search_h);
819 /* If we have a tunnel, our urge for connections is much bigger */
820 strength = (NULL != cp->t) ? 32 : 1;
821 if (NULL != cp->connectivity_suggestion)
822 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
823 cp->connectivity_suggestion
824 = GNUNET_ATS_connectivity_suggest (ats_ch,
831 * Retrieve the CadetPeer stucture associated with the
832 * peer. Optionally create one and insert it in the appropriate
833 * structures if the peer is not known yet.
835 * @param peer_id Full identity of the peer.
836 * @param create #GNUNET_YES if a new peer should be created if unknown.
837 * #GNUNET_NO to return NULL if peer is unknown.
838 * @return Existing or newly created peer structure.
839 * NULL if unknown and not requested @a create
842 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
845 struct CadetPeer *cp;
847 cp = GNUNET_CONTAINER_multipeermap_get (peers,
851 if (GNUNET_NO == create)
853 cp = GNUNET_new (struct CadetPeer);
855 cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
857 cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
858 GNUNET_assert (GNUNET_YES ==
859 GNUNET_CONTAINER_multipeermap_put (peers,
862 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
863 LOG (GNUNET_ERROR_TYPE_DEBUG,
864 "Creating peer %s\n",
871 * Obtain the peer identity for a `struct CadetPeer`.
873 * @param cp our peer handle
874 * @return the peer identity
876 const struct GNUNET_PeerIdentity *
877 GCP_get_id (struct CadetPeer *cp)
884 * Iterate over all known peers.
886 * @param iter Iterator.
887 * @param cls Closure for @c iter.
890 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
893 GNUNET_CONTAINER_multipeermap_iterate (peers,
900 * Count the number of known paths toward the peer.
902 * @param peer Peer to get path info.
903 * @return Number of known paths.
906 GCP_count_paths (const struct CadetPeer *peer)
908 return peer->num_paths;
913 * Iterate over the paths to a peer.
915 * @param peer Peer to get path info.
916 * @param callback Function to call for every path.
917 * @param callback_cls Closure for @a callback.
918 * @return Number of iterated paths.
921 GCP_iterate_paths (struct CadetPeer *peer,
922 GCP_PathIterator callback,
925 unsigned int ret = 0;
927 for (unsigned int i=0;i<peer->path_dll_length;i++)
929 for (struct CadetPeerPathEntry *pe = peer->path_heads[i];
934 callback (callback_cls,
946 * Iterate over the paths to @a peer where
947 * @a peer is at distance @a dist from us.
949 * @param peer Peer to get path info.
950 * @param dist desired distance of @a peer to us on the path
951 * @param callback Function to call for every path.
952 * @param callback_cls Closure for @a callback.
953 * @return Number of iterated paths.
956 GCP_iterate_paths_at (struct CadetPeer *peer,
958 GCP_PathIterator callback,
961 unsigned int ret = 0;
963 if (dist<peer->path_dll_length)
965 for (struct CadetPeerPathEntry *pe = peer->path_heads[dist];
970 callback (callback_cls,
981 * Get the tunnel towards a peer.
983 * @param cp Peer to get from.
984 * @param create #GNUNET_YES to create a tunnel if we do not have one
985 * @return Tunnel towards peer.
988 GCP_get_tunnel (struct CadetPeer *cp,
993 if ( (NULL != cp->t) ||
994 (GNUNET_NO == create) )
996 cp->t = GCT_create_tunnel (cp);
997 consider_peer_activate (cp);
1003 * Hello offer was passed to the transport service. Mark it
1006 * @param cls the `struct CadetPeer` where the offer completed
1009 hello_offer_done (void *cls)
1011 struct CadetPeer *cp = cls;
1013 cp->hello_offer = NULL;
1018 * We got a HELLO for a @a peer, remember it, and possibly
1019 * trigger adequate actions (like trying to connect).
1021 * @param cp the peer we got a HELLO for
1022 * @param hello the HELLO to remember
1025 GCP_set_hello (struct CadetPeer *cp,
1026 const struct GNUNET_HELLO_Message *hello)
1028 struct GNUNET_HELLO_Message *mrg;
1030 LOG (GNUNET_ERROR_TYPE_DEBUG,
1031 "Got %u byte HELLO for peer %s\n",
1032 (unsigned int) GNUNET_HELLO_size (hello),
1034 if (NULL != cp->hello_offer)
1036 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
1037 cp->hello_offer = NULL;
1039 if (NULL != cp->hello)
1041 mrg = GNUNET_HELLO_merge (hello,
1043 GNUNET_free (cp->hello);
1048 cp->hello = GNUNET_memdup (hello,
1049 GNUNET_HELLO_size (hello));
1052 = GNUNET_TRANSPORT_offer_hello (cfg,
1053 GNUNET_HELLO_get_header (cp->hello) ,
1056 /* New HELLO means cp's destruction time may change... */
1057 consider_peer_destroy (cp);
1062 * The tunnel to the given peer no longer exists, remove it from our
1063 * data structures, and possibly clean up the peer itself.
1065 * @param cp the peer affected
1066 * @param t the dead tunnel
1069 GCP_drop_tunnel (struct CadetPeer *cp,
1070 struct CadetTunnel *t)
1072 LOG (GNUNET_ERROR_TYPE_DEBUG,
1073 "Dropping tunnel %s to peer %s\n",
1076 GNUNET_assert (cp->t == t);
1078 consider_peer_destroy (cp);
1083 * Test if @a cp has a core-level connection
1085 * @param cp peer to test
1086 * @return #GNUNET_YES if @a cp has a core-level connection
1089 GCP_has_core_connection (struct CadetPeer *cp)
1091 return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1096 * Start message queue change notifications.
1098 * @param cp peer to notify for
1099 * @param cb function to call if mq becomes available or unavailable
1100 * @param cb_cls closure for @a cb
1101 * @return handle to cancel request
1103 struct GCP_MessageQueueManager *
1104 GCP_request_mq (struct CadetPeer *cp,
1105 GCP_MessageQueueNotificationCallback cb,
1108 struct GCP_MessageQueueManager *mqm;
1110 mqm = GNUNET_new (struct GCP_MessageQueueManager);
1112 mqm->cb_cls = cb_cls;
1114 GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1117 LOG (GNUNET_ERROR_TYPE_DEBUG,
1118 "Creating MQM %p for peer %s\n",
1121 if (NULL != cp->core_mq)
1129 * Stops message queue change notifications.
1131 * @param mqm handle matching request to cancel
1132 * @param last_env final message to transmit, or NULL
1135 GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1136 struct GNUNET_MQ_Envelope *last_env)
1138 struct CadetPeer *cp = mqm->cp;
1140 LOG (GNUNET_ERROR_TYPE_DEBUG,
1141 "Destroying MQM %p for peer %s%s\n",
1144 (NULL == last_env) ? "" : " with last ditch transmission");
1145 if (NULL != mqm->env)
1146 GNUNET_MQ_discard (mqm->env);
1147 if (NULL != last_env)
1149 if (NULL != cp->core_mq)
1150 GNUNET_MQ_send (cp->core_mq,
1153 GNUNET_MQ_discard (last_env);
1155 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1163 * Send the message in @a env to @a cp, overriding queueing logic.
1164 * This function should only be used to send error messages outside
1165 * of flow and congestion control, similar to ICMP. Note that
1166 * the envelope may be silently discarded as well.
1168 * @param cp peer to send the message to
1169 * @param env envelope with the message to send
1172 GCP_send_ooo (struct CadetPeer *cp,
1173 struct GNUNET_MQ_Envelope *env)
1175 LOG (GNUNET_ERROR_TYPE_DEBUG,
1176 "Sending message to %s out of management\n",
1178 if (NULL == cp->core_mq)
1180 GNUNET_MQ_discard (env);
1183 GNUNET_MQ_send (cp->core_mq,
1190 /* end of gnunet-service-cadet-new_peer.c */