From 430ed7f8b4b33295e84990ec97cbb71431cef923 Mon Sep 17 00:00:00 2001 From: Martin Schanzenbach Date: Mon, 30 Nov 2020 13:19:49 +0900 Subject: -fix communicator cleanup --- src/transport/gnunet-communicator-udp.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'src/transport') diff --git a/src/transport/gnunet-communicator-udp.c b/src/transport/gnunet-communicator-udp.c index 849adf4ab..073b1ea02 100644 --- a/src/transport/gnunet-communicator-udp.c +++ b/src/transport/gnunet-communicator-udp.c @@ -1668,8 +1668,7 @@ static void kce_generate_cb (void *cls) { struct SharedSecret *ss = cls; - - + kce_task = NULL; if (ss->sender->acks_available < KCN_TARGET) { @@ -1699,6 +1698,7 @@ static void kce_generate_rekey_cb (void *cls) { struct SharedSecret *ss = cls; + kce_task_rekey = NULL; if (NULL == kce_task) { @@ -3132,6 +3132,21 @@ do_shutdown (void *cls) GNUNET_SCHEDULER_cancel (broadcast_task); broadcast_task = NULL; } + if (NULL != kce_task_rekey) + { + GNUNET_SCHEDULER_cancel (kce_task_rekey); + kce_task_rekey = NULL; + } + if (NULL != kce_task) + { + GNUNET_SCHEDULER_cancel (kce_task); + kce_task = NULL; + } + if (NULL != timeout_task) + { + GNUNET_SCHEDULER_cancel (timeout_task); + timeout_task = NULL; + } if (NULL != read_task) { GNUNET_SCHEDULER_cancel (read_task); -- cgit v1.2.3 From 948a62546c5c772d89efd5268393464c95eb7f1e Mon Sep 17 00:00:00 2001 From: Martin Schanzenbach Date: Mon, 30 Nov 2020 13:30:07 +0900 Subject: -rename communicator testing logic --- src/transport/Makefile.am | 2 +- src/transport/test_communicator_basic.c | 2 +- src/transport/transport-testing-communicator.c | 1164 ++++++++++++++++++++++++ src/transport/transport-testing-communicator.h | 355 ++++++++ src/transport/transport-testing2.c | 1164 ------------------------ src/transport/transport-testing2.h | 355 -------- 6 files changed, 1521 insertions(+), 1521 deletions(-) create mode 100644 src/transport/transport-testing-communicator.c create mode 100644 src/transport/transport-testing-communicator.h delete mode 100644 src/transport/transport-testing2.c delete mode 100644 src/transport/transport-testing2.h (limited to 'src/transport') diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index e0369059d..477973af9 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -168,7 +168,7 @@ libgnunettransporttesting_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) libgnunettransporttesting2_la_SOURCES = \ - transport-testing2.c transport-testing2.h + transport-testing-communicator.c transport-testing-communicator.h libgnunettransporttesting2_la_LIBADD = \ libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ diff --git a/src/transport/test_communicator_basic.c b/src/transport/test_communicator_basic.c index df3c73b20..7ea04afdb 100644 --- a/src/transport/test_communicator_basic.c +++ b/src/transport/test_communicator_basic.c @@ -26,7 +26,7 @@ */ #include "platform.h" #include "gnunet_util_lib.h" -#include "transport-testing2.h" +#include "transport-testing-communicator.h" #include "gnunet_ats_transport_service.h" #include "gnunet_signatures.h" #include "gnunet_testing_lib.h" diff --git a/src/transport/transport-testing-communicator.c b/src/transport/transport-testing-communicator.c new file mode 100644 index 000000000..6d74b12e8 --- /dev/null +++ b/src/transport/transport-testing-communicator.c @@ -0,0 +1,1164 @@ +/* + This file is part of GNUnet. + Copyright (C) 2019 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 . + + SPDX-License-Identifier: AGPL3.0-or-later + */ + +/** + * @file transport/transport-testing-communicator.c + * @brief functions related to testing-tng + * @author Christian Grothoff + * @author Julius Bünger + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_protocols.h" +#include "gnunet_constants.h" +#include "transport-testing-communicator.h" +#include "gnunet_ats_transport_service.h" +#include "gnunet_hello_lib.h" +#include "gnunet_signatures.h" +#include "transport.h" +#include + +#define LOG(kind, ...) GNUNET_log_from (kind, "transport-testing2", __VA_ARGS__) + +struct MyClient +{ + struct MyClient *prev; + struct MyClient *next; + /** + * @brief Handle to the client + */ + struct GNUNET_SERVICE_Client *client; + + /** + * @brief Handle to the client + */ + struct GNUNET_MQ_Handle *c_mq; + + /** + * The TCH + */ + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc; + +}; + +/** + * @brief Queue of a communicator and some context + */ +struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue +{ + /** + * @brief Handle to the TransportCommunicator + */ + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h; + + /** + * @brief Envelope to a message that requests the opening of the queue. + * + * If the client already requests queue(s), but the communicator is not yet + * connected, we cannot send the request to open the queue. Save it until the + * communicator becomes available and send it then. + */ + struct GNUNET_MQ_Envelope *open_queue_env; + + /** + * @brief Peer ID of the peer on the other side of the queue + */ + struct GNUNET_PeerIdentity peer_id; + + /** + * @brief Queue ID + */ + uint32_t qid; + + /** + * @brief Current message id + */ + uint64_t mid; + + /** + * An `enum GNUNET_NetworkType` in NBO. + */ + uint32_t nt; + + /** + * Maximum transmission unit. UINT32_MAX for unlimited. + */ + uint32_t mtu; + + /** + * Queue length. UINT64_MAX for unlimited. + */ + uint64_t q_len; + + /** + * Queue prio + */ + uint32_t priority; + + /** + * An `enum GNUNET_TRANSPORT_ConnectionStatus` in NBO. + */ + uint32_t cs; + + /** + * @brief Next element inside a DLL + */ + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *next; + + /** + * @brief Previous element inside a DLL + */ + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *prev; +}; + + +/** + * @brief Handle/Context to a single transmission + */ +struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorTransmission +{ +}; + + +/** + * @brief Check whether incoming msg indicating available communicator is + * correct + * + * @param cls Closure + * @param msg Message struct + * + * @return GNUNET_YES in case message is correct + */ +static int +check_communicator_available ( + void *cls, + const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *msg) +{ + uint16_t size; + + size = ntohs (msg->header.size) - sizeof(*msg); + if (0 == size) + return GNUNET_OK; /* receive-only communicator */ + GNUNET_MQ_check_zero_termination (msg); + return GNUNET_OK; +} + + +/** + * @brief Handle new communicator + * + * Store characteristics of communicator, call respective client callback. + * + * @param cls Closure - communicator handle + * @param msg Message struct + */ +static void +handle_communicator_available ( + void *cls, + const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *msg) +{ + struct MyClient *client = cls; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = + client->tc; + uint16_t size; + tc_h->c_mq = client->c_mq; + + size = ntohs (msg->header.size) - sizeof(*msg); + if (0 == size) + { + GNUNET_SERVICE_client_continue (client->client); + return; /* receive-only communicator */ + } + tc_h->c_characteristics = ntohl (msg->cc); + tc_h->c_addr_prefix = GNUNET_strdup ((const char *) &msg[1]); + if (NULL != tc_h->communicator_available_cb) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, "calling communicator_available_cb()\n"); + tc_h->communicator_available_cb (tc_h->cb_cls, + tc_h, + tc_h->c_characteristics, + tc_h->c_addr_prefix); + } + GNUNET_SERVICE_client_continue (client->client); + LOG (GNUNET_ERROR_TYPE_DEBUG, "finished communicator_available_cb()\n"); + +} + + +/** + * Incoming message. Test message is well-formed. + * + * @param cls the client + * @param msg the send message that was sent + * @return #GNUNET_OK if message is well-formed + */ +static int +check_communicator_backchannel (void *cls, + const struct + GNUNET_TRANSPORT_CommunicatorBackchannel *msg) +{ + // struct TransportClient *tc = cls; + + // if (CT_COMMUNICATOR != tc->type) + // { + // GNUNET_break (0); + // return GNUNET_SYSERR; + // } + // GNUNET_MQ_check_boxed_message (msg); + return GNUNET_OK; +} + + +/** + * @brief Receive an incoming message. + * + * Pass the message to the client. + * + * @param cls Closure - communicator handle + * @param msg Message + */ +static void +handle_communicator_backchannel (void *cls, + const struct + GNUNET_TRANSPORT_CommunicatorBackchannel * + bc_msg) +{ + struct MyClient *client = cls; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = + client->tc; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *other_tc_h; + struct GNUNET_MessageHeader *msg; + msg = (struct GNUNET_MessageHeader *) &bc_msg[1]; + uint16_t isize = ntohs (msg->size); + const char *target_communicator = ((const char *) msg) + isize; + struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi; + struct GNUNET_MQ_Envelope *env; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received backchannel message\n"); + if (tc_h->bc_enabled != GNUNET_YES) + { + GNUNET_SERVICE_client_continue (client->client); + return; + } + /* Find client providing this communicator */ + /* Finally, deliver backchannel message to communicator */ + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Delivering backchannel message of type %u to %s\n", + ntohs (msg->type), + target_communicator); + other_tc_h = tc_h->bc_cb (tc_h, msg, (struct + GNUNET_PeerIdentity*) &bc_msg->pid); + env = GNUNET_MQ_msg_extra ( + cbi, + isize, + GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING); + cbi->pid = tc_h->peer_id; + memcpy (&cbi[1], msg, isize); + + + GNUNET_MQ_send (other_tc_h->c_mq, env); + GNUNET_SERVICE_client_continue (client->client); +} + + +/** + * Address of our peer added. Test message is well-formed. + * + * @param cls the client + * @param aam the send message that was sent + * @return #GNUNET_OK if message is well-formed + */ +static int +check_add_address (void *cls, + const struct GNUNET_TRANSPORT_AddAddressMessage *msg) +{ + // if (CT_COMMUNICATOR != tc->type) + // { + // GNUNET_break (0); + // return GNUNET_SYSERR; + // } + GNUNET_MQ_check_zero_termination (msg); + return GNUNET_OK; +} + + +/** + * @brief The communicator informs about an address. + * + * Store address and call client callback. + * + * @param cls Closure - communicator handle + * @param msg Message + */ +static void +handle_add_address (void *cls, + const struct GNUNET_TRANSPORT_AddAddressMessage *msg) +{ + struct MyClient *client = cls; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = + client->tc; + uint16_t size; + size = ntohs (msg->header.size) - sizeof(*msg); + if (0 == size) + return; /* receive-only communicator */ + LOG (GNUNET_ERROR_TYPE_DEBUG, "received add address cb %u\n", size); + tc_h->c_address = GNUNET_strdup ((const char *) &msg[1]); + if (NULL != tc_h->add_address_cb) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, "calling add_address_cb()\n"); + tc_h->add_address_cb (tc_h->cb_cls, + tc_h, + tc_h->c_address, + GNUNET_TIME_relative_ntoh (msg->expiration), + msg->aid, + ntohl (msg->nt)); + } + GNUNET_SERVICE_client_continue (client->client); +} + + +/** + * Incoming message. Test message is well-formed. + * + * @param cls the client + * @param msg the send message that was sent + * @return #GNUNET_OK if message is well-formed + */ +static int +check_incoming_msg (void *cls, + const struct GNUNET_TRANSPORT_IncomingMessage *msg) +{ + // struct TransportClient *tc = cls; + + // if (CT_COMMUNICATOR != tc->type) + // { + // GNUNET_break (0); + // return GNUNET_SYSERR; + // } + GNUNET_MQ_check_boxed_message (msg); + return GNUNET_OK; +} + + +/** + * @brief Receive an incoming message. + * + * Pass the message to the client. + * + * @param cls Closure - communicator handle + * @param msg Message + */ +static void +handle_incoming_msg (void *cls, + const struct GNUNET_TRANSPORT_IncomingMessage *inc_msg) +{ + struct MyClient *client = cls; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = + client->tc; + struct GNUNET_MessageHeader *msg; + msg = (struct GNUNET_MessageHeader *) &inc_msg[1]; + size_t payload_len = ntohs (msg->size) - sizeof (struct + GNUNET_MessageHeader); + if (NULL != tc_h->incoming_msg_cb) + { + tc_h->incoming_msg_cb (tc_h->cb_cls, + tc_h, + (char*) &msg[1], + payload_len); + } + else + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Incoming message from communicator but no handler!\n"); + } + if (GNUNET_YES == ntohl (inc_msg->fc_on)) + { + /* send ACK when done to communicator for flow control! */ + struct GNUNET_MQ_Envelope *env; + struct GNUNET_TRANSPORT_IncomingMessageAck *ack; + + env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK); + GNUNET_assert (NULL != env); + ack->reserved = htonl (0); + ack->fc_id = inc_msg->fc_id; + ack->sender = inc_msg->sender; + GNUNET_MQ_send (tc_h->c_mq, env); + } + + GNUNET_SERVICE_client_continue (client->client); +} + + +/** + * @brief Communicator informs that it tries to establish requested queue + * + * @param cls Closure - communicator handle + * @param msg Message + */ +static void +handle_queue_create_ok (void *cls, + const struct GNUNET_TRANSPORT_CreateQueueResponse *msg) +{ + struct MyClient *client = cls; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = + client->tc; + + if (NULL != tc_h->queue_create_reply_cb) + { + tc_h->queue_create_reply_cb (tc_h->cb_cls, tc_h, GNUNET_YES); + } + GNUNET_SERVICE_client_continue (client->client); +} + + +/** + * @brief Communicator informs that it wont try establishing requested queue. + * + * It will not do so probably because the address is bougus (see comment to + * #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL) + * + * @param cls Closure - communicator handle + * @param msg Message + */ +static void +handle_queue_create_fail ( + void *cls, + const struct GNUNET_TRANSPORT_CreateQueueResponse *msg) +{ + struct MyClient *client = cls; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = + client->tc; + + if (NULL != tc_h->queue_create_reply_cb) + { + tc_h->queue_create_reply_cb (tc_h->cb_cls, tc_h, GNUNET_NO); + } + GNUNET_SERVICE_client_continue (client->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) +{ + GNUNET_MQ_check_zero_termination (aqm); + return GNUNET_OK; +} + + +/** + * @brief Handle new queue + * + * Store context and call client callback. + * + * @param cls Closure - communicator handle + * @param msg Message struct + */ +static void +handle_add_queue_message (void *cls, + const struct GNUNET_TRANSPORT_AddQueueMessage *msg) +{ + struct MyClient *client = cls; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = + client->tc; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Got queue with ID %u\n", msg->qid); + for (tc_queue = tc_h->queue_head; NULL != tc_queue; tc_queue = tc_queue->next) + { + if (tc_queue->qid == msg->qid) + break; + } + if (NULL == tc_queue) + { + tc_queue = + GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue); + tc_queue->tc_h = tc_h; + tc_queue->qid = msg->qid; + tc_queue->peer_id = msg->receiver; + GNUNET_CONTAINER_DLL_insert (tc_h->queue_head, tc_h->queue_tail, tc_queue); + } + GNUNET_assert (tc_queue->qid == msg->qid); + GNUNET_assert (0 == GNUNET_memcmp (&tc_queue->peer_id, &msg->receiver)); + tc_queue->nt = msg->nt; + tc_queue->mtu = ntohl (msg->mtu); + tc_queue->cs = msg->cs; + tc_queue->priority = ntohl (msg->priority); + tc_queue->q_len = GNUNET_ntohll (msg->q_len); + if (NULL != tc_h->add_queue_cb) + { + tc_h->add_queue_cb (tc_h->cb_cls, tc_h, tc_queue, tc_queue->mtu); + } + GNUNET_SERVICE_client_continue (client->client); +} + + +/** + * @brief Handle new queue + * + * Store context and call client callback. + * + * @param cls Closure - communicator handle + * @param msg Message struct + */ +static void +handle_update_queue_message (void *cls, + const struct + GNUNET_TRANSPORT_UpdateQueueMessage *msg) +{ + struct MyClient *client = cls; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = + client->tc; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received queue update message for %u with q_len %" PRIu64 "\n", + msg->qid, GNUNET_ntohll (msg->q_len)); + tc_queue = tc_h->queue_head; + if (NULL != tc_queue) + { + while (tc_queue->qid != msg->qid) + { + tc_queue = tc_queue->next; + } + } + GNUNET_assert (tc_queue->qid == msg->qid); + GNUNET_assert (0 == GNUNET_memcmp (&tc_queue->peer_id, &msg->receiver)); + tc_queue->nt = msg->nt; + tc_queue->mtu = ntohl (msg->mtu); + tc_queue->cs = msg->cs; + tc_queue->priority = ntohl (msg->priority); + // Uncomment this for alternativ 1 of backchannel functionality + tc_queue->q_len += GNUNET_ntohll (msg->q_len); + // Until here for alternativ 1 + // Uncomment this for alternativ 2 of backchannel functionality + // tc_queue->q_len = GNUNET_ntohll (msg->q_len); + // Until here for alternativ 2 + GNUNET_SERVICE_client_continue (client->client); +} + + +/** + * @brief Shut down the service + * + * @param cls Closure - Handle to the service + */ +static void +shutdown_service (void *cls) +{ + struct GNUNET_SERVICE_Handle *h = cls; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Shutting down service!\n"); + + GNUNET_SERVICE_stop (h); +} + + +/** + * @brief Callback called when new Client (Communicator) connects + * + * @param cls Closure - TransporCommmunicator Handle + * @param client Client + * @param mq Messagequeue + * + * @return TransportCommunicator Handle + */ +static void * +connect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + struct GNUNET_MQ_Handle *mq) +{ + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls; + struct MyClient *new_c; + + LOG (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected to %p.\n", + client, tc_h); + new_c = GNUNET_new (struct MyClient); + new_c->client = client; + new_c->c_mq = mq; + new_c->tc = tc_h; + GNUNET_CONTAINER_DLL_insert (tc_h->client_head, + tc_h->client_tail, + new_c); + + if (NULL == tc_h->queue_head) + return new_c; + /* Iterate over queues. They are yet to be opened. Request opening. */ + for (struct + GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue_iter = + tc_h->queue_head; + NULL != tc_queue_iter; + tc_queue_iter = tc_queue_iter->next) + { + if (NULL == tc_queue_iter->open_queue_env) + continue; + /* Send the previously created mq envelope to request the creation of the + * queue. */ + GNUNET_MQ_send (tc_h->c_mq, + tc_queue_iter->open_queue_env); + tc_queue_iter->open_queue_env = NULL; + } + return new_c; +} + + +/** + * @brief Callback called when Client disconnects + * + * @param cls Closure - TransportCommunicator Handle + * @param client Client + * @param internal_cls TransporCommmunicator Handle + */ +static void +disconnect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + void *internal_cls) +{ + struct MyClient *cl = cls; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls; + + for (cl = tc_h->client_head; NULL != cl; cl = cl->next) + { + if (cl->client != client) + continue; + GNUNET_CONTAINER_DLL_remove (tc_h->client_head, + tc_h->client_tail, + cl); + if (cl->c_mq == tc_h->c_mq) + tc_h->c_mq = NULL; + GNUNET_free (cl); + break; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected.\n"); +} + + +/** + * 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 MyClient *client = cls; + GNUNET_SERVICE_client_continue (client->client); + // NOP +} + + +/** + * @brief Start the communicator part of the transport service + * + * @param communicator_available Callback to be called when a new communicator + * becomes available + * @param cfg Configuration + */ +static void +transport_communicator_start ( + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h) +{ + struct GNUNET_MQ_MessageHandler mh[] = { + GNUNET_MQ_hd_var_size (communicator_available, + GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR, + struct GNUNET_TRANSPORT_CommunicatorAvailableMessage, + tc_h), + GNUNET_MQ_hd_var_size (communicator_backchannel, + GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL, + struct GNUNET_TRANSPORT_CommunicatorBackchannel, + tc_h), + GNUNET_MQ_hd_var_size (add_address, + GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS, + struct GNUNET_TRANSPORT_AddAddressMessage, + tc_h), + // 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, + tc_h), + GNUNET_MQ_hd_fixed_size (queue_create_ok, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK, + struct GNUNET_TRANSPORT_CreateQueueResponse, + tc_h), + GNUNET_MQ_hd_fixed_size (queue_create_fail, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL, + struct GNUNET_TRANSPORT_CreateQueueResponse, + tc_h), + GNUNET_MQ_hd_var_size (add_queue_message, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP, + struct GNUNET_TRANSPORT_AddQueueMessage, + tc_h), + GNUNET_MQ_hd_fixed_size (update_queue_message, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE, + struct GNUNET_TRANSPORT_UpdateQueueMessage, + tc_h), + // 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, + tc_h), + GNUNET_MQ_handler_end () + }; + + + tc_h->sh = GNUNET_SERVICE_start ("transport", + tc_h->cfg, + &connect_cb, + &disconnect_cb, + tc_h, + mh); + GNUNET_assert (NULL != tc_h->sh); +} + + +/** + * @brief Task run at shutdown to kill communicator and clean up + * + * @param cls Closure - Process of communicator + */ +static void +shutdown_process (struct GNUNET_OS_Process *proc) +{ + if (0 != GNUNET_OS_process_kill (proc, SIGTERM)) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Error shutting down process with SIGERM, trying SIGKILL\n"); + if (0 != GNUNET_OS_process_kill (proc, SIGKILL)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Error shutting down process with SIGERM and SIGKILL\n"); + } + } + GNUNET_OS_process_destroy (proc); +} + +static void +shutdown_peerstore (void *cls) +{ + struct GNUNET_OS_Process *proc = cls; + shutdown_process (proc); +} + +static void +shutdown_communicator (void *cls) +{ + struct GNUNET_OS_Process *proc = cls; + shutdown_process (proc); +} + + +/** + * @brief Start the communicator + * + * @param cfgname Name of the communicator + */ +static void +communicator_start ( + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h, + const char *binary_name) +{ + char *binary; + char *loprefix; + char *section_name; + + LOG (GNUNET_ERROR_TYPE_DEBUG, "communicator_start\n"); + + section_name = strchr (binary_name, '-'); + section_name++; + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (tc_h->cfg, + section_name, + "PREFIX", + &loprefix)) + loprefix = GNUNET_strdup (""); + + + binary = GNUNET_OS_get_libexec_binary_path (binary_name); + tc_h->c_proc = GNUNET_OS_start_process_s (GNUNET_OS_INHERIT_STD_OUT_AND_ERR, + NULL, + loprefix, + binary, + binary_name, + "-c", + tc_h->cfg_filename, + NULL); + if (NULL == tc_h->c_proc) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start communicator!"); + return; + } + LOG (GNUNET_ERROR_TYPE_INFO, "started communicator\n"); + GNUNET_free (binary); +} + + +/** + * @brief Task run at shutdown to kill communicator and clean up + * + * @param cls Closure - Process of communicator + */ +static void +shutdown_nat (void *cls) +{ + struct GNUNET_OS_Process *proc = cls; + shutdown_process (proc); +} + + +/** + * @brief Task run at shutdown to kill the resolver process + * + * @param cls Closure - Process of communicator + */ +static void +shutdown_resolver (void *cls) +{ + struct GNUNET_OS_Process *proc = cls; + shutdown_process (proc); +} + + +static void +resolver_start (struct + GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h) +{ + char *binary; + + LOG (GNUNET_ERROR_TYPE_DEBUG, "resolver_start\n"); + binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver"); + tc_h->resolver_proc = GNUNET_OS_start_process ( + GNUNET_OS_INHERIT_STD_OUT_AND_ERR + | GNUNET_OS_USE_PIPE_CONTROL, + NULL, + NULL, + NULL, + binary, + "gnunet-service-resolver", + "-c", + tc_h->cfg_filename, + NULL); + if (NULL == tc_h->resolver_proc) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start resolver service!"); + return; + } + LOG (GNUNET_ERROR_TYPE_INFO, "started resolver service\n"); + GNUNET_free (binary); + +} + + +/** + * @brief Start Peerstore + * + */ +static void +peerstore_start ( + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h) +{ + char *binary; + + binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-peerstore"); + tc_h->ps_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR, + NULL, + NULL, + NULL, + binary, + "gnunet-service-peerstore", + "-c", + tc_h->cfg_filename, + NULL); + if (NULL == tc_h->ps_proc) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start Peerstore!"); + return; + } + LOG (GNUNET_ERROR_TYPE_INFO, "started Peerstore\n"); + GNUNET_free (binary); +} + +/** + * @brief Start NAT + * + */ +static void +nat_start ( + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h) +{ + char *binary; + + LOG (GNUNET_ERROR_TYPE_DEBUG, "nat_start\n"); + binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-nat"); + tc_h->nat_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR + | GNUNET_OS_USE_PIPE_CONTROL, + NULL, + NULL, + NULL, + binary, + "gnunet-service-nat", + "-c", + tc_h->cfg_filename, + NULL); + if (NULL == tc_h->nat_proc) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start NAT!"); + return; + } + LOG (GNUNET_ERROR_TYPE_INFO, "started NAT\n"); + GNUNET_free (binary); +} + + +/** + * @brief Start communicator part of transport service and communicator + * + * @param service_name Name of the service + * @param cfg Configuration handle + * @param communicator_available_cb Callback that is called when a new + * @param add_address_cb Callback that is called when a new + * communicator becomes available + * @param cb_cls Closure to @a communicator_available_cb and @a + * + * @return Handle to the communicator duo + */ +struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle * +GNUNET_TRANSPORT_TESTING_transport_communicator_service_start ( + const char *service_name, + const char *binary_name, + const char *cfg_filename, + const struct GNUNET_PeerIdentity *peer_id, + GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback + communicator_available_cb, + GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb, + GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb, + GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb, + GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_message_cb, + GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb, + void *cb_cls) +{ + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Starting new transport/communicator combo with config %s\n", + cfg_filename); + tc_h = + GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle); + tc_h->cfg_filename = GNUNET_strdup (cfg_filename); + tc_h->cfg = GNUNET_CONFIGURATION_create (); + if ((GNUNET_SYSERR == GNUNET_CONFIGURATION_load (tc_h->cfg, cfg_filename))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _ ("Malformed configuration file `%s', exit ...\n"), + cfg_filename); + GNUNET_free (tc_h->cfg_filename); + GNUNET_CONFIGURATION_destroy (tc_h->cfg); + GNUNET_free (tc_h); + return NULL; + } + tc_h->bc_enabled = GNUNET_CONFIGURATION_get_value_yesno (tc_h->cfg, + "communicator-test", + "BACKCHANNEL_ENABLED"); + tc_h->communicator_available_cb = communicator_available_cb; + tc_h->add_address_cb = add_address_cb; + tc_h->queue_create_reply_cb = queue_create_reply_cb; + tc_h->add_queue_cb = add_queue_cb; + tc_h->incoming_msg_cb = incoming_message_cb; + tc_h->bc_cb = bc_cb; + tc_h->peer_id = *peer_id; + tc_h->cb_cls = cb_cls; + + /* Start communicator part of service */ + transport_communicator_start (tc_h); + /* Start NAT */ + nat_start (tc_h); + /* Start resolver service */ + resolver_start (tc_h); + /* Start peerstore service */ + peerstore_start (tc_h); + /* Schedule start communicator */ + communicator_start (tc_h, + binary_name); + return tc_h; +} + + +void +GNUNET_TRANSPORT_TESTING_transport_communicator_service_stop ( + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h) +{ + shutdown_communicator (tc_h->c_proc); + shutdown_service (tc_h->sh); + shutdown_nat (tc_h->nat_proc); + shutdown_resolver (tc_h->resolver_proc); + shutdown_peerstore (tc_h->ps_proc); + GNUNET_CONFIGURATION_destroy (tc_h->cfg); + GNUNET_free (tc_h); +} + + +/** + * @brief Instruct communicator to open a queue + * + * @param tc_h Handle to communicator which shall open queue + * @param peer_id Towards which peer + * @param address For which address + */ +void +GNUNET_TRANSPORT_TESTING_transport_communicator_open_queue ( + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h, + const struct GNUNET_PeerIdentity *peer_id, + const char *address) +{ + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue; + static uint32_t idgen; + char *prefix; + struct GNUNET_TRANSPORT_CreateQueue *msg; + struct GNUNET_MQ_Envelope *env; + size_t alen; + + tc_queue = + GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue); + tc_queue->tc_h = tc_h; + prefix = GNUNET_HELLO_address_to_prefix (address); + if (NULL == prefix) + { + GNUNET_break (0); /* We got an invalid address!? */ + GNUNET_free (tc_queue); + return; + } + GNUNET_free (prefix); + alen = strlen (address) + 1; + env = + GNUNET_MQ_msg_extra (msg, alen, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE); + msg->request_id = htonl (idgen++); + tc_queue->qid = msg->request_id; + msg->receiver = *peer_id; + tc_queue->peer_id = *peer_id; + memcpy (&msg[1], address, alen); + if (NULL != tc_h->c_mq) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Sending queue create immediately\n"); + GNUNET_MQ_send (tc_h->c_mq, env); + } + else + { + tc_queue->open_queue_env = env; + } + GNUNET_CONTAINER_DLL_insert (tc_h->queue_head, tc_h->queue_tail, tc_queue); +} + + +/** + * @brief Instruct communicator to send data + * + * @param tc_queue The queue to use for sending + * @param cont function to call when done sending + * @param cont_cls closure for @a cont + * @param payload Data to send + * @param payload_size Size of the @a payload + */ +void +GNUNET_TRANSPORT_TESTING_transport_communicator_send + (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h, + GNUNET_SCHEDULER_TaskCallback cont, + void *cont_cls, + const void *payload, + size_t payload_size) +{ + struct GNUNET_MessageHeader *mh; + struct GNUNET_TRANSPORT_SendMessageTo *msg; + struct GNUNET_MQ_Envelope *env; + size_t inbox_size; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue; + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue_tmp; + + tc_queue = NULL; + for (tc_queue_tmp = tc_h->queue_head; + NULL != tc_queue_tmp; + tc_queue_tmp = tc_queue_tmp->next) + { + if (tc_queue_tmp->q_len <= 0) + continue; + if (NULL == tc_queue) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Selecting queue with prio %u, len %" PRIu64 " and MTU %u\n", + tc_queue_tmp->priority, + tc_queue_tmp->q_len, + tc_queue_tmp->mtu); + tc_queue = tc_queue_tmp; + continue; + } + if (tc_queue->priority < tc_queue_tmp->priority) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Selecting queue with prio %u, len %" PRIu64 " and MTU %u\n", + tc_queue_tmp->priority, + tc_queue_tmp->q_len, + tc_queue_tmp->mtu); + tc_queue = tc_queue_tmp; + } + } + GNUNET_assert (NULL != tc_queue); + // Uncomment this for alternativ 1 of backchannel functionality + if (tc_queue->q_len != GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED) + tc_queue->q_len--; + // Until here for alternativ 1 + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending message\n"); + inbox_size = sizeof (struct GNUNET_MessageHeader) + payload_size; + env = GNUNET_MQ_msg_extra (msg, + inbox_size, + GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG); + GNUNET_assert (NULL != env); + msg->qid = htonl (tc_queue->qid); + msg->mid = tc_queue->mid++; + msg->receiver = tc_queue->peer_id; + mh = (struct GNUNET_MessageHeader *) &msg[1]; + mh->size = htons (inbox_size); + mh->type = GNUNET_MESSAGE_TYPE_DUMMY; + memcpy (&mh[1], + payload, + payload_size); + if (NULL != cont) + GNUNET_MQ_notify_sent (env, + cont, + cont_cls); + GNUNET_MQ_send (tc_queue->tc_h->c_mq, + env); +} diff --git a/src/transport/transport-testing-communicator.h b/src/transport/transport-testing-communicator.h new file mode 100644 index 000000000..693e61515 --- /dev/null +++ b/src/transport/transport-testing-communicator.h @@ -0,0 +1,355 @@ +/* + This file is part of GNUnet. + Copyright (C) 2019 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 . + + SPDX-License-Identifier: AGPL3.0-or-later + */ + +/** + * @file transport/transport-testing-communicator.h + * @brief functions and structures related to testing-tng + * @author Christian Grothoff + * @author Julius Bünger + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_ats_transport_service.h" +#include "transport.h" + +/** + * @brief Queue of a communicator and some context + */ +struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue; + + +/** + * @brief Handle/Context to a single transmission + */ +struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorTransmission; + +/** + * @brief Function signature for callbacks that are called when new + * backchannel message arrived + * + * @param cls Closure + * @param msg Backchannel message + * @param pid Target peer + */ +typedef struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle * +(*GNUNET_TRANSPORT_TESTING_BackchannelCallback)(void *cls, + struct GNUNET_MessageHeader *msg, + struct GNUNET_PeerIdentity *pid); + + +/** + * @brief Function signature for callbacks that are called when new + * communicators become available + * + * @param cls Closure + * @param tc_h Communicator handle + * @param cc Characteristics of communicator + * @param address_prefix Prefix of the address + */ +typedef void +(*GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback)(void *cls, + struct + GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle + *tc_h, + enum + GNUNET_TRANSPORT_CommunicatorCharacteristics + cc, + char *address_prefix); + + +/** + * @brief Receive information about the address of a communicator. + * + * @param cls Closure + * @param tc_h Communicator handle + * @param address Address represented as string + * @param expiration Expiration + * @param aid Aid + * @param nt Network Type + */ +typedef void +(*GNUNET_TRANSPORT_TESTING_AddAddressCallback)(void *cls, + struct + GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle + *tc_h, + const char *address, + struct GNUNET_TIME_Relative + expiration, + uint32_t aid, + enum GNUNET_NetworkType nt); + + +/** + * @brief Get informed about the success of a queue request. + * + * @param cls Closure + * @param tc_h Communicator handle + * @param will_try #GNUNET_YES if communicator will try to create queue + */ +typedef void +(*GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback)(void *cls, + struct + GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle + *tc_h, + int will_try); + + +/** + * @brief Handle opening of queue + * + * @param cls Closure + * @param tc_h Communicator handle + * @param tc_queue Handle to newly opened queue + */ +typedef void +(*GNUNET_TRANSPORT_TESTING_AddQueueCallback)(void *cls, + struct + GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle + *tc_h, + struct + GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue + *tc_queue, + size_t mtu); + + +/** + * @brief Handle an incoming message + * + * @param cls Closure + * @param tc_h Handle to the receiving communicator + * @param msg Received message + */ +typedef void +(*GNUNET_TRANSPORT_TESTING_IncomingMessageCallback)(void *cls, + struct + GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle + *tc_h, + const char*payload, + size_t payload_len); + +/** + * @brief Handle to a transport communicator + */ +struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle +{ + /** + * Clients + */ + struct MyClient *client_head; + struct MyClient *client_tail; + + /** + * @brief Handle to the client + */ + struct GNUNET_MQ_Handle *c_mq; + + /** + * @brief Handle to the configuration + */ + struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * @brief File name of configuration file + */ + char *cfg_filename; + + struct GNUNET_PeerIdentity peer_id; + + /** + * @brief Handle to the transport service + */ + struct GNUNET_SERVICE_Handle *tsh; + + /** + * @brief Task that will be run on shutdown to stop and clean transport + * service + */ + struct GNUNET_SCHEDULER_Task *ts_shutdown_task; + + + /** + * @brief Process of the communicator + */ + struct GNUNET_OS_Process *c_proc; + + /** + * NAT process + */ + struct GNUNET_OS_Process *nat_proc; + + /** + * resolver service process + */ + struct GNUNET_OS_Process *resolver_proc; + + /** + * peerstore service process + */ + struct GNUNET_OS_Process *ps_proc; + + /** + * @brief Task that will be run on shutdown to stop and clean communicator + */ + struct GNUNET_SCHEDULER_Task *c_shutdown_task; + + /** + * @brief Characteristics of the communicator + */ + enum GNUNET_TRANSPORT_CommunicatorCharacteristics c_characteristics; + + /** + * @brief Specifies supported addresses + */ + char *c_addr_prefix; + + /** + * @brief Specifies supported addresses + */ + char *c_address; + + /** + * @brief Head of the DLL of queues associated with this communicator + */ + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_head; + + /** + * @brief Tail of the DLL of queues associated with this communicator + */ + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_tail; + + /* Callbacks + Closures */ + /** + * @brief Callback called when a new communicator connects + */ + GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback + communicator_available_cb; + + /** + * @brief Callback called when a new communicator connects + */ + GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb; + + /** + * @brief Callback called when a new communicator connects + */ + GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb; + + /** + * @brief Callback called when a new communicator connects + */ + GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb; + + /** + * @brief Callback called when a new communicator connects + */ + GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_msg_cb; + + /** + * @brief Backchannel callback + */ + GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb; + + /** + * Our service handle + */ + struct GNUNET_SERVICE_Handle *sh; + + /** + * @brief Closure to the callback + */ + void *cb_cls; + + /** + * Backchannel supported + */ + int bc_enabled; +}; + +/** + * @brief Start communicator part of transport service and communicator + * + * @param service_name Name of the service + * @param cfg Configuration handle + * @param communicator_available Callback that is called when a new + * communicator becomes available + * @param add_address_cb Callback handling new addresses + * @param queue_create_reply_cb Callback handling success of queue requests + * @param add_queue_cb Callback handling freshly created queues + * @param incoming_message_cb Callback handling incoming messages + * @param cb_cls Closure to @p communicator_available + * + * @return Handle to the communicator duo + */ +struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle * +GNUNET_TRANSPORT_TESTING_transport_communicator_service_start ( + const char *service_name, + const char *binary_name, + const char *cfg_filename, + const struct GNUNET_PeerIdentity *peer_id, + GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback + communicator_available_cb, + GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb, + GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb, + GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb, + GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_message_cb, + GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb, + void *cb_cls); + + +void +GNUNET_TRANSPORT_TESTING_transport_communicator_service_stop ( + struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h); + + +/** + * @brief Instruct communicator to open a queue + * + * @param tc_h Handle to communicator which shall open queue + * @param peer_id Towards which peer + * @param address For which address + */ +void +GNUNET_TRANSPORT_TESTING_transport_communicator_open_queue (struct + GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle + *tc_h, + const struct + GNUNET_PeerIdentity + *peer_id, + const char *address); + + +/** + * @brief Instruct communicator to send data + * + * @param tc_queue The queue to use for sending + * @param cont function to call when done sending + * @param cont_cls closure for @a cont + * @param payload Data to send + * @param payload_size Size of the @a payload + */ +void +GNUNET_TRANSPORT_TESTING_transport_communicator_send (struct + GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle + *tc_h, + GNUNET_SCHEDULER_TaskCallback + cont, + void *cont_cls, + const void *payload, + size_t payload_size); diff --git a/src/transport/transport-testing2.c b/src/transport/transport-testing2.c deleted file mode 100644 index 076fbf331..000000000 --- a/src/transport/transport-testing2.c +++ /dev/null @@ -1,1164 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2019 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 . - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file transport/transport-testing2.c - * @brief functions related to testing-tng - * @author Christian Grothoff - * @author Julius Bünger - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_protocols.h" -#include "gnunet_constants.h" -#include "transport-testing2.h" -#include "gnunet_ats_transport_service.h" -#include "gnunet_hello_lib.h" -#include "gnunet_signatures.h" -#include "transport.h" -#include - -#define LOG(kind, ...) GNUNET_log_from (kind, "transport-testing2", __VA_ARGS__) - -struct MyClient -{ - struct MyClient *prev; - struct MyClient *next; - /** - * @brief Handle to the client - */ - struct GNUNET_SERVICE_Client *client; - - /** - * @brief Handle to the client - */ - struct GNUNET_MQ_Handle *c_mq; - - /** - * The TCH - */ - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc; - -}; - -/** - * @brief Queue of a communicator and some context - */ -struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue -{ - /** - * @brief Handle to the TransportCommunicator - */ - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h; - - /** - * @brief Envelope to a message that requests the opening of the queue. - * - * If the client already requests queue(s), but the communicator is not yet - * connected, we cannot send the request to open the queue. Save it until the - * communicator becomes available and send it then. - */ - struct GNUNET_MQ_Envelope *open_queue_env; - - /** - * @brief Peer ID of the peer on the other side of the queue - */ - struct GNUNET_PeerIdentity peer_id; - - /** - * @brief Queue ID - */ - uint32_t qid; - - /** - * @brief Current message id - */ - uint64_t mid; - - /** - * An `enum GNUNET_NetworkType` in NBO. - */ - uint32_t nt; - - /** - * Maximum transmission unit. UINT32_MAX for unlimited. - */ - uint32_t mtu; - - /** - * Queue length. UINT64_MAX for unlimited. - */ - uint64_t q_len; - - /** - * Queue prio - */ - uint32_t priority; - - /** - * An `enum GNUNET_TRANSPORT_ConnectionStatus` in NBO. - */ - uint32_t cs; - - /** - * @brief Next element inside a DLL - */ - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *next; - - /** - * @brief Previous element inside a DLL - */ - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *prev; -}; - - -/** - * @brief Handle/Context to a single transmission - */ -struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorTransmission -{ -}; - - -/** - * @brief Check whether incoming msg indicating available communicator is - * correct - * - * @param cls Closure - * @param msg Message struct - * - * @return GNUNET_YES in case message is correct - */ -static int -check_communicator_available ( - void *cls, - const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *msg) -{ - uint16_t size; - - size = ntohs (msg->header.size) - sizeof(*msg); - if (0 == size) - return GNUNET_OK; /* receive-only communicator */ - GNUNET_MQ_check_zero_termination (msg); - return GNUNET_OK; -} - - -/** - * @brief Handle new communicator - * - * Store characteristics of communicator, call respective client callback. - * - * @param cls Closure - communicator handle - * @param msg Message struct - */ -static void -handle_communicator_available ( - void *cls, - const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *msg) -{ - struct MyClient *client = cls; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = - client->tc; - uint16_t size; - tc_h->c_mq = client->c_mq; - - size = ntohs (msg->header.size) - sizeof(*msg); - if (0 == size) - { - GNUNET_SERVICE_client_continue (client->client); - return; /* receive-only communicator */ - } - tc_h->c_characteristics = ntohl (msg->cc); - tc_h->c_addr_prefix = GNUNET_strdup ((const char *) &msg[1]); - if (NULL != tc_h->communicator_available_cb) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "calling communicator_available_cb()\n"); - tc_h->communicator_available_cb (tc_h->cb_cls, - tc_h, - tc_h->c_characteristics, - tc_h->c_addr_prefix); - } - GNUNET_SERVICE_client_continue (client->client); - LOG (GNUNET_ERROR_TYPE_DEBUG, "finished communicator_available_cb()\n"); - -} - - -/** - * Incoming message. Test message is well-formed. - * - * @param cls the client - * @param msg the send message that was sent - * @return #GNUNET_OK if message is well-formed - */ -static int -check_communicator_backchannel (void *cls, - const struct - GNUNET_TRANSPORT_CommunicatorBackchannel *msg) -{ - // struct TransportClient *tc = cls; - - // if (CT_COMMUNICATOR != tc->type) - // { - // GNUNET_break (0); - // return GNUNET_SYSERR; - // } - // GNUNET_MQ_check_boxed_message (msg); - return GNUNET_OK; -} - - -/** - * @brief Receive an incoming message. - * - * Pass the message to the client. - * - * @param cls Closure - communicator handle - * @param msg Message - */ -static void -handle_communicator_backchannel (void *cls, - const struct - GNUNET_TRANSPORT_CommunicatorBackchannel * - bc_msg) -{ - struct MyClient *client = cls; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = - client->tc; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *other_tc_h; - struct GNUNET_MessageHeader *msg; - msg = (struct GNUNET_MessageHeader *) &bc_msg[1]; - uint16_t isize = ntohs (msg->size); - const char *target_communicator = ((const char *) msg) + isize; - struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi; - struct GNUNET_MQ_Envelope *env; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received backchannel message\n"); - if (tc_h->bc_enabled != GNUNET_YES) - { - GNUNET_SERVICE_client_continue (client->client); - return; - } - /* Find client providing this communicator */ - /* Finally, deliver backchannel message to communicator */ - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Delivering backchannel message of type %u to %s\n", - ntohs (msg->type), - target_communicator); - other_tc_h = tc_h->bc_cb (tc_h, msg, (struct - GNUNET_PeerIdentity*) &bc_msg->pid); - env = GNUNET_MQ_msg_extra ( - cbi, - isize, - GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING); - cbi->pid = tc_h->peer_id; - memcpy (&cbi[1], msg, isize); - - - GNUNET_MQ_send (other_tc_h->c_mq, env); - GNUNET_SERVICE_client_continue (client->client); -} - - -/** - * Address of our peer added. Test message is well-formed. - * - * @param cls the client - * @param aam the send message that was sent - * @return #GNUNET_OK if message is well-formed - */ -static int -check_add_address (void *cls, - const struct GNUNET_TRANSPORT_AddAddressMessage *msg) -{ - // if (CT_COMMUNICATOR != tc->type) - // { - // GNUNET_break (0); - // return GNUNET_SYSERR; - // } - GNUNET_MQ_check_zero_termination (msg); - return GNUNET_OK; -} - - -/** - * @brief The communicator informs about an address. - * - * Store address and call client callback. - * - * @param cls Closure - communicator handle - * @param msg Message - */ -static void -handle_add_address (void *cls, - const struct GNUNET_TRANSPORT_AddAddressMessage *msg) -{ - struct MyClient *client = cls; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = - client->tc; - uint16_t size; - size = ntohs (msg->header.size) - sizeof(*msg); - if (0 == size) - return; /* receive-only communicator */ - LOG (GNUNET_ERROR_TYPE_DEBUG, "received add address cb %u\n", size); - tc_h->c_address = GNUNET_strdup ((const char *) &msg[1]); - if (NULL != tc_h->add_address_cb) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "calling add_address_cb()\n"); - tc_h->add_address_cb (tc_h->cb_cls, - tc_h, - tc_h->c_address, - GNUNET_TIME_relative_ntoh (msg->expiration), - msg->aid, - ntohl (msg->nt)); - } - GNUNET_SERVICE_client_continue (client->client); -} - - -/** - * Incoming message. Test message is well-formed. - * - * @param cls the client - * @param msg the send message that was sent - * @return #GNUNET_OK if message is well-formed - */ -static int -check_incoming_msg (void *cls, - const struct GNUNET_TRANSPORT_IncomingMessage *msg) -{ - // struct TransportClient *tc = cls; - - // if (CT_COMMUNICATOR != tc->type) - // { - // GNUNET_break (0); - // return GNUNET_SYSERR; - // } - GNUNET_MQ_check_boxed_message (msg); - return GNUNET_OK; -} - - -/** - * @brief Receive an incoming message. - * - * Pass the message to the client. - * - * @param cls Closure - communicator handle - * @param msg Message - */ -static void -handle_incoming_msg (void *cls, - const struct GNUNET_TRANSPORT_IncomingMessage *inc_msg) -{ - struct MyClient *client = cls; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = - client->tc; - struct GNUNET_MessageHeader *msg; - msg = (struct GNUNET_MessageHeader *) &inc_msg[1]; - size_t payload_len = ntohs (msg->size) - sizeof (struct - GNUNET_MessageHeader); - if (NULL != tc_h->incoming_msg_cb) - { - tc_h->incoming_msg_cb (tc_h->cb_cls, - tc_h, - (char*) &msg[1], - payload_len); - } - else - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Incoming message from communicator but no handler!\n"); - } - if (GNUNET_YES == ntohl (inc_msg->fc_on)) - { - /* send ACK when done to communicator for flow control! */ - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TRANSPORT_IncomingMessageAck *ack; - - env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK); - GNUNET_assert (NULL != env); - ack->reserved = htonl (0); - ack->fc_id = inc_msg->fc_id; - ack->sender = inc_msg->sender; - GNUNET_MQ_send (tc_h->c_mq, env); - } - - GNUNET_SERVICE_client_continue (client->client); -} - - -/** - * @brief Communicator informs that it tries to establish requested queue - * - * @param cls Closure - communicator handle - * @param msg Message - */ -static void -handle_queue_create_ok (void *cls, - const struct GNUNET_TRANSPORT_CreateQueueResponse *msg) -{ - struct MyClient *client = cls; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = - client->tc; - - if (NULL != tc_h->queue_create_reply_cb) - { - tc_h->queue_create_reply_cb (tc_h->cb_cls, tc_h, GNUNET_YES); - } - GNUNET_SERVICE_client_continue (client->client); -} - - -/** - * @brief Communicator informs that it wont try establishing requested queue. - * - * It will not do so probably because the address is bougus (see comment to - * #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL) - * - * @param cls Closure - communicator handle - * @param msg Message - */ -static void -handle_queue_create_fail ( - void *cls, - const struct GNUNET_TRANSPORT_CreateQueueResponse *msg) -{ - struct MyClient *client = cls; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = - client->tc; - - if (NULL != tc_h->queue_create_reply_cb) - { - tc_h->queue_create_reply_cb (tc_h->cb_cls, tc_h, GNUNET_NO); - } - GNUNET_SERVICE_client_continue (client->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) -{ - GNUNET_MQ_check_zero_termination (aqm); - return GNUNET_OK; -} - - -/** - * @brief Handle new queue - * - * Store context and call client callback. - * - * @param cls Closure - communicator handle - * @param msg Message struct - */ -static void -handle_add_queue_message (void *cls, - const struct GNUNET_TRANSPORT_AddQueueMessage *msg) -{ - struct MyClient *client = cls; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = - client->tc; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Got queue with ID %u\n", msg->qid); - for (tc_queue = tc_h->queue_head; NULL != tc_queue; tc_queue = tc_queue->next) - { - if (tc_queue->qid == msg->qid) - break; - } - if (NULL == tc_queue) - { - tc_queue = - GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue); - tc_queue->tc_h = tc_h; - tc_queue->qid = msg->qid; - tc_queue->peer_id = msg->receiver; - GNUNET_CONTAINER_DLL_insert (tc_h->queue_head, tc_h->queue_tail, tc_queue); - } - GNUNET_assert (tc_queue->qid == msg->qid); - GNUNET_assert (0 == GNUNET_memcmp (&tc_queue->peer_id, &msg->receiver)); - tc_queue->nt = msg->nt; - tc_queue->mtu = ntohl (msg->mtu); - tc_queue->cs = msg->cs; - tc_queue->priority = ntohl (msg->priority); - tc_queue->q_len = GNUNET_ntohll (msg->q_len); - if (NULL != tc_h->add_queue_cb) - { - tc_h->add_queue_cb (tc_h->cb_cls, tc_h, tc_queue, tc_queue->mtu); - } - GNUNET_SERVICE_client_continue (client->client); -} - - -/** - * @brief Handle new queue - * - * Store context and call client callback. - * - * @param cls Closure - communicator handle - * @param msg Message struct - */ -static void -handle_update_queue_message (void *cls, - const struct - GNUNET_TRANSPORT_UpdateQueueMessage *msg) -{ - struct MyClient *client = cls; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = - client->tc; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received queue update message for %u with q_len %" PRIu64 "\n", - msg->qid, GNUNET_ntohll (msg->q_len)); - tc_queue = tc_h->queue_head; - if (NULL != tc_queue) - { - while (tc_queue->qid != msg->qid) - { - tc_queue = tc_queue->next; - } - } - GNUNET_assert (tc_queue->qid == msg->qid); - GNUNET_assert (0 == GNUNET_memcmp (&tc_queue->peer_id, &msg->receiver)); - tc_queue->nt = msg->nt; - tc_queue->mtu = ntohl (msg->mtu); - tc_queue->cs = msg->cs; - tc_queue->priority = ntohl (msg->priority); - // Uncomment this for alternativ 1 of backchannel functionality - tc_queue->q_len += GNUNET_ntohll (msg->q_len); - // Until here for alternativ 1 - // Uncomment this for alternativ 2 of backchannel functionality - // tc_queue->q_len = GNUNET_ntohll (msg->q_len); - // Until here for alternativ 2 - GNUNET_SERVICE_client_continue (client->client); -} - - -/** - * @brief Shut down the service - * - * @param cls Closure - Handle to the service - */ -static void -shutdown_service (void *cls) -{ - struct GNUNET_SERVICE_Handle *h = cls; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Shutting down service!\n"); - - GNUNET_SERVICE_stop (h); -} - - -/** - * @brief Callback called when new Client (Communicator) connects - * - * @param cls Closure - TransporCommmunicator Handle - * @param client Client - * @param mq Messagequeue - * - * @return TransportCommunicator Handle - */ -static void * -connect_cb (void *cls, - struct GNUNET_SERVICE_Client *client, - struct GNUNET_MQ_Handle *mq) -{ - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls; - struct MyClient *new_c; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected to %p.\n", - client, tc_h); - new_c = GNUNET_new (struct MyClient); - new_c->client = client; - new_c->c_mq = mq; - new_c->tc = tc_h; - GNUNET_CONTAINER_DLL_insert (tc_h->client_head, - tc_h->client_tail, - new_c); - - if (NULL == tc_h->queue_head) - return new_c; - /* Iterate over queues. They are yet to be opened. Request opening. */ - for (struct - GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue_iter = - tc_h->queue_head; - NULL != tc_queue_iter; - tc_queue_iter = tc_queue_iter->next) - { - if (NULL == tc_queue_iter->open_queue_env) - continue; - /* Send the previously created mq envelope to request the creation of the - * queue. */ - GNUNET_MQ_send (tc_h->c_mq, - tc_queue_iter->open_queue_env); - tc_queue_iter->open_queue_env = NULL; - } - return new_c; -} - - -/** - * @brief Callback called when Client disconnects - * - * @param cls Closure - TransportCommunicator Handle - * @param client Client - * @param internal_cls TransporCommmunicator Handle - */ -static void -disconnect_cb (void *cls, - struct GNUNET_SERVICE_Client *client, - void *internal_cls) -{ - struct MyClient *cl = cls; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h = cls; - - for (cl = tc_h->client_head; NULL != cl; cl = cl->next) - { - if (cl->client != client) - continue; - GNUNET_CONTAINER_DLL_remove (tc_h->client_head, - tc_h->client_tail, - cl); - if (cl->c_mq == tc_h->c_mq) - tc_h->c_mq = NULL; - GNUNET_free (cl); - break; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected.\n"); -} - - -/** - * 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 MyClient *client = cls; - GNUNET_SERVICE_client_continue (client->client); - // NOP -} - - -/** - * @brief Start the communicator part of the transport service - * - * @param communicator_available Callback to be called when a new communicator - * becomes available - * @param cfg Configuration - */ -static void -transport_communicator_start ( - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h) -{ - struct GNUNET_MQ_MessageHandler mh[] = { - GNUNET_MQ_hd_var_size (communicator_available, - GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR, - struct GNUNET_TRANSPORT_CommunicatorAvailableMessage, - tc_h), - GNUNET_MQ_hd_var_size (communicator_backchannel, - GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL, - struct GNUNET_TRANSPORT_CommunicatorBackchannel, - tc_h), - GNUNET_MQ_hd_var_size (add_address, - GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS, - struct GNUNET_TRANSPORT_AddAddressMessage, - tc_h), - // 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, - tc_h), - GNUNET_MQ_hd_fixed_size (queue_create_ok, - GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK, - struct GNUNET_TRANSPORT_CreateQueueResponse, - tc_h), - GNUNET_MQ_hd_fixed_size (queue_create_fail, - GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL, - struct GNUNET_TRANSPORT_CreateQueueResponse, - tc_h), - GNUNET_MQ_hd_var_size (add_queue_message, - GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP, - struct GNUNET_TRANSPORT_AddQueueMessage, - tc_h), - GNUNET_MQ_hd_fixed_size (update_queue_message, - GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE, - struct GNUNET_TRANSPORT_UpdateQueueMessage, - tc_h), - // 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, - tc_h), - GNUNET_MQ_handler_end () - }; - - - tc_h->sh = GNUNET_SERVICE_start ("transport", - tc_h->cfg, - &connect_cb, - &disconnect_cb, - tc_h, - mh); - GNUNET_assert (NULL != tc_h->sh); -} - - -/** - * @brief Task run at shutdown to kill communicator and clean up - * - * @param cls Closure - Process of communicator - */ -static void -shutdown_process (struct GNUNET_OS_Process *proc) -{ - if (0 != GNUNET_OS_process_kill (proc, SIGTERM)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Error shutting down process with SIGERM, trying SIGKILL\n"); - if (0 != GNUNET_OS_process_kill (proc, SIGKILL)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Error shutting down process with SIGERM and SIGKILL\n"); - } - } - GNUNET_OS_process_destroy (proc); -} - -static void -shutdown_peerstore (void *cls) -{ - struct GNUNET_OS_Process *proc = cls; - shutdown_process (proc); -} - -static void -shutdown_communicator (void *cls) -{ - struct GNUNET_OS_Process *proc = cls; - shutdown_process (proc); -} - - -/** - * @brief Start the communicator - * - * @param cfgname Name of the communicator - */ -static void -communicator_start ( - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h, - const char *binary_name) -{ - char *binary; - char *loprefix; - char *section_name; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "communicator_start\n"); - - section_name = strchr (binary_name, '-'); - section_name++; - - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (tc_h->cfg, - section_name, - "PREFIX", - &loprefix)) - loprefix = GNUNET_strdup (""); - - - binary = GNUNET_OS_get_libexec_binary_path (binary_name); - tc_h->c_proc = GNUNET_OS_start_process_s (GNUNET_OS_INHERIT_STD_OUT_AND_ERR, - NULL, - loprefix, - binary, - binary_name, - "-c", - tc_h->cfg_filename, - NULL); - if (NULL == tc_h->c_proc) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start communicator!"); - return; - } - LOG (GNUNET_ERROR_TYPE_INFO, "started communicator\n"); - GNUNET_free (binary); -} - - -/** - * @brief Task run at shutdown to kill communicator and clean up - * - * @param cls Closure - Process of communicator - */ -static void -shutdown_nat (void *cls) -{ - struct GNUNET_OS_Process *proc = cls; - shutdown_process (proc); -} - - -/** - * @brief Task run at shutdown to kill the resolver process - * - * @param cls Closure - Process of communicator - */ -static void -shutdown_resolver (void *cls) -{ - struct GNUNET_OS_Process *proc = cls; - shutdown_process (proc); -} - - -static void -resolver_start (struct - GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h) -{ - char *binary; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "resolver_start\n"); - binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver"); - tc_h->resolver_proc = GNUNET_OS_start_process ( - GNUNET_OS_INHERIT_STD_OUT_AND_ERR - | GNUNET_OS_USE_PIPE_CONTROL, - NULL, - NULL, - NULL, - binary, - "gnunet-service-resolver", - "-c", - tc_h->cfg_filename, - NULL); - if (NULL == tc_h->resolver_proc) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start resolver service!"); - return; - } - LOG (GNUNET_ERROR_TYPE_INFO, "started resolver service\n"); - GNUNET_free (binary); - -} - - -/** - * @brief Start Peerstore - * - */ -static void -peerstore_start ( - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h) -{ - char *binary; - - binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-peerstore"); - tc_h->ps_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR, - NULL, - NULL, - NULL, - binary, - "gnunet-service-peerstore", - "-c", - tc_h->cfg_filename, - NULL); - if (NULL == tc_h->ps_proc) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start Peerstore!"); - return; - } - LOG (GNUNET_ERROR_TYPE_INFO, "started Peerstore\n"); - GNUNET_free (binary); -} - -/** - * @brief Start NAT - * - */ -static void -nat_start ( - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h) -{ - char *binary; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "nat_start\n"); - binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-nat"); - tc_h->nat_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR - | GNUNET_OS_USE_PIPE_CONTROL, - NULL, - NULL, - NULL, - binary, - "gnunet-service-nat", - "-c", - tc_h->cfg_filename, - NULL); - if (NULL == tc_h->nat_proc) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start NAT!"); - return; - } - LOG (GNUNET_ERROR_TYPE_INFO, "started NAT\n"); - GNUNET_free (binary); -} - - -/** - * @brief Start communicator part of transport service and communicator - * - * @param service_name Name of the service - * @param cfg Configuration handle - * @param communicator_available_cb Callback that is called when a new - * @param add_address_cb Callback that is called when a new - * communicator becomes available - * @param cb_cls Closure to @a communicator_available_cb and @a - * - * @return Handle to the communicator duo - */ -struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle * -GNUNET_TRANSPORT_TESTING_transport_communicator_service_start ( - const char *service_name, - const char *binary_name, - const char *cfg_filename, - const struct GNUNET_PeerIdentity *peer_id, - GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback - communicator_available_cb, - GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb, - GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb, - GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb, - GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_message_cb, - GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb, - void *cb_cls) -{ - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Starting new transport/communicator combo with config %s\n", - cfg_filename); - tc_h = - GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle); - tc_h->cfg_filename = GNUNET_strdup (cfg_filename); - tc_h->cfg = GNUNET_CONFIGURATION_create (); - if ((GNUNET_SYSERR == GNUNET_CONFIGURATION_load (tc_h->cfg, cfg_filename))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ ("Malformed configuration file `%s', exit ...\n"), - cfg_filename); - GNUNET_free (tc_h->cfg_filename); - GNUNET_CONFIGURATION_destroy (tc_h->cfg); - GNUNET_free (tc_h); - return NULL; - } - tc_h->bc_enabled = GNUNET_CONFIGURATION_get_value_yesno (tc_h->cfg, - "communicator-test", - "BACKCHANNEL_ENABLED"); - tc_h->communicator_available_cb = communicator_available_cb; - tc_h->add_address_cb = add_address_cb; - tc_h->queue_create_reply_cb = queue_create_reply_cb; - tc_h->add_queue_cb = add_queue_cb; - tc_h->incoming_msg_cb = incoming_message_cb; - tc_h->bc_cb = bc_cb; - tc_h->peer_id = *peer_id; - tc_h->cb_cls = cb_cls; - - /* Start communicator part of service */ - transport_communicator_start (tc_h); - /* Start NAT */ - nat_start (tc_h); - /* Start resolver service */ - resolver_start (tc_h); - /* Start peerstore service */ - peerstore_start (tc_h); - /* Schedule start communicator */ - communicator_start (tc_h, - binary_name); - return tc_h; -} - - -void -GNUNET_TRANSPORT_TESTING_transport_communicator_service_stop ( - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h) -{ - shutdown_communicator (tc_h->c_proc); - shutdown_service (tc_h->sh); - shutdown_nat (tc_h->nat_proc); - shutdown_resolver (tc_h->resolver_proc); - shutdown_peerstore (tc_h->ps_proc); - GNUNET_CONFIGURATION_destroy (tc_h->cfg); - GNUNET_free (tc_h); -} - - -/** - * @brief Instruct communicator to open a queue - * - * @param tc_h Handle to communicator which shall open queue - * @param peer_id Towards which peer - * @param address For which address - */ -void -GNUNET_TRANSPORT_TESTING_transport_communicator_open_queue ( - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h, - const struct GNUNET_PeerIdentity *peer_id, - const char *address) -{ - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue; - static uint32_t idgen; - char *prefix; - struct GNUNET_TRANSPORT_CreateQueue *msg; - struct GNUNET_MQ_Envelope *env; - size_t alen; - - tc_queue = - GNUNET_new (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue); - tc_queue->tc_h = tc_h; - prefix = GNUNET_HELLO_address_to_prefix (address); - if (NULL == prefix) - { - GNUNET_break (0); /* We got an invalid address!? */ - GNUNET_free (tc_queue); - return; - } - GNUNET_free (prefix); - alen = strlen (address) + 1; - env = - GNUNET_MQ_msg_extra (msg, alen, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE); - msg->request_id = htonl (idgen++); - tc_queue->qid = msg->request_id; - msg->receiver = *peer_id; - tc_queue->peer_id = *peer_id; - memcpy (&msg[1], address, alen); - if (NULL != tc_h->c_mq) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Sending queue create immediately\n"); - GNUNET_MQ_send (tc_h->c_mq, env); - } - else - { - tc_queue->open_queue_env = env; - } - GNUNET_CONTAINER_DLL_insert (tc_h->queue_head, tc_h->queue_tail, tc_queue); -} - - -/** - * @brief Instruct communicator to send data - * - * @param tc_queue The queue to use for sending - * @param cont function to call when done sending - * @param cont_cls closure for @a cont - * @param payload Data to send - * @param payload_size Size of the @a payload - */ -void -GNUNET_TRANSPORT_TESTING_transport_communicator_send - (struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h, - GNUNET_SCHEDULER_TaskCallback cont, - void *cont_cls, - const void *payload, - size_t payload_size) -{ - struct GNUNET_MessageHeader *mh; - struct GNUNET_TRANSPORT_SendMessageTo *msg; - struct GNUNET_MQ_Envelope *env; - size_t inbox_size; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue; - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue_tmp; - - tc_queue = NULL; - for (tc_queue_tmp = tc_h->queue_head; - NULL != tc_queue_tmp; - tc_queue_tmp = tc_queue_tmp->next) - { - if (tc_queue_tmp->q_len <= 0) - continue; - if (NULL == tc_queue) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Selecting queue with prio %u, len %" PRIu64 " and MTU %u\n", - tc_queue_tmp->priority, - tc_queue_tmp->q_len, - tc_queue_tmp->mtu); - tc_queue = tc_queue_tmp; - continue; - } - if (tc_queue->priority < tc_queue_tmp->priority) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Selecting queue with prio %u, len %" PRIu64 " and MTU %u\n", - tc_queue_tmp->priority, - tc_queue_tmp->q_len, - tc_queue_tmp->mtu); - tc_queue = tc_queue_tmp; - } - } - GNUNET_assert (NULL != tc_queue); - // Uncomment this for alternativ 1 of backchannel functionality - if (tc_queue->q_len != GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED) - tc_queue->q_len--; - // Until here for alternativ 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending message\n"); - inbox_size = sizeof (struct GNUNET_MessageHeader) + payload_size; - env = GNUNET_MQ_msg_extra (msg, - inbox_size, - GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG); - GNUNET_assert (NULL != env); - msg->qid = htonl (tc_queue->qid); - msg->mid = tc_queue->mid++; - msg->receiver = tc_queue->peer_id; - mh = (struct GNUNET_MessageHeader *) &msg[1]; - mh->size = htons (inbox_size); - mh->type = GNUNET_MESSAGE_TYPE_DUMMY; - memcpy (&mh[1], - payload, - payload_size); - if (NULL != cont) - GNUNET_MQ_notify_sent (env, - cont, - cont_cls); - GNUNET_MQ_send (tc_queue->tc_h->c_mq, - env); -} diff --git a/src/transport/transport-testing2.h b/src/transport/transport-testing2.h deleted file mode 100644 index 04f75fc88..000000000 --- a/src/transport/transport-testing2.h +++ /dev/null @@ -1,355 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2019 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 . - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file transport/transport-testing2.h - * @brief functions and structures related to testing-tng - * @author Christian Grothoff - * @author Julius Bünger - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_ats_transport_service.h" -#include "transport.h" - -/** - * @brief Queue of a communicator and some context - */ -struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue; - - -/** - * @brief Handle/Context to a single transmission - */ -struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorTransmission; - -/** - * @brief Function signature for callbacks that are called when new - * backchannel message arrived - * - * @param cls Closure - * @param msg Backchannel message - * @param pid Target peer - */ -typedef struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle * -(*GNUNET_TRANSPORT_TESTING_BackchannelCallback)(void *cls, - struct GNUNET_MessageHeader *msg, - struct GNUNET_PeerIdentity *pid); - - -/** - * @brief Function signature for callbacks that are called when new - * communicators become available - * - * @param cls Closure - * @param tc_h Communicator handle - * @param cc Characteristics of communicator - * @param address_prefix Prefix of the address - */ -typedef void -(*GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback)(void *cls, - struct - GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle - *tc_h, - enum - GNUNET_TRANSPORT_CommunicatorCharacteristics - cc, - char *address_prefix); - - -/** - * @brief Receive information about the address of a communicator. - * - * @param cls Closure - * @param tc_h Communicator handle - * @param address Address represented as string - * @param expiration Expiration - * @param aid Aid - * @param nt Network Type - */ -typedef void -(*GNUNET_TRANSPORT_TESTING_AddAddressCallback)(void *cls, - struct - GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle - *tc_h, - const char *address, - struct GNUNET_TIME_Relative - expiration, - uint32_t aid, - enum GNUNET_NetworkType nt); - - -/** - * @brief Get informed about the success of a queue request. - * - * @param cls Closure - * @param tc_h Communicator handle - * @param will_try #GNUNET_YES if communicator will try to create queue - */ -typedef void -(*GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback)(void *cls, - struct - GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle - *tc_h, - int will_try); - - -/** - * @brief Handle opening of queue - * - * @param cls Closure - * @param tc_h Communicator handle - * @param tc_queue Handle to newly opened queue - */ -typedef void -(*GNUNET_TRANSPORT_TESTING_AddQueueCallback)(void *cls, - struct - GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle - *tc_h, - struct - GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue - *tc_queue, - size_t mtu); - - -/** - * @brief Handle an incoming message - * - * @param cls Closure - * @param tc_h Handle to the receiving communicator - * @param msg Received message - */ -typedef void -(*GNUNET_TRANSPORT_TESTING_IncomingMessageCallback)(void *cls, - struct - GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle - *tc_h, - const char*payload, - size_t payload_len); - -/** - * @brief Handle to a transport communicator - */ -struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle -{ - /** - * Clients - */ - struct MyClient *client_head; - struct MyClient *client_tail; - - /** - * @brief Handle to the client - */ - struct GNUNET_MQ_Handle *c_mq; - - /** - * @brief Handle to the configuration - */ - struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * @brief File name of configuration file - */ - char *cfg_filename; - - struct GNUNET_PeerIdentity peer_id; - - /** - * @brief Handle to the transport service - */ - struct GNUNET_SERVICE_Handle *tsh; - - /** - * @brief Task that will be run on shutdown to stop and clean transport - * service - */ - struct GNUNET_SCHEDULER_Task *ts_shutdown_task; - - - /** - * @brief Process of the communicator - */ - struct GNUNET_OS_Process *c_proc; - - /** - * NAT process - */ - struct GNUNET_OS_Process *nat_proc; - - /** - * resolver service process - */ - struct GNUNET_OS_Process *resolver_proc; - - /** - * peerstore service process - */ - struct GNUNET_OS_Process *ps_proc; - - /** - * @brief Task that will be run on shutdown to stop and clean communicator - */ - struct GNUNET_SCHEDULER_Task *c_shutdown_task; - - /** - * @brief Characteristics of the communicator - */ - enum GNUNET_TRANSPORT_CommunicatorCharacteristics c_characteristics; - - /** - * @brief Specifies supported addresses - */ - char *c_addr_prefix; - - /** - * @brief Specifies supported addresses - */ - char *c_address; - - /** - * @brief Head of the DLL of queues associated with this communicator - */ - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_head; - - /** - * @brief Tail of the DLL of queues associated with this communicator - */ - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_tail; - - /* Callbacks + Closures */ - /** - * @brief Callback called when a new communicator connects - */ - GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback - communicator_available_cb; - - /** - * @brief Callback called when a new communicator connects - */ - GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb; - - /** - * @brief Callback called when a new communicator connects - */ - GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb; - - /** - * @brief Callback called when a new communicator connects - */ - GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb; - - /** - * @brief Callback called when a new communicator connects - */ - GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_msg_cb; - - /** - * @brief Backchannel callback - */ - GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb; - - /** - * Our service handle - */ - struct GNUNET_SERVICE_Handle *sh; - - /** - * @brief Closure to the callback - */ - void *cb_cls; - - /** - * Backchannel supported - */ - int bc_enabled; -}; - -/** - * @brief Start communicator part of transport service and communicator - * - * @param service_name Name of the service - * @param cfg Configuration handle - * @param communicator_available Callback that is called when a new - * communicator becomes available - * @param add_address_cb Callback handling new addresses - * @param queue_create_reply_cb Callback handling success of queue requests - * @param add_queue_cb Callback handling freshly created queues - * @param incoming_message_cb Callback handling incoming messages - * @param cb_cls Closure to @p communicator_available - * - * @return Handle to the communicator duo - */ -struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle * -GNUNET_TRANSPORT_TESTING_transport_communicator_service_start ( - const char *service_name, - const char *binary_name, - const char *cfg_filename, - const struct GNUNET_PeerIdentity *peer_id, - GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback - communicator_available_cb, - GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb, - GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb, - GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb, - GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_message_cb, - GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb, - void *cb_cls); - - -void -GNUNET_TRANSPORT_TESTING_transport_communicator_service_stop ( - struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h); - - -/** - * @brief Instruct communicator to open a queue - * - * @param tc_h Handle to communicator which shall open queue - * @param peer_id Towards which peer - * @param address For which address - */ -void -GNUNET_TRANSPORT_TESTING_transport_communicator_open_queue (struct - GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle - *tc_h, - const struct - GNUNET_PeerIdentity - *peer_id, - const char *address); - - -/** - * @brief Instruct communicator to send data - * - * @param tc_queue The queue to use for sending - * @param cont function to call when done sending - * @param cont_cls closure for @a cont - * @param payload Data to send - * @param payload_size Size of the @a payload - */ -void -GNUNET_TRANSPORT_TESTING_transport_communicator_send (struct - GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle - *tc_h, - GNUNET_SCHEDULER_TaskCallback - cont, - void *cont_cls, - const void *payload, - size_t payload_size); -- cgit v1.2.3 From 172ef59b934c067dd7ec8e72650e196c7ae2a04b Mon Sep 17 00:00:00 2001 From: Martin Schanzenbach Date: Mon, 30 Nov 2020 18:08:25 +0900 Subject: -start TNG transport test logic --- src/transport/Makefile.am | 5 + src/transport/transport-testing2.c | 923 ++++++++++++++++++++++++++++++++++++ src/transport/transport-testing2.h | 924 +++++++++++++++++++++++++++++++++++++ 3 files changed, 1852 insertions(+) create mode 100644 src/transport/transport-testing2.c create mode 100644 src/transport/transport-testing2.h (limited to 'src/transport') diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 477973af9..605d89cc0 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -168,10 +168,15 @@ libgnunettransporttesting_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) libgnunettransporttesting2_la_SOURCES = \ + transport-testing2.c transport-testing2.h \ transport-testing-communicator.c transport-testing-communicator.h libgnunettransporttesting2_la_LIBADD = \ libgnunettransport.la \ + libgnunettransportapplication.la \ + libgnunettransportcore.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ + $(top_builddir)/src/peerstore/libgnunetpeerstore.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunettransporttesting2_la_LDFLAGS = \ $(GN_LIBINTL) \ diff --git a/src/transport/transport-testing2.c b/src/transport/transport-testing2.c new file mode 100644 index 000000000..ca338c52f --- /dev/null +++ b/src/transport/transport-testing2.c @@ -0,0 +1,923 @@ +/* + This file is part of GNUnet. + Copyright (C) 2006, 2009, 2015, 2016 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 . + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/** + * @file transport-testing.c + * @brief testing lib for transport service + * @author Matthias Wachs + * @author Christian Grothoff + */ +#include "transport-testing2.h" + + +#define LOG(kind, ...) GNUNET_log_from (kind, "transport-testing", __VA_ARGS__) + + +static struct GNUNET_TRANSPORT_TESTING_PeerContext * +find_peer_context (struct GNUNET_TRANSPORT_TESTING_Handle *tth, + const struct GNUNET_PeerIdentity *peer) +{ + struct GNUNET_TRANSPORT_TESTING_PeerContext *t; + + for (t = tth->p_head; NULL != t; t = t->next) + if (0 == memcmp (&t->id, + peer, + sizeof(struct GNUNET_PeerIdentity))) + return t; + return NULL; +} + + +/** + * Find any connecting context matching the given pair of peers. + * + * @param p1 first peer + * @param p2 second peer + * @param cb function to call + * @param cb_cls closure for @a cb + */ +void +GNUNET_TRANSPORT_TESTING_find_connecting_context (struct + GNUNET_TRANSPORT_TESTING_PeerContext + *p1, + struct + GNUNET_TRANSPORT_TESTING_PeerContext + *p2, + GNUNET_TRANSPORT_TESTING_ConnectContextCallback + cb, + void *cb_cls) +{ + struct GNUNET_TRANSPORT_TESTING_Handle *tth = p1->tth; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn; + + for (cc = tth->cc_head; NULL != cc; cc = ccn) + { + ccn = cc->next; + if ((cc->p1 == p1) && + (cc->p2 == p2)) + cb (cb_cls, + cc); + } +} + + +static void +set_p1c (void *cls, + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx) +{ + int *found = cls; + + if (NULL != found) + *found = GNUNET_YES; + cx->p1_c = GNUNET_YES; +} + + +static void +set_mq (void *cls, + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx) +{ + struct GNUNET_MQ_Handle *mq = cls; + + cx->mq = mq; +} + + +static void +set_p2c (void *cls, + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx) +{ + int *found = cls; + + if (NULL != found) + *found = GNUNET_YES; + cx->p2_c = GNUNET_YES; +} + + +static void +clear_p1c (void *cls, + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx) +{ + int *found = cls; + + if (NULL != found) + *found = GNUNET_YES; + cx->p1_c = GNUNET_NO; +} + + +static void +clear_p2c (void *cls, + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx) +{ + int *found = cls; + + if (NULL != found) + *found = GNUNET_YES; + cx->p2_c = GNUNET_NO; +} + + +static void * +notify_connect (void *cls, + const struct GNUNET_PeerIdentity *peer, + struct GNUNET_MQ_Handle *mq) +{ + struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls; + struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth; + char *p2_s; + struct GNUNET_TRANSPORT_TESTING_PeerContext *p2; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn; + int found; + void *ret; + + p2 = find_peer_context (p->tth, + peer); + if (NULL != p->nc) + ret = p->nc (p->cb_cls, + peer, + mq); + else + ret = NULL; + + if (NULL != p2) + GNUNET_asprintf (&p2_s, + "%u (`%s')", + p2->no, + GNUNET_i2s (&p2->id)); + else + GNUNET_asprintf (&p2_s, + "`%s'", + GNUNET_i2s (peer)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Peers %s connected to peer %u (`%s')\n", + p2_s, + p->no, + GNUNET_i2s (&p->id)); + GNUNET_free (p2_s); + /* update flags in connecting contexts */ + found = GNUNET_NO; + GNUNET_TRANSPORT_TESTING_find_connecting_context (p, + p2, + &set_p1c, + &found); + if (GNUNET_NO == found) + { + cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest); + cc->p1 = p; + cc->p2 = p2; + cc->p1_c = GNUNET_YES; + GNUNET_CONTAINER_DLL_insert (tth->cc_head, + tth->cc_tail, + cc); + } + found = GNUNET_NO; + GNUNET_TRANSPORT_TESTING_find_connecting_context (p2, + p, + &set_p2c, + &found); + if (GNUNET_NO == found) + { + cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest); + cc->p1 = p2; + cc->p2 = p; + cc->p1_c = GNUNET_YES; + GNUNET_CONTAINER_DLL_insert (tth->cc_head, + tth->cc_tail, + cc); + } + GNUNET_TRANSPORT_TESTING_find_connecting_context (p, + p2, + &set_mq, + mq); + /* update set connected flag for all requests */ + for (cc = tth->cc_head; NULL != cc; cc = cc->next) + { + if (GNUNET_YES == cc->connected) + continue; + if ((GNUNET_YES == cc->p1_c) && + (GNUNET_YES == cc->p2_c)) + { + cc->connected = GNUNET_YES; + /* stop trying to connect */ + if (NULL != cc->tct) + { + GNUNET_SCHEDULER_cancel (cc->tct); + cc->tct = NULL; + } + if (NULL != cc->ats_sh) + { + GNUNET_ATS_connectivity_suggest_cancel (cc->ats_sh); + cc->ats_sh = NULL; + } + } + } + /* then notify application */ + for (cc = tth->cc_head; NULL != cc; cc = ccn) + { + ccn = cc->next; + if ((GNUNET_YES == cc->connected) && + (NULL != cc->cb)) + { + cc->cb (cc->cb_cls); + cc->cb = NULL; /* only notify once! */ + } + } + return ret; +} + + +/** + * Offer the current HELLO of P2 to P1. + * + * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequest` + */ +static void +offer_hello (void *cls); + + +static void +notify_disconnect (void *cls, + const struct GNUNET_PeerIdentity *peer, + void *handler_cls) +{ + struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls; + struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth; + char *p2_s; + /* Find PeerContext */ + int no = 0; + struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = NULL; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc; + + p2 = find_peer_context (p->tth, + peer); + no = p->no; + if (NULL != p2) + GNUNET_asprintf (&p2_s, + "%u (`%s')", + p2->no, + GNUNET_i2s (&p2->id)); + else + GNUNET_asprintf (&p2_s, + "`%s'", + GNUNET_i2s (peer)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Peers %s disconnected from peer %u (`%s')\n", + p2_s, + no, + GNUNET_i2s (&p->id)); + GNUNET_free (p2_s); + /* notify about disconnect */ + if (NULL != p->nd) + p->nd (p->cb_cls, + peer, + handler_cls); + if (NULL == p2) + return; + /* clear MQ, it is now invalid */ + GNUNET_TRANSPORT_TESTING_find_connecting_context (p, + p2, + &set_mq, + NULL); + /* update set connected flags for all requests */ + GNUNET_TRANSPORT_TESTING_find_connecting_context (p, + p2, + &clear_p1c, + NULL); + GNUNET_TRANSPORT_TESTING_find_connecting_context (p2, + p, + &clear_p2c, + NULL); + /* resume connectivity requests as necessary */ + for (cc = tth->cc_head; NULL != cc; cc = cc->next) + { + if (GNUNET_NO == cc->connected) + continue; + if ((GNUNET_YES != cc->p1_c) || + (GNUNET_YES != cc->p2_c)) + { + cc->connected = GNUNET_NO; + /* start trying to connect */ + if (NULL == cc->tct) + cc->tct = GNUNET_SCHEDULER_add_now (&offer_hello, + cc); + if (NULL == cc->ats_sh) + cc->ats_sh = GNUNET_ATS_connectivity_suggest (cc->p1->ats, + &p2->id, + 1); + } + } +} + + +static void +hello_iter_cb (void *cb_cls, + const struct GNUNET_PEERSTORE_Record *record, + const char *emsg) +{ + struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cb_cls; + //Check record type et al? + p->hello = GNUNET_malloc (record->value_size); + memcpy (p->hello, record->value, record->value_size); + + GNUNET_PEERSTORE_iterate_cancel (p->pic); + if (NULL != p->start_cb) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Peer %u (`%s') successfully started\n", + p->no, + GNUNET_i2s (&p->id)); + p->start_cb (p->start_cb_cls); + p->start_cb = NULL; + } +} + + +/** + * Start a peer with the given configuration + * @param tth the testing handle + * @param cfgname configuration file + * @param peer_id a unique number to identify the peer + * @param handlers functions for receiving messages + * @param nc connect callback + * @param nd disconnect callback + * @param cb_cls closure for callback + * @param start_cb start callback + * @param start_cb_cls closure for callback + * @return the peer context + */ +struct GNUNET_TRANSPORT_TESTING_PeerContext * +GNUNET_TRANSPORT_TESTING_start_peer (struct + GNUNET_TRANSPORT_TESTING_Handle *tth, + const char *cfgname, + int peer_id, + const struct + GNUNET_MQ_MessageHandler *handlers, + GNUNET_TRANSPORT_NotifyConnect nc, + GNUNET_TRANSPORT_NotifyDisconnect nd, + void *cb_cls, + GNUNET_SCHEDULER_TaskCallback start_cb, + void *start_cb_cls) +{ + char *emsg = NULL; + struct GNUNET_TRANSPORT_TESTING_PeerContext *p; + struct GNUNET_PeerIdentity dummy; + unsigned int i; + + if (GNUNET_NO == GNUNET_DISK_file_test (cfgname)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "File not found: `%s'\n", + cfgname); + return NULL; + } + + p = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_PeerContext); + p->tth = tth; + p->nc = nc; + p->nd = nd; + if (NULL != handlers) + { + for (i = 0; NULL != handlers[i].cb; i++) + ; + p->handlers = GNUNET_new_array (i + 1, + struct GNUNET_MQ_MessageHandler); + GNUNET_memcpy (p->handlers, + handlers, + i * sizeof(struct GNUNET_MQ_MessageHandler)); + } + if (NULL != cb_cls) + p->cb_cls = cb_cls; + else + p->cb_cls = p; + p->start_cb = start_cb; + if (NULL != start_cb_cls) + p->start_cb_cls = start_cb_cls; + else + p->start_cb_cls = p; + GNUNET_CONTAINER_DLL_insert (tth->p_head, + tth->p_tail, + p); + + /* Create configuration and call testing lib to modify it */ + p->cfg = GNUNET_CONFIGURATION_create (); + GNUNET_assert (GNUNET_OK == + GNUNET_CONFIGURATION_load (p->cfg, cfgname)); + if (GNUNET_SYSERR == + GNUNET_TESTING_configuration_create (tth->tl_system, + p->cfg)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Testing library failed to create unique configuration based on `%s'\n", + cfgname); + GNUNET_CONFIGURATION_destroy (p->cfg); + GNUNET_free (p); + return NULL; + } + + p->no = peer_id; + /* Configure peer with configuration */ + p->peer = GNUNET_TESTING_peer_configure (tth->tl_system, + p->cfg, + p->no, + NULL, + &emsg); + if (NULL == p->peer) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Testing library failed to create unique configuration based on `%s': `%s'\n", + cfgname, + emsg); + GNUNET_TRANSPORT_TESTING_stop_peer (p); + GNUNET_free (emsg); + return NULL; + } + GNUNET_free (emsg); + if (GNUNET_OK != GNUNET_TESTING_peer_start (p->peer)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Testing library failed to create unique configuration based on `%s'\n", + cfgname); + GNUNET_TRANSPORT_TESTING_stop_peer (p); + return NULL; + } + + memset (&dummy, + '\0', + sizeof(dummy)); + GNUNET_TESTING_peer_get_identity (p->peer, + &p->id); + if (0 == memcmp (&dummy, + &p->id, + sizeof(struct GNUNET_PeerIdentity))) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Testing library failed to obtain peer identity for peer %u\n", + p->no); + GNUNET_TRANSPORT_TESTING_stop_peer (p); + return NULL; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Peer %u configured with identity `%s'\n", + p->no, + GNUNET_i2s_full (&p->id)); + p->tmh = GNUNET_TRANSPORT_manipulation_connect (p->cfg); + p->th = GNUNET_TRANSPORT_core_connect (p->cfg, + NULL, + handlers, + p, + ¬ify_connect, + ¬ify_disconnect); + if ((NULL == p->th) || + (NULL == p->tmh)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to transport service for peer `%s': `%s'\n", + cfgname, + emsg); + GNUNET_TRANSPORT_TESTING_stop_peer (p); + return NULL; + } + p->ats = GNUNET_ATS_connectivity_init (p->cfg); + if (NULL == p->ats) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to ATS service for peer `%s': `%s'\n", + cfgname, + emsg); + GNUNET_TRANSPORT_TESTING_stop_peer (p); + return NULL; + } + p->pic = GNUNET_PEERSTORE_iterate (p->ph, + "transport", + &p->id, + GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY, + hello_iter_cb, + p); + GNUNET_assert (NULL != p->pic); + + return p; +} + + +/** + * Stops and restarts the given peer, sleeping (!) for 5s in between. + * + * @param p the peer + * @param restart_cb callback to call when restarted + * @param restart_cb_cls callback closure + * @return #GNUNET_OK in success otherwise #GNUNET_SYSERR + */ +int +GNUNET_TRANSPORT_TESTING_restart_peer (struct + GNUNET_TRANSPORT_TESTING_PeerContext *p, + GNUNET_SCHEDULER_TaskCallback restart_cb, + void *restart_cb_cls) +{ + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn; + + /* shutdown */ + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Stopping peer %u (`%s')\n", + p->no, + GNUNET_i2s (&p->id)); + if (NULL != p->pic) + { + GNUNET_PEERSTORE_iterate_cancel (p->pic); + p->pic = NULL; + } + if (NULL != p->th) + { + GNUNET_TRANSPORT_core_disconnect (p->th); + p->th = NULL; + } + if (NULL != p->tmh) + { + GNUNET_TRANSPORT_manipulation_disconnect (p->tmh); + p->tmh = NULL; + } + for (cc = p->tth->cc_head; NULL != cc; cc = ccn) + { + ccn = cc->next; + if ((cc->p1 == p) || + (cc->p2 == p)) + GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc); + } + if (NULL != p->ats) + { + GNUNET_ATS_connectivity_done (p->ats); + p->ats = NULL; + } + if (GNUNET_SYSERR == + GNUNET_TESTING_peer_stop (p->peer)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Failed to stop peer %u (`%s')\n", + p->no, + GNUNET_i2s (&p->id)); + return GNUNET_SYSERR; + } + + sleep (5); // YUCK! + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Restarting peer %u (`%s')\n", + p->no, + GNUNET_i2s (&p->id)); + /* restart */ + if (GNUNET_SYSERR == GNUNET_TESTING_peer_start (p->peer)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Failed to restart peer %u (`%s')\n", + p->no, + GNUNET_i2s (&p->id)); + return GNUNET_SYSERR; + } + + GNUNET_assert (NULL == p->start_cb); + p->start_cb = restart_cb; + p->start_cb_cls = restart_cb_cls; + + p->th = GNUNET_TRANSPORT_core_connect (p->cfg, + NULL, + p->handlers, + p, + ¬ify_connect, + ¬ify_disconnect); + GNUNET_assert (NULL != p->th); + p->ats = GNUNET_ATS_connectivity_init (p->cfg); + p->pic = GNUNET_PEERSTORE_iterate (p->ph, + "transport", + &p->id, + GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY, + hello_iter_cb, + p); + GNUNET_assert (NULL != p->pic); + return GNUNET_OK; +} + + +/** + * Shutdown the given peer + * + * @param p the peer + */ +void +GNUNET_TRANSPORT_TESTING_stop_peer (struct + GNUNET_TRANSPORT_TESTING_PeerContext *p) +{ + struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn; + + for (cc = tth->cc_head; NULL != cc; cc = ccn) + { + ccn = cc->next; + if ((cc->p1 == p) || + (cc->p2 == p)) + GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc); + } + if (NULL != p->pic) + { + GNUNET_PEERSTORE_iterate_cancel (p->pic); + p->pic = NULL; + } + if (NULL != p->tmh) + { + GNUNET_TRANSPORT_manipulation_disconnect (p->tmh); + p->tmh = NULL; + } + if (NULL != p->th) + { + GNUNET_TRANSPORT_core_disconnect (p->th); + p->th = NULL; + } + if (NULL != p->peer) + { + if (GNUNET_OK != + GNUNET_TESTING_peer_stop (p->peer)) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Testing lib failed to stop peer %u (`%s')\n", + p->no, + GNUNET_i2s (&p->id)); + } + GNUNET_TESTING_peer_destroy (p->peer); + p->peer = NULL; + } + if (NULL != p->ats) + { + GNUNET_ATS_connectivity_done (p->ats); + p->ats = NULL; + } + if (NULL != p->hello) + { + GNUNET_free (p->hello); + p->hello = NULL; + } + if (NULL != p->cfg) + { + GNUNET_CONFIGURATION_destroy (p->cfg); + p->cfg = NULL; + } + if (NULL != p->handlers) + { + GNUNET_free (p->handlers); + p->handlers = NULL; + } + GNUNET_CONTAINER_DLL_remove (tth->p_head, + tth->p_tail, + p); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Peer %u (`%s') stopped\n", + p->no, + GNUNET_i2s (&p->id)); + GNUNET_free (p); +} + + +/** + * Function called after the HELLO was passed to the + * transport service. + * FIXME maybe schedule the application_validate somehow + */ +/* +static void +hello_offered (void *cls) +{ + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls; + + cc->oh = NULL; + cc->tct = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, + &offer_hello, + cc); +}*/ + + +/** + * Offer the current HELLO of P2 to P1. + * + * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequest` + */ +static void +offer_hello (void *cls) +{ + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls; + struct GNUNET_TRANSPORT_TESTING_PeerContext *p1 = cc->p1; + struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = cc->p2; + struct GNUNET_TIME_Absolute t; + enum GNUNET_NetworkType nt; + char *addr; + + cc->tct = NULL; + { + char *p2_s = GNUNET_strdup (GNUNET_i2s (&p2->id)); + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Asking peer %u (`%s') to connect peer %u (`%s'), providing HELLO with %s\n", + p1->no, + GNUNET_i2s (&p1->id), + p2->no, + p2_s, + cc->p2->hello); + GNUNET_free (p2_s); + } + + addr = GNUNET_HELLO_extract_address (cc->p2->hello, + cc->p2->hello_size, + &cc->p2->id, + &nt, + &t); + GNUNET_assert (NULL == addr); + GNUNET_TRANSPORT_application_validate (cc->p1->ah, + &cc->p2->id, + nt, + addr); + GNUNET_free (addr); +} + + +/** + * Initiate a connection from p1 to p2 by offering p1 p2's HELLO message + * + * Remarks: start_peer's notify_connect callback can be called before. + * + * @param tth transport testing handle + * @param p1 peer 1 + * @param p2 peer 2 + * @param cb the callback to call when both peers notified that they are connected + * @param cls callback cls + * @return a connect request handle + */ +struct GNUNET_TRANSPORT_TESTING_ConnectRequest * +GNUNET_TRANSPORT_TESTING_connect_peers (struct + GNUNET_TRANSPORT_TESTING_PeerContext *p1, + struct + GNUNET_TRANSPORT_TESTING_PeerContext *p2, + GNUNET_SCHEDULER_TaskCallback cb, + void *cls) +{ + struct GNUNET_TRANSPORT_TESTING_Handle *tth = p1->tth; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn; + + ccn = NULL; + for (cc = tth->cc_head; NULL != cc; cc = cc->next) + { + if ((cc->p1 == p1) && + (cc->p2 == p2)) + { + ccn = cc; + break; + } + } + + cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest); + cc->p1 = p1; + cc->p2 = p2; + cc->cb = cb; + if (NULL != cls) + cc->cb_cls = cls; + else + cc->cb_cls = cc; + if (NULL != ccn) + { + cc->p1_c = ccn->p1_c; + cc->p2_c = ccn->p2_c; + cc->connected = ccn->connected; + } + GNUNET_CONTAINER_DLL_insert (tth->cc_head, + tth->cc_tail, + cc); + cc->tct = GNUNET_SCHEDULER_add_now (&offer_hello, + cc); + cc->ats_sh = GNUNET_ATS_connectivity_suggest (cc->p1->ats, + &p2->id, + 1); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "New connect request %p\n", + cc); + return cc; +} + + +/** + * Cancel the request to connect two peers + * Tou MUST cancel the request if you stop the peers before the peers connected succesfully + * + * @param tth transport testing handle + * @param cc a connect request handle + */ +void +GNUNET_TRANSPORT_TESTING_connect_peers_cancel (struct + GNUNET_TRANSPORT_TESTING_ConnectRequest + *cc) +{ + struct GNUNET_TRANSPORT_TESTING_Handle *tth = cc->p1->tth; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Canceling connect request!\n"); + if (NULL != cc->tct) + { + GNUNET_SCHEDULER_cancel (cc->tct); + cc->tct = NULL; + } + if (NULL != cc->ats_sh) + { + GNUNET_ATS_connectivity_suggest_cancel (cc->ats_sh); + cc->ats_sh = NULL; + } + GNUNET_CONTAINER_DLL_remove (tth->cc_head, + tth->cc_tail, + cc); + GNUNET_free (cc); +} + + +/** + * Clean up the transport testing + * + * @param tth transport testing handle + */ +void +GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_Handle *tth) +{ + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc; + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ct; + struct GNUNET_TRANSPORT_TESTING_PeerContext *p; + struct GNUNET_TRANSPORT_TESTING_PeerContext *t; + + if (NULL == tth) + return; + cc = tth->cc_head; + while (NULL != cc) + { + ct = cc->next; + LOG (GNUNET_ERROR_TYPE_ERROR, + "Developer forgot to cancel connect request!\n"); + GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc); + cc = ct; + } + p = tth->p_head; + while (NULL != p) + { + t = p->next; + LOG (GNUNET_ERROR_TYPE_ERROR, + "Developer forgot to stop peer!\n"); + GNUNET_TRANSPORT_TESTING_stop_peer (p); + p = t; + } + GNUNET_TESTING_system_destroy (tth->tl_system, + GNUNET_YES); + + GNUNET_free (tth); +} + + +/** + * Initialize the transport testing + * + * @return transport testing handle + */ +struct GNUNET_TRANSPORT_TESTING_Handle * +GNUNET_TRANSPORT_TESTING_init () +{ + struct GNUNET_TRANSPORT_TESTING_Handle *tth; + + tth = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_Handle); + tth->tl_system = GNUNET_TESTING_system_create ("transport-testing", + NULL, + NULL, + NULL); + if (NULL == tth->tl_system) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to initialize testing library!\n"); + GNUNET_free (tth); + return NULL; + } + return tth; +} + + +/* end of transport-testing.c */ diff --git a/src/transport/transport-testing2.h b/src/transport/transport-testing2.h new file mode 100644 index 000000000..3554436d8 --- /dev/null +++ b/src/transport/transport-testing2.h @@ -0,0 +1,924 @@ +/* + This file is part of GNUnet. + Copyright (C) 2006, 2009, 2015, 2016 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 . + + SPDX-License-Identifier: AGPL3.0-or-later + */ + +/** + * @file transport-testing.h + * @brief testing lib for transport service + * @author Matthias Wachs + * @author Christian Grothoff + */ +#ifndef TRANSPORT_TESTING_H +#define TRANSPORT_TESTING_H +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_hello_lib.h" +#include "gnunet_peerstore_service.h" +#include "gnunet_transport_core_service.h" +#include "gnunet_transport_application_service.h" +#include "gnunet_transport_manipulation_service.h" +#include "gnunet_testing_lib.h" + + +/* ************* Basic functions for starting/stopping/connecting *********** */ + +/** + * Context for a single peer + */ +struct GNUNET_TRANSPORT_TESTING_PeerContext; + +/** + * Definition for a transport testing handle + */ +struct GNUNET_TRANSPORT_TESTING_Handle; + + +/** + * Context for a single peer + */ +struct GNUNET_TRANSPORT_TESTING_PeerContext +{ + /** + * Next element in the DLL + */ + struct GNUNET_TRANSPORT_TESTING_PeerContext *next; + + /** + * Previous element in the DLL + */ + struct GNUNET_TRANSPORT_TESTING_PeerContext *prev; + + /** + * Transport testing handle this peer belongs to + */ + struct GNUNET_TRANSPORT_TESTING_Handle *tth; + + /** + * Application handle + */ + struct GNUNET_TRANSPORT_ApplicationHandle *ah; + + /** + * Peer's configuration + */ + struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Peer's transport service handle + */ + struct GNUNET_TRANSPORT_CoreHandle *th; + + /** + * Peer's transport service manipulation handle + */ + struct GNUNET_TRANSPORT_ManipulationHandle *tmh; + + /** + * Peer's ATS handle. + */ + struct GNUNET_ATS_ConnectivityHandle *ats; + + /** + * Peer's PEERSTORE Handle + */ + struct GNUNET_PEERSTORE_Handle *ph; + + /** + * Peer's transport get hello handle to retrieve peer's HELLO message + */ + struct GNUNET_PEERSTORE_IterateContext *pic; + + /** + * Hello + */ + char *hello; + + /** + * Hello size + */ + size_t hello_size; + + /** + * Peer's testing handle + */ + struct GNUNET_TESTING_Peer *peer; + + /** + * Peer identity + */ + struct GNUNET_PeerIdentity id; + + /** + * Handle for the peer's ARM process + */ + struct GNUNET_OS_Process *arm_proc; + + /** + * Receive callback + */ + struct GNUNET_MQ_MessageHandler *handlers; + + /** + * Notify connect callback + */ + GNUNET_TRANSPORT_NotifyConnect nc; + + /** + * Notify disconnect callback + */ + GNUNET_TRANSPORT_NotifyDisconnect nd; + + /** + * Startup completed callback + */ + GNUNET_SCHEDULER_TaskCallback start_cb; + + /** + * Closure for the @a nc and @a nd callbacks + */ + void *cb_cls; + + /** + * Closure for @e start_cb. + */ + void *start_cb_cls; + + /** + * An unique number to identify the peer + */ + unsigned int no; +}; + + +/** + * Handle for a request to connect two peers. + */ +struct GNUNET_TRANSPORT_TESTING_ConnectRequest +{ + /** + * Kept in a DLL. + */ + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *next; + + /** + * Kept in a DLL. + */ + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *prev; + + /** + * Peer we want to connect. + */ + struct GNUNET_TRANSPORT_TESTING_PeerContext *p1; + + /** + * Peer we want to connect. + */ + struct GNUNET_TRANSPORT_TESTING_PeerContext *p2; + + /** + * Task by which we accomplish the connection. + */ + struct GNUNET_SCHEDULER_Task *tct; + + /** + * Handle by which we ask ATS to faciliate the connection. + */ + struct GNUNET_ATS_ConnectivitySuggestHandle *ats_sh; + + /** + * Function to call upon completion. + */ + GNUNET_SCHEDULER_TaskCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Message queue for sending from @a p1 to @a p2. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * Set if peer1 says the connection is up to peer2. + */ + int p1_c; + + /** + * Set if peer2 says the connection is up to peer1. + */ + int p2_c; + + /** + * #GNUNET_YES if both @e p1_c and @e p2_c are #GNUNET_YES. + */ + int connected; +}; + + +/** + * Handle for a test run. + */ +struct GNUNET_TRANSPORT_TESTING_Handle +{ + /** + * Testing library system handle + */ + struct GNUNET_TESTING_System *tl_system; + + /** + * head DLL of connect contexts + */ + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc_head; + + /** + * head DLL of connect contexts + */ + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc_tail; + + /** + * head DLL of peers + */ + struct GNUNET_TRANSPORT_TESTING_PeerContext *p_head; + + /** + * tail DLL of peers + */ + struct GNUNET_TRANSPORT_TESTING_PeerContext *p_tail; +}; + + +/** + * Initialize the transport testing + * + * @return transport testing handle + */ +struct GNUNET_TRANSPORT_TESTING_Handle * +GNUNET_TRANSPORT_TESTING_init (void); + + +/** + * Clean up the transport testing + * + * @param tth transport testing handle + */ +void +GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_Handle *tth); + + +/** + * Start a peer with the given configuration + * + * @param tth the testing handle + * @param cfgname configuration file + * @param peer_id the peer_id + * @param handlers functions for receiving messages + * @param nc connect callback + * @param nd disconnect callback + * @param cb_cls closure for @a nc and @a nd callback + * @param start_cb start callback + * @param start_cb_cls closure for @a start_cb + * @return the peer context + */ +struct GNUNET_TRANSPORT_TESTING_PeerContext * +GNUNET_TRANSPORT_TESTING_start_peer ( + struct GNUNET_TRANSPORT_TESTING_Handle *tth, + const char *cfgname, + int peer_id, + const struct GNUNET_MQ_MessageHandler *handlers, + GNUNET_TRANSPORT_NotifyConnect nc, + GNUNET_TRANSPORT_NotifyDisconnect nd, + void *cb_cls, + GNUNET_SCHEDULER_TaskCallback start_cb, + void *start_cb_cls); + + +/** + * Shutdown the given peer + * + * @param p the peer + */ +void +GNUNET_TRANSPORT_TESTING_stop_peer ( + struct GNUNET_TRANSPORT_TESTING_PeerContext *pc); + + +/** + * Stops and restarts the given peer, sleeping (!) for 5s in between. + * + * @param p the peer + * @param restart_cb restart callback + * @param restart_cb_cls callback closure + * @return #GNUNET_OK in success otherwise #GNUNET_SYSERR + */ +int +GNUNET_TRANSPORT_TESTING_restart_peer ( + struct GNUNET_TRANSPORT_TESTING_PeerContext *p, + GNUNET_SCHEDULER_TaskCallback restart_cb, + void *restart_cb_cls); + + +/** + * Connect the given peers and call the callback when both peers + * report the inbound connection. Remarks: start_peer's notify_connect + * callback can be called before. + * + * @param p1 peer 1 + * @param p2 peer 2 + * @param cb the callback to call when both peers notified that they are + * connected + * @param cls callback cls + * @return a connect request handle + */ +struct GNUNET_TRANSPORT_TESTING_ConnectRequest * +GNUNET_TRANSPORT_TESTING_connect_peers ( + struct GNUNET_TRANSPORT_TESTING_PeerContext *p1, + struct GNUNET_TRANSPORT_TESTING_PeerContext *p2, + GNUNET_SCHEDULER_TaskCallback cb, + void *cls); + + +/** + * Cancel the request to connect two peers. You MUST cancel the + * request if you stop the peers before the peers connected + * succesfully. + * + * @param cc a connect request handle + */ +void +GNUNET_TRANSPORT_TESTING_connect_peers_cancel ( + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc); + + +/** + * Function called on matching connect requests. + * + * @param cls closure + * @param cc request matching the query + */ +typedef void (*GNUNET_TRANSPORT_TESTING_ConnectContextCallback) ( + void *cls, + struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc); + + +/** + * Find any connecting context matching the given pair of peers. + * + * @param p1 first peer + * @param p2 second peer + * @param cb function to call + * @param cb_cls closure for @a cb + */ +void +GNUNET_TRANSPORT_TESTING_find_connecting_context ( + struct GNUNET_TRANSPORT_TESTING_PeerContext *p1, + struct GNUNET_TRANSPORT_TESTING_PeerContext *p2, + GNUNET_TRANSPORT_TESTING_ConnectContextCallback cb, + void *cb_cls); + + +/* ********************** high-level process functions *************** */ + + +/** + * Function called once the peers have been launched and + * connected by #GNUNET_TRANSPORT_TESTING_connect_check(). + * + * @param cls closure + * @param num_peers size of the @a p array + * @param p the peers that were launched + */ +typedef void (*GNUNET_TRANSPORT_TESTING_ConnectContinuation) ( + void *cls, + unsigned int num_peers, + struct GNUNET_TRANSPORT_TESTING_PeerContext *p[]); + + +/** + * Internal data structure. + */ +struct GNUNET_TRANSPORT_TESTING_ConnectRequestList; + +/** + * Internal data structure. + */ +struct GNUNET_TRANSPORT_TESTING_InternalPeerContext; + + +GNUNET_NETWORK_STRUCT_BEGIN +struct GNUNET_TRANSPORT_TESTING_TestMessage +{ + /** + * Type is (usually) #GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE. + */ + struct GNUNET_MessageHeader header; + + /** + * Monotonically increasing counter throughout the test. + */ + uint32_t num GNUNET_PACKED; +}; +GNUNET_NETWORK_STRUCT_END + + +/** + * Function called by the transport for each received message. + * + * @param cls closure + * @param receiver receiver of the message + * @param sender sender of the message + * @param message the message + */ +typedef void (*GNUNET_TRANSPORT_TESTING_ReceiveCallback) ( + void *cls, + struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver, + const struct GNUNET_PeerIdentity *sender, + const struct GNUNET_TRANSPORT_TESTING_TestMessage *message); + + +/** + * Function called to notify transport users that another + * peer connected to us. + * + * @param cls closure + * @param me peer experiencing the event + * @param other peer that connected to @a me + */ +typedef void (*GNUNET_TRANSPORT_TESTING_NotifyConnect) ( + void *cls, + struct GNUNET_TRANSPORT_TESTING_PeerContext *me, + const struct GNUNET_PeerIdentity *other); + + +/** + * Function called to notify transport users that another + * peer disconnected from us. + * + * @param cls closure + * @param me peer experiencing the event + * @param other peer that disconnected from @a me + */ +typedef void (*GNUNET_TRANSPORT_TESTING_NotifyDisconnect) ( + void *cls, + struct GNUNET_TRANSPORT_TESTING_PeerContext *me, + const struct GNUNET_PeerIdentity *other); + + +/** + * Closure that must be passed to + * #GNUNET_TRANSPORT_TESTING_connect_check. + */ +struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext +{ + /** + * How should we continue after the connect? + */ + GNUNET_SCHEDULER_TaskCallback connect_continuation; + + /** + * Closure for @e connect_continuation. + */ + void *connect_continuation_cls; + + /** + * Which configuration file should we pass to the + * #GNUNET_PROGRAM_run() of the testcase? + */ + const char *config_file; + + /** + * Receiver argument to give for peers we start. + */ + GNUNET_TRANSPORT_TESTING_ReceiveCallback rec; + + /** + * Notify connect argument to give for peers we start. + */ + GNUNET_TRANSPORT_TESTING_NotifyConnect nc; + + /** + * Notify disconnect argument to give for peers we start. + */ + GNUNET_TRANSPORT_TESTING_NotifyDisconnect nd; + + /** + * Closure for @e rec, @e nc and @e nd. + */ + void *cls; + + /** + * Custom task to run on shutdown. + */ + GNUNET_SCHEDULER_TaskCallback shutdown_task; + + /** + * Closure for @e shutdown_task. + */ + void *shutdown_task_cls; + + /** + * Custom task to run after peers were started but before we try to + * connect them. If this function is set, we wait ONE second after + * running this function until we continue with connecting the + * peers. + */ + GNUNET_SCHEDULER_TaskCallback pre_connect_task; + + /** + * Closure for @e shutdown_task. + */ + void *pre_connect_task_cls; + + /** + * When should the testcase time out? + */ + struct GNUNET_TIME_Relative timeout; + + /** + * Should we try to create connections in both directions? + */ + int bi_directional; + + /* ******* fields set by #GNUNET_TRANSPORT_TESTING_connect_check **** */ + + /** + * Number of peers involved in the test. + */ + unsigned int num_peers; + + /** + * Configuration files we have, array with @e num_peers entries. + */ + char **cfg_files; + + /** + * Array with @e num_peers entries. + */ + struct GNUNET_TRANSPORT_TESTING_PeerContext **p; + + /** + * Name of the plugin. + */ + const char *test_plugin; + + /** + * Name of the testcase. + */ + const char *test_name; + + /** + * Configuration object for the testcase. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Main testing handle. + */ + struct GNUNET_TRANSPORT_TESTING_Handle *tth; + + /** + * Result from the main function, set to #GNUNET_OK on success. + * Clients should set to #GNUNET_SYSERR to indicate test failure. + */ + int global_ret; + + /** + * Generator for the `num` field in test messages. Incremented each + * time #GNUNET_TRANSPORT_TESTING_simple_send or + * #GNUNET_TRANSPORT_TESTING_large_send are used to transmit a + * message. + */ + uint32_t send_num_gen; + + /* ******* internal state, clients should not mess with this **** */ + + /** + * Task run on timeout. + */ + struct GNUNET_SCHEDULER_Task *timeout_task; + + /** + * Task run to connect peers. + */ + struct GNUNET_SCHEDULER_Task *connect_task; + + /** + * Number of peers that have been started. + */ + unsigned int started; + + /** + * DLL of active connect requests. + */ + struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl_head; + + /** + * DLL of active connect requests. + */ + struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl_tail; + + /** + * Array with @e num_peers entries. + */ + struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ip; +}; + + +/** + * Find peer by peer ID. + * + * @param ccc context to search + * @param peer peer to look for + * @return NULL if @a peer was not found + */ +struct GNUNET_TRANSPORT_TESTING_PeerContext * +GNUNET_TRANSPORT_TESTING_find_peer ( + struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc, + const struct GNUNET_PeerIdentity *peer); + + +/** + * Common implementation of the #GNUNET_TRANSPORT_TESTING_CheckCallback. + * Starts and connects the two peers, then invokes the + * `connect_continuation` from @a cls. Sets up a timeout to + * abort the test, and a shutdown handler to clean up properly + * on exit. + * + * @param cls closure of type `struct + * GNUNET_TRANSPORT_TESTING_ConnectCheckContext` + * @param tth_ initialized testing handle + * @param test_plugin_ name of the plugin + * @param test_name_ name of the test + * @param num_peers number of entries in the @a cfg_file array + * @param cfg_files array of names of configuration files for the peers + * @return #GNUNET_SYSERR on error + */ +int +GNUNET_TRANSPORT_TESTING_connect_check ( + void *cls, + struct GNUNET_TRANSPORT_TESTING_Handle *tth_, + const char *test_plugin_, + const char *test_name_, + unsigned int num_peers, + char *cfg_files[]); + + +/** + * Main function of a testcase. Called with the initial setup data + * for the test as derived from the source name and the binary name. + * + * @param cls closure + * @param tth_ initialized testing handle + * @param test_plugin_ name of the plugin + * @param test_name_ name of the test + * @param num_peers number of entries in the @a cfg_file array + * @param cfg_files array of names of configuration files for the peers + * @return #GNUNET_SYSERR on error + */ +typedef int (*GNUNET_TRANSPORT_TESTING_CheckCallback) ( + void *cls, + struct GNUNET_TRANSPORT_TESTING_Handle *tth_, + const char *test_plugin_, + const char *test_name_, + unsigned int num_peers, + char *cfg_files[]); + + +/** + * Setup testcase. Calls @a check with the data the test needs. + * + * @param argv0 binary name (argv[0]) + * @param filename source file name (__FILE__) + * @param num_peers number of peers to start + * @param check main function to run + * @param check_cls closure for @a check + * @return #GNUNET_OK on success + */ +int +GNUNET_TRANSPORT_TESTING_main_ (const char *argv0, + const char *filename, + unsigned int num_peers, + GNUNET_TRANSPORT_TESTING_CheckCallback check, + void *check_cls); + + +/** + * Setup testcase. Calls @a check with the data the test needs. + * + * @param num_peers number of peers to start + * @param check main function to run + * @param check_cls closure for @a check + * @return #GNUNET_OK on success + */ +#define GNUNET_TRANSPORT_TESTING_main(num_peers, check, check_cls) \ + GNUNET_TRANSPORT_TESTING_main_ (argv[0], \ + __FILE__, \ + num_peers, \ + check, \ + check_cls) + +/* ***************** Convenience functions for sending ********* */ + +/** + * Send a test message of type @a mtype and size @a msize from + * peer @a sender to peer @a receiver. The peers should be + * connected when this function is called. + * + * @param sender the sending peer + * @param receiver the receiving peer + * @param mtype message type to use + * @param msize size of the message, at least `sizeof (struct + * GNUNET_TRANSPORT_TESTING_TestMessage)` + * @param num unique message number + * @param cont continuation to call after transmission + * @param cont_cls closure for @a cont + * @return #GNUNET_OK if message was queued, + * #GNUNET_NO if peers are not connected + * #GNUNET_SYSERR if @a msize is illegal + */ +int +GNUNET_TRANSPORT_TESTING_send ( + struct GNUNET_TRANSPORT_TESTING_PeerContext *sender, + struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver, + uint16_t mtype, + uint16_t msize, + uint32_t num, + GNUNET_SCHEDULER_TaskCallback cont, + void *cont_cls); + + +/** + * Message type used by #GNUNET_TRANSPORT_TESTING_simple_send(). + */ +#define GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE 12345 + +/** + * Alternative message type for tests. + */ +#define GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE2 12346 + + +/** + * Type of the closure argument to pass to + * #GNUNET_TRANSPORT_TESTING_simple_send() and + * #GNUNET_TRANSPORT_TESTING_large_send(). + */ +struct GNUNET_TRANSPORT_TESTING_SendClosure +{ + /** + * Context for the transmission. + */ + struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc; + + /** + * Function that returns the desired message size. Overrides + * the message size, can be NULL in which case the message + * size is the default. + */ + size_t (*get_size_cb) (unsigned int n); + + /** + * Number of messages to be transmitted in a loop. + * Use zero for "forever" (until external shutdown). + */ + unsigned int num_messages; + + /** + * Function to call after all transmissions, can be NULL. + */ + GNUNET_SCHEDULER_TaskCallback cont; + + /** + * Closure for @e cont. + */ + void *cont_cls; +}; + + +/** + * Task that sends a minimalistic test message from the + * first peer to the second peer. + * + * @param cls the `struct GNUNET_TRANSPORT_TESTING_SendClosure` + * which should contain at least two peers, the first two + * of which should be currently connected + */ +void +GNUNET_TRANSPORT_TESTING_simple_send (void *cls); + +/** + * Size of a message sent with + * #GNUNET_TRANSPORT_TESTING_large_send(). Big enough + * to usually force defragmentation. + */ +#define GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE 2600 + +/** + * Task that sends a large test message from the + * first peer to the second peer. + * + * @param cls the `struct GNUNET_TRANSPORT_TESTING_SendClosure` + * which should contain at least two peers, the first two + * of which should be currently connected + */ +void +GNUNET_TRANSPORT_TESTING_large_send (void *cls); + + +/* ********************** log-only convenience functions ************* */ + + +/** + * Log a connect event. + * + * @param cls NULL + * @param me peer that had the event + * @param other peer that connected. + */ +void +GNUNET_TRANSPORT_TESTING_log_connect ( + void *cls, + struct GNUNET_TRANSPORT_TESTING_PeerContext *me, + const struct GNUNET_PeerIdentity *other); + + +/** + * Log a disconnect event. + * + * @param cls NULL + * @param me peer that had the event + * @param other peer that disconnected. + */ +void +GNUNET_TRANSPORT_TESTING_log_disconnect ( + void *cls, + struct GNUNET_TRANSPORT_TESTING_PeerContext *me, + const struct GNUNET_PeerIdentity *other); + + +/* ********************** low-level filename functions *************** */ + + +/** + * Extracts the test filename from an absolute file name and removes + * the extension. + * + * @param file absolute file name + * @return resulting test name + */ +char * +GNUNET_TRANSPORT_TESTING_get_test_name (const char *file); + + +/** + * This function takes the filename (e.g. argv[0), removes a "lt-"-prefix and + * if existing ".exe"-prefix and adds the peer-number + * + * @param file filename of the test, e.g. argv[0] + * @param count peer number + * @return configuration name to use + */ +char * +GNUNET_TRANSPORT_TESTING_get_config_name (const char *file, int count); + + +/** + * Extracts the plugin anme from an absolute file name and the test name + * @param file absolute file name + * @param test test name + * @return the plugin name + */ +char * +GNUNET_TRANSPORT_TESTING_get_test_plugin_name (const char *executable, + const char *testname); + + +/** + * Extracts the filename from an absolute file name and removes the + * extenstion + * + * @param file absolute file name + * @return the source name + */ +char * +GNUNET_TRANSPORT_TESTING_get_test_source_name (const char *file); + +#endif +/* end of transport_testing.h */ -- cgit v1.2.3 From ddbb4c740614d988431700bdcbb358de00be6313 Mon Sep 17 00:00:00 2001 From: Martin Schanzenbach Date: Mon, 30 Nov 2020 19:14:20 +0900 Subject: -fix link --- src/transport/Makefile.am | 1 + 1 file changed, 1 insertion(+) (limited to 'src/transport') diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 605d89cc0..800a27aa2 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -175,6 +175,7 @@ libgnunettransporttesting2_la_LIBADD = \ libgnunettransportapplication.la \ libgnunettransportcore.la \ $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerstore/libgnunetpeerstore.la \ $(top_builddir)/src/util/libgnunetutil.la -- cgit v1.2.3