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;
150 struct GNUNET_PeerIdentity GST_my_identity;
155 struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
159 * Called whenever a client connects. Allocates our
160 * data structures associated with that client.
162 * @param cls closure, NULL
163 * @param client identification of the client
164 * @param mq message queue for the client
165 * @return our `struct TransportClient`
168 client_connect_cb (void *cls,
169 struct GNUNET_SERVICE_Client *client,
170 struct GNUNET_MQ_Handle *mq)
172 struct TransportClient *tc;
174 tc = GNUNET_new (struct TransportClient);
177 GNUNET_CONTAINER_DLL_insert (clients_head,
180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
181 "Client %p connected\n",
188 * Called whenever a client is disconnected. Frees our
189 * resources associated with that client.
191 * @param cls closure, NULL
192 * @param client identification of the client
193 * @param app_ctx our `struct TransportClient`
196 client_disconnect_cb (void *cls,
197 struct GNUNET_SERVICE_Client *client,
200 struct TransportClient *tc = app_ctx;
202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
203 "Client %p disconnected, cleaning up.\n",
205 GNUNET_CONTAINER_DLL_remove (clients_head,
216 case CT_COMMUNICATOR:
224 * Initialize a "CORE" client. We got a start message from this
225 * client, so add it to the list of clients for broadcasting of
228 * @param cls the client
229 * @param start the start message that was sent
232 handle_client_start (void *cls,
233 const struct StartMessage *start)
235 struct TransportClient *tc = cls;
236 const struct GNUNET_MessageHeader *hello;
239 options = ntohl (start->options);
240 if ( (0 != (1 & options)) &&
242 memcmp (&start->self,
244 sizeof (struct GNUNET_PeerIdentity)) ) )
246 /* client thinks this is a different peer, reject */
248 GNUNET_SERVICE_client_drop (tc->client);
251 if (CT_NONE != tc->type)
254 GNUNET_SERVICE_client_drop (tc->client);
259 hello = GST_hello_get ();
265 GNUNET_SERVICE_client_continue (tc->client);
270 * Client sent us a HELLO. Check the request.
272 * @param cls the client
273 * @param message the HELLO message
276 check_client_hello (void *cls,
277 const struct GNUNET_MessageHeader *message)
280 return GNUNET_OK; /* FIXME: check here? */
285 * Client sent us a HELLO. Process the request.
287 * @param cls the client
288 * @param message the HELLO message
291 handle_client_hello (void *cls,
292 const struct GNUNET_MessageHeader *message)
294 struct TransportClient *tc = cls;
296 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
297 "Received HELLO message\n");
298 GNUNET_SERVICE_client_continue (tc->client);
303 * Client asked for transmission to a peer. Process the request.
305 * @param cls the client
306 * @param obm the send message that was sent
309 check_client_send (void *cls,
310 const struct OutboundMessage *obm)
313 const struct GNUNET_MessageHeader *obmm;
316 size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
317 if (size < sizeof (struct GNUNET_MessageHeader))
320 return GNUNET_SYSERR;
322 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
323 if (size != ntohs (obmm->size))
326 return GNUNET_SYSERR;
333 * Client asked for transmission to a peer. Process the request.
335 * @param cls the client
336 * @param obm the send message that was sent
339 handle_client_send (void *cls,
340 const struct OutboundMessage *obm)
342 struct TransportClient *tc = cls;
343 const struct GNUNET_MessageHeader *obmm;
345 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
350 * Communicator started. Test message is well-formed.
352 * @param cls the client
353 * @param cam the send message that was sent
356 check_communicator_available (void *cls,
357 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
363 size = ntohs (cam->header.size) - sizeof (*cam);
365 return GNUNET_OK; /* receive-only communicator */
366 addr = (const char *) &cam[1];
367 if ('\0' != addr[size-1])
370 return GNUNET_SYSERR;
377 * Communicator started. Process the request.
379 * @param cls the client
380 * @param cam the send message that was sent
383 handle_communicator_available (void *cls,
384 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
386 struct TransportClient *tc = cls;
389 if (CT_NONE != tc->type)
392 GNUNET_SERVICE_client_drop (tc->client);
395 tc->type = CT_COMMUNICATOR;
396 size = ntohs (cam->header.size) - sizeof (*cam);
398 return GNUNET_OK; /* receive-only communicator */
399 tc->details.address_prefix = GNUNET_strdup ((const char *) &cam[1]);
400 GNUNET_SERVICE_client_continue (tc->client);
405 * Address of our peer added. Test message is well-formed.
407 * @param cls the client
408 * @param aam the send message that was sent
411 check_add_address (void *cls,
412 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
418 size = ntohs (aam->header.size) - sizeof (*aam);
422 return GNUNET_SYSERR;
424 addr = (const char *) &cam[1];
425 if ('\0' != addr[size-1])
428 return GNUNET_SYSERR;
435 * Address of our peer added. Process the request.
437 * @param cls the client
438 * @param aam the send message that was sent
441 handle_add_address (void *cls,
442 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
444 struct TransportClient *tc = cls;
446 GNUNET_SERVICE_client_continue (tc->client);
451 * Address of our peer deleted. Process the request.
453 * @param cls the client
454 * @param dam the send message that was sent
457 handle_del_address (void *cls,
458 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
460 struct TransportClient *tc = cls;
462 GNUNET_SERVICE_client_continue (tc->client);
467 * Client asked for transmission to a peer. Process the request.
469 * @param cls the client
470 * @param obm the send message that was sent
473 check_incoming_msg (void *cls,
474 const struct GNUNET_TRANSPORT_IncomingMessage *im)
477 const struct GNUNET_MessageHeader *obmm;
480 size = ntohs (im->header.size) - sizeof (*im);
481 if (size < sizeof (struct GNUNET_MessageHeader))
484 return GNUNET_SYSERR;
486 obmm = (const struct GNUNET_MessageHeader *) &im[1];
487 if (size != ntohs (obmm->size))
490 return GNUNET_SYSERR;
497 * Incoming meessage. Process the request.
499 * @param cls the client
500 * @param im the send message that was received
503 handle_incoming_msg (void *cls,
504 const struct GNUNET_TRANSPORT_IncomingMessage *im)
506 struct TransportClient *tc = cls;
508 GNUNET_SERVICE_client_continue (tc->client);
513 * New queue became available. Check message.
515 * @param cls the client
516 * @param aqm the send message that was sent
519 check_add_queue_message (void *cls,
520 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
526 size = ntohs (aqm->header.size) - sizeof (*aqm);
530 return GNUNET_SYSERR;
532 addr = (const char *) &aqm[1];
533 if ('\0' != addr[size-1])
536 return GNUNET_SYSERR;
543 * New queue became available. Process the request.
545 * @param cls the client
546 * @param aqm the send message that was sent
549 handle_add_queue_message (void *cls,
550 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
552 struct TransportClient *tc = cls;
554 GNUNET_SERVICE_client_continue (tc->client);
559 * Queue to a peer went down. Process the request.
561 * @param cls the client
562 * @param dqm the send message that was sent
565 handle_del_queue_message (void *cls,
566 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
568 struct TransportClient *tc = cls;
570 GNUNET_SERVICE_client_continue (tc->client);
575 * Message was transmitted. Process the request.
577 * @param cls the client
578 * @param sma the send message that was sent
581 handle_send_message_ack (void *cls,
582 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
584 struct TransportClient *tc = cls;
586 GNUNET_SERVICE_client_continue (tc->client);
591 * Initialize a monitor client.
593 * @param cls the client
594 * @param start the start message that was sent
597 handle_monitor_start (void *cls,
598 const struct GNUNET_TRANSPORT_MonitorStart *start)
600 struct TransportClient *tc = cls;
602 if (CT_NONE != tc->type)
605 GNUNET_SERVICE_client_drop (tc->client);
608 tc->type = CT_MONITOR;
609 tc->details.monitor_peer = start->peer;
610 // FIXME: remember also the one_shot flag!
611 GNUNET_SERVICE_client_continue (tc->client);
616 * Function called when the service shuts down. Unloads our plugins
617 * and cancels pending validations.
619 * @param cls closure, unused
622 shutdown_task (void *cls)
626 if (NULL != GST_stats)
628 GNUNET_STATISTICS_destroy (GST_stats,
632 if (NULL != GST_my_private_key)
634 GNUNET_free (GST_my_private_key);
635 GST_my_private_key = NULL;
641 * Initiate transport service.
644 * @param c configuration to use
645 * @param service the initialized service
649 const struct GNUNET_CONFIGURATION_Handle *c,
650 struct GNUNET_SERVICE_Handle *service)
655 GNUNET_CONFIGURATION_get_value_time (c,
660 hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION;
662 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
663 if (NULL == GST_my_private_key)
665 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
666 _("Transport service is lacking key configuration settings. Exiting.\n"));
667 GNUNET_SCHEDULER_shutdown ();
670 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
671 &GST_my_identity.public_key);
672 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
673 "My identity is `%s'\n",
674 GNUNET_i2s_full (&GST_my_identity));
676 GST_stats = GNUNET_STATISTICS_create ("transport",
678 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
680 /* start subsystems */
685 * Define "main" method using service macro.
689 GNUNET_SERVICE_OPTION_NONE,
692 &client_disconnect_cb,
694 /* communication with core */
695 GNUNET_MQ_hd_fixed_size (client_start,
696 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
699 GNUNET_MQ_hd_var_size (client_hello,
700 GNUNET_MESSAGE_TYPE_HELLO,
701 struct GNUNET_MessageHeader,
703 GNUNET_MQ_hd_var_size (client_send,
704 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
705 struct OutboundMessage,
707 /* communication with communicators */
708 GNUNET_MQ_hd_var_size (communicator_available,
709 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
710 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
712 GNUNET_MQ_hd_var_size (add_address,
713 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
714 struct GNUNET_TRANSPORT_AddAddressMessage,
716 GNUNET_MQ_hd_fixed_size (del_address,
717 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
718 struct GNUNET_TRANSPORT_DelAddressMessage,
720 GNUNET_MQ_hd_var_size (incoming_msg,
721 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
722 struct GNUNET_TRANSPORT_IncomingMessage,
724 GNUNET_MQ_hd_var_size (add_queue_message,
725 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
726 struct GNUNET_TRANSPORT_AddQueueMessage,
728 GNUNET_MQ_hd_fixed_size (del_queue_message,
729 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
730 struct GNUNET_TRANSPORT_DelQueueMessage,
732 GNUNET_MQ_hd_fixed_size (send_message_ack,
733 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
734 struct GNUNET_TRANSPORT_SendMessageToAck,
736 /* communication with monitors */
737 GNUNET_MQ_hd_fixed_size (monitor_start,
738 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
739 struct GNUNET_TRANSPORT_MonitorStart,
741 GNUNET_MQ_handler_end ());
744 /* end of file gnunet-service-transport.c */