From 54f722729882247a318fbf686f2b2c31137ab72b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 8 Nov 2018 23:10:47 +0100 Subject: starting with TNG implementation --- src/transport/gnunet-service-tng.c | 719 +++++++++++++++++++++++++++++++++++++ 1 file changed, 719 insertions(+) create mode 100644 src/transport/gnunet-service-tng.c (limited to 'src/transport/gnunet-service-tng.c') diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c new file mode 100644 index 000000000..8cbca3188 --- /dev/null +++ b/src/transport/gnunet-service-tng.c @@ -0,0 +1,719 @@ +/* + This file is part of GNUnet. + Copyright (C) 2010-2016, 2018 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +/** + * @file transport/gnunet-service-transport.c + * @brief main for gnunet-service-transport + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_statistics_service.h" +#include "gnunet_transport_service.h" +#include "gnunet_peerinfo_service.h" +#include "gnunet_ats_service.h" +#include "gnunet-service-transport.h" +#include "transport.h" + + +/** + * How many messages can we have pending for a given client process + * before we start to drop incoming messages? We typically should + * have only one client and so this would be the primary buffer for + * messages, so the number should be chosen rather generously. + * + * The expectation here is that most of the time the queue is large + * enough so that a drop is virtually never required. Note that + * this value must be about as large as 'TOTAL_MSGS' in the + * 'test_transport_api_reliability.c', otherwise that testcase may + * fail. + */ +#define MAX_PENDING (128 * 1024) + + +/** + * What type of client is the `struct TransportClient` about? + */ +enum ClientType +{ + /** + * We do not know yet (client is fresh). + */ + CT_NONE = 0, + + /** + * Is the CORE service, we need to forward traffic to it. + */ + CT_CORE = 1, + + /** + * It is a monitor, forward monitor data. + */ + CT_MONITOR = 2, + + /** + * It is a communicator, use for communication. + */ + CT_COMMUNICATOR = 3 +}; + + +/** + * Client connected to the transport service. + */ +struct TransportClient +{ + + /** + * Kept in a DLL. + */ + struct TransportClient *next; + + /** + * Kept in a DLL. + */ + struct TransportClient *prev; + + /** + * Handle to the client. + */ + struct GNUNET_SERVICE_Client *client; + + /** + * Message queue to the client. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * What type of client is this? + */ + enum ClientType type; + + union + { + + /** + * Peer identity to monitor the addresses of. + * Zero to monitor all neighbours. Valid if + * @e type is #CT_MONITOR. + */ + struct GNUNET_PeerIdentity monitor_peer; + + /** + * If @e type is #CT_COMMUNICATOR, this communicator + * supports communicating using these addresses. + */ + const char *address_prefix; + + } details; + +}; + + +/** + * Head of linked list of all clients to this service. + */ +static struct TransportClient *clients_head; + +/** + * Tail of linked list of all clients to this service. + */ +static struct TransportClient *clients_tail; + +/** + * Statistics handle. + */ +struct GNUNET_STATISTICS_Handle *GST_stats; + +/** + * Configuration handle. + */ +const struct GNUNET_CONFIGURATION_Handle *GST_cfg; + +/** + * Configuration handle. + */ +struct GNUNET_PeerIdentity GST_my_identity; + +/** + * Handle to peerinfo service. + */ +struct GNUNET_PEERINFO_Handle *GST_peerinfo; + +/** + * Our private key. + */ +struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key; + + +/** + * Called whenever a client connects. Allocates our + * data structures associated with that client. + * + * @param cls closure, NULL + * @param client identification of the client + * @param mq message queue for the client + * @return our `struct TransportClient` + */ +static void * +client_connect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + struct GNUNET_MQ_Handle *mq) +{ + struct TransportClient *tc; + + tc = GNUNET_new (struct TransportClient); + tc->client = client; + tc->mq = mq; + GNUNET_CONTAINER_DLL_insert (clients_head, + clients_tail, + tc); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client %p connected\n", + tc); + return tc; +} + + +/** + * Called whenever a client is disconnected. Frees our + * resources associated with that client. + * + * @param cls closure, NULL + * @param client identification of the client + * @param app_ctx our `struct TransportClient` + */ +static void +client_disconnect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + void *app_ctx) +{ + struct TransportClient *tc = app_ctx; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client %p disconnected, cleaning up.\n", + tc); + GNUNET_CONTAINER_DLL_remove (clients_head, + clients_tail, + tc); + switch (tc->type) + { + case CT_NONE: + break; + case CT_CORE: + break; + case CT_MONITOR: + break; + case CT_COMMUNICATOR: + break; + } + GNUNET_free (tc); +} + + +/** + * Initialize a "CORE" client. We got a start message from this + * client, so add it to the list of clients for broadcasting of + * inbound messages. + * + * @param cls the client + * @param start the start message that was sent + */ +static void +handle_client_start (void *cls, + const struct StartMessage *start) +{ + struct TransportClient *tc = cls; + const struct GNUNET_MessageHeader *hello; + uint32_t options; + + options = ntohl (start->options); + if ( (0 != (1 & options)) && + (0 != + memcmp (&start->self, + &GST_my_identity, + sizeof (struct GNUNET_PeerIdentity)) ) ) + { + /* client thinks this is a different peer, reject */ + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); + return; + } + if (CT_NONE != tc->type) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); + return; + } + tc->type = CT_CORE; +#if 0 + hello = GST_hello_get (); + if (NULL != hello) + unicast (tc, + hello, + GNUNET_NO); +#endif + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Client sent us a HELLO. Check the request. + * + * @param cls the client + * @param message the HELLO message + */ +static int +check_client_hello (void *cls, + const struct GNUNET_MessageHeader *message) +{ + (void) cls; + return GNUNET_OK; /* FIXME: check here? */ +} + + +/** + * Client sent us a HELLO. Process the request. + * + * @param cls the client + * @param message the HELLO message + */ +static void +handle_client_hello (void *cls, + const struct GNUNET_MessageHeader *message) +{ + struct TransportClient *tc = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Received HELLO message\n"); + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Client asked for transmission to a peer. Process the request. + * + * @param cls the client + * @param obm the send message that was sent + */ +static int +check_client_send (void *cls, + const struct OutboundMessage *obm) +{ + uint16_t size; + const struct GNUNET_MessageHeader *obmm; + + (void) cls; + size = ntohs (obm->header.size) - sizeof (struct OutboundMessage); + if (size < sizeof (struct GNUNET_MessageHeader)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + obmm = (const struct GNUNET_MessageHeader *) &obm[1]; + if (size != ntohs (obmm->size)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Client asked for transmission to a peer. Process the request. + * + * @param cls the client + * @param obm the send message that was sent + */ +static void +handle_client_send (void *cls, + const struct OutboundMessage *obm) +{ + struct TransportClient *tc = cls; + const struct GNUNET_MessageHeader *obmm; + + obmm = (const struct GNUNET_MessageHeader *) &obm[1]; +} + + +/** + * Communicator started. Test message is well-formed. + * + * @param cls the client + * @param cam the send message that was sent + */ +static int +check_communicator_available (void *cls, + const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam) +{ + const char *addr; + uint16_t size; + + (void) cls; + size = ntohs (cam->header.size) - sizeof (*cam); + if (0 == size) + return GNUNET_OK; /* receive-only communicator */ + addr = (const char *) &cam[1]; + if ('\0' != addr[size-1]) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Communicator started. Process the request. + * + * @param cls the client + * @param cam the send message that was sent + */ +static void +handle_communicator_available (void *cls, + const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam) +{ + struct TransportClient *tc = cls; + uint16_t size; + + if (CT_NONE != tc->type) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); + return; + } + tc->type = CT_COMMUNICATOR; + size = ntohs (cam->header.size) - sizeof (*cam); + if (0 == size) + return GNUNET_OK; /* receive-only communicator */ + tc->details.address_prefix = GNUNET_strdup ((const char *) &cam[1]); + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Address of our peer added. Test message is well-formed. + * + * @param cls the client + * @param aam the send message that was sent + */ +static int +check_add_address (void *cls, + const struct GNUNET_TRANSPORT_AddAddressMessage *aam) +{ + const char *addr; + uint16_t size; + + (void) cls; + size = ntohs (aam->header.size) - sizeof (*aam); + if (0 == size) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + addr = (const char *) &cam[1]; + if ('\0' != addr[size-1]) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Address of our peer added. Process the request. + * + * @param cls the client + * @param aam the send message that was sent + */ +static void +handle_add_address (void *cls, + const struct GNUNET_TRANSPORT_AddAddressMessage *aam) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Address of our peer deleted. Process the request. + * + * @param cls the client + * @param dam the send message that was sent + */ +static void +handle_del_address (void *cls, + const struct GNUNET_TRANSPORT_DelAddressMessage *dam) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Client asked for transmission to a peer. Process the request. + * + * @param cls the client + * @param obm the send message that was sent + */ +static int +check_incoming_msg (void *cls, + const struct GNUNET_TRANSPORT_IncomingMessage *im) +{ + uint16_t size; + const struct GNUNET_MessageHeader *obmm; + + (void) cls; + size = ntohs (im->header.size) - sizeof (*im); + if (size < sizeof (struct GNUNET_MessageHeader)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + obmm = (const struct GNUNET_MessageHeader *) &im[1]; + if (size != ntohs (obmm->size)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Incoming meessage. Process the request. + * + * @param cls the client + * @param im the send message that was received + */ +static void +handle_incoming_msg (void *cls, + const struct GNUNET_TRANSPORT_IncomingMessage *im) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * New queue became available. Check message. + * + * @param cls the client + * @param aqm the send message that was sent + */ +static int +check_add_queue_message (void *cls, + const struct GNUNET_TRANSPORT_AddQueueMessage *aqm) +{ + const char *addr; + uint16_t size; + + (void) cls; + size = ntohs (aqm->header.size) - sizeof (*aqm); + if (0 == size) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + addr = (const char *) &aqm[1]; + if ('\0' != addr[size-1]) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * New queue became available. Process the request. + * + * @param cls the client + * @param aqm the send message that was sent + */ +static void +handle_add_queue_message (void *cls, + const struct GNUNET_TRANSPORT_AddQueueMessage *aqm) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Queue to a peer went down. Process the request. + * + * @param cls the client + * @param dqm the send message that was sent + */ +static void +handle_del_queue_message (void *cls, + const struct GNUNET_TRANSPORT_DelQueueMessage *dqm) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Message was transmitted. Process the request. + * + * @param cls the client + * @param sma the send message that was sent + */ +static void +handle_send_message_ack (void *cls, + const struct GNUNET_TRANSPORT_SendMessageToAck *sma) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Function called when the service shuts down. Unloads our plugins + * and cancels pending validations. + * + * @param cls closure, unused + */ +static void +shutdown_task (void *cls) +{ + (void) cls; + + if (NULL != GST_stats) + { + GNUNET_STATISTICS_destroy (GST_stats, + GNUNET_NO); + GST_stats = NULL; + } + if (NULL != GST_my_private_key) + { + GNUNET_free (GST_my_private_key); + GST_my_private_key = NULL; + } +} + + +/** + * Initiate transport service. + * + * @param cls closure + * @param c configuration to use + * @param service the initialized service + */ +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *c, + struct GNUNET_SERVICE_Handle *service) +{ + /* setup globals */ + GST_cfg = c; + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (c, + "transport", + "HELLO_EXPIRATION", + &hello_expiration)) + { + hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION; + } + GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg); + if (NULL == GST_my_private_key) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + _("Transport service is lacking key configuration settings. Exiting.\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key, + &GST_my_identity.public_key); + GNUNET_log(GNUNET_ERROR_TYPE_INFO, + "My identity is `%s'\n", + GNUNET_i2s_full (&GST_my_identity)); + + GST_stats = GNUNET_STATISTICS_create ("transport", + GST_cfg); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + NULL); + /* start subsystems */ +} + + +/** + * Define "main" method using service macro. + */ +GNUNET_SERVICE_MAIN +("transport", + GNUNET_SERVICE_OPTION_NONE, + &run, + &client_connect_cb, + &client_disconnect_cb, + NULL, + /* communication with core */ + GNUNET_MQ_hd_fixed_size (client_start, + GNUNET_MESSAGE_TYPE_TRANSPORT_START, + struct StartMessage, + NULL), + GNUNET_MQ_hd_var_size (client_hello, + GNUNET_MESSAGE_TYPE_HELLO, + struct GNUNET_MessageHeader, + NULL), + GNUNET_MQ_hd_var_size (client_send, + GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, + struct OutboundMessage, + NULL), + /* communication with communicators */ + GNUNET_MQ_hd_var_size (communicator_available, + GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR, + struct GNUNET_TRANSPORT_CommunicatorAvailableMessage, + NULL), + GNUNET_MQ_hd_var_size (add_address, + GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS, + struct GNUNET_TRANSPORT_AddAddressMessage, + NULL), + GNUNET_MQ_hd_fixed_size (del_address, + GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS, + struct GNUNET_TRANSPORT_DelAddressMessage, + NULL), + GNUNET_MQ_hd_var_size (incoming_msg, + GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG, + struct GNUNET_TRANSPORT_IncomingMessage, + NULL), + GNUNET_MQ_hd_var_size (add_queue_message, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP, + struct GNUNET_TRANSPORT_AddQueueMessage, + NULL), + GNUNET_MQ_hd_fixed_size (del_queue_message, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN, + struct GNUNET_TRANSPORT_DelQueueMessage, + NULL), + GNUNET_MQ_hd_fixed_size (send_message_ack, + GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK, + struct GNUNET_TRANSPORT_SendMessageToAck, + NULL), + GNUNET_MQ_handler_end ()); + + +/* end of file gnunet-service-transport.c */ -- cgit v1.2.3