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/>.
19 * @file transport/gnunet-service-tng.c
20 * @brief main for gnunet-service-tng
21 * @author Christian Grothoff
24 * - figure out how to transmit (selective) ACKs in case of uni-directional
25 * communicators (with/without core? DV-only?) When do we use ACKs?
26 * => communicators use selective ACKs for flow control
27 * => transport uses message-level ACKs for RTT, fragment confirmation
28 * => integrate DV into transport, use neither core nor communicators
29 * but rather give communicators transport-encapsulated messages
30 * (which could be core-data, background-channel traffic, or
31 * transport-to-transport traffic)
34 * - manage fragmentation/defragmentation, retransmission, track RTT, loss, etc.
37 * - use ATS bandwidth allocation callback and schedule transmissions!
40 * - inform ATS about RTT, goodput/loss, overheads, etc.
43 * - change transport-core API to provide proper flow control in both
44 * directions, allow multiple messages per peer simultaneously (tag
45 * confirmations with unique message ID), and replace quota-out with
46 * proper flow control;
48 * Design realizations / discussion:
49 * - communicators do flow control by calling MQ "notify sent"
50 * when 'ready'. They determine flow implicitly (i.e. TCP blocking)
51 * or explicitly via background channel FC ACKs. As long as the
52 * channel is not full, they may 'notify sent' even if the other
53 * peer has not yet confirmed receipt. The other peer confirming
54 * is _only_ for FC, not for more reliable transmission; reliable
55 * transmission (i.e. of fragments) is left to _transport_.
56 * - ACKs sent back in uni-directional communicators are done via
57 * the background channel API; here transport _may_ initially
58 * broadcast (with bounded # hops) if no path is known;
59 * - transport should _integrate_ DV-routing and build a view of
60 * the network; then background channel traffic can be
61 * routed via DV as well as explicit "DV" traffic.
62 * - background channel is also used for ACKs and NAT traversal support
63 * - transport service is responsible for AEAD'ing the background
64 * channel, timestamps and monotonic time are used against replay
65 * of old messages -> peerstore needs to be supplied with
66 * "latest timestamps seen" data
67 * - if transport implements DV, we likely need a 3rd peermap
68 * in addition to ephemerals and (direct) neighbours
69 * => in this data structure, we should track ATS metrics (distance, RTT, etc.)
70 * as well as latest timestamps seen, goodput, fragments for transmission, etc.
71 * ==> check if stuff needs to be moved out of "Neighbour"
72 * - transport should encapsualte core-level messages and do its
73 * own ACKing for RTT/goodput/loss measurements _and_ fragment
77 #include "gnunet_util_lib.h"
78 #include "gnunet_statistics_service.h"
79 #include "gnunet_transport_monitor_service.h"
80 #include "gnunet_peerstore_service.h"
81 #include "gnunet_hello_lib.h"
82 #include "gnunet_ats_transport_service.h"
83 #include "transport.h"
87 * How many messages can we have pending for a given client process
88 * before we start to drop incoming messages? We typically should
89 * have only one client and so this would be the primary buffer for
90 * messages, so the number should be chosen rather generously.
92 * The expectation here is that most of the time the queue is large
93 * enough so that a drop is virtually never required. Note that
94 * this value must be about as large as 'TOTAL_MSGS' in the
95 * 'test_transport_api_reliability.c', otherwise that testcase may
98 #define MAX_PENDING (128 * 1024)
101 GNUNET_NETWORK_STRUCT_BEGIN
104 * Outer layer of an encapsulated backchannel message.
106 struct TransportBackchannelEncapsulationMessage
109 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION.
111 struct GNUNET_MessageHeader header;
114 * Distance the backchannel message has traveled, to be updated at
115 * each hop. Used to bound the number of hops in case a backchannel
116 * message is broadcast and thus travels without routing
117 * information (during initial backchannel discovery).
122 * Target's peer identity (as backchannels may be transmitted
123 * indirectly, or even be broadcast).
125 struct GNUNET_PeerIdentity target;
128 * Ephemeral key setup by the sender for @e target, used
129 * to encrypt the payload.
131 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
134 * HMAC over the ciphertext of the encrypted, variable-size
135 * body that follows. Verified via DH of @e target and
138 struct GNUNET_HashCode hmac;
140 /* Followed by encrypted, variable-size payload */
145 * Message by which a peer confirms that it is using an
148 struct EphemeralConfirmation
152 * Purpose is #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
154 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
157 * How long is this signature over the ephemeral key
160 struct GNUNET_TIME_AbsoluteNBO ephemeral_validity;
163 * Ephemeral key setup by the sender for @e target, used
164 * to encrypt the payload.
166 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
171 * Plaintext of the variable-size payload that is encrypted
172 * within a `struct TransportBackchannelEncapsulationMessage`
174 struct TransportBackchannelRequestPayload
178 * Sender's peer identity.
180 struct GNUNET_PeerIdentity sender;
183 * Signature of the sender over an
184 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
186 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
189 * How long is this signature over the ephemeral key
192 struct GNUNET_TIME_AbsoluteNBO ephemeral_validity;
195 * Current monotonic time of the sending transport service. Used to
196 * detect replayed messages. Note that the receiver should remember
197 * a list of the recently seen timestamps and only reject messages
198 * if the timestamp is in the list, or the list is "full" and the
199 * timestamp is smaller than the lowest in the list. This list of
200 * timestamps per peer should be persisted to guard against replays
203 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
205 /* Followed by a `struct GNUNET_MessageHeader` with a message
206 for a communicator */
208 /* Followed by a 0-termianted string specifying the name of
209 the communicator which is to receive the message */
213 GNUNET_NETWORK_STRUCT_END
218 * What type of client is the `struct TransportClient` about?
223 * We do not know yet (client is fresh).
228 * Is the CORE service, we need to forward traffic to it.
233 * It is a monitor, forward monitor data.
238 * It is a communicator, use for communication.
245 * Entry in our cache of ephemeral keys we currently use.
247 struct EphemeralCacheEntry
251 * Target's peer identity (we don't re-use ephemerals
252 * to limit linkability of messages).
254 struct GNUNET_PeerIdentity target;
257 * Signature affirming @e ephemeral_key of type
258 * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
260 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
263 * How long is @e sender_sig valid
265 struct GNUNET_TIME_Absolute ephemeral_validity;
270 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
273 * Node in the ephemeral cache for this entry.
274 * Used for expiration.
276 struct GNUNET_CONTAINER_HeapNode *hn;
281 * Client connected to the transport service.
283 struct TransportClient;
287 * A neighbour that at least one communicator is connected to.
293 * An ATS session is a message queue provided by a communicator
294 * via which we can reach a particular neighbour.
296 struct GNUNET_ATS_Session
301 struct GNUNET_ATS_Session *next_neighbour;
306 struct GNUNET_ATS_Session *prev_neighbour;
311 struct GNUNET_ATS_Session *prev_client;
316 struct GNUNET_ATS_Session *next_client;
319 * Which neighbour is this ATS session for?
321 struct Neighbour *neighbour;
324 * Which communicator offers this ATS session?
326 struct TransportClient *tc;
329 * Address served by the ATS session.
334 * Our current RTT estimate for this ATS session.
336 struct GNUNET_TIME_Relative rtt;
339 * Unique identifier of this ATS session with the communicator.
344 * Maximum transmission unit supported by this ATS session.
349 * Distance to the target of this ATS session.
354 * Network type offered by this ATS session.
356 enum GNUNET_NetworkType nt;
359 * Connection status for this ATS session.
361 enum GNUNET_TRANSPORT_ConnectionStatus cs;
366 uint32_t num_msg_pending;
371 uint32_t num_bytes_pending;
374 * How much outbound bandwidth do we have available for this session?
376 struct GNUNET_BANDWIDTH_Tracker tracker_out;
379 * How much inbound bandwidth do we have available for this session?
381 struct GNUNET_BANDWIDTH_Tracker tracker_in;
386 * A neighbour that at least one communicator is connected to.
392 * Which peer is this about?
394 struct GNUNET_PeerIdentity pid;
397 * Head of list of messages pending for this neighbour.
399 struct PendingMessage *pending_msg_head;
402 * Tail of list of messages pending for this neighbour.
404 struct PendingMessage *pending_msg_tail;
407 * Head of DLL of ATS sessions to this peer.
409 struct GNUNET_ATS_Session *session_head;
412 * Tail of DLL of ATS sessions to this peer.
414 struct GNUNET_ATS_Session *session_tail;
417 * Quota at which CORE is allowed to transmit to this peer
420 * FIXME: not yet used, tricky to get right given multiple queues!
421 * (=> Idea: let ATS set a quota per queue and we add them up here?)
422 * FIXME: how do we set this value initially when we tell CORE?
423 * Options: start at a minimum value or at literally zero (before ATS?)
424 * (=> Current thought: clean would be zero!)
426 struct GNUNET_BANDWIDTH_Value32NBO quota_out;
432 * Transmission request from CORE that is awaiting delivery.
434 struct PendingMessage
437 * Kept in a MDLL of messages for this @a target.
439 struct PendingMessage *next_neighbour;
442 * Kept in a MDLL of messages for this @a target.
444 struct PendingMessage *prev_neighbour;
447 * Kept in a MDLL of messages from this @a client.
449 struct PendingMessage *next_client;
452 * Kept in a MDLL of messages from this @a client.
454 struct PendingMessage *prev_client;
457 * Target of the request.
459 struct Neighbour *target;
462 * Client that issued the transmission request.
464 struct TransportClient *client;
467 * Size of the original message.
475 * One of the addresses of this peer.
477 struct AddressListEntry
483 struct AddressListEntry *next;
488 struct AddressListEntry *prev;
491 * Which communicator provides this address?
493 struct TransportClient *tc;
496 * The actual address.
501 * Current context for storing this address in the peerstore.
503 struct GNUNET_PEERSTORE_StoreContext *sc;
506 * Task to periodically do @e st operation.
508 struct GNUNET_SCHEDULER_Task *st;
511 * What is a typical lifetime the communicator expects this
512 * address to have? (Always from now.)
514 struct GNUNET_TIME_Relative expiration;
517 * Address identifier used by the communicator.
522 * Network type offered by this address.
524 enum GNUNET_NetworkType nt;
530 * Client connected to the transport service.
532 struct TransportClient
538 struct TransportClient *next;
543 struct TransportClient *prev;
546 * Handle to the client.
548 struct GNUNET_SERVICE_Client *client;
551 * Message queue to the client.
553 struct GNUNET_MQ_Handle *mq;
556 * What type of client is this?
558 enum ClientType type;
564 * Information for @e type #CT_CORE.
569 * Head of list of messages pending for this client.
571 struct PendingMessage *pending_msg_head;
574 * Tail of list of messages pending for this client.
576 struct PendingMessage *pending_msg_tail;
581 * Information for @e type #CT_MONITOR.
586 * Peer identity to monitor the addresses of.
587 * Zero to monitor all neighbours. Valid if
588 * @e type is #CT_MONITOR.
590 struct GNUNET_PeerIdentity peer;
593 * Is this a one-shot monitor?
601 * Information for @e type #CT_COMMUNICATOR.
605 * If @e type is #CT_COMMUNICATOR, this communicator
606 * supports communicating using these addresses.
608 char *address_prefix;
611 * Head of DLL of queues offered by this communicator.
613 struct GNUNET_ATS_Session *session_head;
616 * Tail of DLL of queues offered by this communicator.
618 struct GNUNET_ATS_Session *session_tail;
621 * Head of list of the addresses of this peer offered by this communicator.
623 struct AddressListEntry *addr_head;
626 * Tail of list of the addresses of this peer offered by this communicator.
628 struct AddressListEntry *addr_tail;
631 * Characteristics of this communicator.
633 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc;
643 * Head of linked list of all clients to this service.
645 static struct TransportClient *clients_head;
648 * Tail of linked list of all clients to this service.
650 static struct TransportClient *clients_tail;
655 static struct GNUNET_STATISTICS_Handle *GST_stats;
658 * Configuration handle.
660 static const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
665 static struct GNUNET_PeerIdentity GST_my_identity;
670 static struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
673 * Map from PIDs to `struct Neighbour` entries. A peer is
674 * a neighbour if we have an MQ to it from some communicator.
676 static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
679 * Database for peer's HELLOs.
681 static struct GNUNET_PEERSTORE_Handle *peerstore;
684 * Heap sorting `struct EphemeralCacheEntry` by their
685 * key/signature validity.
687 static struct GNUNET_CONTAINER_Heap *ephemeral_heap;
690 * Hash map for looking up `struct EphemeralCacheEntry`s
691 * by peer identity. (We may have ephemerals in our
692 * cache for which we do not have a neighbour entry,
693 * and similar many neighbours may not need ephemerals,
694 * so we use a second map.)
696 static struct GNUNET_CONTAINER_MultiPeerMap *ephemeral_map;
699 * Our connection to ATS for allocation and bootstrapping.
701 static struct GNUNET_ATS_TransportHandle *ats;
705 * Free cached ephemeral key.
707 * @param ece cached signature to free
710 free_ephemeral (struct EphemeralCacheEntry *ece)
712 GNUNET_CONTAINER_multipeermap_remove (ephemeral_map,
715 GNUNET_CONTAINER_heap_remove_node (ece->hn);
721 * Lookup neighbour record for peer @a pid.
723 * @param pid neighbour to look for
724 * @return NULL if we do not have this peer as a neighbour
726 static struct Neighbour *
727 lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
729 return GNUNET_CONTAINER_multipeermap_get (neighbours,
735 * Details about what to notify monitors about.
740 * @deprecated To be discussed if we keep these...
742 struct GNUNET_TIME_Absolute last_validation;
743 struct GNUNET_TIME_Absolute valid_until;
744 struct GNUNET_TIME_Absolute next_validation;
747 * Current round-trip time estimate.
749 struct GNUNET_TIME_Relative rtt;
754 enum GNUNET_TRANSPORT_ConnectionStatus cs;
759 uint32_t num_msg_pending;
764 uint32_t num_bytes_pending;
771 * Notify monitor @a tc about an event. That @a tc
772 * cares about the event has already been checked.
774 * Send @a tc information in @a me about a @a peer's status with
775 * respect to some @a address to all monitors that care.
777 * @param tc monitor to inform
778 * @param peer peer the information is about
779 * @param address address the information is about
780 * @param nt network type associated with @a address
781 * @param me detailed information to transmit
784 notify_monitor (struct TransportClient *tc,
785 const struct GNUNET_PeerIdentity *peer,
787 enum GNUNET_NetworkType nt,
788 const struct MonitorEvent *me)
790 struct GNUNET_MQ_Envelope *env;
791 struct GNUNET_TRANSPORT_MonitorData *md;
792 size_t addr_len = strlen (address) + 1;
794 env = GNUNET_MQ_msg_extra (md,
796 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA);
797 md->nt = htonl ((uint32_t) nt);
799 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
800 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
801 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
802 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
803 md->cs = htonl ((uint32_t) me->cs);
804 md->num_msg_pending = htonl (me->num_msg_pending);
805 md->num_bytes_pending = htonl (me->num_bytes_pending);
809 GNUNET_MQ_send (tc->mq,
815 * Send information in @a me about a @a peer's status with respect
816 * to some @a address to all monitors that care.
818 * @param peer peer the information is about
819 * @param address address the information is about
820 * @param nt network type associated with @a address
821 * @param me detailed information to transmit
824 notify_monitors (const struct GNUNET_PeerIdentity *peer,
826 enum GNUNET_NetworkType nt,
827 const struct MonitorEvent *me)
829 static struct GNUNET_PeerIdentity zero;
831 for (struct TransportClient *tc = clients_head;
835 if (CT_MONITOR != tc->type)
837 if (tc->details.monitor.one_shot)
839 if ( (0 != memcmp (&tc->details.monitor.peer,
842 (0 != memcmp (&tc->details.monitor.peer,
856 * Called whenever a client connects. Allocates our
857 * data structures associated with that client.
859 * @param cls closure, NULL
860 * @param client identification of the client
861 * @param mq message queue for the client
862 * @return our `struct TransportClient`
865 client_connect_cb (void *cls,
866 struct GNUNET_SERVICE_Client *client,
867 struct GNUNET_MQ_Handle *mq)
869 struct TransportClient *tc;
871 tc = GNUNET_new (struct TransportClient);
874 GNUNET_CONTAINER_DLL_insert (clients_head,
877 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
878 "Client %p connected\n",
885 * Release memory used by @a neighbour.
887 * @param neighbour neighbour entry to free
890 free_neighbour (struct Neighbour *neighbour)
892 GNUNET_assert (NULL == neighbour->session_head);
893 GNUNET_assert (GNUNET_YES ==
894 GNUNET_CONTAINER_multipeermap_remove (neighbours,
897 GNUNET_free (neighbour);
902 * Send message to CORE clients that we lost a connection.
904 * @param tc client to inform (must be CORE client)
905 * @param pid peer the connection is for
906 * @param quota_out current quota for the peer
909 core_send_connect_info (struct TransportClient *tc,
910 const struct GNUNET_PeerIdentity *pid,
911 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
913 struct GNUNET_MQ_Envelope *env;
914 struct ConnectInfoMessage *cim;
916 GNUNET_assert (CT_CORE == tc->type);
917 env = GNUNET_MQ_msg (cim,
918 GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
919 cim->quota_out = quota_out;
921 GNUNET_MQ_send (tc->mq,
927 * Send message to CORE clients that we gained a connection
929 * @param pid peer the queue was for
930 * @param quota_out current quota for the peer
933 cores_send_connect_info (const struct GNUNET_PeerIdentity *pid,
934 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
936 for (struct TransportClient *tc = clients_head;
940 if (CT_CORE != tc->type)
942 core_send_connect_info (tc,
950 * Send message to CORE clients that we lost a connection.
952 * @param pid peer the connection was for
955 cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
957 for (struct TransportClient *tc = clients_head;
961 struct GNUNET_MQ_Envelope *env;
962 struct DisconnectInfoMessage *dim;
964 if (CT_CORE != tc->type)
966 env = GNUNET_MQ_msg (dim,
967 GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
969 GNUNET_MQ_send (tc->mq,
978 * @param queue the queue to free
981 free_queue (struct GNUNET_ATS_Session *queue)
983 struct Neighbour *neighbour = queue->neighbour;
984 struct TransportClient *tc = queue->tc;
985 struct MonitorEvent me = {
986 .cs = GNUNET_TRANSPORT_CS_DOWN,
987 .rtt = GNUNET_TIME_UNIT_FOREVER_REL
990 GNUNET_CONTAINER_MDLL_remove (neighbour,
991 neighbour->session_head,
992 neighbour->session_tail,
994 GNUNET_CONTAINER_MDLL_remove (client,
995 tc->details.communicator.session_head,
996 tc->details.communicator.session_tail,
999 notify_monitors (&neighbour->pid,
1003 GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_in);
1004 GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_out);
1005 GNUNET_free (queue);
1006 if (NULL == neighbour->session_head)
1008 cores_send_disconnect_info (&neighbour->pid);
1009 free_neighbour (neighbour);
1017 * @param ale address list entry to free
1020 free_address_list_entry (struct AddressListEntry *ale)
1022 struct TransportClient *tc = ale->tc;
1024 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
1025 tc->details.communicator.addr_tail,
1027 if (NULL != ale->sc)
1029 GNUNET_PEERSTORE_store_cancel (ale->sc);
1032 if (NULL != ale->st)
1034 GNUNET_SCHEDULER_cancel (ale->st);
1042 * Called whenever a client is disconnected. Frees our
1043 * resources associated with that client.
1045 * @param cls closure, NULL
1046 * @param client identification of the client
1047 * @param app_ctx our `struct TransportClient`
1050 client_disconnect_cb (void *cls,
1051 struct GNUNET_SERVICE_Client *client,
1054 struct TransportClient *tc = app_ctx;
1056 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1057 "Client %p disconnected, cleaning up.\n",
1059 GNUNET_CONTAINER_DLL_remove (clients_head,
1068 struct PendingMessage *pm;
1070 while (NULL != (pm = tc->details.core.pending_msg_head))
1072 GNUNET_CONTAINER_MDLL_remove (client,
1073 tc->details.core.pending_msg_head,
1074 tc->details.core.pending_msg_tail,
1082 case CT_COMMUNICATOR:
1084 struct GNUNET_ATS_Session *q;
1085 struct AddressListEntry *ale;
1087 while (NULL != (q = tc->details.communicator.session_head))
1089 while (NULL != (ale = tc->details.communicator.addr_head))
1090 free_address_list_entry (ale);
1091 GNUNET_free (tc->details.communicator.address_prefix);
1100 * Iterator telling new CORE client about all existing
1101 * connections to peers.
1103 * @param cls the new `struct TransportClient`
1104 * @param pid a connected peer
1105 * @param value the `struct Neighbour` with more information
1106 * @return #GNUNET_OK (continue to iterate)
1109 notify_client_connect_info (void *cls,
1110 const struct GNUNET_PeerIdentity *pid,
1113 struct TransportClient *tc = cls;
1114 struct Neighbour *neighbour = value;
1116 core_send_connect_info (tc,
1118 neighbour->quota_out);
1124 * Initialize a "CORE" client. We got a start message from this
1125 * client, so add it to the list of clients for broadcasting of
1128 * @param cls the client
1129 * @param start the start message that was sent
1132 handle_client_start (void *cls,
1133 const struct StartMessage *start)
1135 struct TransportClient *tc = cls;
1138 options = ntohl (start->options);
1139 if ( (0 != (1 & options)) &&
1141 memcmp (&start->self,
1143 sizeof (struct GNUNET_PeerIdentity)) ) )
1145 /* client thinks this is a different peer, reject */
1147 GNUNET_SERVICE_client_drop (tc->client);
1150 if (CT_NONE != tc->type)
1153 GNUNET_SERVICE_client_drop (tc->client);
1157 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1158 ¬ify_client_connect_info,
1160 GNUNET_SERVICE_client_continue (tc->client);
1165 * Client asked for transmission to a peer. Process the request.
1167 * @param cls the client
1168 * @param obm the send message that was sent
1171 check_client_send (void *cls,
1172 const struct OutboundMessage *obm)
1174 struct TransportClient *tc = cls;
1176 const struct GNUNET_MessageHeader *obmm;
1178 if (CT_CORE != tc->type)
1181 return GNUNET_SYSERR;
1183 size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
1184 if (size < sizeof (struct GNUNET_MessageHeader))
1187 return GNUNET_SYSERR;
1189 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
1190 if (size != ntohs (obmm->size))
1193 return GNUNET_SYSERR;
1200 * Send a response to the @a pm that we have processed a
1201 * "send" request with status @a success. We
1202 * transmitted @a bytes_physical on the actual wire.
1203 * Sends a confirmation to the "core" client responsible
1204 * for the original request and free's @a pm.
1206 * @param pm handle to the original pending message
1207 * @param success status code, #GNUNET_OK on success, #GNUNET_SYSERR
1208 * for transmission failure
1209 * @param bytes_physical amount of bandwidth consumed
1212 client_send_response (struct PendingMessage *pm,
1214 uint32_t bytes_physical)
1216 struct TransportClient *tc = pm->client;
1217 struct Neighbour *target = pm->target;
1218 struct GNUNET_MQ_Envelope *env;
1219 struct SendOkMessage *som;
1223 env = GNUNET_MQ_msg (som,
1224 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1225 som->success = htonl ((uint32_t) success);
1226 som->bytes_msg = htonl (pm->bytes_msg);
1227 som->bytes_physical = htonl (bytes_physical);
1228 som->peer = target->pid;
1229 GNUNET_MQ_send (tc->mq,
1231 GNUNET_CONTAINER_MDLL_remove (client,
1232 tc->details.core.pending_msg_head,
1233 tc->details.core.pending_msg_tail,
1236 GNUNET_CONTAINER_MDLL_remove (neighbour,
1237 target->pending_msg_head,
1238 target->pending_msg_tail,
1245 * Client asked for transmission to a peer. Process the request.
1247 * @param cls the client
1248 * @param obm the send message that was sent
1251 handle_client_send (void *cls,
1252 const struct OutboundMessage *obm)
1254 struct TransportClient *tc = cls;
1255 struct PendingMessage *pm;
1256 const struct GNUNET_MessageHeader *obmm;
1257 struct Neighbour *target;
1260 GNUNET_assert (CT_CORE == tc->type);
1261 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
1262 bytes_msg = ntohs (obmm->size);
1263 target = lookup_neighbour (&obm->peer);
1266 /* Failure: don't have this peer as a neighbour (anymore).
1267 Might have gone down asynchronously, so this is NOT
1268 a protocol violation by CORE. Still count the event,
1269 as this should be rare. */
1270 struct GNUNET_MQ_Envelope *env;
1271 struct SendOkMessage *som;
1273 env = GNUNET_MQ_msg (som,
1274 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1275 som->success = htonl (GNUNET_SYSERR);
1276 som->bytes_msg = htonl (bytes_msg);
1277 som->bytes_physical = htonl (0);
1278 som->peer = obm->peer;
1279 GNUNET_MQ_send (tc->mq,
1281 GNUNET_SERVICE_client_continue (tc->client);
1282 GNUNET_STATISTICS_update (GST_stats,
1283 "# messages dropped (neighbour unknown)",
1288 pm = GNUNET_new (struct PendingMessage);
1290 pm->target = target;
1291 pm->bytes_msg = bytes_msg;
1292 GNUNET_CONTAINER_MDLL_insert (neighbour,
1293 target->pending_msg_head,
1294 target->pending_msg_tail,
1296 GNUNET_CONTAINER_MDLL_insert (client,
1297 tc->details.core.pending_msg_head,
1298 tc->details.core.pending_msg_tail,
1300 // FIXME: do the work, final continuation with call to:
1301 client_send_response (pm,
1308 * Communicator started. Test message is well-formed.
1310 * @param cls the client
1311 * @param cam the send message that was sent
1314 check_communicator_available (void *cls,
1315 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1317 struct TransportClient *tc = cls;
1320 if (CT_NONE != tc->type)
1323 return GNUNET_SYSERR;
1325 tc->type = CT_COMMUNICATOR;
1326 size = ntohs (cam->header.size) - sizeof (*cam);
1328 return GNUNET_OK; /* receive-only communicator */
1329 GNUNET_MQ_check_zero_termination (cam);
1335 * Communicator started. Process the request.
1337 * @param cls the client
1338 * @param cam the send message that was sent
1341 handle_communicator_available (void *cls,
1342 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1344 struct TransportClient *tc = cls;
1347 size = ntohs (cam->header.size) - sizeof (*cam);
1349 return; /* receive-only communicator */
1350 tc->details.communicator.address_prefix
1351 = GNUNET_strdup ((const char *) &cam[1]);
1352 tc->details.communicator.cc
1353 = (enum GNUNET_TRANSPORT_CommunicatorCharacteristics) ntohl (cam->cc);
1354 GNUNET_SERVICE_client_continue (tc->client);
1359 * Address of our peer added. Test message is well-formed.
1361 * @param cls the client
1362 * @param aam the send message that was sent
1365 check_add_address (void *cls,
1366 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1368 struct TransportClient *tc = cls;
1370 if (CT_COMMUNICATOR != tc->type)
1373 return GNUNET_SYSERR;
1375 GNUNET_MQ_check_zero_termination (aam);
1381 * Ask peerstore to store our address.
1383 * @param cls an `struct AddressListEntry *`
1386 store_pi (void *cls);
1390 * Function called when peerstore is done storing our address.
1393 peerstore_store_cb (void *cls,
1396 struct AddressListEntry *ale = cls;
1399 if (GNUNET_YES != success)
1400 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1401 "Failed to store our own address `%s' in peerstore!\n",
1403 /* refresh period is 1/4 of expiration time, that should be plenty
1404 without being excessive. */
1405 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
1413 * Ask peerstore to store our address.
1415 * @param cls an `struct AddressListEntry *`
1418 store_pi (void *cls)
1420 struct AddressListEntry *ale = cls;
1423 struct GNUNET_TIME_Absolute expiration;
1426 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
1427 GNUNET_HELLO_sign_address (ale->address,
1433 ale->sc = GNUNET_PEERSTORE_store (peerstore,
1436 GNUNET_HELLO_PEERSTORE_KEY,
1440 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
1441 &peerstore_store_cb,
1444 if (NULL == ale->sc)
1446 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1447 "Failed to store our address `%s' with peerstore\n",
1449 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
1457 * Address of our peer added. Process the request.
1459 * @param cls the client
1460 * @param aam the send message that was sent
1463 handle_add_address (void *cls,
1464 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1466 struct TransportClient *tc = cls;
1467 struct AddressListEntry *ale;
1470 slen = ntohs (aam->header.size) - sizeof (*aam);
1471 ale = GNUNET_malloc (sizeof (struct AddressListEntry) + slen);
1473 ale->address = (const char *) &ale[1];
1474 ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
1475 ale->aid = aam->aid;
1476 ale->nt = (enum GNUNET_NetworkType) ntohl (aam->nt);
1480 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
1481 tc->details.communicator.addr_tail,
1483 ale->st = GNUNET_SCHEDULER_add_now (&store_pi,
1485 GNUNET_SERVICE_client_continue (tc->client);
1490 * Address of our peer deleted. Process the request.
1492 * @param cls the client
1493 * @param dam the send message that was sent
1496 handle_del_address (void *cls,
1497 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
1499 struct TransportClient *tc = cls;
1501 if (CT_COMMUNICATOR != tc->type)
1504 GNUNET_SERVICE_client_drop (tc->client);
1507 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
1511 if (dam->aid != ale->aid)
1513 GNUNET_assert (ale->tc == tc);
1514 free_address_list_entry (ale);
1515 GNUNET_SERVICE_client_continue (tc->client);
1518 GNUNET_SERVICE_client_drop (tc->client);
1523 * Client notified us about transmission from a peer. Process the request.
1525 * @param cls the client
1526 * @param obm the send message that was sent
1529 check_incoming_msg (void *cls,
1530 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1532 struct TransportClient *tc = cls;
1534 const struct GNUNET_MessageHeader *obmm;
1536 if (CT_COMMUNICATOR != tc->type)
1539 return GNUNET_SYSERR;
1541 size = ntohs (im->header.size) - sizeof (*im);
1542 if (size < sizeof (struct GNUNET_MessageHeader))
1545 return GNUNET_SYSERR;
1547 obmm = (const struct GNUNET_MessageHeader *) &im[1];
1548 if (size != ntohs (obmm->size))
1551 return GNUNET_SYSERR;
1558 * Incoming meessage. Process the request.
1560 * @param cls the client
1561 * @param im the send message that was received
1564 handle_incoming_msg (void *cls,
1565 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1567 struct TransportClient *tc = cls;
1569 GNUNET_SERVICE_client_continue (tc->client);
1574 * New queue became available. Check message.
1576 * @param cls the client
1577 * @param aqm the send message that was sent
1580 check_add_queue_message (void *cls,
1581 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1583 struct TransportClient *tc = cls;
1585 if (CT_COMMUNICATOR != tc->type)
1588 return GNUNET_SYSERR;
1590 GNUNET_MQ_check_zero_termination (aqm);
1596 * Bandwidth tracker informs us that the delay until we
1597 * can transmit again changed.
1599 * @param cls a `struct GNUNET_ATS_Session` for which the delay changed
1602 tracker_update_cb (void *cls)
1604 struct GNUNET_ATS_Session *queue = cls;
1606 // FIXME: re-schedule transmission tasks if applicable!
1611 * Bandwidth tracker informs us that excessive bandwidth was allocated
1612 * which is not being used.
1614 * @param cls a `struct GNUNET_ATS_Session` for which the excess was noted
1617 tracker_excess_cb (void *cls)
1619 /* FIXME: what do we do? */
1624 * New queue became available. Process the request.
1626 * @param cls the client
1627 * @param aqm the send message that was sent
1630 handle_add_queue_message (void *cls,
1631 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1633 struct TransportClient *tc = cls;
1634 struct GNUNET_ATS_Session *queue;
1635 struct Neighbour *neighbour;
1639 neighbour = lookup_neighbour (&aqm->receiver);
1640 if (NULL == neighbour)
1642 neighbour = GNUNET_new (struct Neighbour);
1643 neighbour->pid = aqm->receiver;
1644 GNUNET_assert (GNUNET_OK ==
1645 GNUNET_CONTAINER_multipeermap_put (neighbours,
1648 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1649 cores_send_connect_info (&neighbour->pid,
1650 GNUNET_BANDWIDTH_ZERO);
1651 // FIXME: notify ATS!
1653 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
1654 addr = (const char *) &aqm[1];
1656 queue = GNUNET_malloc (sizeof (struct GNUNET_ATS_Session) + addr_len);
1658 queue->address = (const char *) &queue[1];
1659 queue->rtt = GNUNET_TIME_UNIT_FOREVER_REL;
1660 queue->qid = aqm->qid;
1661 queue->mtu = ntohl (aqm->mtu);
1662 queue->distance = ntohl (aqm->distance);
1663 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
1664 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
1665 queue->neighbour = neighbour;
1666 GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_in,
1669 GNUNET_BANDWIDTH_ZERO,
1670 0 /* FIXME: max carry in seconds! */,
1673 GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_out,
1676 GNUNET_BANDWIDTH_ZERO,
1677 0 /* FIXME: max carry in seconds! */,
1683 /* notify monitors about new queue */
1685 struct MonitorEvent me = {
1690 notify_monitors (&neighbour->pid,
1695 GNUNET_CONTAINER_MDLL_insert (neighbour,
1696 neighbour->session_head,
1697 neighbour->session_tail,
1699 GNUNET_CONTAINER_MDLL_insert (client,
1700 tc->details.communicator.session_head,
1701 tc->details.communicator.session_tail,
1703 // FIXME: possibly transmit queued messages?
1704 GNUNET_SERVICE_client_continue (tc->client);
1709 * Queue to a peer went down. Process the request.
1711 * @param cls the client
1712 * @param dqm the send message that was sent
1715 handle_del_queue_message (void *cls,
1716 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
1718 struct TransportClient *tc = cls;
1720 if (CT_COMMUNICATOR != tc->type)
1723 GNUNET_SERVICE_client_drop (tc->client);
1726 for (struct GNUNET_ATS_Session *queue = tc->details.communicator.session_head;
1728 queue = queue->next_client)
1730 struct Neighbour *neighbour = queue->neighbour;
1732 if ( (dqm->qid != queue->qid) ||
1733 (0 != memcmp (&dqm->receiver,
1735 sizeof (struct GNUNET_PeerIdentity))) )
1738 GNUNET_SERVICE_client_continue (tc->client);
1742 GNUNET_SERVICE_client_drop (tc->client);
1747 * Message was transmitted. Process the request.
1749 * @param cls the client
1750 * @param sma the send message that was sent
1753 handle_send_message_ack (void *cls,
1754 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
1756 struct TransportClient *tc = cls;
1758 if (CT_COMMUNICATOR != tc->type)
1761 GNUNET_SERVICE_client_drop (tc->client);
1764 GNUNET_SERVICE_client_continue (tc->client);
1769 * Iterator telling new MONITOR client about all existing
1772 * @param cls the new `struct TransportClient`
1773 * @param pid a connected peer
1774 * @param value the `struct Neighbour` with more information
1775 * @return #GNUNET_OK (continue to iterate)
1778 notify_client_queues (void *cls,
1779 const struct GNUNET_PeerIdentity *pid,
1782 struct TransportClient *tc = cls;
1783 struct Neighbour *neighbour = value;
1785 GNUNET_assert (CT_MONITOR == tc->type);
1786 for (struct GNUNET_ATS_Session *q = neighbour->session_head;
1788 q = q->next_neighbour)
1790 struct MonitorEvent me = {
1793 .num_msg_pending = q->num_msg_pending,
1794 .num_bytes_pending = q->num_bytes_pending
1808 * Initialize a monitor client.
1810 * @param cls the client
1811 * @param start the start message that was sent
1814 handle_monitor_start (void *cls,
1815 const struct GNUNET_TRANSPORT_MonitorStart *start)
1817 struct TransportClient *tc = cls;
1819 if (CT_NONE != tc->type)
1822 GNUNET_SERVICE_client_drop (tc->client);
1825 tc->type = CT_MONITOR;
1826 tc->details.monitor.peer = start->peer;
1827 tc->details.monitor.one_shot = ntohl (start->one_shot);
1828 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1829 ¬ify_client_queues,
1831 GNUNET_SERVICE_client_mark_monitor (tc->client);
1832 GNUNET_SERVICE_client_continue (tc->client);
1837 * Signature of a function called by ATS with the current bandwidth
1838 * allocation to be used as determined by ATS.
1840 * @param cls closure, NULL
1841 * @param session session this is about
1842 * @param bandwidth_out assigned outbound bandwidth for the connection,
1843 * 0 to signal disconnect
1844 * @param bandwidth_in assigned inbound bandwidth for the connection,
1845 * 0 to signal disconnect
1848 ats_allocation_cb (void *cls,
1849 struct GNUNET_ATS_Session *session,
1850 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
1851 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
1854 GNUNET_BANDWIDTH_tracker_update_quota (&session->tracker_out,
1856 GNUNET_BANDWIDTH_tracker_update_quota (&session->tracker_in,
1862 * Find transport client providing communication service
1863 * for the protocol @a prefix.
1865 * @param prefix communicator name
1866 * @return NULL if no such transport client is available
1868 static struct TransportClient *
1869 lookup_communicator (const char *prefix)
1871 GNUNET_break (0); // FIXME: implement
1877 * Signature of a function called by ATS suggesting transport to
1878 * try connecting with a particular address.
1880 * @param cls closure, NULL
1881 * @param pid target peer
1882 * @param address the address to try
1885 ats_suggestion_cb (void *cls,
1886 const struct GNUNET_PeerIdentity *pid,
1887 const char *address)
1889 struct TransportClient *tc;
1893 prefix = NULL; // FIXME
1894 tc = lookup_communicator (prefix);
1900 // FIXME: forward suggestion to tc
1905 * Free neighbour entry.
1909 * @param value a `struct Neighbour`
1910 * @return #GNUNET_OK (always)
1913 free_neighbour_cb (void *cls,
1914 const struct GNUNET_PeerIdentity *pid,
1917 struct Neighbour *neighbour = value;
1921 GNUNET_break (0); // should this ever happen?
1922 free_neighbour (neighbour);
1929 * Free ephemeral entry.
1933 * @param value a `struct Neighbour`
1934 * @return #GNUNET_OK (always)
1937 free_ephemeral_cb (void *cls,
1938 const struct GNUNET_PeerIdentity *pid,
1941 struct EphemeralCacheEntry *ece = value;
1945 free_ephemeral (ece);
1951 * Function called when the service shuts down. Unloads our plugins
1952 * and cancels pending validations.
1954 * @param cls closure, unused
1957 do_shutdown (void *cls)
1961 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1966 GNUNET_ATS_transport_done (ats);
1969 if (NULL != peerstore)
1971 GNUNET_PEERSTORE_disconnect (peerstore,
1975 if (NULL != GST_stats)
1977 GNUNET_STATISTICS_destroy (GST_stats,
1981 if (NULL != GST_my_private_key)
1983 GNUNET_free (GST_my_private_key);
1984 GST_my_private_key = NULL;
1986 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
1988 GNUNET_CONTAINER_multipeermap_iterate (ephemeral_map,
1991 GNUNET_CONTAINER_multipeermap_destroy (ephemeral_map);
1992 ephemeral_map = NULL;
1993 GNUNET_CONTAINER_heap_destroy (ephemeral_heap);
1994 ephemeral_heap = NULL;
1999 * Initiate transport service.
2001 * @param cls closure
2002 * @param c configuration to use
2003 * @param service the initialized service
2007 const struct GNUNET_CONFIGURATION_Handle *c,
2008 struct GNUNET_SERVICE_Handle *service)
2013 neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
2015 ephemeral_map = GNUNET_CONTAINER_multipeermap_create (32,
2017 ephemeral_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2018 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
2019 if (NULL == GST_my_private_key)
2021 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2022 _("Transport service is lacking key configuration settings. Exiting.\n"));
2023 GNUNET_SCHEDULER_shutdown ();
2026 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
2027 &GST_my_identity.public_key);
2028 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2029 "My identity is `%s'\n",
2030 GNUNET_i2s_full (&GST_my_identity));
2031 GST_stats = GNUNET_STATISTICS_create ("transport",
2033 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
2035 peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
2036 if (NULL == peerstore)
2039 GNUNET_SCHEDULER_shutdown ();
2042 ats = GNUNET_ATS_transport_init (GST_cfg,
2050 GNUNET_SCHEDULER_shutdown ();
2057 * Define "main" method using service macro.
2061 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
2064 &client_disconnect_cb,
2066 /* communication with core */
2067 GNUNET_MQ_hd_fixed_size (client_start,
2068 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
2069 struct StartMessage,
2071 GNUNET_MQ_hd_var_size (client_send,
2072 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
2073 struct OutboundMessage,
2075 /* communication with communicators */
2076 GNUNET_MQ_hd_var_size (communicator_available,
2077 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
2078 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
2080 GNUNET_MQ_hd_var_size (add_address,
2081 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
2082 struct GNUNET_TRANSPORT_AddAddressMessage,
2084 GNUNET_MQ_hd_fixed_size (del_address,
2085 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
2086 struct GNUNET_TRANSPORT_DelAddressMessage,
2088 GNUNET_MQ_hd_var_size (incoming_msg,
2089 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
2090 struct GNUNET_TRANSPORT_IncomingMessage,
2092 GNUNET_MQ_hd_var_size (add_queue_message,
2093 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
2094 struct GNUNET_TRANSPORT_AddQueueMessage,
2096 GNUNET_MQ_hd_fixed_size (del_queue_message,
2097 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
2098 struct GNUNET_TRANSPORT_DelQueueMessage,
2100 GNUNET_MQ_hd_fixed_size (send_message_ack,
2101 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
2102 struct GNUNET_TRANSPORT_SendMessageToAck,
2104 /* communication with monitors */
2105 GNUNET_MQ_hd_fixed_size (monitor_start,
2106 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
2107 struct GNUNET_TRANSPORT_MonitorStart,
2109 GNUNET_MQ_handler_end ());
2112 /* end of file gnunet-service-transport.c */