2 This file is part of GNUnet.
3 Copyright (C) 2010-2016, 2018, 2019 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @file transport/gnunet-service-tng.c
22 * @brief main for gnunet-service-tng
23 * @author Christian Grothoff
26 * - figure out how to transmit (selective) ACKs in case of uni-directional
27 * communicators (with/without core? DV-only?) When do we use ACKs?
28 * => communicators use selective ACKs for flow control
29 * => transport uses message-level ACKs for RTT, fragment confirmation
30 * => integrate DV into transport, use neither core nor communicators
31 * but rather give communicators transport-encapsulated messages
32 * (which could be core-data, background-channel traffic, or
33 * transport-to-transport traffic)
36 * - manage fragmentation/defragmentation, retransmission, track RTT, loss, etc.
39 * - use ATS bandwidth allocation callback and schedule transmissions!
42 * - inform ATS about RTT, goodput/loss, overheads, etc. (GNUNET_ATS_session_update())
45 * - change transport-core API to provide proper flow control in both
46 * directions, allow multiple messages per peer simultaneously (tag
47 * confirmations with unique message ID), and replace quota-out with
48 * proper flow control;
50 * Design realizations / discussion:
51 * - communicators do flow control by calling MQ "notify sent"
52 * when 'ready'. They determine flow implicitly (i.e. TCP blocking)
53 * or explicitly via background channel FC ACKs. As long as the
54 * channel is not full, they may 'notify sent' even if the other
55 * peer has not yet confirmed receipt. The other peer confirming
56 * is _only_ for FC, not for more reliable transmission; reliable
57 * transmission (i.e. of fragments) is left to _transport_.
58 * - ACKs sent back in uni-directional communicators are done via
59 * the background channel API; here transport _may_ initially
60 * broadcast (with bounded # hops) if no path is known;
61 * - transport should _integrate_ DV-routing and build a view of
62 * the network; then background channel traffic can be
63 * routed via DV as well as explicit "DV" traffic.
64 * - background channel is also used for ACKs and NAT traversal support
65 * - transport service is responsible for AEAD'ing the background
66 * channel, timestamps and monotonic time are used against replay
67 * of old messages -> peerstore needs to be supplied with
68 * "latest timestamps seen" data
69 * - if transport implements DV, we likely need a 3rd peermap
70 * in addition to ephemerals and (direct) neighbours
71 * => in this data structure, we should track ATS metrics (distance, RTT, etc.)
72 * as well as latest timestamps seen, goodput, fragments for transmission, etc.
73 * ==> check if stuff needs to be moved out of "Neighbour"
74 * - transport should encapsualte core-level messages and do its
75 * own ACKing for RTT/goodput/loss measurements _and_ fragment
79 #include "gnunet_util_lib.h"
80 #include "gnunet_statistics_service.h"
81 #include "gnunet_transport_monitor_service.h"
82 #include "gnunet_peerstore_service.h"
83 #include "gnunet_hello_lib.h"
84 #include "gnunet_ats_transport_service.h"
85 #include "transport.h"
89 * What is the size we assume for a read operation in the
90 * absence of an MTU for the purpose of flow control?
92 #define IN_PACKET_SIZE_WITHOUT_MTU 128
95 * If a queue delays the next message by more than this number
96 * of seconds we log a warning. Note: this is for testing,
97 * the value chosen here might be too aggressively low!
99 #define DELAY_WARN_THRESHOLD GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
102 * How many messages can we have pending for a given client process
103 * before we start to drop incoming messages? We typically should
104 * have only one client and so this would be the primary buffer for
105 * messages, so the number should be chosen rather generously.
107 * The expectation here is that most of the time the queue is large
108 * enough so that a drop is virtually never required. Note that
109 * this value must be about as large as 'TOTAL_MSGS' in the
110 * 'test_transport_api_reliability.c', otherwise that testcase may
113 #define MAX_PENDING (128 * 1024)
116 GNUNET_NETWORK_STRUCT_BEGIN
119 * Outer layer of an encapsulated backchannel message.
121 struct TransportBackchannelEncapsulationMessage
124 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION.
126 struct GNUNET_MessageHeader header;
129 * Distance the backchannel message has traveled, to be updated at
130 * each hop. Used to bound the number of hops in case a backchannel
131 * message is broadcast and thus travels without routing
132 * information (during initial backchannel discovery).
137 * Target's peer identity (as backchannels may be transmitted
138 * indirectly, or even be broadcast).
140 struct GNUNET_PeerIdentity target;
143 * Ephemeral key setup by the sender for @e target, used
144 * to encrypt the payload.
146 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
149 * HMAC over the ciphertext of the encrypted, variable-size
150 * body that follows. Verified via DH of @e target and
153 struct GNUNET_HashCode hmac;
155 /* Followed by encrypted, variable-size payload */
160 * Message by which a peer confirms that it is using an
163 struct EphemeralConfirmation
167 * Purpose is #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
169 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
172 * How long is this signature over the ephemeral key
175 struct GNUNET_TIME_AbsoluteNBO ephemeral_validity;
178 * Ephemeral key setup by the sender for @e target, used
179 * to encrypt the payload.
181 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
187 * Plaintext of the variable-size payload that is encrypted
188 * within a `struct TransportBackchannelEncapsulationMessage`
190 struct TransportBackchannelRequestPayload
194 * Sender's peer identity.
196 struct GNUNET_PeerIdentity sender;
199 * Signature of the sender over an
200 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
202 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
205 * How long is this signature over the ephemeral key
208 struct GNUNET_TIME_AbsoluteNBO ephemeral_validity;
211 * Current monotonic time of the sending transport service. Used to
212 * detect replayed messages. Note that the receiver should remember
213 * a list of the recently seen timestamps and only reject messages
214 * if the timestamp is in the list, or the list is "full" and the
215 * timestamp is smaller than the lowest in the list. This list of
216 * timestamps per peer should be persisted to guard against replays
219 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
221 /* Followed by a `struct GNUNET_MessageHeader` with a message
222 for a communicator */
224 /* Followed by a 0-termianted string specifying the name of
225 the communicator which is to receive the message */
231 * Outer layer of an encapsulated unfragmented application message sent
232 * over an unreliable channel.
234 struct TransportReliabilityBox
237 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX
239 struct GNUNET_MessageHeader header;
242 * Number of messages still to be sent before a commulative
243 * ACK is requested. Zero if an ACK is requested immediately.
244 * In NBO. Note that the receiver may send the ACK faster
245 * if it believes that is reasonable.
247 uint32_t ack_countdown GNUNET_PACKED;
250 * Unique ID of the message used for signalling receipt of
251 * messages sent over possibly unreliable channels. Should
254 struct GNUNET_ShortHashCode msg_uuid;
259 * Confirmation that the receiver got a
260 * #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX. Note that the
261 * confirmation may be transmitted over a completely different queue,
262 * so ACKs are identified by a combination of PID of sender and
263 * message UUID, without the queue playing any role!
265 struct TransportReliabilityAckMessage
268 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK
270 struct GNUNET_MessageHeader header;
275 uint32_t reserved GNUNET_PACKED;
278 * How long was the ACK delayed relative to the average time of
279 * receipt of the messages being acknowledged? Used to calculate
280 * the average RTT by taking the receipt time of the ack minus the
281 * average transmission time of the sender minus this value.
283 struct GNUNET_TIME_RelativeNBO avg_ack_delay;
285 /* followed by any number of `struct GNUNET_ShortHashCode`
286 messages providing ACKs */
291 * Outer layer of an encapsulated fragmented application message.
293 struct TransportFragmentBox
296 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT
298 struct GNUNET_MessageHeader header;
301 * Unique ID of this fragment (and fragment transmission!). Will
302 * change even if a fragement is retransmitted to make each
303 * transmission attempt unique! Should be incremented by one for
304 * each fragment transmission. If a client receives a duplicate
305 * fragment (same @e frag_off), it must send
306 * #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK immediately.
308 uint32_t frag_uuid GNUNET_PACKED;
311 * Original message ID for of the message that all the1
312 * fragments belong to. Must be the same for all fragments.
314 struct GNUNET_ShortHashCode msg_uuid;
317 * Offset of this fragment in the overall message.
319 uint16_t frag_off GNUNET_PACKED;
322 * Total size of the message that is being fragmented.
324 uint16_t msg_size GNUNET_PACKED;
330 * Outer layer of an fragmented application message sent over a queue
331 * with finite MTU. When a #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT is
332 * received, the receiver has two RTTs or 64 further fragments with
333 * the same basic message time to send an acknowledgement, possibly
334 * acknowledging up to 65 fragments in one ACK. ACKs must also be
335 * sent immediately once all fragments were sent.
337 struct TransportFragmentAckMessage
340 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK
342 struct GNUNET_MessageHeader header;
345 * Unique ID of the lowest fragment UUID being acknowledged.
347 uint32_t frag_uuid GNUNET_PACKED;
350 * Bitfield of up to 64 additional fragments following the
351 * @e msg_uuid being acknowledged by this message.
353 uint64_t extra_acks GNUNET_PACKED;
356 * Original message ID for of the message that all the
357 * fragments belong to.
359 struct GNUNET_ShortHashCode msg_uuid;
362 * How long was the ACK delayed relative to the average time of
363 * receipt of the fragments being acknowledged? Used to calculate
364 * the average RTT by taking the receipt time of the ack minus the
365 * average transmission time of the sender minus this value.
367 struct GNUNET_TIME_RelativeNBO avg_ack_delay;
372 * Internal message used by transport for distance vector learning.
373 * If @e num_hops does not exceed the threshold, peers should append
374 * themselves to the peer list and flood the message (possibly only
375 * to a subset of their neighbours to limit discoverability of the
376 * network topology). To the extend that the @e bidirectional bits
377 * are set, peers may learn the inverse paths even if they did not
380 * Unless received on a bidirectional queue and @e num_hops just
381 * zero, peers that can forward to the initator should always try to
382 * forward to the initiator.
384 struct TransportDVLearn
387 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN
389 struct GNUNET_MessageHeader header;
392 * Number of hops this messages has travelled, in NBO. Zero if
395 uint16_t num_hops GNUNET_PACKED;
398 * Bitmask of the last 16 hops indicating whether they are confirmed
399 * available (without DV) in both directions or not, in NBO. Used
400 * to possibly instantly learn a path in both directions. Each peer
401 * should shift this value by one to the left, and then set the
402 * lowest bit IF the current sender can be reached from it (without
405 uint16_t bidirectional GNUNET_PACKED;
408 * Peers receiving this message and delaying forwarding to other
409 * peers for any reason should increment this value such as to
410 * enable the origin to determine the actual network-only delay
411 * in addition to the real-time delay (assuming the message loops
412 * back to the origin).
414 struct GNUNET_TIME_Relative cummulative_non_network_delay;
417 * Identity of the peer that started this learning activity.
419 struct GNUNET_PeerIdentity initiator;
421 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values,
422 excluding the initiator of the DV trace; the last entry is the
423 current sender; the current peer must not be included except if
430 * Outer layer of an encapsulated message send over multiple hops.
431 * The path given only includes the identities of the subsequent
432 * peers, i.e. it will be empty if we are the receiver. Each
433 * forwarding peer should scan the list from the end, and if it can,
434 * forward to the respective peer. The list should then be shortened
435 * by all the entries up to and including that peer. Each hop should
436 * also increment @e total_hops to allow the receiver to get a precise
437 * estimate on the number of hops the message travelled. Senders must
438 * provide a learned path that thus should work, but intermediaries
439 * know of a shortcut, they are allowed to send the message via that
442 * If a peer finds itself still on the list, it must drop the message.
444 struct TransportDVBox
447 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX
449 struct GNUNET_MessageHeader header;
452 * Number of total hops this messages travelled. In NBO.
453 * @e origin sets this to zero, to be incremented at
456 uint16_t total_hops GNUNET_PACKED;
459 * Number of hops this messages includes. In NBO.
461 uint16_t num_hops GNUNET_PACKED;
464 * Identity of the peer that originated the message.
466 struct GNUNET_PeerIdentity origin;
468 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
469 excluding the @e origin and the current peer, the last must be
470 the ultimate target; if @e num_hops is zero, the receiver of this
471 message is the ultimate target. */
473 /* Followed by the actual message, which itself may be
474 another box, but not a DV_LEARN or DV_BOX message! */
478 GNUNET_NETWORK_STRUCT_END
483 * What type of client is the `struct TransportClient` about?
488 * We do not know yet (client is fresh).
493 * Is the CORE service, we need to forward traffic to it.
498 * It is a monitor, forward monitor data.
503 * It is a communicator, use for communication.
510 * Entry in our cache of ephemeral keys we currently use.
512 struct EphemeralCacheEntry
516 * Target's peer identity (we don't re-use ephemerals
517 * to limit linkability of messages).
519 struct GNUNET_PeerIdentity target;
522 * Signature affirming @e ephemeral_key of type
523 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
525 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
528 * How long is @e sender_sig valid
530 struct GNUNET_TIME_Absolute ephemeral_validity;
535 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
538 * Node in the ephemeral cache for this entry.
539 * Used for expiration.
541 struct GNUNET_CONTAINER_HeapNode *hn;
546 * Client connected to the transport service.
548 struct TransportClient;
552 * A neighbour that at least one communicator is connected to.
558 * An ATS session is a message queue provided by a communicator
559 * via which we can reach a particular neighbour.
561 struct GNUNET_ATS_Session
566 struct GNUNET_ATS_Session *next_neighbour;
571 struct GNUNET_ATS_Session *prev_neighbour;
576 struct GNUNET_ATS_Session *prev_client;
581 struct GNUNET_ATS_Session *next_client;
584 * Which neighbour is this ATS session for?
586 struct Neighbour *neighbour;
589 * Which communicator offers this ATS session?
591 struct TransportClient *tc;
594 * Address served by the ATS session.
599 * Handle by which we inform ATS about this queue.
601 struct GNUNET_ATS_SessionRecord *sr;
604 * Task scheduled for the time when this queue can (likely) transmit the
605 * next message. Still needs to check with the @e tracker_out to be sure.
607 struct GNUNET_SCHEDULER_Task *transmit_task;
610 * Our current RTT estimate for this ATS session.
612 struct GNUNET_TIME_Relative rtt;
615 * Unique identifier of this ATS session with the communicator.
620 * Maximum transmission unit supported by this ATS session.
625 * Distance to the target of this ATS session.
630 * Network type offered by this ATS session.
632 enum GNUNET_NetworkType nt;
635 * Connection status for this ATS session.
637 enum GNUNET_TRANSPORT_ConnectionStatus cs;
642 uint32_t num_msg_pending;
647 uint32_t num_bytes_pending;
650 * How much outbound bandwidth do we have available for this session?
652 struct GNUNET_BANDWIDTH_Tracker tracker_out;
655 * How much inbound bandwidth do we have available for this session?
657 struct GNUNET_BANDWIDTH_Tracker tracker_in;
662 * A neighbour that at least one communicator is connected to.
668 * Which peer is this about?
670 struct GNUNET_PeerIdentity pid;
673 * Head of list of messages pending for this neighbour.
675 struct PendingMessage *pending_msg_head;
678 * Tail of list of messages pending for this neighbour.
680 struct PendingMessage *pending_msg_tail;
683 * Head of DLL of ATS sessions to this peer.
685 struct GNUNET_ATS_Session *session_head;
688 * Tail of DLL of ATS sessions to this peer.
690 struct GNUNET_ATS_Session *session_tail;
693 * Task run to cleanup pending messages that have exceeded their timeout.
695 struct GNUNET_SCHEDULER_Task *timeout_task;
698 * Quota at which CORE is allowed to transmit to this peer
701 * FIXME: not yet used, tricky to get right given multiple queues!
702 * (=> Idea: let ATS set a quota per queue and we add them up here?)
703 * FIXME: how do we set this value initially when we tell CORE?
704 * Options: start at a minimum value or at literally zero (before ATS?)
705 * (=> Current thought: clean would be zero!)
707 struct GNUNET_BANDWIDTH_Value32NBO quota_out;
710 * What is the earliest timeout of any message in @e pending_msg_tail?
712 struct GNUNET_TIME_Absolute earliest_timeout;
718 * Types of different pending messages.
720 enum PendingMessageType
724 * Ordinary message received from the CORE service.
731 PMT_FRAGMENT_BOX = 1,
736 PMT_RELIABILITY_BOX = 2,
739 * Any type of acknowledgement.
741 PMT_ACKNOWLEDGEMENT = 3
748 * Transmission request that is awaiting delivery. The original
749 * transmission requests from CORE may be too big for some queues.
750 * In this case, a *tree* of fragments is created. At each
751 * level of the tree, fragments are kept in a DLL ordered by which
752 * fragment should be sent next (at the head). The tree is searched
753 * top-down, with the original message at the root.
755 * To select a node for transmission, first it is checked if the
756 * current node's message fits with the MTU. If it does not, we
757 * either calculate the next fragment (based on @e frag_off) from the
758 * current node, or, if all fragments have already been created,
759 * descend to the @e head_frag. Even though the node was already
760 * fragmented, the fragment may be too big if the fragment was
761 * generated for a queue with a larger MTU. In this case, the node
762 * may be fragmented again, thus creating a tree.
764 * When acknowledgements for fragments are received, the tree
765 * must be pruned, removing those parts that were already
766 * acknowledged. When fragments are sent over a reliable
767 * channel, they can be immediately removed.
769 * If a message is ever fragmented, then the original "full" message
770 * is never again transmitted (even if it fits below the MTU), and
771 * only (remaining) fragments are sent.
773 struct PendingMessage
776 * Kept in a MDLL of messages for this @a target.
778 struct PendingMessage *next_neighbour;
781 * Kept in a MDLL of messages for this @a target.
783 struct PendingMessage *prev_neighbour;
786 * Kept in a MDLL of messages from this @a client (if @e pmt is #PMT_CORE)
788 struct PendingMessage *next_client;
791 * Kept in a MDLL of messages from this @a client (if @e pmt is #PMT_CORE)
793 struct PendingMessage *prev_client;
796 * Kept in a MDLL of messages from this @a cpm (if @e pmt is #PMT_FRAGMENT_BOx)
798 struct PendingMessage *next_frag;
801 * Kept in a MDLL of messages from this @a cpm (if @e pmt is #PMT_FRAGMENT_BOX)
803 struct PendingMessage *prev_frag;
806 * Target of the request.
808 struct Neighbour *target;
811 * Client that issued the transmission request, if @e pmt is #PMT_CORE.
813 struct TransportClient *client;
816 * Head of a MDLL of fragments created for this core message.
818 struct PendingMessage *head_frag;
821 * Tail of a MDLL of fragments created for this core message.
823 struct PendingMessage *tail_frag;
826 * Our parent in the fragmentation tree.
828 struct PendingMessage *frag_parent;
831 * At what time should we give up on the transmission (and no longer retry)?
833 struct GNUNET_TIME_Absolute timeout;
836 * What is the earliest time for us to retry transmission of this message?
838 struct GNUNET_TIME_Absolute next_attempt;
841 * UUID to use for this message (used for reassembly of fragments, only
842 * initialized if @e msg_uuid_set is #GNUNET_YES).
844 struct GNUNET_ShortHashCode msg_uuid;
847 * Counter incremented per generated fragment.
849 uint32_t frag_uuidgen;
852 * Type of the pending message.
854 enum PendingMessageType pmt;
857 * Size of the original message.
862 * Offset at which we should generate the next fragment.
867 * #GNUNET_YES once @e msg_uuid was initialized
869 int16_t msg_uuid_set;
871 /* Followed by @e bytes_msg to transmit */
876 * One of the addresses of this peer.
878 struct AddressListEntry
884 struct AddressListEntry *next;
889 struct AddressListEntry *prev;
892 * Which communicator provides this address?
894 struct TransportClient *tc;
897 * The actual address.
902 * Current context for storing this address in the peerstore.
904 struct GNUNET_PEERSTORE_StoreContext *sc;
907 * Task to periodically do @e st operation.
909 struct GNUNET_SCHEDULER_Task *st;
912 * What is a typical lifetime the communicator expects this
913 * address to have? (Always from now.)
915 struct GNUNET_TIME_Relative expiration;
918 * Address identifier used by the communicator.
923 * Network type offered by this address.
925 enum GNUNET_NetworkType nt;
931 * Client connected to the transport service.
933 struct TransportClient
939 struct TransportClient *next;
944 struct TransportClient *prev;
947 * Handle to the client.
949 struct GNUNET_SERVICE_Client *client;
952 * Message queue to the client.
954 struct GNUNET_MQ_Handle *mq;
957 * What type of client is this?
959 enum ClientType type;
965 * Information for @e type #CT_CORE.
970 * Head of list of messages pending for this client, sorted by
971 * transmission time ("next_attempt" + possibly internal prioritization).
973 struct PendingMessage *pending_msg_head;
976 * Tail of list of messages pending for this client.
978 struct PendingMessage *pending_msg_tail;
983 * Information for @e type #CT_MONITOR.
988 * Peer identity to monitor the addresses of.
989 * Zero to monitor all neighbours. Valid if
990 * @e type is #CT_MONITOR.
992 struct GNUNET_PeerIdentity peer;
995 * Is this a one-shot monitor?
1003 * Information for @e type #CT_COMMUNICATOR.
1007 * If @e type is #CT_COMMUNICATOR, this communicator
1008 * supports communicating using these addresses.
1010 char *address_prefix;
1013 * Head of DLL of queues offered by this communicator.
1015 struct GNUNET_ATS_Session *session_head;
1018 * Tail of DLL of queues offered by this communicator.
1020 struct GNUNET_ATS_Session *session_tail;
1023 * Head of list of the addresses of this peer offered by this communicator.
1025 struct AddressListEntry *addr_head;
1028 * Tail of list of the addresses of this peer offered by this communicator.
1030 struct AddressListEntry *addr_tail;
1033 * Characteristics of this communicator.
1035 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc;
1045 * Head of linked list of all clients to this service.
1047 static struct TransportClient *clients_head;
1050 * Tail of linked list of all clients to this service.
1052 static struct TransportClient *clients_tail;
1055 * Statistics handle.
1057 static struct GNUNET_STATISTICS_Handle *GST_stats;
1060 * Configuration handle.
1062 static const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
1067 static struct GNUNET_PeerIdentity GST_my_identity;
1072 static struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
1075 * Map from PIDs to `struct Neighbour` entries. A peer is
1076 * a neighbour if we have an MQ to it from some communicator.
1078 static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
1081 * Database for peer's HELLOs.
1083 static struct GNUNET_PEERSTORE_Handle *peerstore;
1086 * Heap sorting `struct EphemeralCacheEntry` by their
1087 * key/signature validity.
1089 static struct GNUNET_CONTAINER_Heap *ephemeral_heap;
1092 * Hash map for looking up `struct EphemeralCacheEntry`s
1093 * by peer identity. (We may have ephemerals in our
1094 * cache for which we do not have a neighbour entry,
1095 * and similar many neighbours may not need ephemerals,
1096 * so we use a second map.)
1098 static struct GNUNET_CONTAINER_MultiPeerMap *ephemeral_map;
1101 * Our connection to ATS for allocation and bootstrapping.
1103 static struct GNUNET_ATS_TransportHandle *ats;
1107 * Free cached ephemeral key.
1109 * @param ece cached signature to free
1112 free_ephemeral (struct EphemeralCacheEntry *ece)
1114 GNUNET_CONTAINER_multipeermap_remove (ephemeral_map,
1117 GNUNET_CONTAINER_heap_remove_node (ece->hn);
1123 * Lookup neighbour record for peer @a pid.
1125 * @param pid neighbour to look for
1126 * @return NULL if we do not have this peer as a neighbour
1128 static struct Neighbour *
1129 lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
1131 return GNUNET_CONTAINER_multipeermap_get (neighbours,
1137 * Details about what to notify monitors about.
1142 * @deprecated To be discussed if we keep these...
1144 struct GNUNET_TIME_Absolute last_validation;
1145 struct GNUNET_TIME_Absolute valid_until;
1146 struct GNUNET_TIME_Absolute next_validation;
1149 * Current round-trip time estimate.
1151 struct GNUNET_TIME_Relative rtt;
1154 * Connection status.
1156 enum GNUNET_TRANSPORT_ConnectionStatus cs;
1161 uint32_t num_msg_pending;
1166 uint32_t num_bytes_pending;
1173 * Notify monitor @a tc about an event. That @a tc
1174 * cares about the event has already been checked.
1176 * Send @a tc information in @a me about a @a peer's status with
1177 * respect to some @a address to all monitors that care.
1179 * @param tc monitor to inform
1180 * @param peer peer the information is about
1181 * @param address address the information is about
1182 * @param nt network type associated with @a address
1183 * @param me detailed information to transmit
1186 notify_monitor (struct TransportClient *tc,
1187 const struct GNUNET_PeerIdentity *peer,
1188 const char *address,
1189 enum GNUNET_NetworkType nt,
1190 const struct MonitorEvent *me)
1192 struct GNUNET_MQ_Envelope *env;
1193 struct GNUNET_TRANSPORT_MonitorData *md;
1194 size_t addr_len = strlen (address) + 1;
1196 env = GNUNET_MQ_msg_extra (md,
1198 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA);
1199 md->nt = htonl ((uint32_t) nt);
1201 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
1202 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
1203 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
1204 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
1205 md->cs = htonl ((uint32_t) me->cs);
1206 md->num_msg_pending = htonl (me->num_msg_pending);
1207 md->num_bytes_pending = htonl (me->num_bytes_pending);
1211 GNUNET_MQ_send (tc->mq,
1217 * Send information in @a me about a @a peer's status with respect
1218 * to some @a address to all monitors that care.
1220 * @param peer peer the information is about
1221 * @param address address the information is about
1222 * @param nt network type associated with @a address
1223 * @param me detailed information to transmit
1226 notify_monitors (const struct GNUNET_PeerIdentity *peer,
1227 const char *address,
1228 enum GNUNET_NetworkType nt,
1229 const struct MonitorEvent *me)
1231 static struct GNUNET_PeerIdentity zero;
1233 for (struct TransportClient *tc = clients_head;
1237 if (CT_MONITOR != tc->type)
1239 if (tc->details.monitor.one_shot)
1241 if ( (0 != memcmp (&tc->details.monitor.peer,
1244 (0 != memcmp (&tc->details.monitor.peer,
1258 * Called whenever a client connects. Allocates our
1259 * data structures associated with that client.
1261 * @param cls closure, NULL
1262 * @param client identification of the client
1263 * @param mq message queue for the client
1264 * @return our `struct TransportClient`
1267 client_connect_cb (void *cls,
1268 struct GNUNET_SERVICE_Client *client,
1269 struct GNUNET_MQ_Handle *mq)
1271 struct TransportClient *tc;
1273 tc = GNUNET_new (struct TransportClient);
1274 tc->client = client;
1276 GNUNET_CONTAINER_DLL_insert (clients_head,
1279 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1280 "Client %p connected\n",
1287 * Release memory used by @a neighbour.
1289 * @param neighbour neighbour entry to free
1292 free_neighbour (struct Neighbour *neighbour)
1294 GNUNET_assert (NULL == neighbour->session_head);
1295 GNUNET_assert (GNUNET_YES ==
1296 GNUNET_CONTAINER_multipeermap_remove (neighbours,
1299 if (NULL != neighbour->timeout_task)
1300 GNUNET_SCHEDULER_cancel (neighbour->timeout_task);
1301 GNUNET_free (neighbour);
1306 * Send message to CORE clients that we lost a connection.
1308 * @param tc client to inform (must be CORE client)
1309 * @param pid peer the connection is for
1310 * @param quota_out current quota for the peer
1313 core_send_connect_info (struct TransportClient *tc,
1314 const struct GNUNET_PeerIdentity *pid,
1315 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
1317 struct GNUNET_MQ_Envelope *env;
1318 struct ConnectInfoMessage *cim;
1320 GNUNET_assert (CT_CORE == tc->type);
1321 env = GNUNET_MQ_msg (cim,
1322 GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
1323 cim->quota_out = quota_out;
1325 GNUNET_MQ_send (tc->mq,
1331 * Send message to CORE clients that we gained a connection
1333 * @param pid peer the queue was for
1334 * @param quota_out current quota for the peer
1337 cores_send_connect_info (const struct GNUNET_PeerIdentity *pid,
1338 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
1340 for (struct TransportClient *tc = clients_head;
1344 if (CT_CORE != tc->type)
1346 core_send_connect_info (tc,
1354 * Send message to CORE clients that we lost a connection.
1356 * @param pid peer the connection was for
1359 cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
1361 for (struct TransportClient *tc = clients_head;
1365 struct GNUNET_MQ_Envelope *env;
1366 struct DisconnectInfoMessage *dim;
1368 if (CT_CORE != tc->type)
1370 env = GNUNET_MQ_msg (dim,
1371 GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
1373 GNUNET_MQ_send (tc->mq,
1382 * @param queue the queue to free
1385 free_queue (struct GNUNET_ATS_Session *queue)
1387 struct Neighbour *neighbour = queue->neighbour;
1388 struct TransportClient *tc = queue->tc;
1389 struct MonitorEvent me = {
1390 .cs = GNUNET_TRANSPORT_CS_DOWN,
1391 .rtt = GNUNET_TIME_UNIT_FOREVER_REL
1394 if (NULL != queue->transmit_task)
1396 GNUNET_SCHEDULER_cancel (queue->transmit_task);
1397 queue->transmit_task = NULL;
1399 GNUNET_CONTAINER_MDLL_remove (neighbour,
1400 neighbour->session_head,
1401 neighbour->session_tail,
1403 GNUNET_CONTAINER_MDLL_remove (client,
1404 tc->details.communicator.session_head,
1405 tc->details.communicator.session_tail,
1407 notify_monitors (&neighbour->pid,
1411 GNUNET_ATS_session_del (queue->sr);
1412 GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_in);
1413 GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_out);
1414 GNUNET_free (queue);
1415 if (NULL == neighbour->session_head)
1417 cores_send_disconnect_info (&neighbour->pid);
1418 free_neighbour (neighbour);
1426 * @param ale address list entry to free
1429 free_address_list_entry (struct AddressListEntry *ale)
1431 struct TransportClient *tc = ale->tc;
1433 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
1434 tc->details.communicator.addr_tail,
1436 if (NULL != ale->sc)
1438 GNUNET_PEERSTORE_store_cancel (ale->sc);
1441 if (NULL != ale->st)
1443 GNUNET_SCHEDULER_cancel (ale->st);
1451 * Called whenever a client is disconnected. Frees our
1452 * resources associated with that client.
1454 * @param cls closure, NULL
1455 * @param client identification of the client
1456 * @param app_ctx our `struct TransportClient`
1459 client_disconnect_cb (void *cls,
1460 struct GNUNET_SERVICE_Client *client,
1463 struct TransportClient *tc = app_ctx;
1465 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1466 "Client %p disconnected, cleaning up.\n",
1468 GNUNET_CONTAINER_DLL_remove (clients_head,
1477 struct PendingMessage *pm;
1479 while (NULL != (pm = tc->details.core.pending_msg_head))
1481 GNUNET_CONTAINER_MDLL_remove (client,
1482 tc->details.core.pending_msg_head,
1483 tc->details.core.pending_msg_tail,
1491 case CT_COMMUNICATOR:
1493 struct GNUNET_ATS_Session *q;
1494 struct AddressListEntry *ale;
1496 while (NULL != (q = tc->details.communicator.session_head))
1498 while (NULL != (ale = tc->details.communicator.addr_head))
1499 free_address_list_entry (ale);
1500 GNUNET_free (tc->details.communicator.address_prefix);
1509 * Iterator telling new CORE client about all existing
1510 * connections to peers.
1512 * @param cls the new `struct TransportClient`
1513 * @param pid a connected peer
1514 * @param value the `struct Neighbour` with more information
1515 * @return #GNUNET_OK (continue to iterate)
1518 notify_client_connect_info (void *cls,
1519 const struct GNUNET_PeerIdentity *pid,
1522 struct TransportClient *tc = cls;
1523 struct Neighbour *neighbour = value;
1525 core_send_connect_info (tc,
1527 neighbour->quota_out);
1533 * Initialize a "CORE" client. We got a start message from this
1534 * client, so add it to the list of clients for broadcasting of
1537 * @param cls the client
1538 * @param start the start message that was sent
1541 handle_client_start (void *cls,
1542 const struct StartMessage *start)
1544 struct TransportClient *tc = cls;
1547 options = ntohl (start->options);
1548 if ( (0 != (1 & options)) &&
1550 memcmp (&start->self,
1552 sizeof (struct GNUNET_PeerIdentity)) ) )
1554 /* client thinks this is a different peer, reject */
1556 GNUNET_SERVICE_client_drop (tc->client);
1559 if (CT_NONE != tc->type)
1562 GNUNET_SERVICE_client_drop (tc->client);
1566 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1567 ¬ify_client_connect_info,
1569 GNUNET_SERVICE_client_continue (tc->client);
1574 * Client asked for transmission to a peer. Process the request.
1576 * @param cls the client
1577 * @param obm the send message that was sent
1580 check_client_send (void *cls,
1581 const struct OutboundMessage *obm)
1583 struct TransportClient *tc = cls;
1585 const struct GNUNET_MessageHeader *obmm;
1587 if (CT_CORE != tc->type)
1590 return GNUNET_SYSERR;
1592 size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
1593 if (size < sizeof (struct GNUNET_MessageHeader))
1596 return GNUNET_SYSERR;
1598 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
1599 if (size != ntohs (obmm->size))
1602 return GNUNET_SYSERR;
1609 * Free fragment tree below @e root, excluding @e root itself.
1611 * @param root root of the tree to free
1614 free_fragment_tree (struct PendingMessage *root)
1616 struct PendingMessage *frag;
1618 while (NULL != (frag = root->head_frag))
1620 free_fragment_tree (frag);
1621 GNUNET_CONTAINER_MDLL_remove (frag,
1631 * Send a response to the @a pm that we have processed a
1632 * "send" request with status @a success. We
1633 * transmitted @a bytes_physical on the actual wire.
1634 * Sends a confirmation to the "core" client responsible
1635 * for the original request and free's @a pm.
1637 * @param pm handle to the original pending message
1638 * @param success status code, #GNUNET_OK on success, #GNUNET_SYSERR
1639 * for transmission failure
1640 * @param bytes_physical amount of bandwidth consumed
1643 client_send_response (struct PendingMessage *pm,
1645 uint32_t bytes_physical)
1647 struct TransportClient *tc = pm->client;
1648 struct Neighbour *target = pm->target;
1649 struct GNUNET_MQ_Envelope *env;
1650 struct SendOkMessage *som;
1654 env = GNUNET_MQ_msg (som,
1655 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1656 som->success = htonl ((uint32_t) success);
1657 som->bytes_msg = htons (pm->bytes_msg);
1658 som->bytes_physical = htonl (bytes_physical);
1659 som->peer = target->pid;
1660 GNUNET_MQ_send (tc->mq,
1662 GNUNET_CONTAINER_MDLL_remove (client,
1663 tc->details.core.pending_msg_head,
1664 tc->details.core.pending_msg_tail,
1667 GNUNET_CONTAINER_MDLL_remove (neighbour,
1668 target->pending_msg_head,
1669 target->pending_msg_tail,
1671 free_fragment_tree (pm);
1677 * Checks the message queue for a neighbour for messages that have timed
1678 * out and purges them.
1680 * @param cls a `struct Neighbour`
1683 check_queue_timeouts (void *cls)
1685 struct Neighbour *n = cls;
1686 struct PendingMessage *pm;
1687 struct GNUNET_TIME_Absolute now;
1688 struct GNUNET_TIME_Absolute earliest_timeout;
1690 n->timeout_task = NULL;
1691 earliest_timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1692 now = GNUNET_TIME_absolute_get ();
1693 for (struct PendingMessage *pos = n->pending_msg_head;
1697 pm = pos->next_neighbour;
1698 if (pos->timeout.abs_value_us <= now.abs_value_us)
1700 GNUNET_STATISTICS_update (GST_stats,
1701 "# messages dropped (timeout before confirmation)",
1704 client_send_response (pm,
1709 earliest_timeout = GNUNET_TIME_absolute_min (earliest_timeout,
1712 n->earliest_timeout = earliest_timeout;
1713 if (NULL != n->pending_msg_head)
1714 n->timeout_task = GNUNET_SCHEDULER_add_at (earliest_timeout,
1715 &check_queue_timeouts,
1721 * Client asked for transmission to a peer. Process the request.
1723 * @param cls the client
1724 * @param obm the send message that was sent
1727 handle_client_send (void *cls,
1728 const struct OutboundMessage *obm)
1730 struct TransportClient *tc = cls;
1731 struct PendingMessage *pm;
1732 const struct GNUNET_MessageHeader *obmm;
1733 struct Neighbour *target;
1736 GNUNET_assert (CT_CORE == tc->type);
1737 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
1738 bytes_msg = ntohs (obmm->size);
1739 target = lookup_neighbour (&obm->peer);
1742 /* Failure: don't have this peer as a neighbour (anymore).
1743 Might have gone down asynchronously, so this is NOT
1744 a protocol violation by CORE. Still count the event,
1745 as this should be rare. */
1746 struct GNUNET_MQ_Envelope *env;
1747 struct SendOkMessage *som;
1749 env = GNUNET_MQ_msg (som,
1750 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1751 som->success = htonl (GNUNET_SYSERR);
1752 som->bytes_msg = htonl (bytes_msg);
1753 som->bytes_physical = htonl (0);
1754 som->peer = obm->peer;
1755 GNUNET_MQ_send (tc->mq,
1757 GNUNET_SERVICE_client_continue (tc->client);
1758 GNUNET_STATISTICS_update (GST_stats,
1759 "# messages dropped (neighbour unknown)",
1764 pm = GNUNET_malloc (sizeof (struct PendingMessage) + bytes_msg);
1766 pm->target = target;
1767 pm->bytes_msg = bytes_msg;
1768 pm->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_ntoh (obm->timeout));
1772 GNUNET_CONTAINER_MDLL_insert (neighbour,
1773 target->pending_msg_head,
1774 target->pending_msg_tail,
1776 GNUNET_CONTAINER_MDLL_insert (client,
1777 tc->details.core.pending_msg_head,
1778 tc->details.core.pending_msg_tail,
1780 if (target->earliest_timeout.abs_value_us > pm->timeout.abs_value_us)
1782 target->earliest_timeout.abs_value_us = pm->timeout.abs_value_us;
1783 if (NULL != target->timeout_task)
1784 GNUNET_SCHEDULER_cancel (target->timeout_task);
1785 target->timeout_task
1786 = GNUNET_SCHEDULER_add_at (target->earliest_timeout,
1787 &check_queue_timeouts,
1794 * Communicator started. Test message is well-formed.
1796 * @param cls the client
1797 * @param cam the send message that was sent
1800 check_communicator_available (void *cls,
1801 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1803 struct TransportClient *tc = cls;
1806 if (CT_NONE != tc->type)
1809 return GNUNET_SYSERR;
1811 tc->type = CT_COMMUNICATOR;
1812 size = ntohs (cam->header.size) - sizeof (*cam);
1814 return GNUNET_OK; /* receive-only communicator */
1815 GNUNET_MQ_check_zero_termination (cam);
1821 * Communicator started. Process the request.
1823 * @param cls the client
1824 * @param cam the send message that was sent
1827 handle_communicator_available (void *cls,
1828 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1830 struct TransportClient *tc = cls;
1833 size = ntohs (cam->header.size) - sizeof (*cam);
1835 return; /* receive-only communicator */
1836 tc->details.communicator.address_prefix
1837 = GNUNET_strdup ((const char *) &cam[1]);
1838 tc->details.communicator.cc
1839 = (enum GNUNET_TRANSPORT_CommunicatorCharacteristics) ntohl (cam->cc);
1840 GNUNET_SERVICE_client_continue (tc->client);
1845 * Address of our peer added. Test message is well-formed.
1847 * @param cls the client
1848 * @param aam the send message that was sent
1851 check_add_address (void *cls,
1852 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1854 struct TransportClient *tc = cls;
1856 if (CT_COMMUNICATOR != tc->type)
1859 return GNUNET_SYSERR;
1861 GNUNET_MQ_check_zero_termination (aam);
1867 * Ask peerstore to store our address.
1869 * @param cls an `struct AddressListEntry *`
1872 store_pi (void *cls);
1876 * Function called when peerstore is done storing our address.
1879 peerstore_store_cb (void *cls,
1882 struct AddressListEntry *ale = cls;
1885 if (GNUNET_YES != success)
1886 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1887 "Failed to store our own address `%s' in peerstore!\n",
1889 /* refresh period is 1/4 of expiration time, that should be plenty
1890 without being excessive. */
1891 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
1899 * Ask peerstore to store our address.
1901 * @param cls an `struct AddressListEntry *`
1904 store_pi (void *cls)
1906 struct AddressListEntry *ale = cls;
1909 struct GNUNET_TIME_Absolute expiration;
1912 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
1913 GNUNET_HELLO_sign_address (ale->address,
1919 ale->sc = GNUNET_PEERSTORE_store (peerstore,
1922 GNUNET_HELLO_PEERSTORE_KEY,
1926 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
1927 &peerstore_store_cb,
1930 if (NULL == ale->sc)
1932 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1933 "Failed to store our address `%s' with peerstore\n",
1935 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
1943 * Address of our peer added. Process the request.
1945 * @param cls the client
1946 * @param aam the send message that was sent
1949 handle_add_address (void *cls,
1950 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1952 struct TransportClient *tc = cls;
1953 struct AddressListEntry *ale;
1956 slen = ntohs (aam->header.size) - sizeof (*aam);
1957 ale = GNUNET_malloc (sizeof (struct AddressListEntry) + slen);
1959 ale->address = (const char *) &ale[1];
1960 ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
1961 ale->aid = aam->aid;
1962 ale->nt = (enum GNUNET_NetworkType) ntohl (aam->nt);
1966 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
1967 tc->details.communicator.addr_tail,
1969 ale->st = GNUNET_SCHEDULER_add_now (&store_pi,
1971 GNUNET_SERVICE_client_continue (tc->client);
1976 * Address of our peer deleted. Process the request.
1978 * @param cls the client
1979 * @param dam the send message that was sent
1982 handle_del_address (void *cls,
1983 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
1985 struct TransportClient *tc = cls;
1987 if (CT_COMMUNICATOR != tc->type)
1990 GNUNET_SERVICE_client_drop (tc->client);
1993 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
1997 if (dam->aid != ale->aid)
1999 GNUNET_assert (ale->tc == tc);
2000 free_address_list_entry (ale);
2001 GNUNET_SERVICE_client_continue (tc->client);
2004 GNUNET_SERVICE_client_drop (tc->client);
2009 * Client notified us about transmission from a peer. Process the request.
2011 * @param cls the client
2012 * @param obm the send message that was sent
2015 check_incoming_msg (void *cls,
2016 const struct GNUNET_TRANSPORT_IncomingMessage *im)
2018 struct TransportClient *tc = cls;
2020 const struct GNUNET_MessageHeader *obmm;
2022 if (CT_COMMUNICATOR != tc->type)
2025 return GNUNET_SYSERR;
2027 size = ntohs (im->header.size) - sizeof (*im);
2028 if (size < sizeof (struct GNUNET_MessageHeader))
2031 return GNUNET_SYSERR;
2033 obmm = (const struct GNUNET_MessageHeader *) &im[1];
2034 if (size != ntohs (obmm->size))
2037 return GNUNET_SYSERR;
2044 * Incoming meessage. Process the request.
2046 * @param cls the client
2047 * @param im the send message that was received
2050 handle_incoming_msg (void *cls,
2051 const struct GNUNET_TRANSPORT_IncomingMessage *im)
2053 struct TransportClient *tc = cls;
2055 GNUNET_SERVICE_client_continue (tc->client);
2060 * New queue became available. Check message.
2062 * @param cls the client
2063 * @param aqm the send message that was sent
2066 check_add_queue_message (void *cls,
2067 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
2069 struct TransportClient *tc = cls;
2071 if (CT_COMMUNICATOR != tc->type)
2074 return GNUNET_SYSERR;
2076 GNUNET_MQ_check_zero_termination (aqm);
2082 * Bandwidth tracker informs us that the delay until we should receive
2085 * @param cls a `struct GNUNET_ATS_Session` for which the delay changed
2088 tracker_update_in_cb (void *cls)
2090 struct GNUNET_ATS_Session *queue = cls;
2091 struct GNUNET_TIME_Relative in_delay;
2094 rsize = (0 == queue->mtu) ? IN_PACKET_SIZE_WITHOUT_MTU : queue->mtu;
2095 in_delay = GNUNET_BANDWIDTH_tracker_get_delay (&queue->tracker_in,
2097 // FIXME: how exactly do we do inbound flow control?
2102 * We believe we are ready to transmit a message on a queue. Double-checks
2103 * with the queue's "tracker_out" and then gives the message to the
2104 * communicator for transmission (updating the tracker, and re-scheduling
2105 * itself if applicable).
2107 * @param cls the `struct GNUNET_ATS_Session` to process transmissions for
2110 transmit_on_queue (void *cls);
2114 * Schedule next run of #transmit_on_queue(). Does NOTHING if
2115 * we should run immediately or if the message queue is empty.
2116 * Test for no task being added AND queue not being empty to
2117 * transmit immediately afterwards! This function must only
2118 * be called if the message queue is non-empty!
2120 * @param queue the queue to do scheduling for
2123 schedule_transmit_on_queue (struct GNUNET_ATS_Session *queue)
2125 struct Neighbour *n = queue->neighbour;
2126 struct PendingMessage *pm = n->pending_msg_head;
2127 struct GNUNET_TIME_Relative out_delay;
2130 GNUNET_assert (NULL != pm);
2131 wsize = (0 == queue->mtu)
2132 ? pm->bytes_msg /* FIXME: add overheads? */
2134 out_delay = GNUNET_BANDWIDTH_tracker_get_delay (&queue->tracker_out,
2136 out_delay = GNUNET_TIME_relative_max (GNUNET_TIME_absolute_get_remaining (pm->next_attempt),
2138 if (0 == out_delay.rel_value_us)
2139 return; /* we should run immediately! */
2140 /* queue has changed since we were scheduled, reschedule again */
2141 queue->transmit_task = GNUNET_SCHEDULER_add_delayed (out_delay,
2144 if (out_delay.rel_value_us > DELAY_WARN_THRESHOLD.rel_value_us)
2145 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2146 "Next transmission on queue `%s' in %s (high delay)\n",
2148 GNUNET_STRINGS_relative_time_to_string (out_delay,
2151 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2152 "Next transmission on queue `%s' in %s\n",
2154 GNUNET_STRINGS_relative_time_to_string (out_delay,
2160 * Fragment the given @a pm to the given @a mtu. Adds
2161 * additional fragments to the neighbour as well. If the
2162 * @a mtu is too small, generates and error for the @a pm
2165 * @param pm pending message to fragment for transmission
2166 * @param mtu MTU to apply
2167 * @return new message to transmit
2169 static struct PendingMessage *
2170 fragment_message (struct PendingMessage *pm,
2173 struct PendingMessage *ff;
2175 if (GNUNET_NO == pm->msg_uuid_set)
2177 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
2179 sizeof (pm->msg_uuid));
2180 pm->msg_uuid_set = GNUNET_YES;
2183 /* This invariant is established in #handle_add_queue_message() */
2184 GNUNET_assert (mtu > sizeof (struct TransportFragmentBox));
2186 /* select fragment for transmission, descending the tree if it has
2187 been expanded until we are at a leaf or at a fragment that is small enough */
2189 while ( ( (ff->bytes_msg > mtu) ||
2191 (ff->frag_off == ff->bytes_msg) &&
2192 (NULL != ff->head_frag) )
2194 ff = ff->head_frag; /* descent into fragmented fragments */
2197 if ( ( (ff->bytes_msg > mtu) ||
2199 (pm->frag_off < pm->bytes_msg) )
2201 /* Did not yet calculate all fragments, calculate next fragment */
2202 struct PendingMessage *frag;
2203 struct TransportFragmentBox tfb;
2211 orig = (const char *) &ff[1];
2212 msize = ff->bytes_msg;
2215 const struct TransportFragmentBox *tfbo;
2217 tfbo = (const struct TransportFragmentBox *) orig;
2218 orig += sizeof (struct TransportFragmentBox);
2219 msize -= sizeof (struct TransportFragmentBox);
2220 xoff = ntohs (tfbo->frag_off);
2222 fragmax = mtu - sizeof (struct TransportFragmentBox);
2223 fragsize = GNUNET_MIN (msize - ff->frag_off,
2225 frag = GNUNET_malloc (sizeof (struct PendingMessage) +
2226 sizeof (struct TransportFragmentBox) +
2228 frag->target = pm->target;
2229 frag->frag_parent = ff;
2230 frag->timeout = pm->timeout;
2231 frag->bytes_msg = sizeof (struct TransportFragmentBox) + fragsize;
2232 frag->pmt = PMT_FRAGMENT_BOX;
2233 msg = (char *) &frag[1];
2234 tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT);
2235 tfb.header.size = htons (sizeof (struct TransportFragmentBox) +
2237 tfb.frag_uuid = htonl (pm->frag_uuidgen++);
2238 tfb.msg_uuid = pm->msg_uuid;
2239 tfb.frag_off = htons (ff->frag_off + xoff);
2240 tfb.msg_size = htons (pm->bytes_msg);
2244 memcpy (&msg[sizeof (tfb)],
2245 &orig[ff->frag_off],
2247 GNUNET_CONTAINER_MDLL_insert (frag,
2251 ff->frag_off += fragsize;
2255 /* Move head to the tail and return it */
2256 GNUNET_CONTAINER_MDLL_remove (frag,
2257 ff->frag_parent->head_frag,
2258 ff->frag_parent->tail_frag,
2260 GNUNET_CONTAINER_MDLL_insert_tail (frag,
2261 ff->frag_parent->head_frag,
2262 ff->frag_parent->tail_frag,
2269 * Reliability-box the given @a pm. On error (can there be any), NULL
2270 * may be returned, otherwise the "replacement" for @a pm (which
2271 * should then be added to the respective neighbour's queue instead of
2272 * @a pm). If the @a pm is already fragmented or reliability boxed,
2273 * or itself an ACK, this function simply returns @a pm.
2275 * @param pm pending message to box for transmission over unreliabile queue
2276 * @return new message to transmit
2278 static struct PendingMessage *
2279 reliability_box_message (struct PendingMessage *pm)
2281 if (PMT_CORE != pm->pmt)
2283 /* already fragmented or reliability boxed, or control message: do nothing */
2291 client_send_response (pm,
2297 /* FIXME: return boxed PM here! */
2303 * We believe we are ready to transmit a message on a queue. Double-checks
2304 * with the queue's "tracker_out" and then gives the message to the
2305 * communicator for transmission (updating the tracker, and re-scheduling
2306 * itself if applicable).
2308 * @param cls the `struct GNUNET_ATS_Session` to process transmissions for
2311 transmit_on_queue (void *cls)
2313 struct GNUNET_ATS_Session *queue = cls;
2314 struct Neighbour *n = queue->neighbour;
2315 struct PendingMessage *pm;
2316 struct PendingMessage *s;
2319 queue->transmit_task = NULL;
2320 if (NULL == (pm = n->pending_msg_head))
2322 /* no message pending, nothing to do here! */
2325 schedule_transmit_on_queue (queue);
2326 if (NULL != queue->transmit_task)
2327 return; /* do it later */
2329 if (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc)
2330 overhead += sizeof (struct TransportReliabilityBox);
2332 if ( ( (0 != queue->mtu) &&
2333 (pm->bytes_msg + overhead > queue->mtu) ) ||
2334 (NULL != pm->head_frag /* fragments already exist, should
2335 respect that even if MTU is 0 for
2337 s = fragment_message (s,
2339 ? UINT16_MAX /* no real maximum */
2343 /* Fragmentation failed, try next message... */
2344 schedule_transmit_on_queue (queue);
2347 if (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc)
2348 s = reliability_box_message (s);
2351 /* Reliability boxing failed, try next message... */
2352 schedule_transmit_on_queue (queue);
2356 // FIXME: actually give 's' to communicator for transmission here!
2358 // FIXME: do something similar to the logic below
2359 // in defragmentation / reliability ACK handling!
2361 /* Check if this transmission somehow conclusively finished handing 'pm'
2362 even without any explicit ACKs */
2363 if ( (PMT_CORE == s->pmt) &&
2364 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc) )
2366 /* Full message sent, and over reliabile channel */
2367 client_send_response (pm,
2371 else if ( (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc) &&
2372 (PMT_FRAGMENT_BOX == s->pmt) )
2374 struct PendingMessage *pos;
2376 /* Fragment sent over reliabile channel */
2377 free_fragment_tree (s);
2378 pos = s->frag_parent;
2379 GNUNET_CONTAINER_MDLL_remove (frag,
2384 /* check if subtree is done */
2385 while ( (NULL == pos->head_frag) &&
2386 (pos->frag_off == pos->bytes_msg) &&
2390 pos = s->frag_parent;
2391 GNUNET_CONTAINER_MDLL_remove (frag,
2398 /* Was this the last applicable fragmment? */
2399 if ( (NULL == pm->head_frag) &&
2400 (pm->frag_off == pm->bytes_msg) )
2401 client_send_response (pm,
2403 pm->bytes_msg /* FIXME: calculate and add overheads! */);
2405 else if (PMT_CORE != pm->pmt)
2407 /* This was an acknowledgement of some type, always free */
2409 struct Neighbour *neighbour = pm->target;
2410 GNUNET_CONTAINER_MDLL_remove (neighbour,
2411 neighbour->pending_msg_head,
2412 neighbour->pending_msg_tail,
2418 /* message not finished, waiting for acknowledgement */
2419 // FIXME: update time by which we might retransmit 's' based on
2420 // queue characteristics (i.e. RTT)
2422 // FIXME: move 'pm' back in the transmission queue (simplistic: to
2423 // the end, better: with position depending on type, timeout,
2427 /* finally, re-schedule self */
2428 schedule_transmit_on_queue (queue);
2433 * Bandwidth tracker informs us that the delay until we
2434 * can transmit again changed.
2436 * @param cls a `struct GNUNET_ATS_Session` for which the delay changed
2439 tracker_update_out_cb (void *cls)
2441 struct GNUNET_ATS_Session *queue = cls;
2442 struct Neighbour *n = queue->neighbour;
2444 if (NULL == n->pending_msg_head)
2446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2447 "Bandwidth allocation updated for empty transmission queue `%s'\n",
2449 return; /* no message pending, nothing to do here! */
2451 GNUNET_SCHEDULER_cancel (queue->transmit_task);
2452 queue->transmit_task = NULL;
2453 schedule_transmit_on_queue (queue);
2458 * Bandwidth tracker informs us that excessive outbound bandwidth was
2459 * allocated which is not being used.
2461 * @param cls a `struct GNUNET_ATS_Session` for which the excess was noted
2464 tracker_excess_out_cb (void *cls)
2466 /* FIXME: trigger excess bandwidth report to core? Right now,
2467 this is done internally within transport_api2_core already,
2468 but we probably want to change the logic and trigger it
2469 from here via a message instead! */
2470 /* TODO: maybe inform ATS at this point? */
2471 GNUNET_STATISTICS_update (GST_stats,
2472 "# Excess outbound bandwidth reported",
2480 * Bandwidth tracker informs us that excessive inbound bandwidth was allocated
2481 * which is not being used.
2483 * @param cls a `struct GNUNET_ATS_Session` for which the excess was noted
2486 tracker_excess_in_cb (void *cls)
2488 /* TODO: maybe inform ATS at this point? */
2489 GNUNET_STATISTICS_update (GST_stats,
2490 "# Excess inbound bandwidth reported",
2497 * New queue became available. Process the request.
2499 * @param cls the client
2500 * @param aqm the send message that was sent
2503 handle_add_queue_message (void *cls,
2504 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
2506 struct TransportClient *tc = cls;
2507 struct GNUNET_ATS_Session *queue;
2508 struct Neighbour *neighbour;
2512 if (ntohl (aqm->mtu) <= sizeof (struct TransportFragmentBox))
2514 /* MTU so small as to be useless for transmissions,
2515 required for #fragment_message()! */
2516 GNUNET_break_op (0);
2517 GNUNET_SERVICE_client_drop (tc->client);
2520 neighbour = lookup_neighbour (&aqm->receiver);
2521 if (NULL == neighbour)
2523 neighbour = GNUNET_new (struct Neighbour);
2524 neighbour->earliest_timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
2525 neighbour->pid = aqm->receiver;
2526 GNUNET_assert (GNUNET_OK ==
2527 GNUNET_CONTAINER_multipeermap_put (neighbours,
2530 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2531 cores_send_connect_info (&neighbour->pid,
2532 GNUNET_BANDWIDTH_ZERO);
2534 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
2535 addr = (const char *) &aqm[1];
2537 queue = GNUNET_malloc (sizeof (struct GNUNET_ATS_Session) + addr_len);
2539 queue->address = (const char *) &queue[1];
2540 queue->rtt = GNUNET_TIME_UNIT_FOREVER_REL;
2541 queue->qid = aqm->qid;
2542 queue->mtu = ntohl (aqm->mtu);
2543 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
2544 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
2545 queue->neighbour = neighbour;
2546 GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_in,
2547 &tracker_update_in_cb,
2549 GNUNET_BANDWIDTH_ZERO,
2550 GNUNET_CONSTANTS_MAX_BANDWIDTH_CARRY_S,
2551 &tracker_excess_in_cb,
2553 GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_out,
2554 &tracker_update_out_cb,
2556 GNUNET_BANDWIDTH_ZERO,
2557 GNUNET_CONSTANTS_MAX_BANDWIDTH_CARRY_S,
2558 &tracker_excess_out_cb,
2563 /* notify ATS about new queue */
2565 struct GNUNET_ATS_Properties prop = {
2566 .delay = GNUNET_TIME_UNIT_FOREVER_REL,
2569 .cc = tc->details.communicator.cc
2572 queue->sr = GNUNET_ATS_session_add (ats,
2577 if (NULL == queue->sr)
2579 /* This can only happen if the 'address' was way too long for ATS
2580 (approaching 64k in strlen()!). In this case, the communicator
2581 must be buggy and we drop it. */
2583 GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_in);
2584 GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_out);
2585 GNUNET_free (queue);
2586 if (NULL == neighbour->session_head)
2588 cores_send_disconnect_info (&neighbour->pid);
2589 free_neighbour (neighbour);
2591 GNUNET_SERVICE_client_drop (tc->client);
2595 /* notify monitors about new queue */
2597 struct MonitorEvent me = {
2602 notify_monitors (&neighbour->pid,
2607 GNUNET_CONTAINER_MDLL_insert (neighbour,
2608 neighbour->session_head,
2609 neighbour->session_tail,
2611 GNUNET_CONTAINER_MDLL_insert (client,
2612 tc->details.communicator.session_head,
2613 tc->details.communicator.session_tail,
2615 GNUNET_SERVICE_client_continue (tc->client);
2620 * Queue to a peer went down. Process the request.
2622 * @param cls the client
2623 * @param dqm the send message that was sent
2626 handle_del_queue_message (void *cls,
2627 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
2629 struct TransportClient *tc = cls;
2631 if (CT_COMMUNICATOR != tc->type)
2634 GNUNET_SERVICE_client_drop (tc->client);
2637 for (struct GNUNET_ATS_Session *queue = tc->details.communicator.session_head;
2639 queue = queue->next_client)
2641 struct Neighbour *neighbour = queue->neighbour;
2643 if ( (dqm->qid != queue->qid) ||
2644 (0 != memcmp (&dqm->receiver,
2646 sizeof (struct GNUNET_PeerIdentity))) )
2649 GNUNET_SERVICE_client_continue (tc->client);
2653 GNUNET_SERVICE_client_drop (tc->client);
2658 * Message was transmitted. Process the request.
2660 * @param cls the client
2661 * @param sma the send message that was sent
2664 handle_send_message_ack (void *cls,
2665 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
2667 struct TransportClient *tc = cls;
2669 if (CT_COMMUNICATOR != tc->type)
2672 GNUNET_SERVICE_client_drop (tc->client);
2675 // FIXME: react to communicator status about transmission request. We got:
2676 sma->status; // OK success, SYSERR failure
2677 sma->mid; // message ID of original message
2678 sma->receiver; // receiver of original message
2681 GNUNET_SERVICE_client_continue (tc->client);
2686 * Iterator telling new MONITOR client about all existing
2689 * @param cls the new `struct TransportClient`
2690 * @param pid a connected peer
2691 * @param value the `struct Neighbour` with more information
2692 * @return #GNUNET_OK (continue to iterate)
2695 notify_client_queues (void *cls,
2696 const struct GNUNET_PeerIdentity *pid,
2699 struct TransportClient *tc = cls;
2700 struct Neighbour *neighbour = value;
2702 GNUNET_assert (CT_MONITOR == tc->type);
2703 for (struct GNUNET_ATS_Session *q = neighbour->session_head;
2705 q = q->next_neighbour)
2707 struct MonitorEvent me = {
2710 .num_msg_pending = q->num_msg_pending,
2711 .num_bytes_pending = q->num_bytes_pending
2725 * Initialize a monitor client.
2727 * @param cls the client
2728 * @param start the start message that was sent
2731 handle_monitor_start (void *cls,
2732 const struct GNUNET_TRANSPORT_MonitorStart *start)
2734 struct TransportClient *tc = cls;
2736 if (CT_NONE != tc->type)
2739 GNUNET_SERVICE_client_drop (tc->client);
2742 tc->type = CT_MONITOR;
2743 tc->details.monitor.peer = start->peer;
2744 tc->details.monitor.one_shot = ntohl (start->one_shot);
2745 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
2746 ¬ify_client_queues,
2748 GNUNET_SERVICE_client_mark_monitor (tc->client);
2749 GNUNET_SERVICE_client_continue (tc->client);
2754 * Signature of a function called by ATS with the current bandwidth
2755 * allocation to be used as determined by ATS.
2757 * @param cls closure, NULL
2758 * @param session session this is about
2759 * @param bandwidth_out assigned outbound bandwidth for the connection,
2760 * 0 to signal disconnect
2761 * @param bandwidth_in assigned inbound bandwidth for the connection,
2762 * 0 to signal disconnect
2765 ats_allocation_cb (void *cls,
2766 struct GNUNET_ATS_Session *session,
2767 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
2768 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
2771 GNUNET_BANDWIDTH_tracker_update_quota (&session->tracker_out,
2773 GNUNET_BANDWIDTH_tracker_update_quota (&session->tracker_in,
2779 * Find transport client providing communication service
2780 * for the protocol @a prefix.
2782 * @param prefix communicator name
2783 * @return NULL if no such transport client is available
2785 static struct TransportClient *
2786 lookup_communicator (const char *prefix)
2788 for (struct TransportClient *tc = clients_head;
2792 if (CT_COMMUNICATOR != tc->type)
2794 if (0 == strcmp (prefix,
2795 tc->details.communicator.address_prefix))
2798 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2799 "ATS suggested use of communicator for `%s', but we do not have such a communicator!\n",
2806 * Signature of a function called by ATS suggesting transport to
2807 * try connecting with a particular address.
2809 * @param cls closure, NULL
2810 * @param pid target peer
2811 * @param address the address to try
2814 ats_suggestion_cb (void *cls,
2815 const struct GNUNET_PeerIdentity *pid,
2816 const char *address)
2818 static uint32_t idgen;
2819 struct TransportClient *tc;
2821 struct GNUNET_TRANSPORT_CreateQueue *cqm;
2822 struct GNUNET_MQ_Envelope *env;
2826 prefix = GNUNET_HELLO_address_to_prefix (address);
2829 GNUNET_break (0); /* ATS gave invalid address!? */
2832 tc = lookup_communicator (prefix);
2835 GNUNET_STATISTICS_update (GST_stats,
2836 "# ATS suggestions ignored due to missing communicator",
2841 /* forward suggestion for queue creation to communicator */
2842 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2843 "Request #%u for `%s' communicator to create queue to `%s'\n",
2844 (unsigned int) idgen,
2847 alen = strlen (address) + 1;
2848 env = GNUNET_MQ_msg_extra (cqm,
2850 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE);
2851 cqm->request_id = htonl (idgen++);
2852 cqm->receiver = *pid;
2856 GNUNET_MQ_send (tc->mq,
2862 * Communicator tells us that our request to create a queue "worked", that
2863 * is setting up the queue is now in process.
2865 * @param cls the `struct TransportClient`
2866 * @param cqr confirmation message
2869 handle_queue_create_ok (void *cls,
2870 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
2872 struct TransportClient *tc = cls;
2874 if (CT_COMMUNICATOR != tc->type)
2877 GNUNET_SERVICE_client_drop (tc->client);
2880 GNUNET_STATISTICS_update (GST_stats,
2881 "# ATS suggestions succeeded at communicator",
2884 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2885 "Request #%u for communicator to create queue succeeded\n",
2886 (unsigned int) ntohs (cqr->request_id));
2887 GNUNET_SERVICE_client_continue (tc->client);
2892 * Communicator tells us that our request to create a queue failed. This usually
2893 * indicates that the provided address is simply invalid or that the communicator's
2894 * resources are exhausted.
2896 * @param cls the `struct TransportClient`
2897 * @param cqr failure message
2900 handle_queue_create_fail (void *cls,
2901 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
2903 struct TransportClient *tc = cls;
2905 if (CT_COMMUNICATOR != tc->type)
2908 GNUNET_SERVICE_client_drop (tc->client);
2911 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2912 "Request #%u for communicator to create queue failed\n",
2913 (unsigned int) ntohs (cqr->request_id));
2914 GNUNET_STATISTICS_update (GST_stats,
2915 "# ATS suggestions failed in queue creation at communicator",
2918 GNUNET_SERVICE_client_continue (tc->client);
2923 * Free neighbour entry.
2927 * @param value a `struct Neighbour`
2928 * @return #GNUNET_OK (always)
2931 free_neighbour_cb (void *cls,
2932 const struct GNUNET_PeerIdentity *pid,
2935 struct Neighbour *neighbour = value;
2939 GNUNET_break (0); // should this ever happen?
2940 free_neighbour (neighbour);
2947 * Free ephemeral entry.
2951 * @param value a `struct Neighbour`
2952 * @return #GNUNET_OK (always)
2955 free_ephemeral_cb (void *cls,
2956 const struct GNUNET_PeerIdentity *pid,
2959 struct EphemeralCacheEntry *ece = value;
2963 free_ephemeral (ece);
2969 * Function called when the service shuts down. Unloads our plugins
2970 * and cancels pending validations.
2972 * @param cls closure, unused
2975 do_shutdown (void *cls)
2979 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
2984 GNUNET_ATS_transport_done (ats);
2987 if (NULL != peerstore)
2989 GNUNET_PEERSTORE_disconnect (peerstore,
2993 if (NULL != GST_stats)
2995 GNUNET_STATISTICS_destroy (GST_stats,
2999 if (NULL != GST_my_private_key)
3001 GNUNET_free (GST_my_private_key);
3002 GST_my_private_key = NULL;
3004 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
3006 GNUNET_CONTAINER_multipeermap_iterate (ephemeral_map,
3009 GNUNET_CONTAINER_multipeermap_destroy (ephemeral_map);
3010 ephemeral_map = NULL;
3011 GNUNET_CONTAINER_heap_destroy (ephemeral_heap);
3012 ephemeral_heap = NULL;
3017 * Initiate transport service.
3019 * @param cls closure
3020 * @param c configuration to use
3021 * @param service the initialized service
3025 const struct GNUNET_CONFIGURATION_Handle *c,
3026 struct GNUNET_SERVICE_Handle *service)
3031 neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
3033 ephemeral_map = GNUNET_CONTAINER_multipeermap_create (32,
3035 ephemeral_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3036 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
3037 if (NULL == GST_my_private_key)
3039 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3040 _("Transport service is lacking key configuration settings. Exiting.\n"));
3041 GNUNET_SCHEDULER_shutdown ();
3044 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
3045 &GST_my_identity.public_key);
3046 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
3047 "My identity is `%s'\n",
3048 GNUNET_i2s_full (&GST_my_identity));
3049 GST_stats = GNUNET_STATISTICS_create ("transport",
3051 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
3053 peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
3054 if (NULL == peerstore)
3057 GNUNET_SCHEDULER_shutdown ();
3060 ats = GNUNET_ATS_transport_init (GST_cfg,
3068 GNUNET_SCHEDULER_shutdown ();
3075 * Define "main" method using service macro.
3079 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
3082 &client_disconnect_cb,
3084 /* communication with core */
3085 GNUNET_MQ_hd_fixed_size (client_start,
3086 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
3087 struct StartMessage,
3089 GNUNET_MQ_hd_var_size (client_send,
3090 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
3091 struct OutboundMessage,
3093 /* communication with communicators */
3094 GNUNET_MQ_hd_var_size (communicator_available,
3095 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
3096 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
3098 GNUNET_MQ_hd_var_size (add_address,
3099 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
3100 struct GNUNET_TRANSPORT_AddAddressMessage,
3102 GNUNET_MQ_hd_fixed_size (del_address,
3103 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
3104 struct GNUNET_TRANSPORT_DelAddressMessage,
3106 GNUNET_MQ_hd_var_size (incoming_msg,
3107 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
3108 struct GNUNET_TRANSPORT_IncomingMessage,
3110 GNUNET_MQ_hd_fixed_size (queue_create_ok,
3111 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK,
3112 struct GNUNET_TRANSPORT_CreateQueueResponse,
3114 GNUNET_MQ_hd_fixed_size (queue_create_fail,
3115 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL,
3116 struct GNUNET_TRANSPORT_CreateQueueResponse,
3118 GNUNET_MQ_hd_var_size (add_queue_message,
3119 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
3120 struct GNUNET_TRANSPORT_AddQueueMessage,
3122 GNUNET_MQ_hd_fixed_size (del_queue_message,
3123 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
3124 struct GNUNET_TRANSPORT_DelQueueMessage,
3126 GNUNET_MQ_hd_fixed_size (send_message_ack,
3127 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
3128 struct GNUNET_TRANSPORT_SendMessageToAck,
3130 /* communication with monitors */
3131 GNUNET_MQ_hd_fixed_size (monitor_start,
3132 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
3133 struct GNUNET_TRANSPORT_MonitorStart,
3135 GNUNET_MQ_handler_end ());
3138 /* end of file gnunet-service-transport.c */