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 #include "gnunet_util_lib.h"
25 #include "gnunet_statistics_service.h"
26 #include "gnunet_transport_service.h"
27 #include "gnunet_peerinfo_service.h"
28 #include "gnunet_ats_service.h"
29 #include "gnunet-service-transport.h"
30 #include "transport.h"
34 * How many messages can we have pending for a given client process
35 * before we start to drop incoming messages? We typically should
36 * have only one client and so this would be the primary buffer for
37 * messages, so the number should be chosen rather generously.
39 * The expectation here is that most of the time the queue is large
40 * enough so that a drop is virtually never required. Note that
41 * this value must be about as large as 'TOTAL_MSGS' in the
42 * 'test_transport_api_reliability.c', otherwise that testcase may
45 #define MAX_PENDING (128 * 1024)
49 * What type of client is the `struct TransportClient` about?
54 * We do not know yet (client is fresh).
59 * Is the CORE service, we need to forward traffic to it.
64 * It is a monitor, forward monitor data.
69 * It is a communicator, use for communication.
76 * Client connected to the transport service.
78 struct TransportClient
84 struct TransportClient *next;
89 struct TransportClient *prev;
92 * Handle to the client.
94 struct GNUNET_SERVICE_Client *client;
97 * Message queue to the client.
99 struct GNUNET_MQ_Handle *mq;
102 * What type of client is this?
104 enum ClientType type;
110 * Peer identity to monitor the addresses of.
111 * Zero to monitor all neighbours. Valid if
112 * @e type is #CT_MONITOR.
114 struct GNUNET_PeerIdentity monitor_peer;
117 * If @e type is #CT_COMMUNICATOR, this communicator
118 * supports communicating using these addresses.
120 const char *address_prefix;
128 * Head of linked list of all clients to this service.
130 static struct TransportClient *clients_head;
133 * Tail of linked list of all clients to this service.
135 static struct TransportClient *clients_tail;
140 struct GNUNET_STATISTICS_Handle *GST_stats;
143 * Configuration handle.
145 const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
148 * Configuration handle.
150 struct GNUNET_PeerIdentity GST_my_identity;
153 * Handle to peerinfo service.
155 struct GNUNET_PEERINFO_Handle *GST_peerinfo;
160 struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
164 * Called whenever a client connects. Allocates our
165 * data structures associated with that client.
167 * @param cls closure, NULL
168 * @param client identification of the client
169 * @param mq message queue for the client
170 * @return our `struct TransportClient`
173 client_connect_cb (void *cls,
174 struct GNUNET_SERVICE_Client *client,
175 struct GNUNET_MQ_Handle *mq)
177 struct TransportClient *tc;
179 tc = GNUNET_new (struct TransportClient);
182 GNUNET_CONTAINER_DLL_insert (clients_head,
185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
186 "Client %p connected\n",
193 * Called whenever a client is disconnected. Frees our
194 * resources associated with that client.
196 * @param cls closure, NULL
197 * @param client identification of the client
198 * @param app_ctx our `struct TransportClient`
201 client_disconnect_cb (void *cls,
202 struct GNUNET_SERVICE_Client *client,
205 struct TransportClient *tc = app_ctx;
207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
208 "Client %p disconnected, cleaning up.\n",
210 GNUNET_CONTAINER_DLL_remove (clients_head,
221 case CT_COMMUNICATOR:
229 * Initialize a "CORE" client. We got a start message from this
230 * client, so add it to the list of clients for broadcasting of
233 * @param cls the client
234 * @param start the start message that was sent
237 handle_client_start (void *cls,
238 const struct StartMessage *start)
240 struct TransportClient *tc = cls;
241 const struct GNUNET_MessageHeader *hello;
244 options = ntohl (start->options);
245 if ( (0 != (1 & options)) &&
247 memcmp (&start->self,
249 sizeof (struct GNUNET_PeerIdentity)) ) )
251 /* client thinks this is a different peer, reject */
253 GNUNET_SERVICE_client_drop (tc->client);
256 if (CT_NONE != tc->type)
259 GNUNET_SERVICE_client_drop (tc->client);
264 hello = GST_hello_get ();
270 GNUNET_SERVICE_client_continue (tc->client);
275 * Client sent us a HELLO. Check the request.
277 * @param cls the client
278 * @param message the HELLO message
281 check_client_hello (void *cls,
282 const struct GNUNET_MessageHeader *message)
285 return GNUNET_OK; /* FIXME: check here? */
290 * Client sent us a HELLO. Process the request.
292 * @param cls the client
293 * @param message the HELLO message
296 handle_client_hello (void *cls,
297 const struct GNUNET_MessageHeader *message)
299 struct TransportClient *tc = cls;
301 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
302 "Received HELLO message\n");
303 GNUNET_SERVICE_client_continue (tc->client);
308 * Client asked for transmission to a peer. Process the request.
310 * @param cls the client
311 * @param obm the send message that was sent
314 check_client_send (void *cls,
315 const struct OutboundMessage *obm)
318 const struct GNUNET_MessageHeader *obmm;
321 size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
322 if (size < sizeof (struct GNUNET_MessageHeader))
325 return GNUNET_SYSERR;
327 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
328 if (size != ntohs (obmm->size))
331 return GNUNET_SYSERR;
338 * Client asked for transmission to a peer. Process the request.
340 * @param cls the client
341 * @param obm the send message that was sent
344 handle_client_send (void *cls,
345 const struct OutboundMessage *obm)
347 struct TransportClient *tc = cls;
348 const struct GNUNET_MessageHeader *obmm;
350 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
355 * Communicator started. Test message is well-formed.
357 * @param cls the client
358 * @param cam the send message that was sent
361 check_communicator_available (void *cls,
362 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
368 size = ntohs (cam->header.size) - sizeof (*cam);
370 return GNUNET_OK; /* receive-only communicator */
371 addr = (const char *) &cam[1];
372 if ('\0' != addr[size-1])
375 return GNUNET_SYSERR;
382 * Communicator started. Process the request.
384 * @param cls the client
385 * @param cam the send message that was sent
388 handle_communicator_available (void *cls,
389 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
391 struct TransportClient *tc = cls;
394 if (CT_NONE != tc->type)
397 GNUNET_SERVICE_client_drop (tc->client);
400 tc->type = CT_COMMUNICATOR;
401 size = ntohs (cam->header.size) - sizeof (*cam);
403 return GNUNET_OK; /* receive-only communicator */
404 tc->details.address_prefix = GNUNET_strdup ((const char *) &cam[1]);
405 GNUNET_SERVICE_client_continue (tc->client);
410 * Address of our peer added. Test message is well-formed.
412 * @param cls the client
413 * @param aam the send message that was sent
416 check_add_address (void *cls,
417 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
423 size = ntohs (aam->header.size) - sizeof (*aam);
427 return GNUNET_SYSERR;
429 addr = (const char *) &cam[1];
430 if ('\0' != addr[size-1])
433 return GNUNET_SYSERR;
440 * Address of our peer added. Process the request.
442 * @param cls the client
443 * @param aam the send message that was sent
446 handle_add_address (void *cls,
447 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
449 struct TransportClient *tc = cls;
451 GNUNET_SERVICE_client_continue (tc->client);
456 * Address of our peer deleted. Process the request.
458 * @param cls the client
459 * @param dam the send message that was sent
462 handle_del_address (void *cls,
463 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
465 struct TransportClient *tc = cls;
467 GNUNET_SERVICE_client_continue (tc->client);
472 * Client asked for transmission to a peer. Process the request.
474 * @param cls the client
475 * @param obm the send message that was sent
478 check_incoming_msg (void *cls,
479 const struct GNUNET_TRANSPORT_IncomingMessage *im)
482 const struct GNUNET_MessageHeader *obmm;
485 size = ntohs (im->header.size) - sizeof (*im);
486 if (size < sizeof (struct GNUNET_MessageHeader))
489 return GNUNET_SYSERR;
491 obmm = (const struct GNUNET_MessageHeader *) &im[1];
492 if (size != ntohs (obmm->size))
495 return GNUNET_SYSERR;
502 * Incoming meessage. Process the request.
504 * @param cls the client
505 * @param im the send message that was received
508 handle_incoming_msg (void *cls,
509 const struct GNUNET_TRANSPORT_IncomingMessage *im)
511 struct TransportClient *tc = cls;
513 GNUNET_SERVICE_client_continue (tc->client);
518 * New queue became available. Check message.
520 * @param cls the client
521 * @param aqm the send message that was sent
524 check_add_queue_message (void *cls,
525 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
531 size = ntohs (aqm->header.size) - sizeof (*aqm);
535 return GNUNET_SYSERR;
537 addr = (const char *) &aqm[1];
538 if ('\0' != addr[size-1])
541 return GNUNET_SYSERR;
548 * New queue became available. Process the request.
550 * @param cls the client
551 * @param aqm the send message that was sent
554 handle_add_queue_message (void *cls,
555 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
557 struct TransportClient *tc = cls;
559 GNUNET_SERVICE_client_continue (tc->client);
564 * Queue to a peer went down. Process the request.
566 * @param cls the client
567 * @param dqm the send message that was sent
570 handle_del_queue_message (void *cls,
571 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
573 struct TransportClient *tc = cls;
575 GNUNET_SERVICE_client_continue (tc->client);
580 * Message was transmitted. Process the request.
582 * @param cls the client
583 * @param sma the send message that was sent
586 handle_send_message_ack (void *cls,
587 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
589 struct TransportClient *tc = cls;
591 GNUNET_SERVICE_client_continue (tc->client);
596 * Function called when the service shuts down. Unloads our plugins
597 * and cancels pending validations.
599 * @param cls closure, unused
602 shutdown_task (void *cls)
606 if (NULL != GST_stats)
608 GNUNET_STATISTICS_destroy (GST_stats,
612 if (NULL != GST_my_private_key)
614 GNUNET_free (GST_my_private_key);
615 GST_my_private_key = NULL;
621 * Initiate transport service.
624 * @param c configuration to use
625 * @param service the initialized service
629 const struct GNUNET_CONFIGURATION_Handle *c,
630 struct GNUNET_SERVICE_Handle *service)
635 GNUNET_CONFIGURATION_get_value_time (c,
640 hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION;
642 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
643 if (NULL == GST_my_private_key)
645 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
646 _("Transport service is lacking key configuration settings. Exiting.\n"));
647 GNUNET_SCHEDULER_shutdown ();
650 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
651 &GST_my_identity.public_key);
652 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
653 "My identity is `%s'\n",
654 GNUNET_i2s_full (&GST_my_identity));
656 GST_stats = GNUNET_STATISTICS_create ("transport",
658 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
660 /* start subsystems */
665 * Define "main" method using service macro.
669 GNUNET_SERVICE_OPTION_NONE,
672 &client_disconnect_cb,
674 /* communication with core */
675 GNUNET_MQ_hd_fixed_size (client_start,
676 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
679 GNUNET_MQ_hd_var_size (client_hello,
680 GNUNET_MESSAGE_TYPE_HELLO,
681 struct GNUNET_MessageHeader,
683 GNUNET_MQ_hd_var_size (client_send,
684 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
685 struct OutboundMessage,
687 /* communication with communicators */
688 GNUNET_MQ_hd_var_size (communicator_available,
689 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
690 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
692 GNUNET_MQ_hd_var_size (add_address,
693 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
694 struct GNUNET_TRANSPORT_AddAddressMessage,
696 GNUNET_MQ_hd_fixed_size (del_address,
697 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
698 struct GNUNET_TRANSPORT_DelAddressMessage,
700 GNUNET_MQ_hd_var_size (incoming_msg,
701 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
702 struct GNUNET_TRANSPORT_IncomingMessage,
704 GNUNET_MQ_hd_var_size (add_queue_message,
705 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
706 struct GNUNET_TRANSPORT_AddQueueMessage,
708 GNUNET_MQ_hd_fixed_size (del_queue_message,
709 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
710 struct GNUNET_TRANSPORT_DelQueueMessage,
712 GNUNET_MQ_hd_fixed_size (send_message_ack,
713 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
714 struct GNUNET_TRANSPORT_SendMessageToAck,
716 GNUNET_MQ_handler_end ());
719 /* end of file gnunet-service-transport.c */