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 * Distance to the target of this queue.
163 * Network type offered by this queue.
165 enum GNUNET_NetworkType nt;
168 * Connection status for this queue.
170 enum GNUNET_TRANSPORT_ConnectionStatus cs;
175 uint32_t num_msg_pending;
180 uint32_t num_bytes_pending;
182 // FIXME: add ATS-specific fields here!
187 * A neighbour that at least one communicator is connected to.
193 * Which peer is this about?
195 struct GNUNET_PeerIdentity pid;
198 * Head of list of messages pending for this neighbour.
200 struct PendingMessage *pending_msg_head;
203 * Tail of list of messages pending for this neighbour.
205 struct PendingMessage *pending_msg_tail;
208 * Head of DLL of queues to this peer.
210 struct Queue *queue_head;
213 * Tail of DLL of queues to this peer.
215 struct Queue *queue_tail;
218 * Quota at which CORE is allowed to transmit to this peer
221 * FIXME: not yet used, tricky to get right given multiple queues!
222 * (=> Idea: let ATS set a quota per queue and we add them up here?)
223 * FIXME: how do we set this value initially when we tell CORE?
224 * Options: start at a minimum value or at literally zero (before ATS?)
225 * (=> Current thought: clean would be zero!)
227 struct GNUNET_BANDWIDTH_Value32NBO quota_out;
233 * Transmission request from CORE that is awaiting delivery.
235 struct PendingMessage
238 * Kept in a MDLL of messages for this @a target.
240 struct PendingMessage *next_neighbour;
243 * Kept in a MDLL of messages for this @a target.
245 struct PendingMessage *prev_neighbour;
248 * Kept in a MDLL of messages from this @a client.
250 struct PendingMessage *next_client;
253 * Kept in a MDLL of messages from this @a client.
255 struct PendingMessage *prev_client;
258 * Target of the request.
260 struct Neighbour *target;
263 * Client that issued the transmission request.
265 struct TransportClient *client;
268 * Size of the original message.
276 * One of the addresses of this peer.
278 struct AddressListEntry
284 struct AddressListEntry *next;
289 struct AddressListEntry *prev;
292 * Which communicator provides this address?
294 struct TransportClient *tc;
297 * The actual address.
302 * Current context for storing this address in the peerstore.
304 struct GNUNET_PEERSTORE_StoreContext *sc;
307 * Task to periodically do @e st operation.
309 struct GNUNET_SCHEDULER_Task *st;
312 * What is a typical lifetime the communicator expects this
313 * address to have? (Always from now.)
315 struct GNUNET_TIME_Relative expiration;
318 * Address identifier used by the communicator.
323 * Network type offered by this address.
325 enum GNUNET_NetworkType nt;
331 * Client connected to the transport service.
333 struct TransportClient
339 struct TransportClient *next;
344 struct TransportClient *prev;
347 * Handle to the client.
349 struct GNUNET_SERVICE_Client *client;
352 * Message queue to the client.
354 struct GNUNET_MQ_Handle *mq;
357 * What type of client is this?
359 enum ClientType type;
365 * Information for @e type #CT_CORE.
370 * Head of list of messages pending for this client.
372 struct PendingMessage *pending_msg_head;
375 * Tail of list of messages pending for this client.
377 struct PendingMessage *pending_msg_tail;
382 * Information for @e type #CT_MONITOR.
387 * Peer identity to monitor the addresses of.
388 * Zero to monitor all neighbours. Valid if
389 * @e type is #CT_MONITOR.
391 struct GNUNET_PeerIdentity peer;
394 * Is this a one-shot monitor?
402 * Information for @e type #CT_COMMUNICATOR.
406 * If @e type is #CT_COMMUNICATOR, this communicator
407 * supports communicating using these addresses.
409 char *address_prefix;
412 * Head of DLL of queues offered by this communicator.
414 struct Queue *queue_head;
417 * Tail of DLL of queues offered by this communicator.
419 struct Queue *queue_tail;
422 * Head of list of the addresses of this peer offered by this communicator.
424 struct AddressListEntry *addr_head;
427 * Tail of list of the addresses of this peer offered by this communicator.
429 struct AddressListEntry *addr_tail;
432 * Characteristics of this communicator.
434 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc;
444 * Head of linked list of all clients to this service.
446 static struct TransportClient *clients_head;
449 * Tail of linked list of all clients to this service.
451 static struct TransportClient *clients_tail;
456 struct GNUNET_STATISTICS_Handle *GST_stats;
459 * Configuration handle.
461 const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
466 struct GNUNET_PeerIdentity GST_my_identity;
471 struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
474 * Map from PIDs to `struct Neighbour` entries. A peer is
475 * a neighbour if we have an MQ to it from some communicator.
477 static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
480 * Database for peer's HELLOs.
482 static struct GNUNET_PEERSTORE_Handle *peerstore;
486 * Lookup neighbour record for peer @a pid.
488 * @param pid neighbour to look for
489 * @return NULL if we do not have this peer as a neighbour
491 static struct Neighbour *
492 lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
494 return GNUNET_CONTAINER_multipeermap_get (neighbours,
500 * Details about what to notify monitors about.
505 * @deprecated To be discussed if we keep these...
507 struct GNUNET_TIME_Absolute last_validation;
508 struct GNUNET_TIME_Absolute valid_until;
509 struct GNUNET_TIME_Absolute next_validation;
512 * Current round-trip time estimate.
514 struct GNUNET_TIME_Relative rtt;
519 enum GNUNET_TRANSPORT_ConnectionStatus cs;
524 uint32_t num_msg_pending;
529 uint32_t num_bytes_pending;
536 * Notify monitor @a tc about an event. That @a tc
537 * cares about the event has already been checked.
539 * Send @a tc information in @a me about a @a peer's status with
540 * respect to some @a address to all monitors that care.
542 * @param tc monitor to inform
543 * @param peer peer the information is about
544 * @param address address the information is about
545 * @param nt network type associated with @a address
546 * @param me detailed information to transmit
549 notify_monitor (struct TransportClient *tc,
550 const struct GNUNET_PeerIdentity *peer,
552 enum GNUNET_NetworkType nt,
553 const struct MonitorEvent *me)
555 struct GNUNET_MQ_Envelope *env;
556 struct GNUNET_TRANSPORT_MonitorData *md;
557 size_t addr_len = strlen (address) + 1;
559 env = GNUNET_MQ_msg_extra (md,
561 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA);
562 md->nt = htonl ((uint32_t) nt);
564 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
565 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
566 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
567 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
568 md->cs = htonl ((uint32_t) me->cs);
569 md->num_msg_pending = htonl (me->num_msg_pending);
570 md->num_bytes_pending = htonl (me->num_bytes_pending);
574 GNUNET_MQ_send (tc->mq,
580 * Send information in @a me about a @a peer's status with respect
581 * to some @a address to all monitors that care.
583 * @param peer peer the information is about
584 * @param address address the information is about
585 * @param nt network type associated with @a address
586 * @param me detailed information to transmit
589 notify_monitors (const struct GNUNET_PeerIdentity *peer,
591 enum GNUNET_NetworkType nt,
592 const struct MonitorEvent *me)
594 static struct GNUNET_PeerIdentity zero;
596 for (struct TransportClient *tc = clients_head;
600 if (CT_MONITOR != tc->type)
602 if (tc->details.monitor.one_shot)
604 if ( (0 != memcmp (&tc->details.monitor.peer,
607 (0 != memcmp (&tc->details.monitor.peer,
621 * Called whenever a client connects. Allocates our
622 * data structures associated with that client.
624 * @param cls closure, NULL
625 * @param client identification of the client
626 * @param mq message queue for the client
627 * @return our `struct TransportClient`
630 client_connect_cb (void *cls,
631 struct GNUNET_SERVICE_Client *client,
632 struct GNUNET_MQ_Handle *mq)
634 struct TransportClient *tc;
636 tc = GNUNET_new (struct TransportClient);
639 GNUNET_CONTAINER_DLL_insert (clients_head,
642 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
643 "Client %p connected\n",
650 * Release memory used by @a neighbour.
652 * @param neighbour neighbour entry to free
655 free_neighbour (struct Neighbour *neighbour)
657 GNUNET_assert (NULL == neighbour->queue_head);
658 GNUNET_assert (GNUNET_YES ==
659 GNUNET_CONTAINER_multipeermap_remove (neighbours,
662 GNUNET_free (neighbour);
667 * Send message to CORE clients that we lost a connection.
669 * @param tc client to inform (must be CORE client)
670 * @param pid peer the connection is for
671 * @param quota_out current quota for the peer
674 core_send_connect_info (struct TransportClient *tc,
675 const struct GNUNET_PeerIdentity *pid,
676 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
678 struct GNUNET_MQ_Envelope *env;
679 struct ConnectInfoMessage *cim;
681 GNUNET_assert (CT_CORE == tc->type);
682 env = GNUNET_MQ_msg (cim,
683 GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
684 cim->quota_out = quota_out;
686 GNUNET_MQ_send (tc->mq,
692 * Send message to CORE clients that we gained a connection
694 * @param pid peer the queue was for
695 * @param quota_out current quota for the peer
698 cores_send_connect_info (const struct GNUNET_PeerIdentity *pid,
699 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
701 for (struct TransportClient *tc = clients_head;
705 if (CT_CORE != tc->type)
707 core_send_connect_info (tc,
715 * Send message to CORE clients that we lost a connection.
717 * @param pid peer the connection was for
720 cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
722 for (struct TransportClient *tc = clients_head;
726 struct GNUNET_MQ_Envelope *env;
727 struct DisconnectInfoMessage *dim;
729 if (CT_CORE != tc->type)
731 env = GNUNET_MQ_msg (dim,
732 GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
734 GNUNET_MQ_send (tc->mq,
743 * @param queue the queue to free
746 free_queue (struct Queue *queue)
748 struct Neighbour *neighbour = queue->neighbour;
749 struct TransportClient *tc = queue->tc;
750 struct MonitorEvent me = {
751 .cs = GNUNET_TRANSPORT_CS_DOWN,
752 .rtt = GNUNET_TIME_UNIT_FOREVER_REL
755 GNUNET_CONTAINER_MDLL_remove (neighbour,
756 neighbour->queue_head,
757 neighbour->queue_tail,
759 GNUNET_CONTAINER_MDLL_remove (client,
760 tc->details.communicator.queue_head,
761 tc->details.communicator.queue_tail,
764 notify_monitors (&neighbour->pid,
769 if (NULL == neighbour->queue_head)
771 cores_send_disconnect_info (&neighbour->pid);
772 free_neighbour (neighbour);
780 * @param ale address list entry to free
783 free_address_list_entry (struct AddressListEntry *ale)
785 struct TransportClient *tc = ale->tc;
787 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
788 tc->details.communicator.addr_tail,
792 GNUNET_PEERSTORE_store_cancel (ale->sc);
797 GNUNET_SCHEDULER_cancel (ale->st);
805 * Called whenever a client is disconnected. Frees our
806 * resources associated with that client.
808 * @param cls closure, NULL
809 * @param client identification of the client
810 * @param app_ctx our `struct TransportClient`
813 client_disconnect_cb (void *cls,
814 struct GNUNET_SERVICE_Client *client,
817 struct TransportClient *tc = app_ctx;
819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
820 "Client %p disconnected, cleaning up.\n",
822 GNUNET_CONTAINER_DLL_remove (clients_head,
831 struct PendingMessage *pm;
833 while (NULL != (pm = tc->details.core.pending_msg_head))
835 GNUNET_CONTAINER_MDLL_remove (client,
836 tc->details.core.pending_msg_head,
837 tc->details.core.pending_msg_tail,
845 case CT_COMMUNICATOR:
848 struct AddressListEntry *ale;
850 while (NULL != (q = tc->details.communicator.queue_head))
852 while (NULL != (ale = tc->details.communicator.addr_head))
853 free_address_list_entry (ale);
854 GNUNET_free (tc->details.communicator.address_prefix);
863 * Iterator telling new CORE client about all existing
864 * connections to peers.
866 * @param cls the new `struct TransportClient`
867 * @param pid a connected peer
868 * @param value the `struct Neighbour` with more information
869 * @return #GNUNET_OK (continue to iterate)
872 notify_client_connect_info (void *cls,
873 const struct GNUNET_PeerIdentity *pid,
876 struct TransportClient *tc = cls;
877 struct Neighbour *neighbour = value;
879 core_send_connect_info (tc,
881 neighbour->quota_out);
887 * Initialize a "CORE" client. We got a start message from this
888 * client, so add it to the list of clients for broadcasting of
891 * @param cls the client
892 * @param start the start message that was sent
895 handle_client_start (void *cls,
896 const struct StartMessage *start)
898 struct TransportClient *tc = cls;
901 options = ntohl (start->options);
902 if ( (0 != (1 & options)) &&
904 memcmp (&start->self,
906 sizeof (struct GNUNET_PeerIdentity)) ) )
908 /* client thinks this is a different peer, reject */
910 GNUNET_SERVICE_client_drop (tc->client);
913 if (CT_NONE != tc->type)
916 GNUNET_SERVICE_client_drop (tc->client);
920 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
921 ¬ify_client_connect_info,
923 GNUNET_SERVICE_client_continue (tc->client);
928 * Client asked for transmission to a peer. Process the request.
930 * @param cls the client
931 * @param obm the send message that was sent
934 check_client_send (void *cls,
935 const struct OutboundMessage *obm)
937 struct TransportClient *tc = cls;
939 const struct GNUNET_MessageHeader *obmm;
941 if (CT_CORE != tc->type)
944 return GNUNET_SYSERR;
946 size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
947 if (size < sizeof (struct GNUNET_MessageHeader))
950 return GNUNET_SYSERR;
952 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
953 if (size != ntohs (obmm->size))
956 return GNUNET_SYSERR;
963 * Send a response to the @a pm that we have processed a
964 * "send" request with status @a success. We
965 * transmitted @a bytes_physical on the actual wire.
966 * Sends a confirmation to the "core" client responsible
967 * for the original request and free's @a pm.
969 * @param pm handle to the original pending message
970 * @param success status code, #GNUNET_OK on success, #GNUNET_SYSERR
971 * for transmission failure
972 * @param bytes_physical amount of bandwidth consumed
975 client_send_response (struct PendingMessage *pm,
977 uint32_t bytes_physical)
979 struct TransportClient *tc = pm->client;
980 struct Neighbour *target = pm->target;
981 struct GNUNET_MQ_Envelope *env;
982 struct SendOkMessage *som;
986 env = GNUNET_MQ_msg (som,
987 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
988 som->success = htonl ((uint32_t) success);
989 som->bytes_msg = htonl (pm->bytes_msg);
990 som->bytes_physical = htonl (bytes_physical);
991 som->peer = target->pid;
992 GNUNET_MQ_send (tc->mq,
994 GNUNET_CONTAINER_MDLL_remove (client,
995 tc->details.core.pending_msg_head,
996 tc->details.core.pending_msg_tail,
999 GNUNET_CONTAINER_MDLL_remove (neighbour,
1000 target->pending_msg_head,
1001 target->pending_msg_tail,
1008 * Client asked for transmission to a peer. Process the request.
1010 * @param cls the client
1011 * @param obm the send message that was sent
1014 handle_client_send (void *cls,
1015 const struct OutboundMessage *obm)
1017 struct TransportClient *tc = cls;
1018 struct PendingMessage *pm;
1019 const struct GNUNET_MessageHeader *obmm;
1020 struct Neighbour *target;
1023 GNUNET_assert (CT_CORE == tc->type);
1024 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
1025 bytes_msg = ntohs (obmm->size);
1026 target = lookup_neighbour (&obm->peer);
1029 /* Failure: don't have this peer as a neighbour (anymore).
1030 Might have gone down asynchronously, so this is NOT
1031 a protocol violation by CORE. Still count the event,
1032 as this should be rare. */
1033 struct GNUNET_MQ_Envelope *env;
1034 struct SendOkMessage *som;
1036 env = GNUNET_MQ_msg (som,
1037 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1038 som->success = htonl (GNUNET_SYSERR);
1039 som->bytes_msg = htonl (bytes_msg);
1040 som->bytes_physical = htonl (0);
1041 som->peer = obm->peer;
1042 GNUNET_MQ_send (tc->mq,
1044 GNUNET_SERVICE_client_continue (tc->client);
1045 GNUNET_STATISTICS_update (GST_stats,
1046 "# messages dropped (neighbour unknown)",
1051 pm = GNUNET_new (struct PendingMessage);
1053 pm->target = target;
1054 pm->bytes_msg = bytes_msg;
1055 GNUNET_CONTAINER_MDLL_insert (neighbour,
1056 target->pending_msg_head,
1057 target->pending_msg_tail,
1059 GNUNET_CONTAINER_MDLL_insert (client,
1060 tc->details.core.pending_msg_head,
1061 tc->details.core.pending_msg_tail,
1063 // FIXME: do the work, final continuation with call to:
1064 client_send_response (pm,
1071 * Communicator started. Test message is well-formed.
1073 * @param cls the client
1074 * @param cam the send message that was sent
1077 check_communicator_available (void *cls,
1078 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1080 struct TransportClient *tc = cls;
1083 if (CT_NONE != tc->type)
1086 return GNUNET_SYSERR;
1088 tc->type = CT_COMMUNICATOR;
1089 size = ntohs (cam->header.size) - sizeof (*cam);
1091 return GNUNET_OK; /* receive-only communicator */
1092 GNUNET_MQ_check_zero_termination (cam);
1098 * Communicator started. Process the request.
1100 * @param cls the client
1101 * @param cam the send message that was sent
1104 handle_communicator_available (void *cls,
1105 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1107 struct TransportClient *tc = cls;
1110 size = ntohs (cam->header.size) - sizeof (*cam);
1112 return; /* receive-only communicator */
1113 tc->details.communicator.address_prefix
1114 = GNUNET_strdup ((const char *) &cam[1]);
1115 tc->details.communicator.cc
1116 = (enum GNUNET_TRANSPORT_CommunicatorCharacteristics) ntohl (cam->cc);
1117 GNUNET_SERVICE_client_continue (tc->client);
1122 * Address of our peer added. Test message is well-formed.
1124 * @param cls the client
1125 * @param aam the send message that was sent
1128 check_add_address (void *cls,
1129 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1131 struct TransportClient *tc = cls;
1133 if (CT_COMMUNICATOR != tc->type)
1136 return GNUNET_SYSERR;
1138 GNUNET_MQ_check_zero_termination (aam);
1144 * Ask peerstore to store our address.
1146 * @param cls an `struct AddressListEntry *`
1149 store_pi (void *cls);
1153 * Function called when peerstore is done storing our address.
1156 peerstore_store_cb (void *cls,
1159 struct AddressListEntry *ale = cls;
1162 if (GNUNET_YES != success)
1163 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1164 "Failed to store our own address `%s' in peerstore!\n",
1166 /* refresh period is 1/4 of expiration time, that should be plenty
1167 without being excessive. */
1168 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
1176 * Ask peerstore to store our address.
1178 * @param cls an `struct AddressListEntry *`
1181 store_pi (void *cls)
1183 struct AddressListEntry *ale = cls;
1186 struct GNUNET_TIME_Absolute expiration;
1189 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
1190 GNUNET_HELLO_sign_address (ale->address,
1196 ale->sc = GNUNET_PEERSTORE_store (peerstore,
1203 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
1204 &peerstore_store_cb,
1207 if (NULL == ale->sc)
1209 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1210 "Failed to store our address `%s' with peerstore\n",
1212 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
1220 * Address of our peer added. Process the request.
1222 * @param cls the client
1223 * @param aam the send message that was sent
1226 handle_add_address (void *cls,
1227 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1229 struct TransportClient *tc = cls;
1230 struct AddressListEntry *ale;
1233 slen = ntohs (aam->header.size) - sizeof (*aam);
1234 ale = GNUNET_malloc (sizeof (struct AddressListEntry) + slen);
1236 ale->address = (const char *) &ale[1];
1237 ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
1238 ale->aid = aam->aid;
1239 ale->nt = (enum GNUNET_NetworkType) ntohl (aam->nt);
1243 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
1244 tc->details.communicator.addr_tail,
1246 ale->st = GNUNET_SCHEDULER_add_now (&store_pi,
1248 GNUNET_SERVICE_client_continue (tc->client);
1253 * Address of our peer deleted. Process the request.
1255 * @param cls the client
1256 * @param dam the send message that was sent
1259 handle_del_address (void *cls,
1260 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
1262 struct TransportClient *tc = cls;
1264 if (CT_COMMUNICATOR != tc->type)
1267 GNUNET_SERVICE_client_drop (tc->client);
1270 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
1274 if (dam->aid != ale->aid)
1276 GNUNET_assert (ale->tc == tc);
1277 free_address_list_entry (ale);
1278 GNUNET_SERVICE_client_continue (tc->client);
1281 GNUNET_SERVICE_client_drop (tc->client);
1286 * Client notified us about transmission from a peer. Process the request.
1288 * @param cls the client
1289 * @param obm the send message that was sent
1292 check_incoming_msg (void *cls,
1293 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1295 struct TransportClient *tc = cls;
1297 const struct GNUNET_MessageHeader *obmm;
1299 if (CT_COMMUNICATOR != tc->type)
1302 return GNUNET_SYSERR;
1304 size = ntohs (im->header.size) - sizeof (*im);
1305 if (size < sizeof (struct GNUNET_MessageHeader))
1308 return GNUNET_SYSERR;
1310 obmm = (const struct GNUNET_MessageHeader *) &im[1];
1311 if (size != ntohs (obmm->size))
1314 return GNUNET_SYSERR;
1321 * Incoming meessage. Process the request.
1323 * @param cls the client
1324 * @param im the send message that was received
1327 handle_incoming_msg (void *cls,
1328 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1330 struct TransportClient *tc = cls;
1332 GNUNET_SERVICE_client_continue (tc->client);
1337 * New queue became available. Check message.
1339 * @param cls the client
1340 * @param aqm the send message that was sent
1343 check_add_queue_message (void *cls,
1344 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1346 struct TransportClient *tc = cls;
1348 if (CT_COMMUNICATOR != tc->type)
1351 return GNUNET_SYSERR;
1353 GNUNET_MQ_check_zero_termination (aqm);
1359 * New queue became available. Process the request.
1361 * @param cls the client
1362 * @param aqm the send message that was sent
1365 handle_add_queue_message (void *cls,
1366 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1368 struct TransportClient *tc = cls;
1369 struct Queue *queue;
1370 struct Neighbour *neighbour;
1374 neighbour = lookup_neighbour (&aqm->receiver);
1375 if (NULL == neighbour)
1377 neighbour = GNUNET_new (struct Neighbour);
1378 neighbour->pid = aqm->receiver;
1379 GNUNET_assert (GNUNET_OK ==
1380 GNUNET_CONTAINER_multipeermap_put (neighbours,
1383 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1384 cores_send_connect_info (&neighbour->pid,
1385 GNUNET_BANDWIDTH_ZERO);
1386 // FIXME: notify ATS!
1388 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
1389 addr = (const char *) &aqm[1];
1391 queue = GNUNET_malloc (sizeof (struct Queue) + addr_len);
1393 queue->address = (const char *) &queue[1];
1394 queue->rtt = GNUNET_TIME_UNIT_FOREVER_REL;
1395 queue->qid = aqm->qid;
1396 queue->mtu = ntohl (aqm->mtu);
1397 queue->distance = ntohl (aqm->distance);
1398 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
1399 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
1400 queue->neighbour = neighbour;
1404 /* notify monitors about new queue */
1406 struct MonitorEvent me = {
1411 notify_monitors (&neighbour->pid,
1416 GNUNET_CONTAINER_MDLL_insert (neighbour,
1417 neighbour->queue_head,
1418 neighbour->queue_tail,
1420 GNUNET_CONTAINER_MDLL_insert (client,
1421 tc->details.communicator.queue_head,
1422 tc->details.communicator.queue_tail,
1424 // FIXME: possibly transmit queued messages?
1425 GNUNET_SERVICE_client_continue (tc->client);
1430 * Queue to a peer went down. Process the request.
1432 * @param cls the client
1433 * @param dqm the send message that was sent
1436 handle_del_queue_message (void *cls,
1437 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
1439 struct TransportClient *tc = cls;
1441 if (CT_COMMUNICATOR != tc->type)
1444 GNUNET_SERVICE_client_drop (tc->client);
1447 for (struct Queue *queue = tc->details.communicator.queue_head;
1449 queue = queue->next_client)
1451 struct Neighbour *neighbour = queue->neighbour;
1453 if ( (dqm->qid != queue->qid) ||
1454 (0 != memcmp (&dqm->receiver,
1456 sizeof (struct GNUNET_PeerIdentity))) )
1459 GNUNET_SERVICE_client_continue (tc->client);
1463 GNUNET_SERVICE_client_drop (tc->client);
1468 * Message was transmitted. Process the request.
1470 * @param cls the client
1471 * @param sma the send message that was sent
1474 handle_send_message_ack (void *cls,
1475 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
1477 struct TransportClient *tc = cls;
1479 if (CT_COMMUNICATOR != tc->type)
1482 GNUNET_SERVICE_client_drop (tc->client);
1485 GNUNET_SERVICE_client_continue (tc->client);
1490 * Iterator telling new MONITOR client about all existing
1493 * @param cls the new `struct TransportClient`
1494 * @param pid a connected peer
1495 * @param value the `struct Neighbour` with more information
1496 * @return #GNUNET_OK (continue to iterate)
1499 notify_client_queues (void *cls,
1500 const struct GNUNET_PeerIdentity *pid,
1503 struct TransportClient *tc = cls;
1504 struct Neighbour *neighbour = value;
1506 GNUNET_assert (CT_MONITOR == tc->type);
1507 for (struct Queue *q = neighbour->queue_head;
1509 q = q->next_neighbour)
1511 struct MonitorEvent me = {
1514 .num_msg_pending = q->num_msg_pending,
1515 .num_bytes_pending = q->num_bytes_pending
1529 * Initialize a monitor client.
1531 * @param cls the client
1532 * @param start the start message that was sent
1535 handle_monitor_start (void *cls,
1536 const struct GNUNET_TRANSPORT_MonitorStart *start)
1538 struct TransportClient *tc = cls;
1540 if (CT_NONE != tc->type)
1543 GNUNET_SERVICE_client_drop (tc->client);
1546 tc->type = CT_MONITOR;
1547 tc->details.monitor.peer = start->peer;
1548 tc->details.monitor.one_shot = ntohl (start->one_shot);
1549 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1550 ¬ify_client_queues,
1552 GNUNET_SERVICE_client_mark_monitor (tc->client);
1553 GNUNET_SERVICE_client_continue (tc->client);
1558 * Free neighbour entry.
1562 * @param value a `struct Neighbour`
1563 * @return #GNUNET_OK (always)
1566 free_neighbour_cb (void *cls,
1567 const struct GNUNET_PeerIdentity *pid,
1570 struct Neighbour *neighbour = value;
1574 GNUNET_break (0); // should this ever happen?
1575 free_neighbour (neighbour);
1582 * Function called when the service shuts down. Unloads our plugins
1583 * and cancels pending validations.
1585 * @param cls closure, unused
1588 do_shutdown (void *cls)
1592 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1595 if (NULL != peerstore)
1597 GNUNET_PEERSTORE_disconnect (peerstore,
1601 if (NULL != GST_stats)
1603 GNUNET_STATISTICS_destroy (GST_stats,
1607 if (NULL != GST_my_private_key)
1609 GNUNET_free (GST_my_private_key);
1610 GST_my_private_key = NULL;
1612 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
1617 * Initiate transport service.
1619 * @param cls closure
1620 * @param c configuration to use
1621 * @param service the initialized service
1625 const struct GNUNET_CONFIGURATION_Handle *c,
1626 struct GNUNET_SERVICE_Handle *service)
1631 neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
1633 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
1634 if (NULL == GST_my_private_key)
1636 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1637 _("Transport service is lacking key configuration settings. Exiting.\n"));
1638 GNUNET_SCHEDULER_shutdown ();
1641 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
1642 &GST_my_identity.public_key);
1643 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1644 "My identity is `%s'\n",
1645 GNUNET_i2s_full (&GST_my_identity));
1647 GST_stats = GNUNET_STATISTICS_create ("transport",
1649 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1651 peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
1652 if (NULL == peerstore)
1655 GNUNET_SCHEDULER_shutdown ();
1658 /* start subsystems */
1663 * Define "main" method using service macro.
1667 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
1670 &client_disconnect_cb,
1672 /* communication with core */
1673 GNUNET_MQ_hd_fixed_size (client_start,
1674 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
1675 struct StartMessage,
1677 GNUNET_MQ_hd_var_size (client_send,
1678 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
1679 struct OutboundMessage,
1681 /* communication with communicators */
1682 GNUNET_MQ_hd_var_size (communicator_available,
1683 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
1684 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
1686 GNUNET_MQ_hd_var_size (add_address,
1687 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
1688 struct GNUNET_TRANSPORT_AddAddressMessage,
1690 GNUNET_MQ_hd_fixed_size (del_address,
1691 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
1692 struct GNUNET_TRANSPORT_DelAddressMessage,
1694 GNUNET_MQ_hd_var_size (incoming_msg,
1695 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
1696 struct GNUNET_TRANSPORT_IncomingMessage,
1698 GNUNET_MQ_hd_var_size (add_queue_message,
1699 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
1700 struct GNUNET_TRANSPORT_AddQueueMessage,
1702 GNUNET_MQ_hd_fixed_size (del_queue_message,
1703 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
1704 struct GNUNET_TRANSPORT_DelQueueMessage,
1706 GNUNET_MQ_hd_fixed_size (send_message_ack,
1707 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
1708 struct GNUNET_TRANSPORT_SendMessageToAck,
1710 /* communication with monitors */
1711 GNUNET_MQ_hd_fixed_size (monitor_start,
1712 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
1713 struct GNUNET_TRANSPORT_MonitorStart,
1715 GNUNET_MQ_handler_end ());
1718 /* end of file gnunet-service-transport.c */