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. (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 * 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 * Handle by which we inform ATS about this queue.
338 struct GNUNET_ATS_SessionRecord *sr;
341 * Our current RTT estimate for this ATS session.
343 struct GNUNET_TIME_Relative rtt;
346 * Unique identifier of this ATS session with the communicator.
351 * Maximum transmission unit supported by this ATS session.
356 * Distance to the target of this ATS session.
361 * Network type offered by this ATS session.
363 enum GNUNET_NetworkType nt;
366 * Connection status for this ATS session.
368 enum GNUNET_TRANSPORT_ConnectionStatus cs;
373 uint32_t num_msg_pending;
378 uint32_t num_bytes_pending;
381 * How much outbound bandwidth do we have available for this session?
383 struct GNUNET_BANDWIDTH_Tracker tracker_out;
386 * How much inbound bandwidth do we have available for this session?
388 struct GNUNET_BANDWIDTH_Tracker tracker_in;
393 * A neighbour that at least one communicator is connected to.
399 * Which peer is this about?
401 struct GNUNET_PeerIdentity pid;
404 * Head of list of messages pending for this neighbour.
406 struct PendingMessage *pending_msg_head;
409 * Tail of list of messages pending for this neighbour.
411 struct PendingMessage *pending_msg_tail;
414 * Head of DLL of ATS sessions to this peer.
416 struct GNUNET_ATS_Session *session_head;
419 * Tail of DLL of ATS sessions to this peer.
421 struct GNUNET_ATS_Session *session_tail;
424 * Quota at which CORE is allowed to transmit to this peer
427 * FIXME: not yet used, tricky to get right given multiple queues!
428 * (=> Idea: let ATS set a quota per queue and we add them up here?)
429 * FIXME: how do we set this value initially when we tell CORE?
430 * Options: start at a minimum value or at literally zero (before ATS?)
431 * (=> Current thought: clean would be zero!)
433 struct GNUNET_BANDWIDTH_Value32NBO quota_out;
439 * Transmission request from CORE that is awaiting delivery.
441 struct PendingMessage
444 * Kept in a MDLL of messages for this @a target.
446 struct PendingMessage *next_neighbour;
449 * Kept in a MDLL of messages for this @a target.
451 struct PendingMessage *prev_neighbour;
454 * Kept in a MDLL of messages from this @a client.
456 struct PendingMessage *next_client;
459 * Kept in a MDLL of messages from this @a client.
461 struct PendingMessage *prev_client;
464 * Target of the request.
466 struct Neighbour *target;
469 * Client that issued the transmission request.
471 struct TransportClient *client;
474 * Size of the original message.
482 * One of the addresses of this peer.
484 struct AddressListEntry
490 struct AddressListEntry *next;
495 struct AddressListEntry *prev;
498 * Which communicator provides this address?
500 struct TransportClient *tc;
503 * The actual address.
508 * Current context for storing this address in the peerstore.
510 struct GNUNET_PEERSTORE_StoreContext *sc;
513 * Task to periodically do @e st operation.
515 struct GNUNET_SCHEDULER_Task *st;
518 * What is a typical lifetime the communicator expects this
519 * address to have? (Always from now.)
521 struct GNUNET_TIME_Relative expiration;
524 * Address identifier used by the communicator.
529 * Network type offered by this address.
531 enum GNUNET_NetworkType nt;
537 * Client connected to the transport service.
539 struct TransportClient
545 struct TransportClient *next;
550 struct TransportClient *prev;
553 * Handle to the client.
555 struct GNUNET_SERVICE_Client *client;
558 * Message queue to the client.
560 struct GNUNET_MQ_Handle *mq;
563 * What type of client is this?
565 enum ClientType type;
571 * Information for @e type #CT_CORE.
576 * Head of list of messages pending for this client.
578 struct PendingMessage *pending_msg_head;
581 * Tail of list of messages pending for this client.
583 struct PendingMessage *pending_msg_tail;
588 * Information for @e type #CT_MONITOR.
593 * Peer identity to monitor the addresses of.
594 * Zero to monitor all neighbours. Valid if
595 * @e type is #CT_MONITOR.
597 struct GNUNET_PeerIdentity peer;
600 * Is this a one-shot monitor?
608 * Information for @e type #CT_COMMUNICATOR.
612 * If @e type is #CT_COMMUNICATOR, this communicator
613 * supports communicating using these addresses.
615 char *address_prefix;
618 * Head of DLL of queues offered by this communicator.
620 struct GNUNET_ATS_Session *session_head;
623 * Tail of DLL of queues offered by this communicator.
625 struct GNUNET_ATS_Session *session_tail;
628 * Head of list of the addresses of this peer offered by this communicator.
630 struct AddressListEntry *addr_head;
633 * Tail of list of the addresses of this peer offered by this communicator.
635 struct AddressListEntry *addr_tail;
638 * Characteristics of this communicator.
640 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc;
650 * Head of linked list of all clients to this service.
652 static struct TransportClient *clients_head;
655 * Tail of linked list of all clients to this service.
657 static struct TransportClient *clients_tail;
662 static struct GNUNET_STATISTICS_Handle *GST_stats;
665 * Configuration handle.
667 static const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
672 static struct GNUNET_PeerIdentity GST_my_identity;
677 static struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
680 * Map from PIDs to `struct Neighbour` entries. A peer is
681 * a neighbour if we have an MQ to it from some communicator.
683 static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
686 * Database for peer's HELLOs.
688 static struct GNUNET_PEERSTORE_Handle *peerstore;
691 * Heap sorting `struct EphemeralCacheEntry` by their
692 * key/signature validity.
694 static struct GNUNET_CONTAINER_Heap *ephemeral_heap;
697 * Hash map for looking up `struct EphemeralCacheEntry`s
698 * by peer identity. (We may have ephemerals in our
699 * cache for which we do not have a neighbour entry,
700 * and similar many neighbours may not need ephemerals,
701 * so we use a second map.)
703 static struct GNUNET_CONTAINER_MultiPeerMap *ephemeral_map;
706 * Our connection to ATS for allocation and bootstrapping.
708 static struct GNUNET_ATS_TransportHandle *ats;
712 * Free cached ephemeral key.
714 * @param ece cached signature to free
717 free_ephemeral (struct EphemeralCacheEntry *ece)
719 GNUNET_CONTAINER_multipeermap_remove (ephemeral_map,
722 GNUNET_CONTAINER_heap_remove_node (ece->hn);
728 * Lookup neighbour record for peer @a pid.
730 * @param pid neighbour to look for
731 * @return NULL if we do not have this peer as a neighbour
733 static struct Neighbour *
734 lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
736 return GNUNET_CONTAINER_multipeermap_get (neighbours,
742 * Details about what to notify monitors about.
747 * @deprecated To be discussed if we keep these...
749 struct GNUNET_TIME_Absolute last_validation;
750 struct GNUNET_TIME_Absolute valid_until;
751 struct GNUNET_TIME_Absolute next_validation;
754 * Current round-trip time estimate.
756 struct GNUNET_TIME_Relative rtt;
761 enum GNUNET_TRANSPORT_ConnectionStatus cs;
766 uint32_t num_msg_pending;
771 uint32_t num_bytes_pending;
778 * Notify monitor @a tc about an event. That @a tc
779 * cares about the event has already been checked.
781 * Send @a tc information in @a me about a @a peer's status with
782 * respect to some @a address to all monitors that care.
784 * @param tc monitor to inform
785 * @param peer peer the information is about
786 * @param address address the information is about
787 * @param nt network type associated with @a address
788 * @param me detailed information to transmit
791 notify_monitor (struct TransportClient *tc,
792 const struct GNUNET_PeerIdentity *peer,
794 enum GNUNET_NetworkType nt,
795 const struct MonitorEvent *me)
797 struct GNUNET_MQ_Envelope *env;
798 struct GNUNET_TRANSPORT_MonitorData *md;
799 size_t addr_len = strlen (address) + 1;
801 env = GNUNET_MQ_msg_extra (md,
803 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA);
804 md->nt = htonl ((uint32_t) nt);
806 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
807 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
808 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
809 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
810 md->cs = htonl ((uint32_t) me->cs);
811 md->num_msg_pending = htonl (me->num_msg_pending);
812 md->num_bytes_pending = htonl (me->num_bytes_pending);
816 GNUNET_MQ_send (tc->mq,
822 * Send information in @a me about a @a peer's status with respect
823 * to some @a address to all monitors that care.
825 * @param peer peer the information is about
826 * @param address address the information is about
827 * @param nt network type associated with @a address
828 * @param me detailed information to transmit
831 notify_monitors (const struct GNUNET_PeerIdentity *peer,
833 enum GNUNET_NetworkType nt,
834 const struct MonitorEvent *me)
836 static struct GNUNET_PeerIdentity zero;
838 for (struct TransportClient *tc = clients_head;
842 if (CT_MONITOR != tc->type)
844 if (tc->details.monitor.one_shot)
846 if ( (0 != memcmp (&tc->details.monitor.peer,
849 (0 != memcmp (&tc->details.monitor.peer,
863 * Called whenever a client connects. Allocates our
864 * data structures associated with that client.
866 * @param cls closure, NULL
867 * @param client identification of the client
868 * @param mq message queue for the client
869 * @return our `struct TransportClient`
872 client_connect_cb (void *cls,
873 struct GNUNET_SERVICE_Client *client,
874 struct GNUNET_MQ_Handle *mq)
876 struct TransportClient *tc;
878 tc = GNUNET_new (struct TransportClient);
881 GNUNET_CONTAINER_DLL_insert (clients_head,
884 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
885 "Client %p connected\n",
892 * Release memory used by @a neighbour.
894 * @param neighbour neighbour entry to free
897 free_neighbour (struct Neighbour *neighbour)
899 GNUNET_assert (NULL == neighbour->session_head);
900 GNUNET_assert (GNUNET_YES ==
901 GNUNET_CONTAINER_multipeermap_remove (neighbours,
904 GNUNET_free (neighbour);
909 * Send message to CORE clients that we lost a connection.
911 * @param tc client to inform (must be CORE client)
912 * @param pid peer the connection is for
913 * @param quota_out current quota for the peer
916 core_send_connect_info (struct TransportClient *tc,
917 const struct GNUNET_PeerIdentity *pid,
918 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
920 struct GNUNET_MQ_Envelope *env;
921 struct ConnectInfoMessage *cim;
923 GNUNET_assert (CT_CORE == tc->type);
924 env = GNUNET_MQ_msg (cim,
925 GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
926 cim->quota_out = quota_out;
928 GNUNET_MQ_send (tc->mq,
934 * Send message to CORE clients that we gained a connection
936 * @param pid peer the queue was for
937 * @param quota_out current quota for the peer
940 cores_send_connect_info (const struct GNUNET_PeerIdentity *pid,
941 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
943 for (struct TransportClient *tc = clients_head;
947 if (CT_CORE != tc->type)
949 core_send_connect_info (tc,
957 * Send message to CORE clients that we lost a connection.
959 * @param pid peer the connection was for
962 cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
964 for (struct TransportClient *tc = clients_head;
968 struct GNUNET_MQ_Envelope *env;
969 struct DisconnectInfoMessage *dim;
971 if (CT_CORE != tc->type)
973 env = GNUNET_MQ_msg (dim,
974 GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
976 GNUNET_MQ_send (tc->mq,
985 * @param queue the queue to free
988 free_queue (struct GNUNET_ATS_Session *queue)
990 struct Neighbour *neighbour = queue->neighbour;
991 struct TransportClient *tc = queue->tc;
992 struct MonitorEvent me = {
993 .cs = GNUNET_TRANSPORT_CS_DOWN,
994 .rtt = GNUNET_TIME_UNIT_FOREVER_REL
997 GNUNET_CONTAINER_MDLL_remove (neighbour,
998 neighbour->session_head,
999 neighbour->session_tail,
1001 GNUNET_CONTAINER_MDLL_remove (client,
1002 tc->details.communicator.session_head,
1003 tc->details.communicator.session_tail,
1005 notify_monitors (&neighbour->pid,
1009 GNUNET_ATS_session_del (queue->sr);
1010 GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_in);
1011 GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_out);
1012 GNUNET_free (queue);
1013 if (NULL == neighbour->session_head)
1015 cores_send_disconnect_info (&neighbour->pid);
1016 free_neighbour (neighbour);
1024 * @param ale address list entry to free
1027 free_address_list_entry (struct AddressListEntry *ale)
1029 struct TransportClient *tc = ale->tc;
1031 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
1032 tc->details.communicator.addr_tail,
1034 if (NULL != ale->sc)
1036 GNUNET_PEERSTORE_store_cancel (ale->sc);
1039 if (NULL != ale->st)
1041 GNUNET_SCHEDULER_cancel (ale->st);
1049 * Called whenever a client is disconnected. Frees our
1050 * resources associated with that client.
1052 * @param cls closure, NULL
1053 * @param client identification of the client
1054 * @param app_ctx our `struct TransportClient`
1057 client_disconnect_cb (void *cls,
1058 struct GNUNET_SERVICE_Client *client,
1061 struct TransportClient *tc = app_ctx;
1063 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1064 "Client %p disconnected, cleaning up.\n",
1066 GNUNET_CONTAINER_DLL_remove (clients_head,
1075 struct PendingMessage *pm;
1077 while (NULL != (pm = tc->details.core.pending_msg_head))
1079 GNUNET_CONTAINER_MDLL_remove (client,
1080 tc->details.core.pending_msg_head,
1081 tc->details.core.pending_msg_tail,
1089 case CT_COMMUNICATOR:
1091 struct GNUNET_ATS_Session *q;
1092 struct AddressListEntry *ale;
1094 while (NULL != (q = tc->details.communicator.session_head))
1096 while (NULL != (ale = tc->details.communicator.addr_head))
1097 free_address_list_entry (ale);
1098 GNUNET_free (tc->details.communicator.address_prefix);
1107 * Iterator telling new CORE client about all existing
1108 * connections to peers.
1110 * @param cls the new `struct TransportClient`
1111 * @param pid a connected peer
1112 * @param value the `struct Neighbour` with more information
1113 * @return #GNUNET_OK (continue to iterate)
1116 notify_client_connect_info (void *cls,
1117 const struct GNUNET_PeerIdentity *pid,
1120 struct TransportClient *tc = cls;
1121 struct Neighbour *neighbour = value;
1123 core_send_connect_info (tc,
1125 neighbour->quota_out);
1131 * Initialize a "CORE" client. We got a start message from this
1132 * client, so add it to the list of clients for broadcasting of
1135 * @param cls the client
1136 * @param start the start message that was sent
1139 handle_client_start (void *cls,
1140 const struct StartMessage *start)
1142 struct TransportClient *tc = cls;
1145 options = ntohl (start->options);
1146 if ( (0 != (1 & options)) &&
1148 memcmp (&start->self,
1150 sizeof (struct GNUNET_PeerIdentity)) ) )
1152 /* client thinks this is a different peer, reject */
1154 GNUNET_SERVICE_client_drop (tc->client);
1157 if (CT_NONE != tc->type)
1160 GNUNET_SERVICE_client_drop (tc->client);
1164 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1165 ¬ify_client_connect_info,
1167 GNUNET_SERVICE_client_continue (tc->client);
1172 * Client asked for transmission to a peer. Process the request.
1174 * @param cls the client
1175 * @param obm the send message that was sent
1178 check_client_send (void *cls,
1179 const struct OutboundMessage *obm)
1181 struct TransportClient *tc = cls;
1183 const struct GNUNET_MessageHeader *obmm;
1185 if (CT_CORE != tc->type)
1188 return GNUNET_SYSERR;
1190 size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
1191 if (size < sizeof (struct GNUNET_MessageHeader))
1194 return GNUNET_SYSERR;
1196 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
1197 if (size != ntohs (obmm->size))
1200 return GNUNET_SYSERR;
1207 * Send a response to the @a pm that we have processed a
1208 * "send" request with status @a success. We
1209 * transmitted @a bytes_physical on the actual wire.
1210 * Sends a confirmation to the "core" client responsible
1211 * for the original request and free's @a pm.
1213 * @param pm handle to the original pending message
1214 * @param success status code, #GNUNET_OK on success, #GNUNET_SYSERR
1215 * for transmission failure
1216 * @param bytes_physical amount of bandwidth consumed
1219 client_send_response (struct PendingMessage *pm,
1221 uint32_t bytes_physical)
1223 struct TransportClient *tc = pm->client;
1224 struct Neighbour *target = pm->target;
1225 struct GNUNET_MQ_Envelope *env;
1226 struct SendOkMessage *som;
1230 env = GNUNET_MQ_msg (som,
1231 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1232 som->success = htonl ((uint32_t) success);
1233 som->bytes_msg = htonl (pm->bytes_msg);
1234 som->bytes_physical = htonl (bytes_physical);
1235 som->peer = target->pid;
1236 GNUNET_MQ_send (tc->mq,
1238 GNUNET_CONTAINER_MDLL_remove (client,
1239 tc->details.core.pending_msg_head,
1240 tc->details.core.pending_msg_tail,
1243 GNUNET_CONTAINER_MDLL_remove (neighbour,
1244 target->pending_msg_head,
1245 target->pending_msg_tail,
1252 * Client asked for transmission to a peer. Process the request.
1254 * @param cls the client
1255 * @param obm the send message that was sent
1258 handle_client_send (void *cls,
1259 const struct OutboundMessage *obm)
1261 struct TransportClient *tc = cls;
1262 struct PendingMessage *pm;
1263 const struct GNUNET_MessageHeader *obmm;
1264 struct Neighbour *target;
1267 GNUNET_assert (CT_CORE == tc->type);
1268 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
1269 bytes_msg = ntohs (obmm->size);
1270 target = lookup_neighbour (&obm->peer);
1273 /* Failure: don't have this peer as a neighbour (anymore).
1274 Might have gone down asynchronously, so this is NOT
1275 a protocol violation by CORE. Still count the event,
1276 as this should be rare. */
1277 struct GNUNET_MQ_Envelope *env;
1278 struct SendOkMessage *som;
1280 env = GNUNET_MQ_msg (som,
1281 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1282 som->success = htonl (GNUNET_SYSERR);
1283 som->bytes_msg = htonl (bytes_msg);
1284 som->bytes_physical = htonl (0);
1285 som->peer = obm->peer;
1286 GNUNET_MQ_send (tc->mq,
1288 GNUNET_SERVICE_client_continue (tc->client);
1289 GNUNET_STATISTICS_update (GST_stats,
1290 "# messages dropped (neighbour unknown)",
1295 pm = GNUNET_new (struct PendingMessage);
1297 pm->target = target;
1298 pm->bytes_msg = bytes_msg;
1299 GNUNET_CONTAINER_MDLL_insert (neighbour,
1300 target->pending_msg_head,
1301 target->pending_msg_tail,
1303 GNUNET_CONTAINER_MDLL_insert (client,
1304 tc->details.core.pending_msg_head,
1305 tc->details.core.pending_msg_tail,
1307 // FIXME: do the work, final continuation with call to:
1308 client_send_response (pm,
1315 * Communicator started. Test message is well-formed.
1317 * @param cls the client
1318 * @param cam the send message that was sent
1321 check_communicator_available (void *cls,
1322 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1324 struct TransportClient *tc = cls;
1327 if (CT_NONE != tc->type)
1330 return GNUNET_SYSERR;
1332 tc->type = CT_COMMUNICATOR;
1333 size = ntohs (cam->header.size) - sizeof (*cam);
1335 return GNUNET_OK; /* receive-only communicator */
1336 GNUNET_MQ_check_zero_termination (cam);
1342 * Communicator started. Process the request.
1344 * @param cls the client
1345 * @param cam the send message that was sent
1348 handle_communicator_available (void *cls,
1349 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1351 struct TransportClient *tc = cls;
1354 size = ntohs (cam->header.size) - sizeof (*cam);
1356 return; /* receive-only communicator */
1357 tc->details.communicator.address_prefix
1358 = GNUNET_strdup ((const char *) &cam[1]);
1359 tc->details.communicator.cc
1360 = (enum GNUNET_TRANSPORT_CommunicatorCharacteristics) ntohl (cam->cc);
1361 GNUNET_SERVICE_client_continue (tc->client);
1366 * Address of our peer added. Test message is well-formed.
1368 * @param cls the client
1369 * @param aam the send message that was sent
1372 check_add_address (void *cls,
1373 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1375 struct TransportClient *tc = cls;
1377 if (CT_COMMUNICATOR != tc->type)
1380 return GNUNET_SYSERR;
1382 GNUNET_MQ_check_zero_termination (aam);
1388 * Ask peerstore to store our address.
1390 * @param cls an `struct AddressListEntry *`
1393 store_pi (void *cls);
1397 * Function called when peerstore is done storing our address.
1400 peerstore_store_cb (void *cls,
1403 struct AddressListEntry *ale = cls;
1406 if (GNUNET_YES != success)
1407 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1408 "Failed to store our own address `%s' in peerstore!\n",
1410 /* refresh period is 1/4 of expiration time, that should be plenty
1411 without being excessive. */
1412 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
1420 * Ask peerstore to store our address.
1422 * @param cls an `struct AddressListEntry *`
1425 store_pi (void *cls)
1427 struct AddressListEntry *ale = cls;
1430 struct GNUNET_TIME_Absolute expiration;
1433 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
1434 GNUNET_HELLO_sign_address (ale->address,
1440 ale->sc = GNUNET_PEERSTORE_store (peerstore,
1443 GNUNET_HELLO_PEERSTORE_KEY,
1447 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
1448 &peerstore_store_cb,
1451 if (NULL == ale->sc)
1453 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1454 "Failed to store our address `%s' with peerstore\n",
1456 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
1464 * Address of our peer added. Process the request.
1466 * @param cls the client
1467 * @param aam the send message that was sent
1470 handle_add_address (void *cls,
1471 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1473 struct TransportClient *tc = cls;
1474 struct AddressListEntry *ale;
1477 slen = ntohs (aam->header.size) - sizeof (*aam);
1478 ale = GNUNET_malloc (sizeof (struct AddressListEntry) + slen);
1480 ale->address = (const char *) &ale[1];
1481 ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
1482 ale->aid = aam->aid;
1483 ale->nt = (enum GNUNET_NetworkType) ntohl (aam->nt);
1487 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
1488 tc->details.communicator.addr_tail,
1490 ale->st = GNUNET_SCHEDULER_add_now (&store_pi,
1492 GNUNET_SERVICE_client_continue (tc->client);
1497 * Address of our peer deleted. Process the request.
1499 * @param cls the client
1500 * @param dam the send message that was sent
1503 handle_del_address (void *cls,
1504 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
1506 struct TransportClient *tc = cls;
1508 if (CT_COMMUNICATOR != tc->type)
1511 GNUNET_SERVICE_client_drop (tc->client);
1514 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
1518 if (dam->aid != ale->aid)
1520 GNUNET_assert (ale->tc == tc);
1521 free_address_list_entry (ale);
1522 GNUNET_SERVICE_client_continue (tc->client);
1525 GNUNET_SERVICE_client_drop (tc->client);
1530 * Client notified us about transmission from a peer. Process the request.
1532 * @param cls the client
1533 * @param obm the send message that was sent
1536 check_incoming_msg (void *cls,
1537 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1539 struct TransportClient *tc = cls;
1541 const struct GNUNET_MessageHeader *obmm;
1543 if (CT_COMMUNICATOR != tc->type)
1546 return GNUNET_SYSERR;
1548 size = ntohs (im->header.size) - sizeof (*im);
1549 if (size < sizeof (struct GNUNET_MessageHeader))
1552 return GNUNET_SYSERR;
1554 obmm = (const struct GNUNET_MessageHeader *) &im[1];
1555 if (size != ntohs (obmm->size))
1558 return GNUNET_SYSERR;
1565 * Incoming meessage. Process the request.
1567 * @param cls the client
1568 * @param im the send message that was received
1571 handle_incoming_msg (void *cls,
1572 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1574 struct TransportClient *tc = cls;
1576 GNUNET_SERVICE_client_continue (tc->client);
1581 * New queue became available. Check message.
1583 * @param cls the client
1584 * @param aqm the send message that was sent
1587 check_add_queue_message (void *cls,
1588 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1590 struct TransportClient *tc = cls;
1592 if (CT_COMMUNICATOR != tc->type)
1595 return GNUNET_SYSERR;
1597 GNUNET_MQ_check_zero_termination (aqm);
1603 * Bandwidth tracker informs us that the delay until we
1604 * can transmit again changed.
1606 * @param cls a `struct GNUNET_ATS_Session` for which the delay changed
1609 tracker_update_cb (void *cls)
1611 struct GNUNET_ATS_Session *queue = cls;
1613 // FIXME: re-schedule transmission tasks if applicable!
1618 * Bandwidth tracker informs us that excessive bandwidth was allocated
1619 * which is not being used.
1621 * @param cls a `struct GNUNET_ATS_Session` for which the excess was noted
1624 tracker_excess_cb (void *cls)
1626 /* FIXME: what do we do? */
1631 * New queue became available. Process the request.
1633 * @param cls the client
1634 * @param aqm the send message that was sent
1637 handle_add_queue_message (void *cls,
1638 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1640 struct TransportClient *tc = cls;
1641 struct GNUNET_ATS_Session *queue;
1642 struct Neighbour *neighbour;
1646 neighbour = lookup_neighbour (&aqm->receiver);
1647 if (NULL == neighbour)
1649 neighbour = GNUNET_new (struct Neighbour);
1650 neighbour->pid = aqm->receiver;
1651 GNUNET_assert (GNUNET_OK ==
1652 GNUNET_CONTAINER_multipeermap_put (neighbours,
1655 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1656 cores_send_connect_info (&neighbour->pid,
1657 GNUNET_BANDWIDTH_ZERO);
1659 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
1660 addr = (const char *) &aqm[1];
1662 queue = GNUNET_malloc (sizeof (struct GNUNET_ATS_Session) + addr_len);
1664 queue->address = (const char *) &queue[1];
1665 queue->rtt = GNUNET_TIME_UNIT_FOREVER_REL;
1666 queue->qid = aqm->qid;
1667 queue->mtu = ntohl (aqm->mtu);
1668 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
1669 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
1670 queue->neighbour = neighbour;
1671 GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_in,
1674 GNUNET_BANDWIDTH_ZERO,
1675 0 /* FIXME: max carry in seconds! */,
1678 GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_out,
1681 GNUNET_BANDWIDTH_ZERO,
1682 0 /* FIXME: max carry in seconds! */,
1688 /* notify ATS about new queue */
1690 struct GNUNET_ATS_Properties prop = {
1691 .delay = GNUNET_TIME_UNIT_FOREVER_REL,
1694 .cc = tc->details.communicator.cc
1697 queue->sr = GNUNET_ATS_session_add (ats,
1702 if (NULL == queue->sr)
1704 /* This can only happen if the 'address' was way too long for ATS
1705 (approaching 64k in strlen()!). In this case, the communicator
1706 must be buggy and we drop it. */
1708 GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_in);
1709 GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_out);
1710 GNUNET_free (queue);
1711 if (NULL == neighbour->session_head)
1713 cores_send_disconnect_info (&neighbour->pid);
1714 free_neighbour (neighbour);
1716 GNUNET_SERVICE_client_drop (tc->client);
1720 /* notify monitors about new queue */
1722 struct MonitorEvent me = {
1727 notify_monitors (&neighbour->pid,
1732 GNUNET_CONTAINER_MDLL_insert (neighbour,
1733 neighbour->session_head,
1734 neighbour->session_tail,
1736 GNUNET_CONTAINER_MDLL_insert (client,
1737 tc->details.communicator.session_head,
1738 tc->details.communicator.session_tail,
1740 GNUNET_SERVICE_client_continue (tc->client);
1745 * Queue to a peer went down. Process the request.
1747 * @param cls the client
1748 * @param dqm the send message that was sent
1751 handle_del_queue_message (void *cls,
1752 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
1754 struct TransportClient *tc = cls;
1756 if (CT_COMMUNICATOR != tc->type)
1759 GNUNET_SERVICE_client_drop (tc->client);
1762 for (struct GNUNET_ATS_Session *queue = tc->details.communicator.session_head;
1764 queue = queue->next_client)
1766 struct Neighbour *neighbour = queue->neighbour;
1768 if ( (dqm->qid != queue->qid) ||
1769 (0 != memcmp (&dqm->receiver,
1771 sizeof (struct GNUNET_PeerIdentity))) )
1774 GNUNET_SERVICE_client_continue (tc->client);
1778 GNUNET_SERVICE_client_drop (tc->client);
1783 * Message was transmitted. Process the request.
1785 * @param cls the client
1786 * @param sma the send message that was sent
1789 handle_send_message_ack (void *cls,
1790 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
1792 struct TransportClient *tc = cls;
1794 if (CT_COMMUNICATOR != tc->type)
1797 GNUNET_SERVICE_client_drop (tc->client);
1800 // FIXME: react to communicator status about transmission request. We got:
1801 sma->status; // OK success, SYSERR failure
1802 sma->mid; // message ID of original message
1803 sma->receiver; // receiver of original message
1806 GNUNET_SERVICE_client_continue (tc->client);
1811 * Iterator telling new MONITOR client about all existing
1814 * @param cls the new `struct TransportClient`
1815 * @param pid a connected peer
1816 * @param value the `struct Neighbour` with more information
1817 * @return #GNUNET_OK (continue to iterate)
1820 notify_client_queues (void *cls,
1821 const struct GNUNET_PeerIdentity *pid,
1824 struct TransportClient *tc = cls;
1825 struct Neighbour *neighbour = value;
1827 GNUNET_assert (CT_MONITOR == tc->type);
1828 for (struct GNUNET_ATS_Session *q = neighbour->session_head;
1830 q = q->next_neighbour)
1832 struct MonitorEvent me = {
1835 .num_msg_pending = q->num_msg_pending,
1836 .num_bytes_pending = q->num_bytes_pending
1850 * Initialize a monitor client.
1852 * @param cls the client
1853 * @param start the start message that was sent
1856 handle_monitor_start (void *cls,
1857 const struct GNUNET_TRANSPORT_MonitorStart *start)
1859 struct TransportClient *tc = cls;
1861 if (CT_NONE != tc->type)
1864 GNUNET_SERVICE_client_drop (tc->client);
1867 tc->type = CT_MONITOR;
1868 tc->details.monitor.peer = start->peer;
1869 tc->details.monitor.one_shot = ntohl (start->one_shot);
1870 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1871 ¬ify_client_queues,
1873 GNUNET_SERVICE_client_mark_monitor (tc->client);
1874 GNUNET_SERVICE_client_continue (tc->client);
1879 * Signature of a function called by ATS with the current bandwidth
1880 * allocation to be used as determined by ATS.
1882 * @param cls closure, NULL
1883 * @param session session this is about
1884 * @param bandwidth_out assigned outbound bandwidth for the connection,
1885 * 0 to signal disconnect
1886 * @param bandwidth_in assigned inbound bandwidth for the connection,
1887 * 0 to signal disconnect
1890 ats_allocation_cb (void *cls,
1891 struct GNUNET_ATS_Session *session,
1892 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
1893 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
1896 GNUNET_BANDWIDTH_tracker_update_quota (&session->tracker_out,
1898 GNUNET_BANDWIDTH_tracker_update_quota (&session->tracker_in,
1904 * Find transport client providing communication service
1905 * for the protocol @a prefix.
1907 * @param prefix communicator name
1908 * @return NULL if no such transport client is available
1910 static struct TransportClient *
1911 lookup_communicator (const char *prefix)
1913 for (struct TransportClient *tc = clients_head;
1917 if (CT_COMMUNICATOR != tc->type)
1919 if (0 == strcmp (prefix,
1920 tc->details.communicator.address_prefix))
1923 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1924 "ATS suggested use of communicator for `%s', but we do not have such a communicator!\n",
1931 * Signature of a function called by ATS suggesting transport to
1932 * try connecting with a particular address.
1934 * @param cls closure, NULL
1935 * @param pid target peer
1936 * @param address the address to try
1939 ats_suggestion_cb (void *cls,
1940 const struct GNUNET_PeerIdentity *pid,
1941 const char *address)
1943 struct TransportClient *tc;
1947 prefix = GNUNET_HELLO_address_to_prefix (address);
1950 GNUNET_break (0); /* ATS gave invalid address!? */
1953 tc = lookup_communicator (prefix);
1956 GNUNET_STATISTICS_update (GST_stats,
1957 "# ATS suggestions ignored due to missing communicator",
1963 // FIXME: forward suggestion to tc
1968 * Free neighbour entry.
1972 * @param value a `struct Neighbour`
1973 * @return #GNUNET_OK (always)
1976 free_neighbour_cb (void *cls,
1977 const struct GNUNET_PeerIdentity *pid,
1980 struct Neighbour *neighbour = value;
1984 GNUNET_break (0); // should this ever happen?
1985 free_neighbour (neighbour);
1992 * Free ephemeral entry.
1996 * @param value a `struct Neighbour`
1997 * @return #GNUNET_OK (always)
2000 free_ephemeral_cb (void *cls,
2001 const struct GNUNET_PeerIdentity *pid,
2004 struct EphemeralCacheEntry *ece = value;
2008 free_ephemeral (ece);
2014 * Function called when the service shuts down. Unloads our plugins
2015 * and cancels pending validations.
2017 * @param cls closure, unused
2020 do_shutdown (void *cls)
2024 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
2029 GNUNET_ATS_transport_done (ats);
2032 if (NULL != peerstore)
2034 GNUNET_PEERSTORE_disconnect (peerstore,
2038 if (NULL != GST_stats)
2040 GNUNET_STATISTICS_destroy (GST_stats,
2044 if (NULL != GST_my_private_key)
2046 GNUNET_free (GST_my_private_key);
2047 GST_my_private_key = NULL;
2049 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
2051 GNUNET_CONTAINER_multipeermap_iterate (ephemeral_map,
2054 GNUNET_CONTAINER_multipeermap_destroy (ephemeral_map);
2055 ephemeral_map = NULL;
2056 GNUNET_CONTAINER_heap_destroy (ephemeral_heap);
2057 ephemeral_heap = NULL;
2062 * Initiate transport service.
2064 * @param cls closure
2065 * @param c configuration to use
2066 * @param service the initialized service
2070 const struct GNUNET_CONFIGURATION_Handle *c,
2071 struct GNUNET_SERVICE_Handle *service)
2076 neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
2078 ephemeral_map = GNUNET_CONTAINER_multipeermap_create (32,
2080 ephemeral_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2081 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
2082 if (NULL == GST_my_private_key)
2084 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2085 _("Transport service is lacking key configuration settings. Exiting.\n"));
2086 GNUNET_SCHEDULER_shutdown ();
2089 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
2090 &GST_my_identity.public_key);
2091 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2092 "My identity is `%s'\n",
2093 GNUNET_i2s_full (&GST_my_identity));
2094 GST_stats = GNUNET_STATISTICS_create ("transport",
2096 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
2098 peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
2099 if (NULL == peerstore)
2102 GNUNET_SCHEDULER_shutdown ();
2105 ats = GNUNET_ATS_transport_init (GST_cfg,
2113 GNUNET_SCHEDULER_shutdown ();
2120 * Define "main" method using service macro.
2124 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
2127 &client_disconnect_cb,
2129 /* communication with core */
2130 GNUNET_MQ_hd_fixed_size (client_start,
2131 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
2132 struct StartMessage,
2134 GNUNET_MQ_hd_var_size (client_send,
2135 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
2136 struct OutboundMessage,
2138 /* communication with communicators */
2139 GNUNET_MQ_hd_var_size (communicator_available,
2140 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
2141 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
2143 GNUNET_MQ_hd_var_size (add_address,
2144 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
2145 struct GNUNET_TRANSPORT_AddAddressMessage,
2147 GNUNET_MQ_hd_fixed_size (del_address,
2148 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
2149 struct GNUNET_TRANSPORT_DelAddressMessage,
2151 GNUNET_MQ_hd_var_size (incoming_msg,
2152 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
2153 struct GNUNET_TRANSPORT_IncomingMessage,
2155 GNUNET_MQ_hd_var_size (add_queue_message,
2156 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
2157 struct GNUNET_TRANSPORT_AddQueueMessage,
2159 GNUNET_MQ_hd_fixed_size (del_queue_message,
2160 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
2161 struct GNUNET_TRANSPORT_DelQueueMessage,
2163 GNUNET_MQ_hd_fixed_size (send_message_ack,
2164 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
2165 struct GNUNET_TRANSPORT_SendMessageToAck,
2167 /* communication with monitors */
2168 GNUNET_MQ_hd_fixed_size (monitor_start,
2169 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
2170 struct GNUNET_TRANSPORT_MonitorStart,
2172 GNUNET_MQ_handler_end ());
2175 /* end of file gnunet-service-transport.c */