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-transport.c
20 * @brief main for gnunet-service-transport
21 * @author Christian Grothoff
25 * - figure out how to transmit (selective) ACKs in case of uni-directional
26 * communicators (with/without core? DV-only?) When do we use ACKs?
27 * How/where do we distinguish between TCP/HTTP and unreliable communicators?
28 * => Should communicator provide reliable/unreliable ("flags") information?
29 * - manage fragmentation/defragmentation, retransmission, track RTT, loss, etc.
30 * - inform ATS about RTT, goodput/loss, overheads, etc.
31 * - ask ATS about bandwidth allocation!
32 * - change transport-core API to provide proper flow control in both
33 * directions, allow multiple messages per peer simultaneously (tag
34 * confirmations with unique message ID), and replace quota-out with
35 * proper flow control;
38 #include "gnunet_util_lib.h"
39 #include "gnunet_statistics_service.h"
40 #include "gnunet_transport_service.h"
41 #include "gnunet_transport_monitor_service.h"
42 #include "gnunet_peerstore_service.h"
43 #include "gnunet_ats_service.h"
44 #include "gnunet-service-transport.h"
45 #include "transport.h"
49 * How many messages can we have pending for a given client process
50 * before we start to drop incoming messages? We typically should
51 * have only one client and so this would be the primary buffer for
52 * messages, so the number should be chosen rather generously.
54 * The expectation here is that most of the time the queue is large
55 * enough so that a drop is virtually never required. Note that
56 * this value must be about as large as 'TOTAL_MSGS' in the
57 * 'test_transport_api_reliability.c', otherwise that testcase may
60 #define MAX_PENDING (128 * 1024)
64 * What type of client is the `struct TransportClient` about?
69 * We do not know yet (client is fresh).
74 * Is the CORE service, we need to forward traffic to it.
79 * It is a monitor, forward monitor data.
84 * It is a communicator, use for communication.
91 * Client connected to the transport service.
93 struct TransportClient;
97 * A neighbour that at least one communicator is connected to.
103 * List of available queues for a particular neighbour.
110 struct Queue *next_neighbour;
115 struct Queue *prev_neighbour;
120 struct Queue *prev_client;
125 struct Queue *next_client;
128 * Which neighbour is this queue for?
130 struct Neighbour *neighbour;
133 * Which communicator offers this queue?
135 struct TransportClient *tc;
138 * Address served by the queue.
143 * Our current RTT estimate for this queue.
145 struct GNUNET_TIME_Relative rtt;
148 * Unique identifier of this queue with the communicator.
153 * Maximum transmission unit supported by this queue.
158 * Network type offered by this queue.
160 enum GNUNET_ATS_Network_Type nt;
163 * Connection status for this queue.
165 enum GNUNET_TRANSPORT_ConnectionStatus cs;
170 uint32_t num_msg_pending;
175 uint32_t num_bytes_pending;
177 // FIXME: add ATS-specific fields here!
182 * A neighbour that at least one communicator is connected to.
188 * Which peer is this about?
190 struct GNUNET_PeerIdentity pid;
193 * Head of list of messages pending for this neighbour.
195 struct PendingMessage *pending_msg_head;
198 * Tail of list of messages pending for this neighbour.
200 struct PendingMessage *pending_msg_tail;
203 * Head of DLL of queues to this peer.
205 struct Queue *queue_head;
208 * Tail of DLL of queues to this peer.
210 struct Queue *queue_tail;
213 * Quota at which CORE is allowed to transmit to this peer
216 * FIXME: not yet used, tricky to get right given multiple queues!
217 * (=> Idea: let ATS set a quota per queue and we add them up here?)
218 * FIXME: how do we set this value initially when we tell CORE?
219 * Options: start at a minimum value or at literally zero (before ATS?)
220 * (=> Current thought: clean would be zero!)
222 struct GNUNET_BANDWIDTH_Value32NBO quota_out;
228 * Transmission request from CORE that is awaiting delivery.
230 struct PendingMessage
233 * Kept in a MDLL of messages for this @a target.
235 struct PendingMessage *next_neighbour;
238 * Kept in a MDLL of messages for this @a target.
240 struct PendingMessage *prev_neighbour;
243 * Kept in a MDLL of messages from this @a client.
245 struct PendingMessage *next_client;
248 * Kept in a MDLL of messages from this @a client.
250 struct PendingMessage *prev_client;
253 * Target of the request.
255 struct Neighbour *target;
258 * Client that issued the transmission request.
260 struct TransportClient *client;
263 * Size of the original message.
271 * One of the addresses of this peer.
273 struct AddressListEntry
279 struct AddressListEntry *next;
284 struct AddressListEntry *prev;
287 * Which communicator provides this address?
289 struct TransportClient *tc;
292 * The actual address.
297 * Current context for storing this address in the peerstore.
299 struct GNUNET_PEERSTORE_StoreContext *sc;
302 * Task to periodically do @e st operation.
304 struct GNUNET_SCHEDULER_Task *st;
307 * What is a typical lifetime the communicator expects this
308 * address to have? (Always from now.)
310 struct GNUNET_TIME_Relative expiration;
313 * Address identifier used by the communicator.
318 * Network type offered by this address.
320 enum GNUNET_ATS_Network_Type nt;
326 * Client connected to the transport service.
328 struct TransportClient
334 struct TransportClient *next;
339 struct TransportClient *prev;
342 * Handle to the client.
344 struct GNUNET_SERVICE_Client *client;
347 * Message queue to the client.
349 struct GNUNET_MQ_Handle *mq;
352 * What type of client is this?
354 enum ClientType type;
360 * Information for @e type #CT_CORE.
365 * Head of list of messages pending for this client.
367 struct PendingMessage *pending_msg_head;
370 * Tail of list of messages pending for this client.
372 struct PendingMessage *pending_msg_tail;
377 * Information for @e type #CT_MONITOR.
382 * Peer identity to monitor the addresses of.
383 * Zero to monitor all neighbours. Valid if
384 * @e type is #CT_MONITOR.
386 struct GNUNET_PeerIdentity peer;
389 * Is this a one-shot monitor?
397 * Information for @e type #CT_COMMUNICATOR.
401 * If @e type is #CT_COMMUNICATOR, this communicator
402 * supports communicating using these addresses.
404 char *address_prefix;
407 * Head of DLL of queues offered by this communicator.
409 struct Queue *queue_head;
412 * Tail of DLL of queues offered by this communicator.
414 struct Queue *queue_tail;
417 * Head of list of the addresses of this peer offered by this communicator.
419 struct AddressListEntry *addr_head;
422 * Tail of list of the addresses of this peer offered by this communicator.
424 struct AddressListEntry *addr_tail;
434 * Head of linked list of all clients to this service.
436 static struct TransportClient *clients_head;
439 * Tail of linked list of all clients to this service.
441 static struct TransportClient *clients_tail;
446 struct GNUNET_STATISTICS_Handle *GST_stats;
449 * Configuration handle.
451 const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
456 struct GNUNET_PeerIdentity GST_my_identity;
461 struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
464 * Map from PIDs to `struct Neighbour` entries. A peer is
465 * a neighbour if we have an MQ to it from some communicator.
467 static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
470 * Database for peer's HELLOs.
472 static struct GNUNET_PEERSTORE_Handle *peerstore;
476 * Lookup neighbour record for peer @a pid.
478 * @param pid neighbour to look for
479 * @return NULL if we do not have this peer as a neighbour
481 static struct Neighbour *
482 lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
484 return GNUNET_CONTAINER_multipeermap_get (neighbours,
490 * Details about what to notify monitors about.
495 * @deprecated To be discussed if we keep these...
497 struct GNUNET_TIME_Absolute last_validation;
498 struct GNUNET_TIME_Absolute valid_until;
499 struct GNUNET_TIME_Absolute next_validation;
502 * Current round-trip time estimate.
504 struct GNUNET_TIME_Relative rtt;
509 enum GNUNET_TRANSPORT_ConnectionStatus cs;
514 uint32_t num_msg_pending;
519 uint32_t num_bytes_pending;
526 * Notify monitor @a tc about an event. That @a tc
527 * cares about the event has already been checked.
529 * Send @a tc information in @a me about a @a peer's status with
530 * respect to some @a address to all monitors that care.
532 * @param tc monitor to inform
533 * @param peer peer the information is about
534 * @param address address the information is about
535 * @param nt network type associated with @a address
536 * @param me detailed information to transmit
539 notify_monitor (struct TransportClient *tc,
540 const struct GNUNET_PeerIdentity *peer,
542 enum GNUNET_ATS_Network_Type nt,
543 const struct MonitorEvent *me)
545 struct GNUNET_MQ_Envelope *env;
546 struct GNUNET_TRANSPORT_MonitorData *md;
547 size_t addr_len = strlen (address) + 1;
549 env = GNUNET_MQ_msg_extra (md,
551 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA);
552 md->nt = htonl ((uint32_t) nt);
554 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
555 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
556 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
557 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
558 md->cs = htonl ((uint32_t) me->cs);
559 md->num_msg_pending = htonl (me->num_msg_pending);
560 md->num_bytes_pending = htonl (me->num_bytes_pending);
564 GNUNET_MQ_send (tc->mq,
570 * Send information in @a me about a @a peer's status with respect
571 * to some @a address to all monitors that care.
573 * @param peer peer the information is about
574 * @param address address the information is about
575 * @param nt network type associated with @a address
576 * @param me detailed information to transmit
579 notify_monitors (const struct GNUNET_PeerIdentity *peer,
581 enum GNUNET_ATS_Network_Type nt,
582 const struct MonitorEvent *me)
584 static struct GNUNET_PeerIdentity zero;
586 for (struct TransportClient *tc = clients_head;
590 if (CT_MONITOR != tc->type)
592 if (tc->details.monitor.one_shot)
594 if ( (0 != memcmp (&tc->details.monitor.peer,
597 (0 != memcmp (&tc->details.monitor.peer,
611 * Called whenever a client connects. Allocates our
612 * data structures associated with that client.
614 * @param cls closure, NULL
615 * @param client identification of the client
616 * @param mq message queue for the client
617 * @return our `struct TransportClient`
620 client_connect_cb (void *cls,
621 struct GNUNET_SERVICE_Client *client,
622 struct GNUNET_MQ_Handle *mq)
624 struct TransportClient *tc;
626 tc = GNUNET_new (struct TransportClient);
629 GNUNET_CONTAINER_DLL_insert (clients_head,
632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
633 "Client %p connected\n",
640 * Release memory used by @a neighbour.
642 * @param neighbour neighbour entry to free
645 free_neighbour (struct Neighbour *neighbour)
647 GNUNET_assert (NULL == neighbour->queue_head);
648 GNUNET_assert (GNUNET_YES ==
649 GNUNET_CONTAINER_multipeermap_remove (neighbours,
652 GNUNET_free (neighbour);
657 * Send message to CORE clients that we lost a connection.
659 * @param tc client to inform (must be CORE client)
660 * @param pid peer the connection is for
661 * @param quota_out current quota for the peer
664 core_send_connect_info (struct TransportClient *tc,
665 const struct GNUNET_PeerIdentity *pid,
666 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
668 struct GNUNET_MQ_Envelope *env;
669 struct ConnectInfoMessage *cim;
671 GNUNET_assert (CT_CORE == tc->type);
672 env = GNUNET_MQ_msg (cim,
673 GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
674 cim->quota_out = quota_out;
676 GNUNET_MQ_send (tc->mq,
682 * Send message to CORE clients that we gained a connection
684 * @param pid peer the queue was for
685 * @param quota_out current quota for the peer
688 cores_send_connect_info (const struct GNUNET_PeerIdentity *pid,
689 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
691 for (struct TransportClient *tc = clients_head;
695 if (CT_CORE != tc->type)
697 core_send_connect_info (tc,
705 * Send message to CORE clients that we lost a connection.
707 * @param pid peer the connection was for
710 cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
712 for (struct TransportClient *tc = clients_head;
716 struct GNUNET_MQ_Envelope *env;
717 struct DisconnectInfoMessage *dim;
719 if (CT_CORE != tc->type)
721 env = GNUNET_MQ_msg (dim,
722 GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
724 GNUNET_MQ_send (tc->mq,
733 * @param queue the queue to free
736 free_queue (struct Queue *queue)
738 struct Neighbour *neighbour = queue->neighbour;
739 struct TransportClient *tc = queue->tc;
740 struct MonitorEvent me = {
741 .cs = GNUNET_TRANSPORT_CS_DOWN,
742 .rtt = GNUNET_TIME_UNIT_FOREVER_REL
745 GNUNET_CONTAINER_MDLL_remove (neighbour,
746 neighbour->queue_head,
747 neighbour->queue_tail,
749 GNUNET_CONTAINER_MDLL_remove (client,
750 tc->details.communicator.queue_head,
751 tc->details.communicator.queue_tail,
754 notify_monitors (&neighbour->pid,
759 if (NULL == neighbour->queue_head)
761 cores_send_disconnect_info (&neighbour->pid);
762 free_neighbour (neighbour);
770 * @param ale address list entry to free
773 free_address_list_entry (struct AddressListEntry *ale)
775 struct TransportClient *tc = ale->tc;
777 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
778 tc->details.communicator.addr_tail,
782 GNUNET_PEERSTORE_store_cancel (ale->sc);
787 GNUNET_SCHEDULER_cancel (ale->st);
795 * Called whenever a client is disconnected. Frees our
796 * resources associated with that client.
798 * @param cls closure, NULL
799 * @param client identification of the client
800 * @param app_ctx our `struct TransportClient`
803 client_disconnect_cb (void *cls,
804 struct GNUNET_SERVICE_Client *client,
807 struct TransportClient *tc = app_ctx;
809 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
810 "Client %p disconnected, cleaning up.\n",
812 GNUNET_CONTAINER_DLL_remove (clients_head,
821 struct PendingMessage *pm;
823 while (NULL != (pm = tc->details.core.pending_msg_head))
825 GNUNET_CONTAINER_MDLL_remove (client,
826 tc->details.core.pending_msg_head,
827 tc->details.core.pending_msg_tail,
835 case CT_COMMUNICATOR:
838 struct AddressListEntry *ale;
840 while (NULL != (q = tc->details.communicator.queue_head))
842 while (NULL != (ale = tc->details.communicator.addr_head))
843 free_address_list_entry (ale);
844 GNUNET_free (tc->details.communicator.address_prefix);
853 * Iterator telling new CORE client about all existing
854 * connections to peers.
856 * @param cls the new `struct TransportClient`
857 * @param pid a connected peer
858 * @param value the `struct Neighbour` with more information
859 * @return #GNUNET_OK (continue to iterate)
862 notify_client_connect_info (void *cls,
863 const struct GNUNET_PeerIdentity *pid,
866 struct TransportClient *tc = cls;
867 struct Neighbour *neighbour = value;
869 core_send_connect_info (tc,
871 neighbour->quota_out);
877 * Initialize a "CORE" client. We got a start message from this
878 * client, so add it to the list of clients for broadcasting of
881 * @param cls the client
882 * @param start the start message that was sent
885 handle_client_start (void *cls,
886 const struct StartMessage *start)
888 struct TransportClient *tc = cls;
891 options = ntohl (start->options);
892 if ( (0 != (1 & options)) &&
894 memcmp (&start->self,
896 sizeof (struct GNUNET_PeerIdentity)) ) )
898 /* client thinks this is a different peer, reject */
900 GNUNET_SERVICE_client_drop (tc->client);
903 if (CT_NONE != tc->type)
906 GNUNET_SERVICE_client_drop (tc->client);
910 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
911 ¬ify_client_connect_info,
913 GNUNET_SERVICE_client_continue (tc->client);
918 * Client asked for transmission to a peer. Process the request.
920 * @param cls the client
921 * @param obm the send message that was sent
924 check_client_send (void *cls,
925 const struct OutboundMessage *obm)
927 struct TransportClient *tc = cls;
929 const struct GNUNET_MessageHeader *obmm;
931 if (CT_CORE != tc->type)
934 return GNUNET_SYSERR;
936 size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
937 if (size < sizeof (struct GNUNET_MessageHeader))
940 return GNUNET_SYSERR;
942 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
943 if (size != ntohs (obmm->size))
946 return GNUNET_SYSERR;
953 * Send a response to the @a pm that we have processed a
954 * "send" request with status @a success. We
955 * transmitted @a bytes_physical on the actual wire.
956 * Sends a confirmation to the "core" client responsible
957 * for the original request and free's @a pm.
959 * @param pm handle to the original pending message
960 * @param success status code, #GNUNET_OK on success, #GNUNET_SYSERR
961 * for transmission failure
962 * @param bytes_physical amount of bandwidth consumed
965 client_send_response (struct PendingMessage *pm,
967 uint32_t bytes_physical)
969 struct TransportClient *tc = pm->client;
970 struct Neighbour *target = pm->target;
971 struct GNUNET_MQ_Envelope *env;
972 struct SendOkMessage *som;
976 env = GNUNET_MQ_msg (som,
977 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
978 som->success = htonl ((uint32_t) success);
979 som->bytes_msg = htonl (pm->bytes_msg);
980 som->bytes_physical = htonl (bytes_physical);
981 som->peer = target->pid;
982 GNUNET_MQ_send (tc->mq,
984 GNUNET_CONTAINER_MDLL_remove (client,
985 tc->details.core.pending_msg_head,
986 tc->details.core.pending_msg_tail,
989 GNUNET_CONTAINER_MDLL_remove (neighbour,
990 target->pending_msg_head,
991 target->pending_msg_tail,
998 * Client asked for transmission to a peer. Process the request.
1000 * @param cls the client
1001 * @param obm the send message that was sent
1004 handle_client_send (void *cls,
1005 const struct OutboundMessage *obm)
1007 struct TransportClient *tc = cls;
1008 struct PendingMessage *pm;
1009 const struct GNUNET_MessageHeader *obmm;
1010 struct Neighbour *target;
1013 GNUNET_assert (CT_CORE == tc->type);
1014 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
1015 bytes_msg = ntohs (obmm->size);
1016 target = lookup_neighbour (&obm->peer);
1019 /* Failure: don't have this peer as a neighbour (anymore).
1020 Might have gone down asynchronously, so this is NOT
1021 a protocol violation by CORE. Still count the event,
1022 as this should be rare. */
1023 struct GNUNET_MQ_Envelope *env;
1024 struct SendOkMessage *som;
1026 env = GNUNET_MQ_msg (som,
1027 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1028 som->success = htonl (GNUNET_SYSERR);
1029 som->bytes_msg = htonl (bytes_msg);
1030 som->bytes_physical = htonl (0);
1031 som->peer = obm->peer;
1032 GNUNET_MQ_send (tc->mq,
1034 GNUNET_SERVICE_client_continue (tc->client);
1035 GNUNET_STATISTICS_update (GST_stats,
1036 "# messages dropped (neighbour unknown)",
1041 pm = GNUNET_new (struct PendingMessage);
1043 pm->target = target;
1044 pm->bytes_msg = bytes_msg;
1045 GNUNET_CONTAINER_MDLL_insert (neighbour,
1046 target->pending_msg_head,
1047 target->pending_msg_tail,
1049 GNUNET_CONTAINER_MDLL_insert (client,
1050 tc->details.core.pending_msg_head,
1051 tc->details.core.pending_msg_tail,
1053 // FIXME: do the work, final continuation with call to:
1054 client_send_response (pm,
1061 * Communicator started. Test message is well-formed.
1063 * @param cls the client
1064 * @param cam the send message that was sent
1067 check_communicator_available (void *cls,
1068 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1070 struct TransportClient *tc = cls;
1074 if (CT_NONE != tc->type)
1077 return GNUNET_SYSERR;
1079 tc->type = CT_COMMUNICATOR;
1080 size = ntohs (cam->header.size) - sizeof (*cam);
1082 return GNUNET_OK; /* receive-only communicator */
1083 addr = (const char *) &cam[1];
1084 if ('\0' != addr[size-1])
1087 return GNUNET_SYSERR;
1094 * Communicator started. Process the request.
1096 * @param cls the client
1097 * @param cam the send message that was sent
1100 handle_communicator_available (void *cls,
1101 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1103 struct TransportClient *tc = cls;
1106 size = ntohs (cam->header.size) - sizeof (*cam);
1108 return; /* receive-only communicator */
1109 tc->details.communicator.address_prefix = GNUNET_strdup ((const char *) &cam[1]);
1110 GNUNET_SERVICE_client_continue (tc->client);
1115 * Address of our peer added. Test message is well-formed.
1117 * @param cls the client
1118 * @param aam the send message that was sent
1121 check_add_address (void *cls,
1122 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1124 struct TransportClient *tc = cls;
1128 if (CT_COMMUNICATOR != tc->type)
1131 return GNUNET_SYSERR;
1133 size = ntohs (aam->header.size) - sizeof (*aam);
1137 return GNUNET_SYSERR;
1139 addr = (const char *) &aam[1];
1140 if ('\0' != addr[size-1])
1143 return GNUNET_SYSERR;
1150 * Ask peerstore to store our address.
1152 * @param cls an `struct AddressListEntry *`
1155 store_pi (void *cls);
1159 * Function called when peerstore is done storing our address.
1162 peerstore_store_cb (void *cls,
1165 struct AddressListEntry *ale = cls;
1168 if (GNUNET_YES != success)
1169 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1170 "Failed to store our own address `%s' in peerstore!\n",
1172 /* refresh period is 1/4 of expiration time, that should be plenty
1173 without being excessive. */
1174 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
1182 * Ask peerstore to store our address.
1184 * @param cls an `struct AddressListEntry *`
1187 store_pi (void *cls)
1189 struct AddressListEntry *ale = cls;
1192 struct GNUNET_TIME_Absolute expiration;
1195 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
1196 GNUNET_HELLO_sign_address (ale->address,
1202 ale->sc = GNUNET_PEERSTORE_store (peerstore,
1209 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
1210 &peerstore_store_cb,
1213 if (NULL == ale->sc)
1215 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1216 "Failed to store our address `%s' with peerstore\n",
1218 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
1226 * Address of our peer added. Process the request.
1228 * @param cls the client
1229 * @param aam the send message that was sent
1232 handle_add_address (void *cls,
1233 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1235 struct TransportClient *tc = cls;
1236 struct AddressListEntry *ale;
1239 slen = ntohs (aam->header.size) - sizeof (*aam);
1240 ale = GNUNET_malloc (sizeof (struct AddressListEntry) + slen);
1242 ale->address = (const char *) &ale[1];
1243 ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
1244 ale->aid = aam->aid;
1245 ale->nt = (enum GNUNET_ATS_Network_Type) ntohl (aam->nt);
1249 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
1250 tc->details.communicator.addr_tail,
1252 ale->st = GNUNET_SCHEDULER_add_now (&store_pi,
1254 GNUNET_SERVICE_client_continue (tc->client);
1259 * Address of our peer deleted. Process the request.
1261 * @param cls the client
1262 * @param dam the send message that was sent
1265 handle_del_address (void *cls,
1266 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
1268 struct TransportClient *tc = cls;
1270 if (CT_COMMUNICATOR != tc->type)
1273 GNUNET_SERVICE_client_drop (tc->client);
1276 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
1280 if (dam->aid != ale->aid)
1282 GNUNET_assert (ale->tc == tc);
1283 free_address_list_entry (ale);
1284 GNUNET_SERVICE_client_continue (tc->client);
1287 GNUNET_SERVICE_client_drop (tc->client);
1292 * Client notified us about transmission from a peer. Process the request.
1294 * @param cls the client
1295 * @param obm the send message that was sent
1298 check_incoming_msg (void *cls,
1299 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1301 struct TransportClient *tc = cls;
1303 const struct GNUNET_MessageHeader *obmm;
1305 if (CT_COMMUNICATOR != tc->type)
1308 return GNUNET_SYSERR;
1310 size = ntohs (im->header.size) - sizeof (*im);
1311 if (size < sizeof (struct GNUNET_MessageHeader))
1314 return GNUNET_SYSERR;
1316 obmm = (const struct GNUNET_MessageHeader *) &im[1];
1317 if (size != ntohs (obmm->size))
1320 return GNUNET_SYSERR;
1327 * Incoming meessage. Process the request.
1329 * @param cls the client
1330 * @param im the send message that was received
1333 handle_incoming_msg (void *cls,
1334 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1336 struct TransportClient *tc = cls;
1338 GNUNET_SERVICE_client_continue (tc->client);
1343 * New queue became available. Check message.
1345 * @param cls the client
1346 * @param aqm the send message that was sent
1349 check_add_queue_message (void *cls,
1350 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1352 struct TransportClient *tc = cls;
1356 if (CT_COMMUNICATOR != tc->type)
1359 return GNUNET_SYSERR;
1361 size = ntohs (aqm->header.size) - sizeof (*aqm);
1365 return GNUNET_SYSERR;
1367 addr = (const char *) &aqm[1];
1368 if ('\0' != addr[size-1])
1371 return GNUNET_SYSERR;
1378 * New queue became available. Process the request.
1380 * @param cls the client
1381 * @param aqm the send message that was sent
1384 handle_add_queue_message (void *cls,
1385 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1387 struct TransportClient *tc = cls;
1388 struct Queue *queue;
1389 struct Neighbour *neighbour;
1393 neighbour = lookup_neighbour (&aqm->receiver);
1394 if (NULL == neighbour)
1396 neighbour = GNUNET_new (struct Neighbour);
1397 neighbour->pid = aqm->receiver;
1398 GNUNET_assert (GNUNET_OK ==
1399 GNUNET_CONTAINER_multipeermap_put (neighbours,
1402 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1403 cores_send_connect_info (&neighbour->pid,
1404 GNUNET_BANDWIDTH_ZERO);
1405 // FIXME: notify ATS!
1407 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
1408 addr = (const char *) &aqm[1];
1410 queue = GNUNET_malloc (sizeof (struct Queue) + addr_len);
1412 queue->address = (const char *) &queue[1];
1413 queue->rtt = GNUNET_TIME_UNIT_FOREVER_REL;
1414 queue->qid = aqm->qid;
1415 queue->mtu = ntohl (aqm->mtu);
1416 queue->nt = (enum GNUNET_ATS_Network_Type) ntohl (aqm->nt);
1417 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
1418 queue->neighbour = neighbour;
1422 /* notify monitors about new queue */
1424 struct MonitorEvent me = {
1429 notify_monitors (&neighbour->pid,
1434 GNUNET_CONTAINER_MDLL_insert (neighbour,
1435 neighbour->queue_head,
1436 neighbour->queue_tail,
1438 GNUNET_CONTAINER_MDLL_insert (client,
1439 tc->details.communicator.queue_head,
1440 tc->details.communicator.queue_tail,
1442 // FIXME: possibly transmit queued messages?
1443 GNUNET_SERVICE_client_continue (tc->client);
1448 * Queue to a peer went down. Process the request.
1450 * @param cls the client
1451 * @param dqm the send message that was sent
1454 handle_del_queue_message (void *cls,
1455 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
1457 struct TransportClient *tc = cls;
1459 if (CT_COMMUNICATOR != tc->type)
1462 GNUNET_SERVICE_client_drop (tc->client);
1465 for (struct Queue *queue = tc->details.communicator.queue_head;
1467 queue = queue->next_client)
1469 struct Neighbour *neighbour = queue->neighbour;
1471 if ( (dqm->qid != queue->qid) ||
1472 (0 != memcmp (&dqm->receiver,
1474 sizeof (struct GNUNET_PeerIdentity))) )
1477 GNUNET_SERVICE_client_continue (tc->client);
1481 GNUNET_SERVICE_client_drop (tc->client);
1486 * Message was transmitted. Process the request.
1488 * @param cls the client
1489 * @param sma the send message that was sent
1492 handle_send_message_ack (void *cls,
1493 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
1495 struct TransportClient *tc = cls;
1497 if (CT_COMMUNICATOR != tc->type)
1500 GNUNET_SERVICE_client_drop (tc->client);
1503 GNUNET_SERVICE_client_continue (tc->client);
1508 * Iterator telling new MONITOR client about all existing
1511 * @param cls the new `struct TransportClient`
1512 * @param pid a connected peer
1513 * @param value the `struct Neighbour` with more information
1514 * @return #GNUNET_OK (continue to iterate)
1517 notify_client_queues (void *cls,
1518 const struct GNUNET_PeerIdentity *pid,
1521 struct TransportClient *tc = cls;
1522 struct Neighbour *neighbour = value;
1524 GNUNET_assert (CT_MONITOR == tc->type);
1525 for (struct Queue *q = neighbour->queue_head;
1527 q = q->next_neighbour)
1529 struct MonitorEvent me = {
1532 .num_msg_pending = q->num_msg_pending,
1533 .num_bytes_pending = q->num_bytes_pending
1547 * Initialize a monitor client.
1549 * @param cls the client
1550 * @param start the start message that was sent
1553 handle_monitor_start (void *cls,
1554 const struct GNUNET_TRANSPORT_MonitorStart *start)
1556 struct TransportClient *tc = cls;
1558 if (CT_NONE != tc->type)
1561 GNUNET_SERVICE_client_drop (tc->client);
1564 tc->type = CT_MONITOR;
1565 tc->details.monitor.peer = start->peer;
1566 tc->details.monitor.one_shot = ntohl (start->one_shot);
1567 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1568 ¬ify_client_queues,
1570 GNUNET_SERVICE_client_mark_monitor (tc->client);
1571 GNUNET_SERVICE_client_continue (tc->client);
1576 * Free neighbour entry.
1580 * @param value a `struct Neighbour`
1581 * @return #GNUNET_OK (always)
1584 free_neighbour_cb (void *cls,
1585 const struct GNUNET_PeerIdentity *pid,
1588 struct Neighbour *neighbour = value;
1592 GNUNET_break (0); // should this ever happen?
1593 free_neighbour (neighbour);
1600 * Function called when the service shuts down. Unloads our plugins
1601 * and cancels pending validations.
1603 * @param cls closure, unused
1606 do_shutdown (void *cls)
1610 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1613 if (NULL != peerstore)
1615 GNUNET_PEERSTORE_disconnect (peerstore,
1619 if (NULL != GST_stats)
1621 GNUNET_STATISTICS_destroy (GST_stats,
1625 if (NULL != GST_my_private_key)
1627 GNUNET_free (GST_my_private_key);
1628 GST_my_private_key = NULL;
1630 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
1635 * Initiate transport service.
1637 * @param cls closure
1638 * @param c configuration to use
1639 * @param service the initialized service
1643 const struct GNUNET_CONFIGURATION_Handle *c,
1644 struct GNUNET_SERVICE_Handle *service)
1649 neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
1651 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
1652 if (NULL == GST_my_private_key)
1654 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1655 _("Transport service is lacking key configuration settings. Exiting.\n"));
1656 GNUNET_SCHEDULER_shutdown ();
1659 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
1660 &GST_my_identity.public_key);
1661 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1662 "My identity is `%s'\n",
1663 GNUNET_i2s_full (&GST_my_identity));
1665 GST_stats = GNUNET_STATISTICS_create ("transport",
1667 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1669 peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
1670 if (NULL == peerstore)
1673 GNUNET_SCHEDULER_shutdown ();
1676 /* start subsystems */
1681 * Define "main" method using service macro.
1685 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
1688 &client_disconnect_cb,
1690 /* communication with core */
1691 GNUNET_MQ_hd_fixed_size (client_start,
1692 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
1693 struct StartMessage,
1695 GNUNET_MQ_hd_var_size (client_send,
1696 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
1697 struct OutboundMessage,
1699 /* communication with communicators */
1700 GNUNET_MQ_hd_var_size (communicator_available,
1701 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
1702 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
1704 GNUNET_MQ_hd_var_size (add_address,
1705 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
1706 struct GNUNET_TRANSPORT_AddAddressMessage,
1708 GNUNET_MQ_hd_fixed_size (del_address,
1709 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
1710 struct GNUNET_TRANSPORT_DelAddressMessage,
1712 GNUNET_MQ_hd_var_size (incoming_msg,
1713 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
1714 struct GNUNET_TRANSPORT_IncomingMessage,
1716 GNUNET_MQ_hd_var_size (add_queue_message,
1717 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
1718 struct GNUNET_TRANSPORT_AddQueueMessage,
1720 GNUNET_MQ_hd_fixed_size (del_queue_message,
1721 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
1722 struct GNUNET_TRANSPORT_DelQueueMessage,
1724 GNUNET_MQ_hd_fixed_size (send_message_ack,
1725 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
1726 struct GNUNET_TRANSPORT_SendMessageToAck,
1728 /* communication with monitors */
1729 GNUNET_MQ_hd_fixed_size (monitor_start,
1730 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
1731 struct GNUNET_TRANSPORT_MonitorStart,
1733 GNUNET_MQ_handler_end ());
1736 /* end of file gnunet-service-transport.c */