2 This file is part of GNUnet.
3 Copyright (C) 2010-2016, 2018 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.
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 * How many messages can we have pending for a given client process
90 * before we start to drop incoming messages? We typically should
91 * have only one client and so this would be the primary buffer for
92 * messages, so the number should be chosen rather generously.
94 * The expectation here is that most of the time the queue is large
95 * enough so that a drop is virtually never required. Note that
96 * this value must be about as large as 'TOTAL_MSGS' in the
97 * 'test_transport_api_reliability.c', otherwise that testcase may
100 #define MAX_PENDING (128 * 1024)
103 GNUNET_NETWORK_STRUCT_BEGIN
106 * Outer layer of an encapsulated backchannel message.
108 struct TransportBackchannelEncapsulationMessage
111 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION.
113 struct GNUNET_MessageHeader header;
116 * Distance the backchannel message has traveled, to be updated at
117 * each hop. Used to bound the number of hops in case a backchannel
118 * message is broadcast and thus travels without routing
119 * information (during initial backchannel discovery).
124 * Target's peer identity (as backchannels may be transmitted
125 * indirectly, or even be broadcast).
127 struct GNUNET_PeerIdentity target;
130 * Ephemeral key setup by the sender for @e target, used
131 * to encrypt the payload.
133 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
136 * HMAC over the ciphertext of the encrypted, variable-size
137 * body that follows. Verified via DH of @e target and
140 struct GNUNET_HashCode hmac;
142 /* Followed by encrypted, variable-size payload */
147 * Message by which a peer confirms that it is using an
150 struct EphemeralConfirmation
154 * Purpose is #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
156 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
159 * How long is this signature over the ephemeral key
162 struct GNUNET_TIME_AbsoluteNBO ephemeral_validity;
165 * Ephemeral key setup by the sender for @e target, used
166 * to encrypt the payload.
168 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
173 * Plaintext of the variable-size payload that is encrypted
174 * within a `struct TransportBackchannelEncapsulationMessage`
176 struct TransportBackchannelRequestPayload
180 * Sender's peer identity.
182 struct GNUNET_PeerIdentity sender;
185 * Signature of the sender over an
186 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
188 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
191 * How long is this signature over the ephemeral key
194 struct GNUNET_TIME_AbsoluteNBO ephemeral_validity;
197 * Current monotonic time of the sending transport service. Used to
198 * detect replayed messages. Note that the receiver should remember
199 * a list of the recently seen timestamps and only reject messages
200 * if the timestamp is in the list, or the list is "full" and the
201 * timestamp is smaller than the lowest in the list. This list of
202 * timestamps per peer should be persisted to guard against replays
205 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
207 /* Followed by a `struct GNUNET_MessageHeader` with a message
208 for a communicator */
210 /* Followed by a 0-termianted string specifying the name of
211 the communicator which is to receive the message */
215 GNUNET_NETWORK_STRUCT_END
220 * What type of client is the `struct TransportClient` about?
225 * We do not know yet (client is fresh).
230 * Is the CORE service, we need to forward traffic to it.
235 * It is a monitor, forward monitor data.
240 * It is a communicator, use for communication.
247 * Entry in our cache of ephemeral keys we currently use.
249 struct EphemeralCacheEntry
253 * Target's peer identity (we don't re-use ephemerals
254 * to limit linkability of messages).
256 struct GNUNET_PeerIdentity target;
259 * Signature affirming @e ephemeral_key of type
260 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
262 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
265 * How long is @e sender_sig valid
267 struct GNUNET_TIME_Absolute ephemeral_validity;
272 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
275 * Node in the ephemeral cache for this entry.
276 * Used for expiration.
278 struct GNUNET_CONTAINER_HeapNode *hn;
283 * Client connected to the transport service.
285 struct TransportClient;
289 * A neighbour that at least one communicator is connected to.
295 * An ATS session is a message queue provided by a communicator
296 * via which we can reach a particular neighbour.
298 struct GNUNET_ATS_Session
303 struct GNUNET_ATS_Session *next_neighbour;
308 struct GNUNET_ATS_Session *prev_neighbour;
313 struct GNUNET_ATS_Session *prev_client;
318 struct GNUNET_ATS_Session *next_client;
321 * Which neighbour is this ATS session for?
323 struct Neighbour *neighbour;
326 * Which communicator offers this ATS session?
328 struct TransportClient *tc;
331 * Address served by the ATS session.
336 * Our current RTT estimate for this ATS session.
338 struct GNUNET_TIME_Relative rtt;
341 * Unique identifier of this ATS session with the communicator.
346 * Maximum transmission unit supported by this ATS session.
351 * Distance to the target of this ATS session.
356 * Network type offered by this ATS session.
358 enum GNUNET_NetworkType nt;
361 * Connection status for this ATS session.
363 enum GNUNET_TRANSPORT_ConnectionStatus cs;
368 uint32_t num_msg_pending;
373 uint32_t num_bytes_pending;
376 * How much outbound bandwidth do we have available for this session?
378 struct GNUNET_BANDWIDTH_Tracker tracker_out;
381 * How much inbound bandwidth do we have available for this session?
383 struct GNUNET_BANDWIDTH_Tracker tracker_in;
388 * A neighbour that at least one communicator is connected to.
394 * Which peer is this about?
396 struct GNUNET_PeerIdentity pid;
399 * Head of list of messages pending for this neighbour.
401 struct PendingMessage *pending_msg_head;
404 * Tail of list of messages pending for this neighbour.
406 struct PendingMessage *pending_msg_tail;
409 * Head of DLL of ATS sessions to this peer.
411 struct GNUNET_ATS_Session *session_head;
414 * Tail of DLL of ATS sessions to this peer.
416 struct GNUNET_ATS_Session *session_tail;
419 * Quota at which CORE is allowed to transmit to this peer
422 * FIXME: not yet used, tricky to get right given multiple queues!
423 * (=> Idea: let ATS set a quota per queue and we add them up here?)
424 * FIXME: how do we set this value initially when we tell CORE?
425 * Options: start at a minimum value or at literally zero (before ATS?)
426 * (=> Current thought: clean would be zero!)
428 struct GNUNET_BANDWIDTH_Value32NBO quota_out;
434 * Transmission request from CORE that is awaiting delivery.
436 struct PendingMessage
439 * Kept in a MDLL of messages for this @a target.
441 struct PendingMessage *next_neighbour;
444 * Kept in a MDLL of messages for this @a target.
446 struct PendingMessage *prev_neighbour;
449 * Kept in a MDLL of messages from this @a client.
451 struct PendingMessage *next_client;
454 * Kept in a MDLL of messages from this @a client.
456 struct PendingMessage *prev_client;
459 * Target of the request.
461 struct Neighbour *target;
464 * Client that issued the transmission request.
466 struct TransportClient *client;
469 * Size of the original message.
477 * One of the addresses of this peer.
479 struct AddressListEntry
485 struct AddressListEntry *next;
490 struct AddressListEntry *prev;
493 * Which communicator provides this address?
495 struct TransportClient *tc;
498 * The actual address.
503 * Current context for storing this address in the peerstore.
505 struct GNUNET_PEERSTORE_StoreContext *sc;
508 * Task to periodically do @e st operation.
510 struct GNUNET_SCHEDULER_Task *st;
513 * What is a typical lifetime the communicator expects this
514 * address to have? (Always from now.)
516 struct GNUNET_TIME_Relative expiration;
519 * Address identifier used by the communicator.
524 * Network type offered by this address.
526 enum GNUNET_NetworkType nt;
532 * Client connected to the transport service.
534 struct TransportClient
540 struct TransportClient *next;
545 struct TransportClient *prev;
548 * Handle to the client.
550 struct GNUNET_SERVICE_Client *client;
553 * Message queue to the client.
555 struct GNUNET_MQ_Handle *mq;
558 * What type of client is this?
560 enum ClientType type;
566 * Information for @e type #CT_CORE.
571 * Head of list of messages pending for this client.
573 struct PendingMessage *pending_msg_head;
576 * Tail of list of messages pending for this client.
578 struct PendingMessage *pending_msg_tail;
583 * Information for @e type #CT_MONITOR.
588 * Peer identity to monitor the addresses of.
589 * Zero to monitor all neighbours. Valid if
590 * @e type is #CT_MONITOR.
592 struct GNUNET_PeerIdentity peer;
595 * Is this a one-shot monitor?
603 * Information for @e type #CT_COMMUNICATOR.
607 * If @e type is #CT_COMMUNICATOR, this communicator
608 * supports communicating using these addresses.
610 char *address_prefix;
613 * Head of DLL of queues offered by this communicator.
615 struct GNUNET_ATS_Session *session_head;
618 * Tail of DLL of queues offered by this communicator.
620 struct GNUNET_ATS_Session *session_tail;
623 * Head of list of the addresses of this peer offered by this communicator.
625 struct AddressListEntry *addr_head;
628 * Tail of list of the addresses of this peer offered by this communicator.
630 struct AddressListEntry *addr_tail;
633 * Characteristics of this communicator.
635 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc;
645 * Head of linked list of all clients to this service.
647 static struct TransportClient *clients_head;
650 * Tail of linked list of all clients to this service.
652 static struct TransportClient *clients_tail;
657 static struct GNUNET_STATISTICS_Handle *GST_stats;
660 * Configuration handle.
662 static const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
667 static struct GNUNET_PeerIdentity GST_my_identity;
672 static struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
675 * Map from PIDs to `struct Neighbour` entries. A peer is
676 * a neighbour if we have an MQ to it from some communicator.
678 static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
681 * Database for peer's HELLOs.
683 static struct GNUNET_PEERSTORE_Handle *peerstore;
686 * Heap sorting `struct EphemeralCacheEntry` by their
687 * key/signature validity.
689 static struct GNUNET_CONTAINER_Heap *ephemeral_heap;
692 * Hash map for looking up `struct EphemeralCacheEntry`s
693 * by peer identity. (We may have ephemerals in our
694 * cache for which we do not have a neighbour entry,
695 * and similar many neighbours may not need ephemerals,
696 * so we use a second map.)
698 static struct GNUNET_CONTAINER_MultiPeerMap *ephemeral_map;
701 * Our connection to ATS for allocation and bootstrapping.
703 static struct GNUNET_ATS_TransportHandle *ats;
707 * Free cached ephemeral key.
709 * @param ece cached signature to free
712 free_ephemeral (struct EphemeralCacheEntry *ece)
714 GNUNET_CONTAINER_multipeermap_remove (ephemeral_map,
717 GNUNET_CONTAINER_heap_remove_node (ece->hn);
723 * Lookup neighbour record for peer @a pid.
725 * @param pid neighbour to look for
726 * @return NULL if we do not have this peer as a neighbour
728 static struct Neighbour *
729 lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
731 return GNUNET_CONTAINER_multipeermap_get (neighbours,
737 * Details about what to notify monitors about.
742 * @deprecated To be discussed if we keep these...
744 struct GNUNET_TIME_Absolute last_validation;
745 struct GNUNET_TIME_Absolute valid_until;
746 struct GNUNET_TIME_Absolute next_validation;
749 * Current round-trip time estimate.
751 struct GNUNET_TIME_Relative rtt;
756 enum GNUNET_TRANSPORT_ConnectionStatus cs;
761 uint32_t num_msg_pending;
766 uint32_t num_bytes_pending;
773 * Notify monitor @a tc about an event. That @a tc
774 * cares about the event has already been checked.
776 * Send @a tc information in @a me about a @a peer's status with
777 * respect to some @a address to all monitors that care.
779 * @param tc monitor to inform
780 * @param peer peer the information is about
781 * @param address address the information is about
782 * @param nt network type associated with @a address
783 * @param me detailed information to transmit
786 notify_monitor (struct TransportClient *tc,
787 const struct GNUNET_PeerIdentity *peer,
789 enum GNUNET_NetworkType nt,
790 const struct MonitorEvent *me)
792 struct GNUNET_MQ_Envelope *env;
793 struct GNUNET_TRANSPORT_MonitorData *md;
794 size_t addr_len = strlen (address) + 1;
796 env = GNUNET_MQ_msg_extra (md,
798 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA);
799 md->nt = htonl ((uint32_t) nt);
801 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
802 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
803 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
804 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
805 md->cs = htonl ((uint32_t) me->cs);
806 md->num_msg_pending = htonl (me->num_msg_pending);
807 md->num_bytes_pending = htonl (me->num_bytes_pending);
811 GNUNET_MQ_send (tc->mq,
817 * Send information in @a me about a @a peer's status with respect
818 * to some @a address to all monitors that care.
820 * @param peer peer the information is about
821 * @param address address the information is about
822 * @param nt network type associated with @a address
823 * @param me detailed information to transmit
826 notify_monitors (const struct GNUNET_PeerIdentity *peer,
828 enum GNUNET_NetworkType nt,
829 const struct MonitorEvent *me)
831 static struct GNUNET_PeerIdentity zero;
833 for (struct TransportClient *tc = clients_head;
837 if (CT_MONITOR != tc->type)
839 if (tc->details.monitor.one_shot)
841 if ( (0 != memcmp (&tc->details.monitor.peer,
844 (0 != memcmp (&tc->details.monitor.peer,
858 * Called whenever a client connects. Allocates our
859 * data structures associated with that client.
861 * @param cls closure, NULL
862 * @param client identification of the client
863 * @param mq message queue for the client
864 * @return our `struct TransportClient`
867 client_connect_cb (void *cls,
868 struct GNUNET_SERVICE_Client *client,
869 struct GNUNET_MQ_Handle *mq)
871 struct TransportClient *tc;
873 tc = GNUNET_new (struct TransportClient);
876 GNUNET_CONTAINER_DLL_insert (clients_head,
879 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
880 "Client %p connected\n",
887 * Release memory used by @a neighbour.
889 * @param neighbour neighbour entry to free
892 free_neighbour (struct Neighbour *neighbour)
894 GNUNET_assert (NULL == neighbour->session_head);
895 GNUNET_assert (GNUNET_YES ==
896 GNUNET_CONTAINER_multipeermap_remove (neighbours,
899 GNUNET_free (neighbour);
904 * Send message to CORE clients that we lost a connection.
906 * @param tc client to inform (must be CORE client)
907 * @param pid peer the connection is for
908 * @param quota_out current quota for the peer
911 core_send_connect_info (struct TransportClient *tc,
912 const struct GNUNET_PeerIdentity *pid,
913 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
915 struct GNUNET_MQ_Envelope *env;
916 struct ConnectInfoMessage *cim;
918 GNUNET_assert (CT_CORE == tc->type);
919 env = GNUNET_MQ_msg (cim,
920 GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
921 cim->quota_out = quota_out;
923 GNUNET_MQ_send (tc->mq,
929 * Send message to CORE clients that we gained a connection
931 * @param pid peer the queue was for
932 * @param quota_out current quota for the peer
935 cores_send_connect_info (const struct GNUNET_PeerIdentity *pid,
936 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
938 for (struct TransportClient *tc = clients_head;
942 if (CT_CORE != tc->type)
944 core_send_connect_info (tc,
952 * Send message to CORE clients that we lost a connection.
954 * @param pid peer the connection was for
957 cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
959 for (struct TransportClient *tc = clients_head;
963 struct GNUNET_MQ_Envelope *env;
964 struct DisconnectInfoMessage *dim;
966 if (CT_CORE != tc->type)
968 env = GNUNET_MQ_msg (dim,
969 GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
971 GNUNET_MQ_send (tc->mq,
980 * @param queue the queue to free
983 free_queue (struct GNUNET_ATS_Session *queue)
985 struct Neighbour *neighbour = queue->neighbour;
986 struct TransportClient *tc = queue->tc;
987 struct MonitorEvent me = {
988 .cs = GNUNET_TRANSPORT_CS_DOWN,
989 .rtt = GNUNET_TIME_UNIT_FOREVER_REL
992 GNUNET_CONTAINER_MDLL_remove (neighbour,
993 neighbour->session_head,
994 neighbour->session_tail,
996 GNUNET_CONTAINER_MDLL_remove (client,
997 tc->details.communicator.session_head,
998 tc->details.communicator.session_tail,
1001 notify_monitors (&neighbour->pid,
1005 GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_in);
1006 GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_out);
1007 GNUNET_free (queue);
1008 if (NULL == neighbour->session_head)
1010 cores_send_disconnect_info (&neighbour->pid);
1011 free_neighbour (neighbour);
1019 * @param ale address list entry to free
1022 free_address_list_entry (struct AddressListEntry *ale)
1024 struct TransportClient *tc = ale->tc;
1026 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
1027 tc->details.communicator.addr_tail,
1029 if (NULL != ale->sc)
1031 GNUNET_PEERSTORE_store_cancel (ale->sc);
1034 if (NULL != ale->st)
1036 GNUNET_SCHEDULER_cancel (ale->st);
1044 * Called whenever a client is disconnected. Frees our
1045 * resources associated with that client.
1047 * @param cls closure, NULL
1048 * @param client identification of the client
1049 * @param app_ctx our `struct TransportClient`
1052 client_disconnect_cb (void *cls,
1053 struct GNUNET_SERVICE_Client *client,
1056 struct TransportClient *tc = app_ctx;
1058 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1059 "Client %p disconnected, cleaning up.\n",
1061 GNUNET_CONTAINER_DLL_remove (clients_head,
1070 struct PendingMessage *pm;
1072 while (NULL != (pm = tc->details.core.pending_msg_head))
1074 GNUNET_CONTAINER_MDLL_remove (client,
1075 tc->details.core.pending_msg_head,
1076 tc->details.core.pending_msg_tail,
1084 case CT_COMMUNICATOR:
1086 struct GNUNET_ATS_Session *q;
1087 struct AddressListEntry *ale;
1089 while (NULL != (q = tc->details.communicator.session_head))
1091 while (NULL != (ale = tc->details.communicator.addr_head))
1092 free_address_list_entry (ale);
1093 GNUNET_free (tc->details.communicator.address_prefix);
1102 * Iterator telling new CORE client about all existing
1103 * connections to peers.
1105 * @param cls the new `struct TransportClient`
1106 * @param pid a connected peer
1107 * @param value the `struct Neighbour` with more information
1108 * @return #GNUNET_OK (continue to iterate)
1111 notify_client_connect_info (void *cls,
1112 const struct GNUNET_PeerIdentity *pid,
1115 struct TransportClient *tc = cls;
1116 struct Neighbour *neighbour = value;
1118 core_send_connect_info (tc,
1120 neighbour->quota_out);
1126 * Initialize a "CORE" client. We got a start message from this
1127 * client, so add it to the list of clients for broadcasting of
1130 * @param cls the client
1131 * @param start the start message that was sent
1134 handle_client_start (void *cls,
1135 const struct StartMessage *start)
1137 struct TransportClient *tc = cls;
1140 options = ntohl (start->options);
1141 if ( (0 != (1 & options)) &&
1143 memcmp (&start->self,
1145 sizeof (struct GNUNET_PeerIdentity)) ) )
1147 /* client thinks this is a different peer, reject */
1149 GNUNET_SERVICE_client_drop (tc->client);
1152 if (CT_NONE != tc->type)
1155 GNUNET_SERVICE_client_drop (tc->client);
1159 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1160 ¬ify_client_connect_info,
1162 GNUNET_SERVICE_client_continue (tc->client);
1167 * Client asked for transmission to a peer. Process the request.
1169 * @param cls the client
1170 * @param obm the send message that was sent
1173 check_client_send (void *cls,
1174 const struct OutboundMessage *obm)
1176 struct TransportClient *tc = cls;
1178 const struct GNUNET_MessageHeader *obmm;
1180 if (CT_CORE != tc->type)
1183 return GNUNET_SYSERR;
1185 size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
1186 if (size < sizeof (struct GNUNET_MessageHeader))
1189 return GNUNET_SYSERR;
1191 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
1192 if (size != ntohs (obmm->size))
1195 return GNUNET_SYSERR;
1202 * Send a response to the @a pm that we have processed a
1203 * "send" request with status @a success. We
1204 * transmitted @a bytes_physical on the actual wire.
1205 * Sends a confirmation to the "core" client responsible
1206 * for the original request and free's @a pm.
1208 * @param pm handle to the original pending message
1209 * @param success status code, #GNUNET_OK on success, #GNUNET_SYSERR
1210 * for transmission failure
1211 * @param bytes_physical amount of bandwidth consumed
1214 client_send_response (struct PendingMessage *pm,
1216 uint32_t bytes_physical)
1218 struct TransportClient *tc = pm->client;
1219 struct Neighbour *target = pm->target;
1220 struct GNUNET_MQ_Envelope *env;
1221 struct SendOkMessage *som;
1225 env = GNUNET_MQ_msg (som,
1226 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1227 som->success = htonl ((uint32_t) success);
1228 som->bytes_msg = htonl (pm->bytes_msg);
1229 som->bytes_physical = htonl (bytes_physical);
1230 som->peer = target->pid;
1231 GNUNET_MQ_send (tc->mq,
1233 GNUNET_CONTAINER_MDLL_remove (client,
1234 tc->details.core.pending_msg_head,
1235 tc->details.core.pending_msg_tail,
1238 GNUNET_CONTAINER_MDLL_remove (neighbour,
1239 target->pending_msg_head,
1240 target->pending_msg_tail,
1247 * Client asked for transmission to a peer. Process the request.
1249 * @param cls the client
1250 * @param obm the send message that was sent
1253 handle_client_send (void *cls,
1254 const struct OutboundMessage *obm)
1256 struct TransportClient *tc = cls;
1257 struct PendingMessage *pm;
1258 const struct GNUNET_MessageHeader *obmm;
1259 struct Neighbour *target;
1262 GNUNET_assert (CT_CORE == tc->type);
1263 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
1264 bytes_msg = ntohs (obmm->size);
1265 target = lookup_neighbour (&obm->peer);
1268 /* Failure: don't have this peer as a neighbour (anymore).
1269 Might have gone down asynchronously, so this is NOT
1270 a protocol violation by CORE. Still count the event,
1271 as this should be rare. */
1272 struct GNUNET_MQ_Envelope *env;
1273 struct SendOkMessage *som;
1275 env = GNUNET_MQ_msg (som,
1276 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1277 som->success = htonl (GNUNET_SYSERR);
1278 som->bytes_msg = htonl (bytes_msg);
1279 som->bytes_physical = htonl (0);
1280 som->peer = obm->peer;
1281 GNUNET_MQ_send (tc->mq,
1283 GNUNET_SERVICE_client_continue (tc->client);
1284 GNUNET_STATISTICS_update (GST_stats,
1285 "# messages dropped (neighbour unknown)",
1290 pm = GNUNET_new (struct PendingMessage);
1292 pm->target = target;
1293 pm->bytes_msg = bytes_msg;
1294 GNUNET_CONTAINER_MDLL_insert (neighbour,
1295 target->pending_msg_head,
1296 target->pending_msg_tail,
1298 GNUNET_CONTAINER_MDLL_insert (client,
1299 tc->details.core.pending_msg_head,
1300 tc->details.core.pending_msg_tail,
1302 // FIXME: do the work, final continuation with call to:
1303 client_send_response (pm,
1310 * Communicator started. Test message is well-formed.
1312 * @param cls the client
1313 * @param cam the send message that was sent
1316 check_communicator_available (void *cls,
1317 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1319 struct TransportClient *tc = cls;
1322 if (CT_NONE != tc->type)
1325 return GNUNET_SYSERR;
1327 tc->type = CT_COMMUNICATOR;
1328 size = ntohs (cam->header.size) - sizeof (*cam);
1330 return GNUNET_OK; /* receive-only communicator */
1331 GNUNET_MQ_check_zero_termination (cam);
1337 * Communicator started. Process the request.
1339 * @param cls the client
1340 * @param cam the send message that was sent
1343 handle_communicator_available (void *cls,
1344 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1346 struct TransportClient *tc = cls;
1349 size = ntohs (cam->header.size) - sizeof (*cam);
1351 return; /* receive-only communicator */
1352 tc->details.communicator.address_prefix
1353 = GNUNET_strdup ((const char *) &cam[1]);
1354 tc->details.communicator.cc
1355 = (enum GNUNET_TRANSPORT_CommunicatorCharacteristics) ntohl (cam->cc);
1356 GNUNET_SERVICE_client_continue (tc->client);
1361 * Address of our peer added. Test message is well-formed.
1363 * @param cls the client
1364 * @param aam the send message that was sent
1367 check_add_address (void *cls,
1368 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1370 struct TransportClient *tc = cls;
1372 if (CT_COMMUNICATOR != tc->type)
1375 return GNUNET_SYSERR;
1377 GNUNET_MQ_check_zero_termination (aam);
1383 * Ask peerstore to store our address.
1385 * @param cls an `struct AddressListEntry *`
1388 store_pi (void *cls);
1392 * Function called when peerstore is done storing our address.
1395 peerstore_store_cb (void *cls,
1398 struct AddressListEntry *ale = cls;
1401 if (GNUNET_YES != success)
1402 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1403 "Failed to store our own address `%s' in peerstore!\n",
1405 /* refresh period is 1/4 of expiration time, that should be plenty
1406 without being excessive. */
1407 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
1415 * Ask peerstore to store our address.
1417 * @param cls an `struct AddressListEntry *`
1420 store_pi (void *cls)
1422 struct AddressListEntry *ale = cls;
1425 struct GNUNET_TIME_Absolute expiration;
1428 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
1429 GNUNET_HELLO_sign_address (ale->address,
1435 ale->sc = GNUNET_PEERSTORE_store (peerstore,
1438 GNUNET_HELLO_PEERSTORE_KEY,
1442 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
1443 &peerstore_store_cb,
1446 if (NULL == ale->sc)
1448 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1449 "Failed to store our address `%s' with peerstore\n",
1451 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
1459 * Address of our peer added. Process the request.
1461 * @param cls the client
1462 * @param aam the send message that was sent
1465 handle_add_address (void *cls,
1466 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1468 struct TransportClient *tc = cls;
1469 struct AddressListEntry *ale;
1472 slen = ntohs (aam->header.size) - sizeof (*aam);
1473 ale = GNUNET_malloc (sizeof (struct AddressListEntry) + slen);
1475 ale->address = (const char *) &ale[1];
1476 ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
1477 ale->aid = aam->aid;
1478 ale->nt = (enum GNUNET_NetworkType) ntohl (aam->nt);
1482 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
1483 tc->details.communicator.addr_tail,
1485 ale->st = GNUNET_SCHEDULER_add_now (&store_pi,
1487 GNUNET_SERVICE_client_continue (tc->client);
1492 * Address of our peer deleted. Process the request.
1494 * @param cls the client
1495 * @param dam the send message that was sent
1498 handle_del_address (void *cls,
1499 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
1501 struct TransportClient *tc = cls;
1503 if (CT_COMMUNICATOR != tc->type)
1506 GNUNET_SERVICE_client_drop (tc->client);
1509 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
1513 if (dam->aid != ale->aid)
1515 GNUNET_assert (ale->tc == tc);
1516 free_address_list_entry (ale);
1517 GNUNET_SERVICE_client_continue (tc->client);
1520 GNUNET_SERVICE_client_drop (tc->client);
1525 * Client notified us about transmission from a peer. Process the request.
1527 * @param cls the client
1528 * @param obm the send message that was sent
1531 check_incoming_msg (void *cls,
1532 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1534 struct TransportClient *tc = cls;
1536 const struct GNUNET_MessageHeader *obmm;
1538 if (CT_COMMUNICATOR != tc->type)
1541 return GNUNET_SYSERR;
1543 size = ntohs (im->header.size) - sizeof (*im);
1544 if (size < sizeof (struct GNUNET_MessageHeader))
1547 return GNUNET_SYSERR;
1549 obmm = (const struct GNUNET_MessageHeader *) &im[1];
1550 if (size != ntohs (obmm->size))
1553 return GNUNET_SYSERR;
1560 * Incoming meessage. Process the request.
1562 * @param cls the client
1563 * @param im the send message that was received
1566 handle_incoming_msg (void *cls,
1567 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1569 struct TransportClient *tc = cls;
1571 GNUNET_SERVICE_client_continue (tc->client);
1576 * New queue became available. Check message.
1578 * @param cls the client
1579 * @param aqm the send message that was sent
1582 check_add_queue_message (void *cls,
1583 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1585 struct TransportClient *tc = cls;
1587 if (CT_COMMUNICATOR != tc->type)
1590 return GNUNET_SYSERR;
1592 GNUNET_MQ_check_zero_termination (aqm);
1598 * Bandwidth tracker informs us that the delay until we
1599 * can transmit again changed.
1601 * @param cls a `struct GNUNET_ATS_Session` for which the delay changed
1604 tracker_update_cb (void *cls)
1606 struct GNUNET_ATS_Session *queue = cls;
1608 // FIXME: re-schedule transmission tasks if applicable!
1613 * Bandwidth tracker informs us that excessive bandwidth was allocated
1614 * which is not being used.
1616 * @param cls a `struct GNUNET_ATS_Session` for which the excess was noted
1619 tracker_excess_cb (void *cls)
1621 /* FIXME: what do we do? */
1626 * New queue became available. Process the request.
1628 * @param cls the client
1629 * @param aqm the send message that was sent
1632 handle_add_queue_message (void *cls,
1633 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1635 struct TransportClient *tc = cls;
1636 struct GNUNET_ATS_Session *queue;
1637 struct Neighbour *neighbour;
1641 neighbour = lookup_neighbour (&aqm->receiver);
1642 if (NULL == neighbour)
1644 neighbour = GNUNET_new (struct Neighbour);
1645 neighbour->pid = aqm->receiver;
1646 GNUNET_assert (GNUNET_OK ==
1647 GNUNET_CONTAINER_multipeermap_put (neighbours,
1650 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1651 cores_send_connect_info (&neighbour->pid,
1652 GNUNET_BANDWIDTH_ZERO);
1653 // FIXME: notify ATS!
1655 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
1656 addr = (const char *) &aqm[1];
1658 queue = GNUNET_malloc (sizeof (struct GNUNET_ATS_Session) + addr_len);
1660 queue->address = (const char *) &queue[1];
1661 queue->rtt = GNUNET_TIME_UNIT_FOREVER_REL;
1662 queue->qid = aqm->qid;
1663 queue->mtu = ntohl (aqm->mtu);
1664 queue->distance = ntohl (aqm->distance);
1665 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
1666 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
1667 queue->neighbour = neighbour;
1668 GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_in,
1671 GNUNET_BANDWIDTH_ZERO,
1672 0 /* FIXME: max carry in seconds! */,
1675 GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_out,
1678 GNUNET_BANDWIDTH_ZERO,
1679 0 /* FIXME: max carry in seconds! */,
1685 /* notify monitors about new queue */
1687 struct MonitorEvent me = {
1692 notify_monitors (&neighbour->pid,
1697 GNUNET_CONTAINER_MDLL_insert (neighbour,
1698 neighbour->session_head,
1699 neighbour->session_tail,
1701 GNUNET_CONTAINER_MDLL_insert (client,
1702 tc->details.communicator.session_head,
1703 tc->details.communicator.session_tail,
1705 // FIXME: possibly transmit queued messages?
1706 GNUNET_SERVICE_client_continue (tc->client);
1711 * Queue to a peer went down. Process the request.
1713 * @param cls the client
1714 * @param dqm the send message that was sent
1717 handle_del_queue_message (void *cls,
1718 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
1720 struct TransportClient *tc = cls;
1722 if (CT_COMMUNICATOR != tc->type)
1725 GNUNET_SERVICE_client_drop (tc->client);
1728 for (struct GNUNET_ATS_Session *queue = tc->details.communicator.session_head;
1730 queue = queue->next_client)
1732 struct Neighbour *neighbour = queue->neighbour;
1734 if ( (dqm->qid != queue->qid) ||
1735 (0 != memcmp (&dqm->receiver,
1737 sizeof (struct GNUNET_PeerIdentity))) )
1740 GNUNET_SERVICE_client_continue (tc->client);
1744 GNUNET_SERVICE_client_drop (tc->client);
1749 * Message was transmitted. Process the request.
1751 * @param cls the client
1752 * @param sma the send message that was sent
1755 handle_send_message_ack (void *cls,
1756 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
1758 struct TransportClient *tc = cls;
1760 if (CT_COMMUNICATOR != tc->type)
1763 GNUNET_SERVICE_client_drop (tc->client);
1766 GNUNET_SERVICE_client_continue (tc->client);
1771 * Iterator telling new MONITOR client about all existing
1774 * @param cls the new `struct TransportClient`
1775 * @param pid a connected peer
1776 * @param value the `struct Neighbour` with more information
1777 * @return #GNUNET_OK (continue to iterate)
1780 notify_client_queues (void *cls,
1781 const struct GNUNET_PeerIdentity *pid,
1784 struct TransportClient *tc = cls;
1785 struct Neighbour *neighbour = value;
1787 GNUNET_assert (CT_MONITOR == tc->type);
1788 for (struct GNUNET_ATS_Session *q = neighbour->session_head;
1790 q = q->next_neighbour)
1792 struct MonitorEvent me = {
1795 .num_msg_pending = q->num_msg_pending,
1796 .num_bytes_pending = q->num_bytes_pending
1810 * Initialize a monitor client.
1812 * @param cls the client
1813 * @param start the start message that was sent
1816 handle_monitor_start (void *cls,
1817 const struct GNUNET_TRANSPORT_MonitorStart *start)
1819 struct TransportClient *tc = cls;
1821 if (CT_NONE != tc->type)
1824 GNUNET_SERVICE_client_drop (tc->client);
1827 tc->type = CT_MONITOR;
1828 tc->details.monitor.peer = start->peer;
1829 tc->details.monitor.one_shot = ntohl (start->one_shot);
1830 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1831 ¬ify_client_queues,
1833 GNUNET_SERVICE_client_mark_monitor (tc->client);
1834 GNUNET_SERVICE_client_continue (tc->client);
1839 * Signature of a function called by ATS with the current bandwidth
1840 * allocation to be used as determined by ATS.
1842 * @param cls closure, NULL
1843 * @param session session this is about
1844 * @param bandwidth_out assigned outbound bandwidth for the connection,
1845 * 0 to signal disconnect
1846 * @param bandwidth_in assigned inbound bandwidth for the connection,
1847 * 0 to signal disconnect
1850 ats_allocation_cb (void *cls,
1851 struct GNUNET_ATS_Session *session,
1852 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
1853 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
1856 GNUNET_BANDWIDTH_tracker_update_quota (&session->tracker_out,
1858 GNUNET_BANDWIDTH_tracker_update_quota (&session->tracker_in,
1864 * Find transport client providing communication service
1865 * for the protocol @a prefix.
1867 * @param prefix communicator name
1868 * @return NULL if no such transport client is available
1870 static struct TransportClient *
1871 lookup_communicator (const char *prefix)
1873 GNUNET_break (0); // FIXME: implement
1879 * Signature of a function called by ATS suggesting transport to
1880 * try connecting with a particular address.
1882 * @param cls closure, NULL
1883 * @param pid target peer
1884 * @param address the address to try
1887 ats_suggestion_cb (void *cls,
1888 const struct GNUNET_PeerIdentity *pid,
1889 const char *address)
1891 struct TransportClient *tc;
1895 prefix = NULL; // FIXME
1896 tc = lookup_communicator (prefix);
1902 // FIXME: forward suggestion to tc
1907 * Free neighbour entry.
1911 * @param value a `struct Neighbour`
1912 * @return #GNUNET_OK (always)
1915 free_neighbour_cb (void *cls,
1916 const struct GNUNET_PeerIdentity *pid,
1919 struct Neighbour *neighbour = value;
1923 GNUNET_break (0); // should this ever happen?
1924 free_neighbour (neighbour);
1931 * Free ephemeral entry.
1935 * @param value a `struct Neighbour`
1936 * @return #GNUNET_OK (always)
1939 free_ephemeral_cb (void *cls,
1940 const struct GNUNET_PeerIdentity *pid,
1943 struct EphemeralCacheEntry *ece = value;
1947 free_ephemeral (ece);
1953 * Function called when the service shuts down. Unloads our plugins
1954 * and cancels pending validations.
1956 * @param cls closure, unused
1959 do_shutdown (void *cls)
1963 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1968 GNUNET_ATS_transport_done (ats);
1971 if (NULL != peerstore)
1973 GNUNET_PEERSTORE_disconnect (peerstore,
1977 if (NULL != GST_stats)
1979 GNUNET_STATISTICS_destroy (GST_stats,
1983 if (NULL != GST_my_private_key)
1985 GNUNET_free (GST_my_private_key);
1986 GST_my_private_key = NULL;
1988 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
1990 GNUNET_CONTAINER_multipeermap_iterate (ephemeral_map,
1993 GNUNET_CONTAINER_multipeermap_destroy (ephemeral_map);
1994 ephemeral_map = NULL;
1995 GNUNET_CONTAINER_heap_destroy (ephemeral_heap);
1996 ephemeral_heap = NULL;
2001 * Initiate transport service.
2003 * @param cls closure
2004 * @param c configuration to use
2005 * @param service the initialized service
2009 const struct GNUNET_CONFIGURATION_Handle *c,
2010 struct GNUNET_SERVICE_Handle *service)
2015 neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
2017 ephemeral_map = GNUNET_CONTAINER_multipeermap_create (32,
2019 ephemeral_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2020 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
2021 if (NULL == GST_my_private_key)
2023 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2024 _("Transport service is lacking key configuration settings. Exiting.\n"));
2025 GNUNET_SCHEDULER_shutdown ();
2028 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
2029 &GST_my_identity.public_key);
2030 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2031 "My identity is `%s'\n",
2032 GNUNET_i2s_full (&GST_my_identity));
2033 GST_stats = GNUNET_STATISTICS_create ("transport",
2035 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
2037 peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
2038 if (NULL == peerstore)
2041 GNUNET_SCHEDULER_shutdown ();
2044 ats = GNUNET_ATS_transport_init (GST_cfg,
2052 GNUNET_SCHEDULER_shutdown ();
2059 * Define "main" method using service macro.
2063 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
2066 &client_disconnect_cb,
2068 /* communication with core */
2069 GNUNET_MQ_hd_fixed_size (client_start,
2070 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
2071 struct StartMessage,
2073 GNUNET_MQ_hd_var_size (client_send,
2074 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
2075 struct OutboundMessage,
2077 /* communication with communicators */
2078 GNUNET_MQ_hd_var_size (communicator_available,
2079 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
2080 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
2082 GNUNET_MQ_hd_var_size (add_address,
2083 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
2084 struct GNUNET_TRANSPORT_AddAddressMessage,
2086 GNUNET_MQ_hd_fixed_size (del_address,
2087 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
2088 struct GNUNET_TRANSPORT_DelAddressMessage,
2090 GNUNET_MQ_hd_var_size (incoming_msg,
2091 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
2092 struct GNUNET_TRANSPORT_IncomingMessage,
2094 GNUNET_MQ_hd_var_size (add_queue_message,
2095 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
2096 struct GNUNET_TRANSPORT_AddQueueMessage,
2098 GNUNET_MQ_hd_fixed_size (del_queue_message,
2099 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
2100 struct GNUNET_TRANSPORT_DelQueueMessage,
2102 GNUNET_MQ_hd_fixed_size (send_message_ack,
2103 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
2104 struct GNUNET_TRANSPORT_SendMessageToAck,
2106 /* communication with monitors */
2107 GNUNET_MQ_hd_fixed_size (monitor_start,
2108 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
2109 struct GNUNET_TRANSPORT_MonitorStart,
2111 GNUNET_MQ_handler_end ());
2114 /* end of file gnunet-service-transport.c */