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
24 * - monitor start: iterate to inform monitor about all existing queues!
25 * - manage fragmentation/defragmentation, retransmission, track RTT, loss, etc.
26 * - inform ATS about RTT, goodput/loss, overheads, etc.
27 * - ask ATS about bandwidth allocation!
31 #include "gnunet_util_lib.h"
32 #include "gnunet_statistics_service.h"
33 #include "gnunet_transport_service.h"
34 #include "gnunet_transport_monitor_service.h"
35 #include "gnunet_peerstore_service.h"
36 #include "gnunet_ats_service.h"
37 #include "gnunet-service-transport.h"
38 #include "transport.h"
42 * How many messages can we have pending for a given client process
43 * before we start to drop incoming messages? We typically should
44 * have only one client and so this would be the primary buffer for
45 * messages, so the number should be chosen rather generously.
47 * The expectation here is that most of the time the queue is large
48 * enough so that a drop is virtually never required. Note that
49 * this value must be about as large as 'TOTAL_MSGS' in the
50 * 'test_transport_api_reliability.c', otherwise that testcase may
53 #define MAX_PENDING (128 * 1024)
57 * What type of client is the `struct TransportClient` about?
62 * We do not know yet (client is fresh).
67 * Is the CORE service, we need to forward traffic to it.
72 * It is a monitor, forward monitor data.
77 * It is a communicator, use for communication.
84 * Client connected to the transport service.
86 struct TransportClient;
90 * A neighbour that at least one communicator is connected to.
96 * List of available queues for a particular neighbour.
103 struct Queue *next_neighbour;
108 struct Queue *prev_neighbour;
113 struct Queue *prev_client;
118 struct Queue *next_client;
121 * Which neighbour is this queue for?
123 struct Neighbour *neighbour;
126 * Which communicator offers this queue?
128 struct TransportClient *tc;
131 * Address served by the queue.
136 * Unique identifier of this queue with the communicator.
141 * Maximum transmission unit supported by this queue.
146 * Network type offered by this queue.
148 enum GNUNET_ATS_Network_Type nt;
150 // FIXME: add ATS-specific fields here!
155 * A neighbour that at least one communicator is connected to.
161 * Which peer is this about?
163 struct GNUNET_PeerIdentity pid;
166 * Head of list of messages pending for this neighbour.
168 struct PendingMessage *pending_msg_head;
171 * Tail of list of messages pending for this neighbour.
173 struct PendingMessage *pending_msg_tail;
176 * Head of DLL of queues to this peer.
178 struct Queue *queue_head;
181 * Tail of DLL of queues to this peer.
183 struct Queue *queue_tail;
186 * Quota at which CORE is allowed to transmit to this peer
189 * FIXME: not yet used, tricky to get right given multiple queues!
190 * (=> Idea: let ATS set a quota per queue and we add them up here?)
191 * FIXME: how do we set this value initially when we tell CORE?
192 * Options: start at a minimum value or at literally zero (before ATS?)
193 * (=> Current thought: clean would be zero!)
195 struct GNUNET_BANDWIDTH_Value32NBO quota_out;
201 * Transmission request from CORE that is awaiting delivery.
203 struct PendingMessage
206 * Kept in a MDLL of messages for this @a target.
208 struct PendingMessage *next_neighbour;
211 * Kept in a MDLL of messages for this @a target.
213 struct PendingMessage *prev_neighbour;
216 * Kept in a MDLL of messages from this @a client.
218 struct PendingMessage *next_client;
221 * Kept in a MDLL of messages from this @a client.
223 struct PendingMessage *prev_client;
226 * Target of the request.
228 struct Neighbour *target;
231 * Client that issued the transmission request.
233 struct TransportClient *client;
236 * Size of the original message.
244 * One of the addresses of this peer.
246 struct AddressListEntry
252 struct AddressListEntry *next;
257 struct AddressListEntry *prev;
260 * Which communicator provides this address?
262 struct TransportClient *tc;
265 * The actual address.
270 * Current context for storing this address in the peerstore.
272 struct GNUNET_PEERSTORE_StoreContext *sc;
275 * Task to periodically do @e st operation.
277 struct GNUNET_SCHEDULER_Task *st;
280 * What is a typical lifetime the communicator expects this
281 * address to have? (Always from now.)
283 struct GNUNET_TIME_Relative expiration;
286 * Address identifier used by the communicator.
291 * Network type offered by this address.
293 enum GNUNET_ATS_Network_Type nt;
299 * Client connected to the transport service.
301 struct TransportClient
307 struct TransportClient *next;
312 struct TransportClient *prev;
315 * Handle to the client.
317 struct GNUNET_SERVICE_Client *client;
320 * Message queue to the client.
322 struct GNUNET_MQ_Handle *mq;
325 * What type of client is this?
327 enum ClientType type;
333 * Information for @e type #CT_CORE.
338 * Head of list of messages pending for this client.
340 struct PendingMessage *pending_msg_head;
343 * Tail of list of messages pending for this client.
345 struct PendingMessage *pending_msg_tail;
350 * Information for @e type #CT_MONITOR.
355 * Peer identity to monitor the addresses of.
356 * Zero to monitor all neighbours. Valid if
357 * @e type is #CT_MONITOR.
359 struct GNUNET_PeerIdentity peer;
362 * Is this a one-shot monitor?
370 * Information for @e type #CT_COMMUNICATOR.
374 * If @e type is #CT_COMMUNICATOR, this communicator
375 * supports communicating using these addresses.
377 char *address_prefix;
380 * Head of DLL of queues offered by this communicator.
382 struct Queue *queue_head;
385 * Tail of DLL of queues offered by this communicator.
387 struct Queue *queue_tail;
390 * Head of list of the addresses of this peer offered by this communicator.
392 struct AddressListEntry *addr_head;
395 * Tail of list of the addresses of this peer offered by this communicator.
397 struct AddressListEntry *addr_tail;
407 * Head of linked list of all clients to this service.
409 static struct TransportClient *clients_head;
412 * Tail of linked list of all clients to this service.
414 static struct TransportClient *clients_tail;
419 struct GNUNET_STATISTICS_Handle *GST_stats;
422 * Configuration handle.
424 const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
429 struct GNUNET_PeerIdentity GST_my_identity;
434 struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
437 * Map from PIDs to `struct Neighbour` entries. A peer is
438 * a neighbour if we have an MQ to it from some communicator.
440 static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
443 * Database for peer's HELLOs.
445 static struct GNUNET_PEERSTORE_Handle *peerstore;
449 * Lookup neighbour record for peer @a pid.
451 * @param pid neighbour to look for
452 * @return NULL if we do not have this peer as a neighbour
454 static struct Neighbour *
455 lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
457 return GNUNET_CONTAINER_multipeermap_get (neighbours,
463 * Details about what to notify monitors about.
468 * @deprecated To be discussed if we keep these...
470 struct GNUNET_TIME_Absolute last_validation;
471 struct GNUNET_TIME_Absolute valid_until;
472 struct GNUNET_TIME_Absolute next_validation;
475 * Current round-trip time estimate.
477 struct GNUNET_TIME_Relative rtt;
482 enum GNUNET_TRANSPORT_ConnectionStatus cs;
487 uint32_t num_msg_pending;
492 uint32_t num_bytes_pending;
499 * Notify monitor @a tc about an event. That @a tc
500 * cares about the event has already been checked.
502 * Send @a tc information in @a me about a @a peer's status with
503 * respect to some @a address to all monitors that care.
505 * @param tc monitor to inform
506 * @param peer peer the information is about
507 * @param address address the information is about
508 * @param nt network type associated with @a address
509 * @param me detailed information to transmit
512 notify_monitor (struct TransportClient *tc,
513 const struct GNUNET_PeerIdentity *peer,
515 enum GNUNET_ATS_Network_Type nt,
516 const struct MonitorEvent *me)
518 struct GNUNET_MQ_Envelope *env;
519 struct GNUNET_TRANSPORT_MonitorData *md;
520 size_t addr_len = strlen (address) + 1;
522 env = GNUNET_MQ_msg_extra (md,
524 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA);
525 md->nt = htonl ((uint32_t) nt);
527 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
528 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
529 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
530 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
531 md->cs = htonl ((uint32_t) me->cs);
532 md->num_msg_pending = htonl (me->num_msg_pending);
533 md->num_bytes_pending = htonl (me->num_bytes_pending);
537 GNUNET_MQ_send (tc->mq,
543 * Send information in @a me about a @a peer's status with respect
544 * to some @a address to all monitors that care.
546 * @param peer peer the information is about
547 * @param address address the information is about
548 * @param nt network type associated with @a address
549 * @param me detailed information to transmit
552 notify_monitors (const struct GNUNET_PeerIdentity *peer,
554 enum GNUNET_ATS_Network_Type nt,
555 const struct MonitorEvent *me)
557 static struct GNUNET_PeerIdentity zero;
559 for (struct TransportClient *tc = clients_head;
563 if (CT_MONITOR != tc->type)
565 if (tc->details.monitor.one_shot)
567 if ( (0 != memcmp (&tc->details.monitor.peer,
570 (0 != memcmp (&tc->details.monitor.peer,
584 * Called whenever a client connects. Allocates our
585 * data structures associated with that client.
587 * @param cls closure, NULL
588 * @param client identification of the client
589 * @param mq message queue for the client
590 * @return our `struct TransportClient`
593 client_connect_cb (void *cls,
594 struct GNUNET_SERVICE_Client *client,
595 struct GNUNET_MQ_Handle *mq)
597 struct TransportClient *tc;
599 tc = GNUNET_new (struct TransportClient);
602 GNUNET_CONTAINER_DLL_insert (clients_head,
605 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
606 "Client %p connected\n",
613 * Release memory used by @a neighbour.
615 * @param neighbour neighbour entry to free
618 free_neighbour (struct Neighbour *neighbour)
620 GNUNET_assert (NULL == neighbour->queue_head);
621 GNUNET_assert (GNUNET_YES ==
622 GNUNET_CONTAINER_multipeermap_remove (neighbours,
625 GNUNET_free (neighbour);
630 * Send message to CORE clients that we lost a connection.
632 * @param tc client to inform (must be CORE client)
633 * @param pid peer the connection is for
634 * @param quota_out current quota for the peer
637 core_send_connect_info (struct TransportClient *tc,
638 const struct GNUNET_PeerIdentity *pid,
639 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
641 struct GNUNET_MQ_Envelope *env;
642 struct ConnectInfoMessage *cim;
644 GNUNET_assert (CT_CORE == tc->type);
645 env = GNUNET_MQ_msg (cim,
646 GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
647 cim->quota_out = quota_out;
649 GNUNET_MQ_send (tc->mq,
655 * Send message to CORE clients that we gained a connection
657 * @param pid peer the queue was for
658 * @param quota_out current quota for the peer
661 cores_send_connect_info (const struct GNUNET_PeerIdentity *pid,
662 struct GNUNET_BANDWIDTH_Value32NBO quota_out)
664 for (struct TransportClient *tc = clients_head;
668 if (CT_CORE != tc->type)
670 core_send_connect_info (tc,
678 * Send message to CORE clients that we lost a connection.
680 * @param pid peer the connection was for
683 cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
685 for (struct TransportClient *tc = clients_head;
689 struct GNUNET_MQ_Envelope *env;
690 struct DisconnectInfoMessage *dim;
692 if (CT_CORE != tc->type)
694 env = GNUNET_MQ_msg (dim,
695 GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
697 GNUNET_MQ_send (tc->mq,
706 * @param queue the queue to free
709 free_queue (struct Queue *queue)
711 struct Neighbour *neighbour = queue->neighbour;
712 struct TransportClient *tc = queue->tc;
713 struct MonitorEvent me = {
714 .cs = GNUNET_TRANSPORT_CS_DOWN,
715 .rtt = GNUNET_TIME_UNIT_FOREVER_REL
718 GNUNET_CONTAINER_MDLL_remove (neighbour,
719 neighbour->queue_head,
720 neighbour->queue_tail,
722 GNUNET_CONTAINER_MDLL_remove (client,
723 tc->details.communicator.queue_head,
724 tc->details.communicator.queue_tail,
727 notify_monitors (&neighbour->pid,
732 if (NULL == neighbour->queue_head)
734 cores_send_disconnect_info (&neighbour->pid);
735 free_neighbour (neighbour);
743 * @param ale address list entry to free
746 free_address_list_entry (struct AddressListEntry *ale)
748 struct TransportClient *tc = ale->tc;
750 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
751 tc->details.communicator.addr_tail,
755 GNUNET_PEERSTORE_store_cancel (ale->sc);
760 GNUNET_SCHEDULER_cancel (ale->st);
768 * Called whenever a client is disconnected. Frees our
769 * resources associated with that client.
771 * @param cls closure, NULL
772 * @param client identification of the client
773 * @param app_ctx our `struct TransportClient`
776 client_disconnect_cb (void *cls,
777 struct GNUNET_SERVICE_Client *client,
780 struct TransportClient *tc = app_ctx;
782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
783 "Client %p disconnected, cleaning up.\n",
785 GNUNET_CONTAINER_DLL_remove (clients_head,
794 struct PendingMessage *pm;
796 while (NULL != (pm = tc->details.core.pending_msg_head))
798 GNUNET_CONTAINER_MDLL_remove (client,
799 tc->details.core.pending_msg_head,
800 tc->details.core.pending_msg_tail,
808 case CT_COMMUNICATOR:
811 struct AddressListEntry *ale;
813 while (NULL != (q = tc->details.communicator.queue_head))
815 while (NULL != (ale = tc->details.communicator.addr_head))
816 free_address_list_entry (ale);
817 GNUNET_free (tc->details.communicator.address_prefix);
826 * Iterator telling new CORE client about all existing
827 * connections to peers.
829 * @param cls the new `struct TransportClient`
830 * @param pid a connected peer
831 * @param value the `struct Neighbour` with more information
832 * @return #GNUNET_OK (continue to iterate)
835 notify_client_connect_info (void *cls,
836 const struct GNUNET_PeerIdentity *pid,
839 struct TransportClient *tc = cls;
840 struct Neighbour *neighbour = value;
842 core_send_connect_info (tc,
844 neighbour->quota_out);
850 * Initialize a "CORE" client. We got a start message from this
851 * client, so add it to the list of clients for broadcasting of
854 * @param cls the client
855 * @param start the start message that was sent
858 handle_client_start (void *cls,
859 const struct StartMessage *start)
861 struct TransportClient *tc = cls;
864 options = ntohl (start->options);
865 if ( (0 != (1 & options)) &&
867 memcmp (&start->self,
869 sizeof (struct GNUNET_PeerIdentity)) ) )
871 /* client thinks this is a different peer, reject */
873 GNUNET_SERVICE_client_drop (tc->client);
876 if (CT_NONE != tc->type)
879 GNUNET_SERVICE_client_drop (tc->client);
883 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
884 ¬ify_client_connect_info,
886 GNUNET_SERVICE_client_continue (tc->client);
891 * Client asked for transmission to a peer. Process the request.
893 * @param cls the client
894 * @param obm the send message that was sent
897 check_client_send (void *cls,
898 const struct OutboundMessage *obm)
900 struct TransportClient *tc = cls;
902 const struct GNUNET_MessageHeader *obmm;
904 if (CT_CORE != tc->type)
907 return GNUNET_SYSERR;
909 size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
910 if (size < sizeof (struct GNUNET_MessageHeader))
913 return GNUNET_SYSERR;
915 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
916 if (size != ntohs (obmm->size))
919 return GNUNET_SYSERR;
926 * Send a response to the @a pm that we have processed a
927 * "send" request with status @a success. We
928 * transmitted @a bytes_physical on the actual wire.
929 * Sends a confirmation to the "core" client responsible
930 * for the original request and free's @a pm.
932 * @param pm handle to the original pending message
933 * @param success status code, #GNUNET_OK on success, #GNUNET_SYSERR
934 * for transmission failure
935 * @param bytes_physical amount of bandwidth consumed
938 client_send_response (struct PendingMessage *pm,
940 uint32_t bytes_physical)
942 struct TransportClient *tc = pm->client;
943 struct Neighbour *target = pm->target;
944 struct GNUNET_MQ_Envelope *env;
945 struct SendOkMessage *som;
949 env = GNUNET_MQ_msg (som,
950 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
951 som->success = htonl ((uint32_t) success);
952 som->bytes_msg = htonl (pm->bytes_msg);
953 som->bytes_physical = htonl (bytes_physical);
954 som->peer = target->pid;
955 GNUNET_MQ_send (tc->mq,
957 GNUNET_CONTAINER_MDLL_remove (client,
958 tc->details.core.pending_msg_head,
959 tc->details.core.pending_msg_tail,
962 GNUNET_CONTAINER_MDLL_remove (neighbour,
963 target->pending_msg_head,
964 target->pending_msg_tail,
971 * Client asked for transmission to a peer. Process the request.
973 * @param cls the client
974 * @param obm the send message that was sent
977 handle_client_send (void *cls,
978 const struct OutboundMessage *obm)
980 struct TransportClient *tc = cls;
981 struct PendingMessage *pm;
982 const struct GNUNET_MessageHeader *obmm;
983 struct Neighbour *target;
986 GNUNET_assert (CT_CORE == tc->type);
987 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
988 bytes_msg = ntohs (obmm->size);
989 target = lookup_neighbour (&obm->peer);
992 /* Failure: don't have this peer as a neighbour (anymore).
993 Might have gone down asynchronously, so this is NOT
994 a protocol violation by CORE. Still count the event,
995 as this should be rare. */
996 struct GNUNET_MQ_Envelope *env;
997 struct SendOkMessage *som;
999 env = GNUNET_MQ_msg (som,
1000 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1001 som->success = htonl (GNUNET_SYSERR);
1002 som->bytes_msg = htonl (bytes_msg);
1003 som->bytes_physical = htonl (0);
1004 som->peer = obm->peer;
1005 GNUNET_MQ_send (tc->mq,
1007 GNUNET_SERVICE_client_continue (tc->client);
1008 GNUNET_STATISTICS_update (GST_stats,
1009 "# messages dropped (neighbour unknown)",
1014 pm = GNUNET_new (struct PendingMessage);
1016 pm->target = target;
1017 pm->bytes_msg = bytes_msg;
1018 GNUNET_CONTAINER_MDLL_insert (neighbour,
1019 target->pending_msg_head,
1020 target->pending_msg_tail,
1022 GNUNET_CONTAINER_MDLL_insert (client,
1023 tc->details.core.pending_msg_head,
1024 tc->details.core.pending_msg_tail,
1026 // FIXME: do the work, final continuation with call to:
1027 client_send_response (pm,
1034 * Communicator started. Test message is well-formed.
1036 * @param cls the client
1037 * @param cam the send message that was sent
1040 check_communicator_available (void *cls,
1041 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1043 struct TransportClient *tc = cls;
1047 if (CT_NONE != tc->type)
1050 return GNUNET_SYSERR;
1052 tc->type = CT_COMMUNICATOR;
1053 size = ntohs (cam->header.size) - sizeof (*cam);
1055 return GNUNET_OK; /* receive-only communicator */
1056 addr = (const char *) &cam[1];
1057 if ('\0' != addr[size-1])
1060 return GNUNET_SYSERR;
1067 * Communicator started. Process the request.
1069 * @param cls the client
1070 * @param cam the send message that was sent
1073 handle_communicator_available (void *cls,
1074 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1076 struct TransportClient *tc = cls;
1079 size = ntohs (cam->header.size) - sizeof (*cam);
1081 return; /* receive-only communicator */
1082 tc->details.communicator.address_prefix = GNUNET_strdup ((const char *) &cam[1]);
1083 GNUNET_SERVICE_client_continue (tc->client);
1088 * Address of our peer added. Test message is well-formed.
1090 * @param cls the client
1091 * @param aam the send message that was sent
1094 check_add_address (void *cls,
1095 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1097 struct TransportClient *tc = cls;
1101 if (CT_COMMUNICATOR != tc->type)
1104 return GNUNET_SYSERR;
1106 size = ntohs (aam->header.size) - sizeof (*aam);
1110 return GNUNET_SYSERR;
1112 addr = (const char *) &aam[1];
1113 if ('\0' != addr[size-1])
1116 return GNUNET_SYSERR;
1123 * Ask peerstore to store our address.
1125 * @param cls an `struct AddressListEntry *`
1128 store_pi (void *cls);
1132 * Function called when peerstore is done storing our address.
1135 peerstore_store_cb (void *cls,
1138 struct AddressListEntry *ale = cls;
1141 if (GNUNET_YES != success)
1142 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1143 "Failed to store our own address `%s' in peerstore!\n",
1145 /* refresh period is 1/4 of expiration time, that should be plenty
1146 without being excessive. */
1147 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
1155 * Ask peerstore to store our address.
1157 * @param cls an `struct AddressListEntry *`
1160 store_pi (void *cls)
1162 struct AddressListEntry *ale = cls;
1165 struct GNUNET_TIME_Absolute expiration;
1168 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
1169 GNUNET_HELLO_sign_address (ale->address,
1175 ale->sc = GNUNET_PEERSTORE_store (peerstore,
1182 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
1183 &peerstore_store_cb,
1186 if (NULL == ale->sc)
1188 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1189 "Failed to store our address `%s' with peerstore\n",
1191 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
1199 * Address of our peer added. Process the request.
1201 * @param cls the client
1202 * @param aam the send message that was sent
1205 handle_add_address (void *cls,
1206 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1208 struct TransportClient *tc = cls;
1209 struct AddressListEntry *ale;
1212 slen = ntohs (aam->header.size) - sizeof (*aam);
1213 ale = GNUNET_malloc (sizeof (struct AddressListEntry) + slen);
1215 ale->address = (const char *) &ale[1];
1216 ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
1217 ale->aid = aam->aid;
1218 ale->nt = (enum GNUNET_ATS_Network_Type) ntohl (aam->nt);
1222 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
1223 tc->details.communicator.addr_tail,
1225 ale->st = GNUNET_SCHEDULER_add_now (&store_pi,
1227 GNUNET_SERVICE_client_continue (tc->client);
1232 * Address of our peer deleted. Process the request.
1234 * @param cls the client
1235 * @param dam the send message that was sent
1238 handle_del_address (void *cls,
1239 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
1241 struct TransportClient *tc = cls;
1243 if (CT_COMMUNICATOR != tc->type)
1246 GNUNET_SERVICE_client_drop (tc->client);
1249 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
1253 if (dam->aid != ale->aid)
1255 GNUNET_assert (ale->tc == tc);
1256 free_address_list_entry (ale);
1257 GNUNET_SERVICE_client_continue (tc->client);
1260 GNUNET_SERVICE_client_drop (tc->client);
1265 * Client notified us about transmission from a peer. Process the request.
1267 * @param cls the client
1268 * @param obm the send message that was sent
1271 check_incoming_msg (void *cls,
1272 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1274 struct TransportClient *tc = cls;
1276 const struct GNUNET_MessageHeader *obmm;
1278 if (CT_COMMUNICATOR != tc->type)
1281 return GNUNET_SYSERR;
1283 size = ntohs (im->header.size) - sizeof (*im);
1284 if (size < sizeof (struct GNUNET_MessageHeader))
1287 return GNUNET_SYSERR;
1289 obmm = (const struct GNUNET_MessageHeader *) &im[1];
1290 if (size != ntohs (obmm->size))
1293 return GNUNET_SYSERR;
1300 * Incoming meessage. Process the request.
1302 * @param cls the client
1303 * @param im the send message that was received
1306 handle_incoming_msg (void *cls,
1307 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1309 struct TransportClient *tc = cls;
1311 GNUNET_SERVICE_client_continue (tc->client);
1316 * New queue became available. Check message.
1318 * @param cls the client
1319 * @param aqm the send message that was sent
1322 check_add_queue_message (void *cls,
1323 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1325 struct TransportClient *tc = cls;
1329 if (CT_COMMUNICATOR != tc->type)
1332 return GNUNET_SYSERR;
1334 size = ntohs (aqm->header.size) - sizeof (*aqm);
1338 return GNUNET_SYSERR;
1340 addr = (const char *) &aqm[1];
1341 if ('\0' != addr[size-1])
1344 return GNUNET_SYSERR;
1351 * New queue became available. Process the request.
1353 * @param cls the client
1354 * @param aqm the send message that was sent
1357 handle_add_queue_message (void *cls,
1358 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1360 struct TransportClient *tc = cls;
1361 struct Queue *queue;
1362 struct Neighbour *neighbour;
1366 neighbour = lookup_neighbour (&aqm->receiver);
1367 if (NULL == neighbour)
1369 neighbour = GNUNET_new (struct Neighbour);
1370 neighbour->pid = aqm->receiver;
1371 GNUNET_assert (GNUNET_OK ==
1372 GNUNET_CONTAINER_multipeermap_put (neighbours,
1375 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1376 cores_send_connect_info (&neighbour->pid,
1377 GNUNET_BANDWIDTH_ZERO);
1378 // FIXME: notify ATS!
1380 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
1381 addr = (const char *) &aqm[1];
1383 queue = GNUNET_malloc (sizeof (struct Queue) + addr_len);
1384 queue->mtu = ntohl (aqm->mtu);
1385 queue->qid = aqm->qid;
1386 queue->nt = (enum GNUNET_ATS_Network_Type) ntohl (aqm->nt);
1388 queue->neighbour = neighbour;
1389 queue->address = (const char *) &queue[1];
1393 /* notify monitors about new queue */
1395 struct MonitorEvent me = {
1396 .cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs)
1399 notify_monitors (&neighbour->pid,
1404 GNUNET_CONTAINER_MDLL_insert (neighbour,
1405 neighbour->queue_head,
1406 neighbour->queue_tail,
1408 GNUNET_CONTAINER_MDLL_insert (client,
1409 tc->details.communicator.queue_head,
1410 tc->details.communicator.queue_tail,
1412 // FIXME: possibly transmit queued messages?
1413 GNUNET_SERVICE_client_continue (tc->client);
1418 * Queue to a peer went down. Process the request.
1420 * @param cls the client
1421 * @param dqm the send message that was sent
1424 handle_del_queue_message (void *cls,
1425 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
1427 struct TransportClient *tc = cls;
1429 if (CT_COMMUNICATOR != tc->type)
1432 GNUNET_SERVICE_client_drop (tc->client);
1435 for (struct Queue *queue = tc->details.communicator.queue_head;
1437 queue = queue->next_client)
1439 struct Neighbour *neighbour = queue->neighbour;
1441 if ( (dqm->qid != queue->qid) ||
1442 (0 != memcmp (&dqm->receiver,
1444 sizeof (struct GNUNET_PeerIdentity))) )
1447 GNUNET_SERVICE_client_continue (tc->client);
1451 GNUNET_SERVICE_client_drop (tc->client);
1456 * Message was transmitted. Process the request.
1458 * @param cls the client
1459 * @param sma the send message that was sent
1462 handle_send_message_ack (void *cls,
1463 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
1465 struct TransportClient *tc = cls;
1467 if (CT_COMMUNICATOR != tc->type)
1470 GNUNET_SERVICE_client_drop (tc->client);
1473 GNUNET_SERVICE_client_continue (tc->client);
1478 * Initialize a monitor client.
1480 * @param cls the client
1481 * @param start the start message that was sent
1484 handle_monitor_start (void *cls,
1485 const struct GNUNET_TRANSPORT_MonitorStart *start)
1487 struct TransportClient *tc = cls;
1489 if (CT_NONE != tc->type)
1492 GNUNET_SERVICE_client_drop (tc->client);
1495 tc->type = CT_MONITOR;
1496 tc->details.monitor.peer = start->peer;
1497 tc->details.monitor.one_shot = ntohl (start->one_shot);
1500 GNUNET_SERVICE_client_mark_monitor (tc->client);
1501 GNUNET_SERVICE_client_continue (tc->client);
1506 * Free neighbour entry.
1510 * @param value a `struct Neighbour`
1511 * @return #GNUNET_OK (always)
1514 free_neighbour_cb (void *cls,
1515 const struct GNUNET_PeerIdentity *pid,
1518 struct Neighbour *neighbour = value;
1522 GNUNET_break (0); // should this ever happen?
1523 free_neighbour (neighbour);
1530 * Function called when the service shuts down. Unloads our plugins
1531 * and cancels pending validations.
1533 * @param cls closure, unused
1536 do_shutdown (void *cls)
1540 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1543 if (NULL != peerstore)
1545 GNUNET_PEERSTORE_disconnect (peerstore,
1549 if (NULL != GST_stats)
1551 GNUNET_STATISTICS_destroy (GST_stats,
1555 if (NULL != GST_my_private_key)
1557 GNUNET_free (GST_my_private_key);
1558 GST_my_private_key = NULL;
1560 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
1565 * Initiate transport service.
1567 * @param cls closure
1568 * @param c configuration to use
1569 * @param service the initialized service
1573 const struct GNUNET_CONFIGURATION_Handle *c,
1574 struct GNUNET_SERVICE_Handle *service)
1579 neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
1581 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
1582 if (NULL == GST_my_private_key)
1584 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1585 _("Transport service is lacking key configuration settings. Exiting.\n"));
1586 GNUNET_SCHEDULER_shutdown ();
1589 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
1590 &GST_my_identity.public_key);
1591 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1592 "My identity is `%s'\n",
1593 GNUNET_i2s_full (&GST_my_identity));
1595 GST_stats = GNUNET_STATISTICS_create ("transport",
1597 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1599 peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
1600 if (NULL == peerstore)
1603 GNUNET_SCHEDULER_shutdown ();
1606 /* start subsystems */
1611 * Define "main" method using service macro.
1615 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
1618 &client_disconnect_cb,
1620 /* communication with core */
1621 GNUNET_MQ_hd_fixed_size (client_start,
1622 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
1623 struct StartMessage,
1625 GNUNET_MQ_hd_var_size (client_send,
1626 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
1627 struct OutboundMessage,
1629 /* communication with communicators */
1630 GNUNET_MQ_hd_var_size (communicator_available,
1631 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
1632 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
1634 GNUNET_MQ_hd_var_size (add_address,
1635 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
1636 struct GNUNET_TRANSPORT_AddAddressMessage,
1638 GNUNET_MQ_hd_fixed_size (del_address,
1639 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
1640 struct GNUNET_TRANSPORT_DelAddressMessage,
1642 GNUNET_MQ_hd_var_size (incoming_msg,
1643 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
1644 struct GNUNET_TRANSPORT_IncomingMessage,
1646 GNUNET_MQ_hd_var_size (add_queue_message,
1647 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
1648 struct GNUNET_TRANSPORT_AddQueueMessage,
1650 GNUNET_MQ_hd_fixed_size (del_queue_message,
1651 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
1652 struct GNUNET_TRANSPORT_DelQueueMessage,
1654 GNUNET_MQ_hd_fixed_size (send_message_ack,
1655 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
1656 struct GNUNET_TRANSPORT_SendMessageToAck,
1658 /* communication with monitors */
1659 GNUNET_MQ_hd_fixed_size (monitor_start,
1660 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
1661 struct GNUNET_TRANSPORT_MonitorStart,
1663 GNUNET_MQ_handler_end ());
1666 /* end of file gnunet-service-transport.c */