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 * - MTU information is missing for queues!
25 * - start supporting monitor logic (add functions to signal monitors!)
26 * - manage fragmentation/defragmentation, retransmission, track RTT, loss, 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_peerstore_service.h"
35 #include "gnunet_ats_service.h"
36 #include "gnunet-service-transport.h"
37 #include "transport.h"
41 * How many messages can we have pending for a given client process
42 * before we start to drop incoming messages? We typically should
43 * have only one client and so this would be the primary buffer for
44 * messages, so the number should be chosen rather generously.
46 * The expectation here is that most of the time the queue is large
47 * enough so that a drop is virtually never required. Note that
48 * this value must be about as large as 'TOTAL_MSGS' in the
49 * 'test_transport_api_reliability.c', otherwise that testcase may
52 #define MAX_PENDING (128 * 1024)
56 * What type of client is the `struct TransportClient` about?
61 * We do not know yet (client is fresh).
66 * Is the CORE service, we need to forward traffic to it.
71 * It is a monitor, forward monitor data.
76 * It is a communicator, use for communication.
83 * Client connected to the transport service.
85 struct TransportClient;
89 * A neighbour that at least one communicator is connected to.
95 * List of available queues for a particular neighbour.
102 struct Queue *next_neighbour;
107 struct Queue *prev_neighbour;
112 struct Queue *prev_client;
117 struct Queue *next_client;
120 * Which neighbour is this queue for?
122 struct Neighbour *neighbour;
125 * Which communicator offers this queue?
127 struct TransportClient *tc;
130 * Address served by the queue.
135 * Unique identifier of this queue with the communicator.
140 * Network type offered by this queue.
142 enum GNUNET_ATS_Network_Type nt;
144 // FIXME: add ATS-specific fields here!
149 * A neighbour that at least one communicator is connected to.
155 * Which peer is this about?
157 struct GNUNET_PeerIdentity pid;
160 * Head of list of messages pending for this neighbour.
162 struct PendingMessage *pending_msg_head;
165 * Tail of list of messages pending for this neighbour.
167 struct PendingMessage *pending_msg_tail;
170 * Head of DLL of queues to this peer.
172 struct Queue *queue_head;
175 * Tail of DLL of queues to this peer.
177 struct Queue *queue_tail;
180 * Quota at which CORE is allowed to transmit to this peer
183 * FIXME: not yet used, tricky to get right given multiple queues!
184 * (=> Idea: let ATS set a quota per queue and we add them up here?)
185 * FIXME: how do we set this value initially when we tell CORE?
186 * Options: start at a minimum value or at literally zero (before ATS?)
187 * (=> Current thought: clean would be zero!)
189 struct GNUNET_BANDWIDTH_Value32NBO quota_out;
195 * Transmission request from CORE that is awaiting delivery.
197 struct PendingMessage
200 * Kept in a MDLL of messages for this @a target.
202 struct PendingMessage *next_neighbour;
205 * Kept in a MDLL of messages for this @a target.
207 struct PendingMessage *prev_neighbour;
210 * Kept in a MDLL of messages from this @a client.
212 struct PendingMessage *next_client;
215 * Kept in a MDLL of messages from this @a client.
217 struct PendingMessage *prev_client;
220 * Target of the request.
222 struct Neighbour *target;
225 * Client that issued the transmission request.
227 struct TransportClient *client;
230 * Size of the original message.
238 * One of the addresses of this peer.
240 struct AddressListEntry
246 struct AddressListEntry *next;
251 struct AddressListEntry *prev;
254 * Which communicator provides this address?
256 struct TransportClient *tc;
259 * The actual address.
264 * Current context for storing this address in the peerstore.
266 struct GNUNET_PEERSTORE_StoreContext *sc;
269 * Task to periodically do @e st operation.
271 struct GNUNET_SCHEDULER_Task *st;
274 * What is a typical lifetime the communicator expects this
275 * address to have? (Always from now.)
277 struct GNUNET_TIME_Relative expiration;
280 * Address identifier used by the communicator.
285 * Network type offered by this address.
287 enum GNUNET_ATS_Network_Type nt;
293 * Client connected to the transport service.
295 struct TransportClient
301 struct TransportClient *next;
306 struct TransportClient *prev;
309 * Handle to the client.
311 struct GNUNET_SERVICE_Client *client;
314 * Message queue to the client.
316 struct GNUNET_MQ_Handle *mq;
319 * What type of client is this?
321 enum ClientType type;
327 * Information for @e type #CT_CORE.
332 * Head of list of messages pending for this client.
334 struct PendingMessage *pending_msg_head;
337 * Tail of list of messages pending for this client.
339 struct PendingMessage *pending_msg_tail;
344 * Information for @e type #CT_MONITOR.
349 * Peer identity to monitor the addresses of.
350 * Zero to monitor all neighbours. Valid if
351 * @e type is #CT_MONITOR.
353 struct GNUNET_PeerIdentity peer;
356 * Is this a one-shot monitor?
364 * Information for @e type #CT_COMMUNICATOR.
368 * If @e type is #CT_COMMUNICATOR, this communicator
369 * supports communicating using these addresses.
371 char *address_prefix;
374 * Head of DLL of queues offered by this communicator.
376 struct Queue *queue_head;
379 * Tail of DLL of queues offered by this communicator.
381 struct Queue *queue_tail;
384 * Head of list of the addresses of this peer offered by this communicator.
386 struct AddressListEntry *addr_head;
389 * Tail of list of the addresses of this peer offered by this communicator.
391 struct AddressListEntry *addr_tail;
401 * Head of linked list of all clients to this service.
403 static struct TransportClient *clients_head;
406 * Tail of linked list of all clients to this service.
408 static struct TransportClient *clients_tail;
413 struct GNUNET_STATISTICS_Handle *GST_stats;
416 * Configuration handle.
418 const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
423 struct GNUNET_PeerIdentity GST_my_identity;
428 struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
431 * Map from PIDs to `struct Neighbour` entries. A peer is
432 * a neighbour if we have an MQ to it from some communicator.
434 static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
437 * Database for peer's HELLOs.
439 static struct GNUNET_PEERSTORE_Handle *peerstore;
443 * Lookup neighbour record for peer @a pid.
445 * @param pid neighbour to look for
446 * @return NULL if we do not have this peer as a neighbour
448 static struct Neighbour *
449 lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
451 return GNUNET_CONTAINER_multipeermap_get (neighbours,
457 * Called whenever a client connects. Allocates our
458 * data structures associated with that client.
460 * @param cls closure, NULL
461 * @param client identification of the client
462 * @param mq message queue for the client
463 * @return our `struct TransportClient`
466 client_connect_cb (void *cls,
467 struct GNUNET_SERVICE_Client *client,
468 struct GNUNET_MQ_Handle *mq)
470 struct TransportClient *tc;
472 tc = GNUNET_new (struct TransportClient);
475 GNUNET_CONTAINER_DLL_insert (clients_head,
478 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
479 "Client %p connected\n",
486 * Release memory used by @a neighbour.
488 * @param neighbour neighbour entry to free
491 free_neighbour (struct Neighbour *neighbour)
493 GNUNET_assert (NULL == neighbour->queue_head);
494 GNUNET_assert (GNUNET_YES ==
495 GNUNET_CONTAINER_multipeermap_remove (neighbours,
498 GNUNET_free (neighbour);
505 * @param queue the queue to free
508 free_queue (struct Queue *queue)
510 struct Neighbour *neighbour = queue->neighbour;
511 struct TransportClient *tc = queue->tc;
513 GNUNET_CONTAINER_MDLL_remove (neighbour,
514 neighbour->queue_head,
515 neighbour->queue_tail,
517 GNUNET_CONTAINER_MDLL_remove (client,
518 tc->details.communicator.queue_head,
519 tc->details.communicator.queue_tail,
522 if (NULL == neighbour->queue_head)
524 // FIXME: notify cores/monitors!
525 free_neighbour (neighbour);
533 * @param ale address list entry to free
536 free_address_list_entry (struct AddressListEntry *ale)
538 struct TransportClient *tc = ale->tc;
540 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
541 tc->details.communicator.addr_tail,
545 GNUNET_PEERSTORE_store_cancel (ale->sc);
550 GNUNET_SCHEDULER_cancel (ale->st);
558 * Called whenever a client is disconnected. Frees our
559 * resources associated with that client.
561 * @param cls closure, NULL
562 * @param client identification of the client
563 * @param app_ctx our `struct TransportClient`
566 client_disconnect_cb (void *cls,
567 struct GNUNET_SERVICE_Client *client,
570 struct TransportClient *tc = app_ctx;
572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
573 "Client %p disconnected, cleaning up.\n",
575 GNUNET_CONTAINER_DLL_remove (clients_head,
584 struct PendingMessage *pm;
586 while (NULL != (pm = tc->details.core.pending_msg_head))
588 GNUNET_CONTAINER_MDLL_remove (client,
589 tc->details.core.pending_msg_head,
590 tc->details.core.pending_msg_tail,
598 case CT_COMMUNICATOR:
601 struct AddressListEntry *ale;
603 while (NULL != (q = tc->details.communicator.queue_head))
605 while (NULL != (ale = tc->details.communicator.addr_head))
606 free_address_list_entry (ale);
607 GNUNET_free (tc->details.communicator.address_prefix);
616 * Initialize a "CORE" client. We got a start message from this
617 * client, so add it to the list of clients for broadcasting of
620 * @param cls the client
621 * @param start the start message that was sent
624 handle_client_start (void *cls,
625 const struct StartMessage *start)
627 struct TransportClient *tc = cls;
630 options = ntohl (start->options);
631 if ( (0 != (1 & options)) &&
633 memcmp (&start->self,
635 sizeof (struct GNUNET_PeerIdentity)) ) )
637 /* client thinks this is a different peer, reject */
639 GNUNET_SERVICE_client_drop (tc->client);
642 if (CT_NONE != tc->type)
645 GNUNET_SERVICE_client_drop (tc->client);
649 GNUNET_SERVICE_client_continue (tc->client);
654 * Client asked for transmission to a peer. Process the request.
656 * @param cls the client
657 * @param obm the send message that was sent
660 check_client_send (void *cls,
661 const struct OutboundMessage *obm)
663 struct TransportClient *tc = cls;
665 const struct GNUNET_MessageHeader *obmm;
667 if (CT_CORE != tc->type)
670 return GNUNET_SYSERR;
672 size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
673 if (size < sizeof (struct GNUNET_MessageHeader))
676 return GNUNET_SYSERR;
678 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
679 if (size != ntohs (obmm->size))
682 return GNUNET_SYSERR;
689 * Send a response to the @a pm that we have processed a
690 * "send" request with status @a success. We
691 * transmitted @a bytes_physical on the actual wire.
692 * Sends a confirmation to the "core" client responsible
693 * for the original request and free's @a pm.
695 * @param pm handle to the original pending message
696 * @param success status code, #GNUNET_OK on success, #GNUNET_SYSERR
697 * for transmission failure
698 * @param bytes_physical amount of bandwidth consumed
701 client_send_response (struct PendingMessage *pm,
703 uint32_t bytes_physical)
705 struct TransportClient *tc = pm->client;
706 struct Neighbour *target = pm->target;
707 struct GNUNET_MQ_Envelope *env;
708 struct SendOkMessage *som;
712 env = GNUNET_MQ_msg (som,
713 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
714 som->success = htonl ((uint32_t) success);
715 som->bytes_msg = htonl (pm->bytes_msg);
716 som->bytes_physical = htonl (bytes_physical);
717 som->peer = target->pid;
718 GNUNET_MQ_send (tc->mq,
720 GNUNET_CONTAINER_MDLL_remove (client,
721 tc->details.core.pending_msg_head,
722 tc->details.core.pending_msg_tail,
725 GNUNET_CONTAINER_MDLL_remove (neighbour,
726 target->pending_msg_head,
727 target->pending_msg_tail,
734 * Client asked for transmission to a peer. Process the request.
736 * @param cls the client
737 * @param obm the send message that was sent
740 handle_client_send (void *cls,
741 const struct OutboundMessage *obm)
743 struct TransportClient *tc = cls;
744 struct PendingMessage *pm;
745 const struct GNUNET_MessageHeader *obmm;
746 struct Neighbour *target;
749 GNUNET_assert (CT_CORE == tc->type);
750 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
751 bytes_msg = ntohs (obmm->size);
752 target = lookup_neighbour (&obm->peer);
755 /* Failure: don't have this peer as a neighbour (anymore).
756 Might have gone down asynchronously, so this is NOT
757 a protocol violation by CORE. Still count the event,
758 as this should be rare. */
759 struct GNUNET_MQ_Envelope *env;
760 struct SendOkMessage *som;
762 env = GNUNET_MQ_msg (som,
763 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
764 som->success = htonl (GNUNET_SYSERR);
765 som->bytes_msg = htonl (bytes_msg);
766 som->bytes_physical = htonl (0);
767 som->peer = obm->peer;
768 GNUNET_MQ_send (tc->mq,
770 GNUNET_SERVICE_client_continue (tc->client);
771 GNUNET_STATISTICS_update (GST_stats,
772 "# messages dropped (neighbour unknown)",
777 pm = GNUNET_new (struct PendingMessage);
780 pm->bytes_msg = bytes_msg;
781 GNUNET_CONTAINER_MDLL_insert (neighbour,
782 target->pending_msg_head,
783 target->pending_msg_tail,
785 GNUNET_CONTAINER_MDLL_insert (client,
786 tc->details.core.pending_msg_head,
787 tc->details.core.pending_msg_tail,
789 // FIXME: do the work, continuation with:
790 client_send_response (pm,
797 * Communicator started. Test message is well-formed.
799 * @param cls the client
800 * @param cam the send message that was sent
803 check_communicator_available (void *cls,
804 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
806 struct TransportClient *tc = cls;
810 if (CT_NONE != tc->type)
813 return GNUNET_SYSERR;
815 tc->type = CT_COMMUNICATOR;
816 size = ntohs (cam->header.size) - sizeof (*cam);
818 return GNUNET_OK; /* receive-only communicator */
819 addr = (const char *) &cam[1];
820 if ('\0' != addr[size-1])
823 return GNUNET_SYSERR;
830 * Communicator started. Process the request.
832 * @param cls the client
833 * @param cam the send message that was sent
836 handle_communicator_available (void *cls,
837 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
839 struct TransportClient *tc = cls;
842 size = ntohs (cam->header.size) - sizeof (*cam);
844 return; /* receive-only communicator */
845 tc->details.communicator.address_prefix = GNUNET_strdup ((const char *) &cam[1]);
846 GNUNET_SERVICE_client_continue (tc->client);
851 * Address of our peer added. Test message is well-formed.
853 * @param cls the client
854 * @param aam the send message that was sent
857 check_add_address (void *cls,
858 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
860 struct TransportClient *tc = cls;
864 if (CT_COMMUNICATOR != tc->type)
867 return GNUNET_SYSERR;
869 size = ntohs (aam->header.size) - sizeof (*aam);
873 return GNUNET_SYSERR;
875 addr = (const char *) &aam[1];
876 if ('\0' != addr[size-1])
879 return GNUNET_SYSERR;
886 * Ask peerstore to store our address.
888 * @param cls an `struct AddressListEntry *`
891 store_pi (void *cls);
895 * Function called when peerstore is done storing our address.
898 peerstore_store_cb (void *cls,
901 struct AddressListEntry *ale = cls;
904 if (GNUNET_YES != success)
905 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
906 "Failed to store our own address `%s' in peerstore!\n",
908 /* refresh period is 1/4 of expiration time, that should be plenty
909 without being excessive. */
910 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
918 * Ask peerstore to store our address.
920 * @param cls an `struct AddressListEntry *`
925 struct AddressListEntry *ale = cls;
928 struct GNUNET_TIME_Absolute expiration;
931 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
932 GNUNET_HELLO_sign_address (ale->address,
937 ale->sc = GNUNET_PEERSTORE_store (peerstore,
944 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
950 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
951 "Failed to store our address `%s' with peerstore\n",
953 ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
961 * Address of our peer added. Process the request.
963 * @param cls the client
964 * @param aam the send message that was sent
967 handle_add_address (void *cls,
968 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
970 struct TransportClient *tc = cls;
971 struct AddressListEntry *ale;
974 slen = ntohs (aam->header.size) - sizeof (*aam);
975 ale = GNUNET_malloc (sizeof (struct AddressListEntry) + slen);
977 ale->address = (const char *) &ale[1];
978 ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
980 ale->nt = (enum GNUNET_ATS_Network_Type) ntohl (aam->nt);
984 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
985 tc->details.communicator.addr_tail,
987 ale->st = GNUNET_SCHEDULER_add_now (&store_pi,
989 GNUNET_SERVICE_client_continue (tc->client);
994 * Address of our peer deleted. Process the request.
996 * @param cls the client
997 * @param dam the send message that was sent
1000 handle_del_address (void *cls,
1001 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
1003 struct TransportClient *tc = cls;
1005 if (CT_COMMUNICATOR != tc->type)
1008 GNUNET_SERVICE_client_drop (tc->client);
1011 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
1015 if (dam->aid != ale->aid)
1017 GNUNET_assert (ale->tc == tc);
1018 free_address_list_entry (ale);
1019 GNUNET_SERVICE_client_continue (tc->client);
1022 GNUNET_SERVICE_client_drop (tc->client);
1027 * Client notified us about transmission from a peer. Process the request.
1029 * @param cls the client
1030 * @param obm the send message that was sent
1033 check_incoming_msg (void *cls,
1034 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1036 struct TransportClient *tc = cls;
1038 const struct GNUNET_MessageHeader *obmm;
1040 if (CT_COMMUNICATOR != tc->type)
1043 return GNUNET_SYSERR;
1045 size = ntohs (im->header.size) - sizeof (*im);
1046 if (size < sizeof (struct GNUNET_MessageHeader))
1049 return GNUNET_SYSERR;
1051 obmm = (const struct GNUNET_MessageHeader *) &im[1];
1052 if (size != ntohs (obmm->size))
1055 return GNUNET_SYSERR;
1062 * Incoming meessage. Process the request.
1064 * @param cls the client
1065 * @param im the send message that was received
1068 handle_incoming_msg (void *cls,
1069 const struct GNUNET_TRANSPORT_IncomingMessage *im)
1071 struct TransportClient *tc = cls;
1073 GNUNET_SERVICE_client_continue (tc->client);
1078 * New queue became available. Check message.
1080 * @param cls the client
1081 * @param aqm the send message that was sent
1084 check_add_queue_message (void *cls,
1085 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1087 struct TransportClient *tc = cls;
1091 if (CT_COMMUNICATOR != tc->type)
1094 return GNUNET_SYSERR;
1096 size = ntohs (aqm->header.size) - sizeof (*aqm);
1100 return GNUNET_SYSERR;
1102 addr = (const char *) &aqm[1];
1103 if ('\0' != addr[size-1])
1106 return GNUNET_SYSERR;
1113 * New queue became available. Process the request.
1115 * @param cls the client
1116 * @param aqm the send message that was sent
1119 handle_add_queue_message (void *cls,
1120 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1122 struct TransportClient *tc = cls;
1123 struct Queue *queue;
1124 struct Neighbour *neighbour;
1128 neighbour = lookup_neighbour (&aqm->receiver);
1129 if (NULL == neighbour)
1131 neighbour = GNUNET_new (struct Neighbour);
1132 neighbour->pid = aqm->receiver;
1133 GNUNET_assert (GNUNET_OK ==
1134 GNUNET_CONTAINER_multipeermap_put (neighbours,
1137 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1138 // FIXME: notify ATS/COREs/monitors!
1140 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
1141 addr = (const char *) &aqm[1];
1143 queue = GNUNET_malloc (sizeof (struct Queue) + addr_len);
1144 queue->qid = aqm->qid;
1145 queue->nt = (enum GNUNET_ATS_Network_Type) ntohl (aqm->nt);
1147 queue->neighbour = neighbour;
1148 queue->address = (const char *) &queue[1];
1152 GNUNET_CONTAINER_MDLL_insert (neighbour,
1153 neighbour->queue_head,
1154 neighbour->queue_tail,
1156 GNUNET_CONTAINER_MDLL_insert (client,
1157 tc->details.communicator.queue_head,
1158 tc->details.communicator.queue_tail,
1160 // FIXME: possibly transmit queued messages?
1161 GNUNET_SERVICE_client_continue (tc->client);
1166 * Queue to a peer went down. Process the request.
1168 * @param cls the client
1169 * @param dqm the send message that was sent
1172 handle_del_queue_message (void *cls,
1173 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
1175 struct TransportClient *tc = cls;
1177 if (CT_COMMUNICATOR != tc->type)
1180 GNUNET_SERVICE_client_drop (tc->client);
1183 for (struct Queue *queue = tc->details.communicator.queue_head;
1185 queue = queue->next_client)
1187 struct Neighbour *neighbour = queue->neighbour;
1189 if ( (dqm->qid != queue->qid) ||
1190 (0 != memcmp (&dqm->receiver,
1192 sizeof (struct GNUNET_PeerIdentity))) )
1195 GNUNET_SERVICE_client_continue (tc->client);
1199 GNUNET_SERVICE_client_drop (tc->client);
1204 * Message was transmitted. Process the request.
1206 * @param cls the client
1207 * @param sma the send message that was sent
1210 handle_send_message_ack (void *cls,
1211 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
1213 struct TransportClient *tc = cls;
1215 if (CT_COMMUNICATOR != tc->type)
1218 GNUNET_SERVICE_client_drop (tc->client);
1221 GNUNET_SERVICE_client_continue (tc->client);
1226 * Initialize a monitor client.
1228 * @param cls the client
1229 * @param start the start message that was sent
1232 handle_monitor_start (void *cls,
1233 const struct GNUNET_TRANSPORT_MonitorStart *start)
1235 struct TransportClient *tc = cls;
1237 if (CT_NONE != tc->type)
1240 GNUNET_SERVICE_client_drop (tc->client);
1243 tc->type = CT_MONITOR;
1244 tc->details.monitor.peer = start->peer;
1245 tc->details.monitor.one_shot = ntohl (start->one_shot);
1247 GNUNET_SERVICE_client_continue (tc->client);
1252 * Free neighbour entry.
1256 * @param value a `struct Neighbour`
1257 * @return #GNUNET_OK (always)
1260 free_neighbour_cb (void *cls,
1261 const struct GNUNET_PeerIdentity *pid,
1264 struct Neighbour *neighbour = value;
1268 GNUNET_break (0); // should this ever happen?
1269 free_neighbour (neighbour);
1276 * Function called when the service shuts down. Unloads our plugins
1277 * and cancels pending validations.
1279 * @param cls closure, unused
1282 do_shutdown (void *cls)
1286 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1289 /* FIXME: if this assertion fails (likely!), make sure we
1290 clean up clients *before* doing the rest of the
1291 shutdown! (i.e. by scheduling rest asynchronously!) */
1292 GNUNET_assert (NULL == clients_head);
1293 if (NULL != peerstore)
1295 GNUNET_PEERSTORE_disconnect (peerstore,
1299 if (NULL != GST_stats)
1301 GNUNET_STATISTICS_destroy (GST_stats,
1305 if (NULL != GST_my_private_key)
1307 GNUNET_free (GST_my_private_key);
1308 GST_my_private_key = NULL;
1310 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
1315 * Initiate transport service.
1317 * @param cls closure
1318 * @param c configuration to use
1319 * @param service the initialized service
1323 const struct GNUNET_CONFIGURATION_Handle *c,
1324 struct GNUNET_SERVICE_Handle *service)
1329 neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
1331 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
1332 if (NULL == GST_my_private_key)
1334 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1335 _("Transport service is lacking key configuration settings. Exiting.\n"));
1336 GNUNET_SCHEDULER_shutdown ();
1339 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
1340 &GST_my_identity.public_key);
1341 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1342 "My identity is `%s'\n",
1343 GNUNET_i2s_full (&GST_my_identity));
1345 GST_stats = GNUNET_STATISTICS_create ("transport",
1347 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1349 peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
1350 if (NULL == peerstore)
1353 GNUNET_SCHEDULER_shutdown ();
1356 /* start subsystems */
1361 * Define "main" method using service macro.
1365 GNUNET_SERVICE_OPTION_NONE,
1368 &client_disconnect_cb,
1370 /* communication with core */
1371 GNUNET_MQ_hd_fixed_size (client_start,
1372 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
1373 struct StartMessage,
1375 GNUNET_MQ_hd_var_size (client_send,
1376 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
1377 struct OutboundMessage,
1379 /* communication with communicators */
1380 GNUNET_MQ_hd_var_size (communicator_available,
1381 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
1382 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
1384 GNUNET_MQ_hd_var_size (add_address,
1385 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
1386 struct GNUNET_TRANSPORT_AddAddressMessage,
1388 GNUNET_MQ_hd_fixed_size (del_address,
1389 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
1390 struct GNUNET_TRANSPORT_DelAddressMessage,
1392 GNUNET_MQ_hd_var_size (incoming_msg,
1393 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
1394 struct GNUNET_TRANSPORT_IncomingMessage,
1396 GNUNET_MQ_hd_var_size (add_queue_message,
1397 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
1398 struct GNUNET_TRANSPORT_AddQueueMessage,
1400 GNUNET_MQ_hd_fixed_size (del_queue_message,
1401 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
1402 struct GNUNET_TRANSPORT_DelQueueMessage,
1404 GNUNET_MQ_hd_fixed_size (send_message_ack,
1405 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
1406 struct GNUNET_TRANSPORT_SendMessageToAck,
1408 /* communication with monitors */
1409 GNUNET_MQ_hd_fixed_size (monitor_start,
1410 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
1411 struct GNUNET_TRANSPORT_MonitorStart,
1413 GNUNET_MQ_handler_end ());
1416 /* end of file gnunet-service-transport.c */