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_ATS_Network_Type 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_ATS_Network_Type 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_ATS_Network_Type 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_ATS_Network_Type 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;
1084 if (CT_NONE != tc->type)
1087 return GNUNET_SYSERR;
1089 tc->type = CT_COMMUNICATOR;
1090 size = ntohs (cam->header.size) - sizeof (*cam);
1092 return GNUNET_OK; /* receive-only communicator */
1093 addr = (const char *) &cam[1];
1094 if ('\0' != addr[size-1])
1097 return GNUNET_SYSERR;
1104 * Communicator started. Process the request.
1106 * @param cls the client
1107 * @param cam the send message that was sent
1110 handle_communicator_available (void *cls,
1111 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1113 struct TransportClient *tc = cls;
1116 size = ntohs (cam->header.size) - sizeof (*cam);
1118 return; /* receive-only communicator */
1119 tc->details.communicator.address_prefix
1120 = GNUNET_strdup ((const char *) &cam[1]);
1121 tc->details.communicator.cc
1122 = (enum GNUNET_TRANSPORT_CommunicatorCharacteristics) ntohl (cam->cc);
1123 GNUNET_SERVICE_client_continue (tc->client);
1128 * Address of our peer added. Test message is well-formed.
1130 * @param cls the client
1131 * @param aam the send message that was sent
1134 check_add_address (void *cls,
1135 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1137 struct TransportClient *tc = cls;
1141 if (CT_COMMUNICATOR != tc->type)
1144 return GNUNET_SYSERR;
1146 size = ntohs (aam->header.size) - sizeof (*aam);
1150 return GNUNET_SYSERR;
1152 addr = (const char *) &aam[1];
1153 if ('\0' != addr[size-1])
1156 return GNUNET_SYSERR;
1163 * Ask peerstore to store our address.
1165 * @param cls an `struct AddressListEntry *`
1168 store_pi (void *cls);
1172 * Function called when peerstore is done storing our address.
1175 peerstore_store_cb (void *cls,
1178 struct AddressListEntry *ale = cls;
1181 if (GNUNET_YES != success)
1182 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1183 "Failed to store our own address `%s' in peerstore!\n",
1185 /* refresh period is 1/4 of expiration time, that should be plenty
1186 without being excessive. */
1187 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
1195 * Ask peerstore to store our address.
1197 * @param cls an `struct AddressListEntry *`
1200 store_pi (void *cls)
1202 struct AddressListEntry *ale = cls;
1205 struct GNUNET_TIME_Absolute expiration;
1208 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
1209 GNUNET_HELLO_sign_address (ale->address,
1215 ale->sc = GNUNET_PEERSTORE_store (peerstore,
1222 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
1223 &peerstore_store_cb,
1226 if (NULL == ale->sc)
1228 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1229 "Failed to store our address `%s' with peerstore\n",
1231 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
1239 * Address of our peer added. Process the request.
1241 * @param cls the client
1242 * @param aam the send message that was sent
1245 handle_add_address (void *cls,
1246 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1248 struct TransportClient *tc = cls;
1249 struct AddressListEntry *ale;
1252 slen = ntohs (aam->header.size) - sizeof (*aam);
1253 ale = GNUNET_malloc (sizeof (struct AddressListEntry) + slen);
1255 ale->address = (const char *) &ale[1];
1256 ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
1257 ale->aid = aam->aid;
1258 ale->nt = (enum GNUNET_ATS_Network_Type) ntohl (aam->nt);
1262 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
1263 tc->details.communicator.addr_tail,
1265 ale->st = GNUNET_SCHEDULER_add_now (&store_pi,
1267 GNUNET_SERVICE_client_continue (tc->client);
1272 * Address of our peer deleted. Process the request.
1274 * @param cls the client
1275 * @param dam the send message that was sent
1278 handle_del_address (void *cls,
1279 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
1281 struct TransportClient *tc = cls;
1283 if (CT_COMMUNICATOR != tc->type)
1286 GNUNET_SERVICE_client_drop (tc->client);
1289 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
1293 if (dam->aid != ale->aid)
1295 GNUNET_assert (ale->tc == tc);
1296 free_address_list_entry (ale);
1297 GNUNET_SERVICE_client_continue (tc->client);
1300 GNUNET_SERVICE_client_drop (tc->client);
1305 * Client notified us about transmission from a peer. Process the request.
1307 * @param cls the client
1308 * @param obm the send message that was sent
1311 check_incoming_msg (void *cls,
1312 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1314 struct TransportClient *tc = cls;
1316 const struct GNUNET_MessageHeader *obmm;
1318 if (CT_COMMUNICATOR != tc->type)
1321 return GNUNET_SYSERR;
1323 size = ntohs (im->header.size) - sizeof (*im);
1324 if (size < sizeof (struct GNUNET_MessageHeader))
1327 return GNUNET_SYSERR;
1329 obmm = (const struct GNUNET_MessageHeader *) &im[1];
1330 if (size != ntohs (obmm->size))
1333 return GNUNET_SYSERR;
1340 * Incoming meessage. Process the request.
1342 * @param cls the client
1343 * @param im the send message that was received
1346 handle_incoming_msg (void *cls,
1347 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1349 struct TransportClient *tc = cls;
1351 GNUNET_SERVICE_client_continue (tc->client);
1356 * New queue became available. Check message.
1358 * @param cls the client
1359 * @param aqm the send message that was sent
1362 check_add_queue_message (void *cls,
1363 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1365 struct TransportClient *tc = cls;
1369 if (CT_COMMUNICATOR != tc->type)
1372 return GNUNET_SYSERR;
1374 size = ntohs (aqm->header.size) - sizeof (*aqm);
1378 return GNUNET_SYSERR;
1380 addr = (const char *) &aqm[1];
1381 if ('\0' != addr[size-1])
1384 return GNUNET_SYSERR;
1391 * New queue became available. Process the request.
1393 * @param cls the client
1394 * @param aqm the send message that was sent
1397 handle_add_queue_message (void *cls,
1398 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1400 struct TransportClient *tc = cls;
1401 struct Queue *queue;
1402 struct Neighbour *neighbour;
1406 neighbour = lookup_neighbour (&aqm->receiver);
1407 if (NULL == neighbour)
1409 neighbour = GNUNET_new (struct Neighbour);
1410 neighbour->pid = aqm->receiver;
1411 GNUNET_assert (GNUNET_OK ==
1412 GNUNET_CONTAINER_multipeermap_put (neighbours,
1415 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1416 cores_send_connect_info (&neighbour->pid,
1417 GNUNET_BANDWIDTH_ZERO);
1418 // FIXME: notify ATS!
1420 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
1421 addr = (const char *) &aqm[1];
1423 queue = GNUNET_malloc (sizeof (struct Queue) + addr_len);
1425 queue->address = (const char *) &queue[1];
1426 queue->rtt = GNUNET_TIME_UNIT_FOREVER_REL;
1427 queue->qid = aqm->qid;
1428 queue->mtu = ntohl (aqm->mtu);
1429 queue->distance = ntohl (aqm->distance);
1430 queue->nt = (enum GNUNET_ATS_Network_Type) ntohl (aqm->nt);
1431 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
1432 queue->neighbour = neighbour;
1436 /* notify monitors about new queue */
1438 struct MonitorEvent me = {
1443 notify_monitors (&neighbour->pid,
1448 GNUNET_CONTAINER_MDLL_insert (neighbour,
1449 neighbour->queue_head,
1450 neighbour->queue_tail,
1452 GNUNET_CONTAINER_MDLL_insert (client,
1453 tc->details.communicator.queue_head,
1454 tc->details.communicator.queue_tail,
1456 // FIXME: possibly transmit queued messages?
1457 GNUNET_SERVICE_client_continue (tc->client);
1462 * Queue to a peer went down. Process the request.
1464 * @param cls the client
1465 * @param dqm the send message that was sent
1468 handle_del_queue_message (void *cls,
1469 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
1471 struct TransportClient *tc = cls;
1473 if (CT_COMMUNICATOR != tc->type)
1476 GNUNET_SERVICE_client_drop (tc->client);
1479 for (struct Queue *queue = tc->details.communicator.queue_head;
1481 queue = queue->next_client)
1483 struct Neighbour *neighbour = queue->neighbour;
1485 if ( (dqm->qid != queue->qid) ||
1486 (0 != memcmp (&dqm->receiver,
1488 sizeof (struct GNUNET_PeerIdentity))) )
1491 GNUNET_SERVICE_client_continue (tc->client);
1495 GNUNET_SERVICE_client_drop (tc->client);
1500 * Message was transmitted. Process the request.
1502 * @param cls the client
1503 * @param sma the send message that was sent
1506 handle_send_message_ack (void *cls,
1507 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
1509 struct TransportClient *tc = cls;
1511 if (CT_COMMUNICATOR != tc->type)
1514 GNUNET_SERVICE_client_drop (tc->client);
1517 GNUNET_SERVICE_client_continue (tc->client);
1522 * Iterator telling new MONITOR client about all existing
1525 * @param cls the new `struct TransportClient`
1526 * @param pid a connected peer
1527 * @param value the `struct Neighbour` with more information
1528 * @return #GNUNET_OK (continue to iterate)
1531 notify_client_queues (void *cls,
1532 const struct GNUNET_PeerIdentity *pid,
1535 struct TransportClient *tc = cls;
1536 struct Neighbour *neighbour = value;
1538 GNUNET_assert (CT_MONITOR == tc->type);
1539 for (struct Queue *q = neighbour->queue_head;
1541 q = q->next_neighbour)
1543 struct MonitorEvent me = {
1546 .num_msg_pending = q->num_msg_pending,
1547 .num_bytes_pending = q->num_bytes_pending
1561 * Initialize a monitor client.
1563 * @param cls the client
1564 * @param start the start message that was sent
1567 handle_monitor_start (void *cls,
1568 const struct GNUNET_TRANSPORT_MonitorStart *start)
1570 struct TransportClient *tc = cls;
1572 if (CT_NONE != tc->type)
1575 GNUNET_SERVICE_client_drop (tc->client);
1578 tc->type = CT_MONITOR;
1579 tc->details.monitor.peer = start->peer;
1580 tc->details.monitor.one_shot = ntohl (start->one_shot);
1581 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1582 ¬ify_client_queues,
1584 GNUNET_SERVICE_client_mark_monitor (tc->client);
1585 GNUNET_SERVICE_client_continue (tc->client);
1590 * Free neighbour entry.
1594 * @param value a `struct Neighbour`
1595 * @return #GNUNET_OK (always)
1598 free_neighbour_cb (void *cls,
1599 const struct GNUNET_PeerIdentity *pid,
1602 struct Neighbour *neighbour = value;
1606 GNUNET_break (0); // should this ever happen?
1607 free_neighbour (neighbour);
1614 * Function called when the service shuts down. Unloads our plugins
1615 * and cancels pending validations.
1617 * @param cls closure, unused
1620 do_shutdown (void *cls)
1624 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1627 if (NULL != peerstore)
1629 GNUNET_PEERSTORE_disconnect (peerstore,
1633 if (NULL != GST_stats)
1635 GNUNET_STATISTICS_destroy (GST_stats,
1639 if (NULL != GST_my_private_key)
1641 GNUNET_free (GST_my_private_key);
1642 GST_my_private_key = NULL;
1644 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
1649 * Initiate transport service.
1651 * @param cls closure
1652 * @param c configuration to use
1653 * @param service the initialized service
1657 const struct GNUNET_CONFIGURATION_Handle *c,
1658 struct GNUNET_SERVICE_Handle *service)
1663 neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
1665 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
1666 if (NULL == GST_my_private_key)
1668 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1669 _("Transport service is lacking key configuration settings. Exiting.\n"));
1670 GNUNET_SCHEDULER_shutdown ();
1673 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
1674 &GST_my_identity.public_key);
1675 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1676 "My identity is `%s'\n",
1677 GNUNET_i2s_full (&GST_my_identity));
1679 GST_stats = GNUNET_STATISTICS_create ("transport",
1681 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1683 peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
1684 if (NULL == peerstore)
1687 GNUNET_SCHEDULER_shutdown ();
1690 /* start subsystems */
1695 * Define "main" method using service macro.
1699 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
1702 &client_disconnect_cb,
1704 /* communication with core */
1705 GNUNET_MQ_hd_fixed_size (client_start,
1706 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
1707 struct StartMessage,
1709 GNUNET_MQ_hd_var_size (client_send,
1710 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
1711 struct OutboundMessage,
1713 /* communication with communicators */
1714 GNUNET_MQ_hd_var_size (communicator_available,
1715 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
1716 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
1718 GNUNET_MQ_hd_var_size (add_address,
1719 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
1720 struct GNUNET_TRANSPORT_AddAddressMessage,
1722 GNUNET_MQ_hd_fixed_size (del_address,
1723 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
1724 struct GNUNET_TRANSPORT_DelAddressMessage,
1726 GNUNET_MQ_hd_var_size (incoming_msg,
1727 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
1728 struct GNUNET_TRANSPORT_IncomingMessage,
1730 GNUNET_MQ_hd_var_size (add_queue_message,
1731 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
1732 struct GNUNET_TRANSPORT_AddQueueMessage,
1734 GNUNET_MQ_hd_fixed_size (del_queue_message,
1735 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
1736 struct GNUNET_TRANSPORT_DelQueueMessage,
1738 GNUNET_MQ_hd_fixed_size (send_message_ack,
1739 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
1740 struct GNUNET_TRANSPORT_SendMessageToAck,
1742 /* communication with monitors */
1743 GNUNET_MQ_hd_fixed_size (monitor_start,
1744 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
1745 struct GNUNET_TRANSPORT_MonitorStart,
1747 GNUNET_MQ_handler_end ());
1750 /* end of file gnunet-service-transport.c */