From 33830e71f8e80334e0c8cf5527b1f2b20804485e Mon Sep 17 00:00:00 2001 From: t3sserakt Date: Fri, 16 Jul 2021 21:05:11 +0200 Subject: - started to implement several cmds to start peers^Ctestcase plugin will be started directly from helper, functionality to communicate between master cmd loop and local cmd loop, code compiles, test is not working atm. --- src/include/gnunet_protocols.h | 20 + src/include/gnunet_testbed_ng_service.h | 9 + src/include/gnunet_testing_ng_lib.h | 1 + src/include/gnunet_testing_plugin.h | 12 +- src/testbed/Makefile.am | 11 +- src/testbed/gnunet-cmd.c | 54 +- src/testbed/gnunet-cmds-helper.c | 719 +++++++++++++++++++++ src/testbed/gnunet-helper-cmds.c | 581 ----------------- src/testbed/netjail_exec.sh | 2 +- src/testbed/plugin_testcmd.c | 19 +- src/testbed/testbed_api.h | 3 +- ...testbed_api_cmd_block_until_all_peers_started.c | 102 +++ src/testbed/testbed_api_cmd_netjail_start.c | 6 + .../testbed_api_cmd_netjail_start_testbed.c | 162 ++++- src/testbed/testbed_api_cmd_send_peer_ready.c | 102 +++ src/testbed/testbed_helper.h | 46 ++ src/testing/testing_api_cmd_start_peer.c | 296 +++++++++ src/testing/testing_api_cmd_system_create.c | 110 ++++ src/testing/testing_api_loop.c | 3 + src/transport/transport-testing.c | 4 +- src/transport/transport-testing2.c | 4 +- src/util/child_management.c | 19 +- 22 files changed, 1649 insertions(+), 636 deletions(-) create mode 100644 src/testbed/gnunet-cmds-helper.c delete mode 100644 src/testbed/gnunet-helper-cmds.c create mode 100644 src/testbed/testbed_api_cmd_block_until_all_peers_started.c create mode 100644 src/testbed/testbed_api_cmd_send_peer_ready.c create mode 100644 src/testing/testing_api_cmd_start_peer.c create mode 100644 src/testing/testing_api_cmd_system_create.c (limited to 'src') diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 8e6e8b1be..1d33d986d 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -3549,6 +3549,26 @@ extern "C" { /*********************************************************************************/ +/*********************************************************************************/ +/********************************** Cmd Testing **********************************/ +/*********************************************************************************/ + +/** + * The initialization message towards gnunet-cmds-helper + */ +#define GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT 1700 + +/** + * The reply message from gnunet-cmds-helper + */ +#define GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY 1701 + +#define GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED 1702 + +#define GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED 1703 + +/*********************************************************************************/ + /** * Type used to match 'all' message types. */ diff --git a/src/include/gnunet_testbed_ng_service.h b/src/include/gnunet_testbed_ng_service.h index 9845b3be6..2ea5e616c 100644 --- a/src/include/gnunet_testbed_ng_service.h +++ b/src/include/gnunet_testbed_ng_service.h @@ -265,4 +265,13 @@ int GNUNET_TESTBED_get_trait_hosts (const struct GNUNET_TESTING_Command *cmd, struct GNUNET_TESTBED_Host ***hosts); + +struct GNUNET_TESTING_Command +GNUNET_TESTING_cmd_block_until_all_peers_started (const char *label, + unsigned int * + all_peers_started); + +struct GNUNET_TESTING_Command +GNUNET_TESTING_cmd_send_peer_ready (const char *label, + TESTBED_CMD_HELPER_write_cb write_message); #endif diff --git a/src/include/gnunet_testing_ng_lib.h b/src/include/gnunet_testing_ng_lib.h index a794562a9..8927fd4f1 100644 --- a/src/include/gnunet_testing_ng_lib.h +++ b/src/include/gnunet_testing_ng_lib.h @@ -28,6 +28,7 @@ #define GNUNET_TESTING_NG_LIB_H #include "gnunet_util_lib.h" +#include "gnunet_testing_plugin.h" /* ********************* Helper functions ********************* */ diff --git a/src/include/gnunet_testing_plugin.h b/src/include/gnunet_testing_plugin.h index 527f509ad..6a54cacd2 100644 --- a/src/include/gnunet_testing_plugin.h +++ b/src/include/gnunet_testing_plugin.h @@ -36,9 +36,17 @@ extern "C" #endif #endif +typedef void +(*TESTBED_CMD_HELPER_write_cb) (struct GNUNET_MessageHeader *message, size_t + msg_length); + +typedef void +(*GNUNET_TESTING_PLUGIN_StartTestCase) (TESTBED_CMD_HELPER_write_cb + write_message, char *router_ip, + char *node_ip); typedef void -(*GNUNET_TESTING_PLUGIN_StartTestCase) (); +(*GNUNET_TESTING_PLUGIN_ALL_PEERS_STARTED) (); struct GNUNET_TESTING_PluginFunctions { @@ -48,6 +56,8 @@ struct GNUNET_TESTING_PluginFunctions void *cls; GNUNET_TESTING_PLUGIN_StartTestCase start_testcase; + + GNUNET_TESTING_PLUGIN_ALL_PEERS_STARTED all_peers_started; }; #if 0 /* keep Emacsens' auto-indent happy */ diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am index 8c4a6342b..dc24eaf26 100644 --- a/src/testbed/Makefile.am +++ b/src/testbed/Makefile.am @@ -24,7 +24,7 @@ endif libexec_PROGRAMS = \ gnunet-cmd \ - gnunet-helper-cmds \ + gnunet-cmds-helper \ gnunet-service-testbed \ gnunet-helper-testbed \ gnunet-daemon-testbed-blacklist \ @@ -45,6 +45,7 @@ libgnunet_plugin_testcmd_la_SOURCES = \ libgnunet_plugin_testcmd_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/testbed/libgnunettestbed.la $(LTLIBINTL) libgnunet_plugin_testcmd_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) @@ -94,9 +95,9 @@ gnunet_cmd_LDADD = $(XLIB) \ libgnunettestbed.la \ $(LTLIBINTL) $(Z_LIBS) -gnunet_helper_cmds_SOURCES = \ - gnunet-helper-cmds.c -gnunet_helper_cmds_LDADD = $(XLIB) \ +gnunet_cmds_helper_SOURCES = \ + gnunet-cmds-helper.c +gnunet_cmds_helper_LDADD = $(XLIB) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunettestbed.la \ @@ -124,6 +125,8 @@ lib_LTLIBRARIES = \ libgnunettestbed.la libgnunettestbed_la_SOURCES = \ + testbed_api_cmd_send_peer_ready.c \ + testbed_api_cmd_block_until_all_peers_started.c \ testbed_api_cmd_netjail_start.c \ testbed_api_cmd_netjail_start_testbed.c \ testbed_api_cmd_netjail_stop_testbed.c \ diff --git a/src/testbed/gnunet-cmd.c b/src/testbed/gnunet-cmd.c index 477c3c454..7889750ba 100644 --- a/src/testbed/gnunet-cmd.c +++ b/src/testbed/gnunet-cmd.c @@ -36,6 +36,9 @@ */ #define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__) +#define NODE_BASE_IP "192.168.15." + +#define ROUTER_BASE_IP "92.68.150." /** * Handle for a plugin. @@ -51,29 +54,44 @@ struct Plugin * Plugin API. */ struct GNUNET_TESTING_PluginFunctions *api; + + char *node_ip; + + char *plugin_name; + + char *global_n; + + char *local_m; + + char *n; + + char *m; }; /** * Main function to run the test cases. * - * @param cls not used. + * @param cls plugin to use. * */ static void run (void *cls) { - struct Plugin *plugin; + struct Plugin *plugin = cls; + char *router_ip; + char *node_ip; + + router_ip = GNUNET_malloc (strlen (ROUTER_BASE_IP) + strlen (plugin->m) + 1); + strcpy (router_ip, ROUTER_BASE_IP); + strcat (router_ip, plugin->m); + + node_ip = GNUNET_malloc (strlen (NODE_BASE_IP) + strlen (plugin->n) + 1); + strcat (node_ip, NODE_BASE_IP); + strcat (node_ip, plugin->n); + + plugin->api->start_testcase (NULL, router_ip, node_ip); - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "gnunet-cmd", - "running plugin.\n"); - LOG (GNUNET_ERROR_TYPE_ERROR, - "running plugin.\n"); - plugin = GNUNET_new (struct Plugin); - plugin->api = GNUNET_PLUGIN_load ("libgnunet_plugin_testcmd", - NULL); - plugin->library_name = GNUNET_strdup ("libgnunet_plugin_testcmd"); - plugin->api->start_testcase (); } @@ -81,13 +99,25 @@ int main (int argc, char *const *argv) { int rv = 0; + struct Plugin *plugin; GNUNET_log_setup ("gnunet-cmd", "DEBUG", NULL); + plugin = GNUNET_new (struct Plugin); + plugin->api = GNUNET_PLUGIN_load (argv[0], + NULL); + plugin->library_name = GNUNET_strdup (argv[0]); + + plugin->global_n = argv[1]; + plugin->local_m = argv[2]; + plugin->n = argv[3]; + plugin->m = argv[4]; + GNUNET_SCHEDULER_run (&run, - NULL); + plugin); + GNUNET_free (plugin); return rv; } diff --git a/src/testbed/gnunet-cmds-helper.c b/src/testbed/gnunet-cmds-helper.c new file mode 100644 index 000000000..693892a9c --- /dev/null +++ b/src/testbed/gnunet-cmds-helper.c @@ -0,0 +1,719 @@ +/* + This file is part of GNUnet + Copyright (C) 2008--2013, 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 testbed/gnunet-cmds-helper.c + * @brief Helper binary that is started from a remote interpreter loop to start + * a local interpreter loop. + * + * This helper monitors for three termination events. They are: (1)The + * stdin of the helper is closed for reading; (2)the helper received + * SIGTERM/SIGINT; (3)the local loop crashed. In case of events 1 and 2 + * the helper kills the interpreter loop. When the interpreter loop + * crashed (event 3), the helper should send a SIGTERM to its own process + * group; this behaviour will help terminate any child processes the loop + * has started and prevents them from leaking and running forever. + * + * @author t3sserakt + * @author Sree Harsha Totakura + */ + + +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_testing_lib.h" +#include "gnunet_testbed_service.h" +#include "testbed_helper.h" +#include "testbed_api.h" +#include "gnunet_testing_plugin.h" +#include +#include "execinfo.h" + +/** + * Generic logging shortcut + */ +#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__) + +/** + * Debug logging shorthand + */ +#define LOG_DEBUG(...) LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) + +#define NODE_BASE_IP "192.168.15." + +#define ROUTER_BASE_IP "92.68.150." + +#define MAX_TRACE_DEPTH 50 + +/** + * Handle for a plugin. + */ +struct Plugin +{ + /** + * Name of the shared library. + */ + char *library_name; + + /** + * Plugin API. + */ + struct GNUNET_TESTING_PluginFunctions *api; + + char *node_ip; + + char *plugin_name; + + char *global_n; + + char *local_m; + + char *n; + + char *m; +}; + +struct NodeIdentifier +{ + char *n; + + char *m; + + char *global_n; + + char *local_m; +}; + +/** + * Context for a single write on a chunk of memory + */ +struct WriteContext +{ + /** + * The data to write + */ + void *data; + + /** + * The length of the data + */ + size_t length; + + /** + * The current position from where the write operation should begin + */ + size_t pos; +}; + +struct Plugin *plugin; + +/** + * The process handle to the testbed service + */ +static struct GNUNET_OS_Process *cmd_binary_process; + +/** + * Handle to the testing system + */ +static struct GNUNET_TESTING_System *test_system; + +/** + * Our message stream tokenizer + */ +struct GNUNET_MessageStreamTokenizer *tokenizer; + +/** + * Disk handle from stdin + */ +static struct GNUNET_DISK_FileHandle *stdin_fd; + +/** + * Disk handle for stdout + */ +static struct GNUNET_DISK_FileHandle *stdout_fd; + +/** + * Pipe used to communicate shutdown via signal. + */ +static struct GNUNET_DISK_PipeHandle *sigpipe; + +/** + * Task identifier for the read task + */ +static struct GNUNET_SCHEDULER_Task *read_task_id; + +/** + * Task identifier for the write task + */ +static struct GNUNET_SCHEDULER_Task *write_task_id; + +/** + * Task to kill the child + */ +static struct GNUNET_SCHEDULER_Task *child_death_task_id; + +/** + * Are we done reading messages from stdin? + */ +static int done_reading; + +/** + * Result to return in case we fail + */ +static int status; + + +struct BacktraceInfo +{ + /** + * Array of strings which make up a backtrace from the point when this + * task was scheduled (essentially, who scheduled the task?) + */ + char **backtrace_strings; + + /** + * Size of the backtrace_strings array + */ + int num_backtrace_strings; +}; + +/** + * Output stack trace of task @a t. + * + * @param t task to dump stack trace of + */ +static void +dump_backtrace (struct BacktraceInfo *t) +{ + + for (unsigned int i = 0; i < t->num_backtrace_strings; i++) + LOG (GNUNET_ERROR_TYPE_ERROR, + "Task %p trace %u: %s\n", + t, + i, + t->backtrace_strings[i]); + +} + + +/** + * Initialize backtrace data for task @a t + * + * @param t task to initialize + */ +static void +init_backtrace () +{ + struct BacktraceInfo *t; + void *backtrace_array[MAX_TRACE_DEPTH]; + + t = GNUNET_new (struct BacktraceInfo); + t->num_backtrace_strings + = backtrace (backtrace_array, MAX_TRACE_DEPTH); + t->backtrace_strings = + backtrace_symbols (backtrace_array, + t->num_backtrace_strings); + dump_backtrace (t); + +} + + +/** + * Task to shut down cleanly + * + * @param cls NULL + */ +static void +shutdown_task (void *cls) +{ + + init_backtrace (); + LOG_DEBUG ("Shutting down.\n"); + LOG (GNUNET_ERROR_TYPE_ERROR, + "Shutting down tokenizer!\n"); + + if (NULL != read_task_id) + { + GNUNET_SCHEDULER_cancel (read_task_id); + read_task_id = NULL; + } + if (NULL != write_task_id) + { + struct WriteContext *wc; + + wc = GNUNET_SCHEDULER_cancel (write_task_id); + write_task_id = NULL; + GNUNET_free (wc->data); + GNUNET_free (wc); + } + if (NULL != child_death_task_id) + { + GNUNET_SCHEDULER_cancel (child_death_task_id); + child_death_task_id = NULL; + } + if (NULL != stdin_fd) + (void) GNUNET_DISK_file_close (stdin_fd); + if (NULL != stdout_fd) + (void) GNUNET_DISK_file_close (stdout_fd); + GNUNET_MST_destroy (tokenizer); + tokenizer = NULL; + + if (NULL != test_system) + { + GNUNET_TESTING_system_destroy (test_system, GNUNET_YES); + test_system = NULL; + } +} + + + + +/** + * Task to write to the standard out + * + * @param cls the WriteContext + */ +static void +write_task (void *cls) +{ + struct WriteContext *wc = cls; + ssize_t bytes_wrote; + + LOG (GNUNET_ERROR_TYPE_ERROR, + "Writing data!\n"); + + GNUNET_assert (NULL != wc); + write_task_id = NULL; + bytes_wrote = GNUNET_DISK_file_write (stdout_fd, + wc->data + wc->pos, + wc->length - wc->pos); + if (GNUNET_SYSERR == bytes_wrote) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Cannot reply back successful initialization\n"); + GNUNET_free (wc->data); + GNUNET_free (wc); + return; + } + wc->pos += bytes_wrote; + if (wc->pos == wc->length) + { + GNUNET_free (wc->data); + GNUNET_free (wc); + LOG (GNUNET_ERROR_TYPE_ERROR, + "Written successfully!\n"); + return; + } + LOG (GNUNET_ERROR_TYPE_ERROR, + "Written data!\n"); + write_task_id = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, + stdout_fd, + &write_task, + wc); +} + + +/** + * Task triggered whenever we receive a SIGCHLD (child + * process died). + * + * @param cls closure, NULL if we need to self-restart + */ +static void +child_death_task (void *cls) +{ + const struct GNUNET_DISK_FileHandle *pr; + char c[16]; + + pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); + child_death_task_id = NULL; + /* consume the signal */ + GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof(c))); + LOG_DEBUG ("Got SIGCHLD\n"); + + LOG_DEBUG ("Child hasn't died. Resuming to monitor its status\n"); + child_death_task_id = + GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + pr, + &child_death_task, + NULL); +} + + +static void +write_message (struct GNUNET_MessageHeader *message, size_t msg_length) +{ + struct WriteContext *wc; + + LOG (GNUNET_ERROR_TYPE_ERROR, + "enter write_message!\n"); + wc = GNUNET_new (struct WriteContext); + wc->length = msg_length; + wc->data = message; + write_task_id = GNUNET_SCHEDULER_add_write_file ( + GNUNET_TIME_UNIT_FOREVER_REL, + stdout_fd, + &write_task, + wc); + LOG (GNUNET_ERROR_TYPE_ERROR, + "leave write_message!\n"); +} + + +/** + * Function to run the test cases. + * + * @param cls plugin to use. + * + */ +static void +run_plugin (void *cls) +{ + struct Plugin *plugin = cls; + char *router_ip; + char *node_ip; + + router_ip = GNUNET_malloc (strlen (ROUTER_BASE_IP) + strlen (plugin->m) + 1); + strcpy (router_ip, ROUTER_BASE_IP); + strcat (router_ip, plugin->m); + + node_ip = GNUNET_malloc (strlen (NODE_BASE_IP) + strlen (plugin->n) + 1); + strcat (node_ip, NODE_BASE_IP); + strcat (node_ip, plugin->n); + + plugin->api->start_testcase (&write_message, router_ip, node_ip); + +} + + +/** + * Functions with this signature are called whenever a + * complete message is received by the tokenizer. + * + * Do not call #GNUNET_mst_destroy() in this callback + * + * @param cls identification of the client + * @param message the actual message + * @return #GNUNET_OK on success, + * #GNUNET_NO to stop further processing (no error) + * #GNUNET_SYSERR to stop further processing with error + */ +static int +tokenizer_cb (void *cls, const struct GNUNET_MessageHeader *message) +{ + struct NodeIdentifier *ni = cls; + const struct GNUNET_CMDS_HelperInit *msg; + struct GNUNET_CMDS_HelperReply *reply; + char *binary; + char *plugin_name; + size_t plugin_name_size; + uint16_t msize; + size_t msg_length; + char *router_ip; + char *node_ip; + + LOG (GNUNET_ERROR_TYPE_ERROR, + "tokenizer \n"); + + msize = ntohs (message->size); + if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED == ntohs ( + message->type)) + { + plugin->api->all_peers_started (); + } + else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT == ntohs (message->type)) + { + msg = (const struct GNUNET_CMDS_HelperInit *) message; + plugin_name_size = ntohs (msg->plugin_name_size); + if ((sizeof(struct GNUNET_CMDS_HelperInit) + plugin_name_size) > msize) + { + GNUNET_break (0); + LOG (GNUNET_ERROR_TYPE_WARNING, + "Received unexpected message -- exiting\n"); + goto error; + } + plugin_name = GNUNET_malloc (plugin_name_size + 1); + GNUNET_strlcpy (plugin_name, + ((char *) &msg[1]), + plugin_name_size + 1); + + binary = GNUNET_OS_get_libexec_binary_path ("gnunet-cmd"); + + LOG (GNUNET_ERROR_TYPE_ERROR, + "plugin_name: %s \n", + plugin_name); + + // cmd_binary_process = GNUNET_OS_start_process ( + /*GNUNET_OS_INHERIT_STD_ERR verbose? , + NULL, + NULL, + NULL, + binary, + plugin_name, + ni->global_n, + ni->local_m, + ni->n, + ni->m, + NULL);*/ + + plugin = GNUNET_new (struct Plugin); + plugin->api = GNUNET_PLUGIN_load (plugin_name, + NULL); + plugin->library_name = GNUNET_strdup (plugin_name); + + plugin->global_n = ni->global_n; + plugin->local_m = ni->local_m; + plugin->n = ni->n; + plugin->m = ni->m; + + router_ip = GNUNET_malloc (strlen (ROUTER_BASE_IP) + strlen (plugin->m) + + 1); + strcpy (router_ip, ROUTER_BASE_IP); + strcat (router_ip, plugin->m); + + node_ip = GNUNET_malloc (strlen (NODE_BASE_IP) + strlen (plugin->n) + 1); + strcat (node_ip, NODE_BASE_IP); + strcat (node_ip, plugin->n); + + plugin->api->start_testcase (&write_message, router_ip, node_ip); + + LOG (GNUNET_ERROR_TYPE_ERROR, + "We got here!\n"); + + /*if (NULL == cmd_binary_process) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Starting plugin failed!\n"); + return GNUNET_SYSERR; + }*/ + + LOG (GNUNET_ERROR_TYPE_ERROR, + "We got here 2!\n"); + + LOG (GNUNET_ERROR_TYPE_ERROR, + "global_n: %s local_n: %s n: %s m: %s.\n", + ni->global_n, + ni->local_m, + ni->n, + ni->m); + + LOG (GNUNET_ERROR_TYPE_ERROR, + "We got here 3!\n"); + + GNUNET_free (binary); + + done_reading = GNUNET_YES; + + msg_length = sizeof(struct GNUNET_CMDS_HelperReply); + reply = GNUNET_new (struct GNUNET_CMDS_HelperReply); + reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY); + reply->header.size = htons ((uint16_t) msg_length); + + LOG (GNUNET_ERROR_TYPE_ERROR, + "We got here 4!\n"); + + write_message ((struct GNUNET_MessageHeader *) reply, msg_length); + + LOG (GNUNET_ERROR_TYPE_ERROR, + "We got here 5!\n"); + + /*child_death_task_id = GNUNET_SCHEDULER_add_read_file ( + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ), + &child_death_task, + NULL);*/ + return GNUNET_OK; + } + else + { + LOG (GNUNET_ERROR_TYPE_WARNING, "Received unexpected message -- exiting\n"); + goto error; + } + + + error: + status = GNUNET_SYSERR; + LOG (GNUNET_ERROR_TYPE_ERROR, + "tokenizer shuting down!\n"); + GNUNET_SCHEDULER_shutdown (); + return GNUNET_SYSERR; +} + + +/** + * Task to read from stdin + * + * @param cls NULL + */ +static void +read_task (void *cls) +{ + char buf[GNUNET_MAX_MESSAGE_SIZE]; + ssize_t sread; + + read_task_id = NULL; + sread = GNUNET_DISK_file_read (stdin_fd, buf, sizeof(buf)); + if ((GNUNET_SYSERR == sread) || (0 == sread)) + { + LOG_DEBUG ("STDIN closed\n"); + LOG (GNUNET_ERROR_TYPE_ERROR, + "tokenizer shuting down during reading!\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (GNUNET_YES == done_reading) + { + /* didn't expect any more data! */ + GNUNET_break_op (0); + LOG (GNUNET_ERROR_TYPE_ERROR, + "tokenizer shuting down during reading, didn't expect any more data!\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + LOG_DEBUG ("Read %u bytes\n", (unsigned int) sread); + /* FIXME: could introduce a GNUNET_MST_read2 to read + directly from 'stdin_fd' and save a memcpy() here */ + if (GNUNET_OK != + GNUNET_MST_from_buffer (tokenizer, buf, sread, GNUNET_NO, GNUNET_NO)) + { + GNUNET_break (0); + LOG (GNUNET_ERROR_TYPE_ERROR, + "tokenizer shuting down during reading, writing to buffer failed!\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + read_task_id /* No timeout while reading */ + = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + stdin_fd, + &read_task, + NULL); +} + + +/** + * Main function that will be run. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct NodeIdentifier *ni = cls; + + LOG_DEBUG ("Starting interpreter loop helper...\n"); + + tokenizer = GNUNET_MST_create (&tokenizer_cb, ni); + stdin_fd = GNUNET_DISK_get_handle_from_native (stdin); + stdout_fd = GNUNET_DISK_get_handle_from_native (stdout); + read_task_id = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + stdin_fd, + &read_task, + NULL); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); +} + + +/** + * Signal handler called for SIGCHLD. + */ +static void +sighandler_child_death () +{ + static char c; + int old_errno; /* back-up errno */ + + old_errno = errno; + GNUNET_break ( + 1 == + GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe, + GNUNET_DISK_PIPE_END_WRITE), + &c, + sizeof(c))); + errno = old_errno; +} + + +/** + * Main function + * + * @param argc the number of command line arguments + * @param argv command line arg array + * @return return code + */ +int +main (int argc, char **argv) +{ + struct NodeIdentifier *ni; + struct GNUNET_SIGNAL_Context *shc_chld; + struct GNUNET_GETOPT_CommandLineOption options[] = + { GNUNET_GETOPT_OPTION_END }; + int ret; + + GNUNET_log_setup ("gnunet-cmds-helper", + "DEBUG", + NULL); + ni = GNUNET_new (struct NodeIdentifier); + ni->global_n = argv[1]; + ni->local_m = argv[2]; + ni->n = argv[3]; + ni->m = argv[4]; + + LOG (GNUNET_ERROR_TYPE_ERROR, + "global_n: %s local_n: %s n: %s m: %s.\n", + ni->global_n, + ni->local_m, + ni->n, + ni->m); + + status = GNUNET_OK; + if (NULL == + (sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE))) + { + GNUNET_break (0); + return 1; + } + shc_chld = + GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); + ret = GNUNET_PROGRAM_run (argc, + argv, + "gnunet-cmds-helper", + "Helper for starting a local interpreter loop", + options, + &run, + ni); + LOG (GNUNET_ERROR_TYPE_ERROR, + "run finished\n"); + GNUNET_SIGNAL_handler_uninstall (shc_chld); + shc_chld = NULL; + GNUNET_DISK_pipe_close (sigpipe); + GNUNET_free (ni); + if (GNUNET_OK != ret) + return 1; + return (GNUNET_OK == status) ? 0 : 1; +} + + +/* end of gnunet-cmds-helper.c */ diff --git a/src/testbed/gnunet-helper-cmds.c b/src/testbed/gnunet-helper-cmds.c deleted file mode 100644 index 3073ebdfb..000000000 --- a/src/testbed/gnunet-helper-cmds.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013, 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 testbed/gnunet-helper-cmds.c - * @brief Helper binary that is started from a remote interpreter loop to start - * a local interpreter loop. - * - * This helper monitors for three termination events. They are: (1)The - * stdin of the helper is closed for reading; (2)the helper received - * SIGTERM/SIGINT; (3)the local loop crashed. In case of events 1 and 2 - * the helper kills the interpreter loop. When the interpreter loop - * crashed (event 3), the helper should send a SIGTERM to its own process - * group; this behaviour will help terminate any child processes the loop - * has started and prevents them from leaking and running forever. - * - * @author t3sserakt - * @author Sree Harsha Totakura - */ - - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testing_lib.h" -#include "gnunet_testbed_service.h" -#include "testbed_helper.h" -#include "testbed_api.h" -#include - -/** - * Generic logging shortcut - */ -#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__) - -/** - * Debug logging shorthand - */ -#define LOG_DEBUG(...) LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) - - -/** - * Context for a single write on a chunk of memory - */ -struct WriteContext -{ - /** - * The data to write - */ - void *data; - - /** - * The length of the data - */ - size_t length; - - /** - * The current position from where the write operation should begin - */ - size_t pos; -}; - -/** - * The process handle to the testbed service - */ -static struct GNUNET_OS_Process *cmd_binary_process; - -/** - * Handle to the testing system - */ -static struct GNUNET_TESTING_System *test_system; - -/** - * Our message stream tokenizer - */ -struct GNUNET_MessageStreamTokenizer *tokenizer; - -/** - * Disk handle from stdin - */ -static struct GNUNET_DISK_FileHandle *stdin_fd; - -/** - * Disk handle for stdout - */ -static struct GNUNET_DISK_FileHandle *stdout_fd; - -/** - * Pipe used to communicate shutdown via signal. - */ -static struct GNUNET_DISK_PipeHandle *sigpipe; - -/** - * Task identifier for the read task - */ -static struct GNUNET_SCHEDULER_Task *read_task_id; - -/** - * Task identifier for the write task - */ -static struct GNUNET_SCHEDULER_Task *write_task_id; - -/** - * Task to kill the child - */ -static struct GNUNET_SCHEDULER_Task *child_death_task_id; - -/** - * Are we done reading messages from stdin? - */ -static int done_reading; - -/** - * Result to return in case we fail - */ -static int status; - - -/** - * Task to shut down cleanly - * - * @param cls NULL - */ -static void -shutdown_task (void *cls) -{ - LOG_DEBUG ("Shutting down\n"); - - if (NULL != read_task_id) - { - GNUNET_SCHEDULER_cancel (read_task_id); - read_task_id = NULL; - } - if (NULL != write_task_id) - { - struct WriteContext *wc; - - wc = GNUNET_SCHEDULER_cancel (write_task_id); - write_task_id = NULL; - GNUNET_free (wc->data); - GNUNET_free (wc); - } - if (NULL != child_death_task_id) - { - GNUNET_SCHEDULER_cancel (child_death_task_id); - child_death_task_id = NULL; - } - if (NULL != stdin_fd) - (void) GNUNET_DISK_file_close (stdin_fd); - if (NULL != stdout_fd) - (void) GNUNET_DISK_file_close (stdout_fd); - GNUNET_MST_destroy (tokenizer); - tokenizer = NULL; - - if (NULL != test_system) - { - GNUNET_TESTING_system_destroy (test_system, GNUNET_YES); - test_system = NULL; - } -} - - -/** - * Task to write to the standard out - * - * @param cls the WriteContext - */ -static void -write_task (void *cls) -{ - struct WriteContext *wc = cls; - ssize_t bytes_wrote; - - GNUNET_assert (NULL != wc); - write_task_id = NULL; - bytes_wrote = GNUNET_DISK_file_write (stdout_fd, - wc->data + wc->pos, - wc->length - wc->pos); - if (GNUNET_SYSERR == bytes_wrote) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Cannot reply back configuration\n"); - GNUNET_free (wc->data); - GNUNET_free (wc); - return; - } - wc->pos += bytes_wrote; - if (wc->pos == wc->length) - { - GNUNET_free (wc->data); - GNUNET_free (wc); - return; - } - write_task_id = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, - stdout_fd, - &write_task, - wc); -} - - -/** - * Task triggered whenever we receive a SIGCHLD (child - * process died). - * - * @param cls closure, NULL if we need to self-restart - */ -static void -child_death_task (void *cls) -{ - const struct GNUNET_DISK_FileHandle *pr; - char c[16]; - - pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); - child_death_task_id = NULL; - /* consume the signal */ - GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof(c))); - LOG_DEBUG ("Got SIGCHLD\n"); - - LOG_DEBUG ("Child hasn't died. Resuming to monitor its status\n"); - child_death_task_id = - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, - pr, - &child_death_task, - NULL); -} - - -/** - * Functions with this signature are called whenever a - * complete message is received by the tokenizer. - * - * Do not call #GNUNET_mst_destroy() in this callback - * - * @param cls identification of the client - * @param message the actual message - * @return #GNUNET_OK on success, - * #GNUNET_NO to stop further processing (no error) - * #GNUNET_SYSERR to stop further processing with error - */ -static int -tokenizer_cb (void *cls, const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_TESTBED_HelperInit *msg; - struct GNUNET_TESTBED_HelperReply *reply; - struct GNUNET_CONFIGURATION_Handle *cfg; - struct WriteContext *wc; - char *binary; - char *trusted_ip; - char *hostname; - char *config; - char *xconfig; - char *evstr; - // char *str; - size_t config_size; - uLongf ul_config_size; - size_t xconfig_size; - uint16_t trusted_ip_size; - uint16_t hostname_size; - uint16_t msize; - - msize = ntohs (message->size); - if ((sizeof(struct GNUNET_TESTBED_HelperInit) >= msize) || - (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT != ntohs (message->type))) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Received unexpected message -- exiting\n"); - goto error; - } - msg = (const struct GNUNET_TESTBED_HelperInit *) message; - trusted_ip_size = ntohs (msg->trusted_ip_size); - trusted_ip = (char *) &msg[1]; - if ('\0' != trusted_ip[trusted_ip_size]) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Trusted IP cannot be empty -- exiting\n"); - goto error; - } - hostname_size = ntohs (msg->hostname_size); - if ((sizeof(struct GNUNET_TESTBED_HelperInit) + trusted_ip_size + 1 - + hostname_size) >= msize) - { - GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_WARNING, "Received unexpected message -- exiting\n"); - goto error; - } - ul_config_size = (uLongf) ntohs (msg->config_size); - config = GNUNET_malloc (ul_config_size); - xconfig_size = msize - (trusted_ip_size + 1 + hostname_size - + sizeof(struct GNUNET_TESTBED_HelperInit)); - int ret = uncompress ((Bytef *) config, - &ul_config_size, - (const Bytef *) (trusted_ip + trusted_ip_size + 1 - + hostname_size), - (uLongf) xconfig_size); - if (Z_OK != ret) - { - switch (ret) - { - case Z_MEM_ERROR: - LOG (GNUNET_ERROR_TYPE_ERROR, "Not enough memory for decompression\n"); - break; - - case Z_BUF_ERROR: - LOG (GNUNET_ERROR_TYPE_ERROR, "Output buffer too small\n"); - break; - - case Z_DATA_ERROR: - LOG (GNUNET_ERROR_TYPE_ERROR, "Data corrupted/incomplete\n"); - break; - - default: - GNUNET_break (0); - } - LOG (GNUNET_ERROR_TYPE_ERROR, - "Error while uncompressing config -- exiting\n"); - GNUNET_free (config); - goto error; - } - cfg = GNUNET_CONFIGURATION_create (); - if (GNUNET_OK != - GNUNET_CONFIGURATION_deserialize (cfg, config, ul_config_size, NULL)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, "Unable to deserialize config -- exiting\n"); - GNUNET_free (config); - goto error; - } - GNUNET_free (config); - hostname = NULL; - if (0 != hostname_size) - { - hostname = GNUNET_malloc (hostname_size + 1); - GNUNET_strlcpy (hostname, - ((char *) &msg[1]) + trusted_ip_size + 1, - hostname_size + 1); - } - /* unset GNUNET_TESTING_PREFIX if present as it is more relevant for testbed */ - evstr = getenv (GNUNET_TESTING_PREFIX); - if (NULL != evstr) - { - /* unsetting the variable will invalidate the pointer! */ - evstr = GNUNET_strdup (evstr); - GNUNET_break (0 == unsetenv (GNUNET_TESTING_PREFIX)); - } - test_system = - GNUNET_TESTING_system_create ("testbed-helper", trusted_ip, hostname, NULL); - if (NULL != evstr) - { - char *evar; - - GNUNET_asprintf (&evar, GNUNET_TESTING_PREFIX "=%s", evstr); - GNUNET_assert (0 == putenv (evar)); /* consumes 'evar', - see putenv(): becomes part of environment! */ - GNUNET_free (evstr); - evstr = NULL; - } - GNUNET_free (hostname); - hostname = NULL; - GNUNET_assert (NULL != test_system); - GNUNET_assert (GNUNET_OK == - GNUNET_TESTING_configuration_create (test_system, cfg)); - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_filename (cfg, - "PATHS", - "DEFAULTCONFIG", - &config)); - if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Unable to write config file: %s -- exiting\n", - config); - GNUNET_CONFIGURATION_destroy (cfg); - GNUNET_free (config); - goto error; - } - LOG_DEBUG ("Staring testbed with config: %s\n", config); - binary = GNUNET_OS_get_libexec_binary_path ("gnunet-cmd"); - { - char *evar; - - /* expose testbed configuration through env variable */ - GNUNET_asprintf (&evar, "%s=%s", ENV_TESTBED_CONFIG, config); - GNUNET_assert (0 == putenv (evar)); /* consumes 'evar', - see putenv(): becomes part of environment! */ - evstr = NULL; - } - - cmd_binary_process = GNUNET_OS_start_process ( - GNUNET_OS_INHERIT_STD_ERR /*verbose? */, - NULL, - NULL, - NULL, - binary); - - if (NULL == cmd_binary_process) - { - return GNUNET_SYSERR; - } - - GNUNET_free (binary); - GNUNET_free (config); - - done_reading = GNUNET_YES; - config = GNUNET_CONFIGURATION_serialize (cfg, &config_size); - GNUNET_CONFIGURATION_destroy (cfg); - cfg = NULL; - xconfig_size = - GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig); - GNUNET_free (config); - wc = GNUNET_new (struct WriteContext); - wc->length = xconfig_size + sizeof(struct GNUNET_TESTBED_HelperReply); - reply = GNUNET_realloc (xconfig, wc->length); - memmove (&reply[1], reply, xconfig_size); - reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY); - reply->header.size = htons ((uint16_t) wc->length); - reply->config_size = htons ((uint16_t) config_size); - wc->data = reply; - write_task_id = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, - stdout_fd, - &write_task, - wc); - child_death_task_id = GNUNET_SCHEDULER_add_read_file ( - GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ), - &child_death_task, - NULL); - return GNUNET_OK; - - error: - status = GNUNET_SYSERR; - GNUNET_SCHEDULER_shutdown (); - return GNUNET_SYSERR; -} - - -/** - * Task to read from stdin - * - * @param cls NULL - */ -static void -read_task (void *cls) -{ - char buf[GNUNET_MAX_MESSAGE_SIZE]; - ssize_t sread; - - read_task_id = NULL; - sread = GNUNET_DISK_file_read (stdin_fd, buf, sizeof(buf)); - if ((GNUNET_SYSERR == sread) || (0 == sread)) - { - LOG_DEBUG ("STDIN closed\n"); - GNUNET_SCHEDULER_shutdown (); - return; - } - if (GNUNET_YES == done_reading) - { - /* didn't expect any more data! */ - GNUNET_break_op (0); - GNUNET_SCHEDULER_shutdown (); - return; - } - LOG_DEBUG ("Read %u bytes\n", (unsigned int) sread); - /* FIXME: could introduce a GNUNET_MST_read2 to read - directly from 'stdin_fd' and save a memcpy() here */ - if (GNUNET_OK != - GNUNET_MST_from_buffer (tokenizer, buf, sread, GNUNET_NO, GNUNET_NO)) - { - GNUNET_break (0); - GNUNET_SCHEDULER_shutdown (); - return; - } - read_task_id /* No timeout while reading */ - = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, - stdin_fd, - &read_task, - NULL); -} - - -/** - * Main function that will be run. - * - * @param cls closure - * @param args remaining command-line arguments - * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param cfg configuration - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - LOG_DEBUG ("Starting interpreter loop helper...\n"); - tokenizer = GNUNET_MST_create (&tokenizer_cb, NULL); - stdin_fd = GNUNET_DISK_get_handle_from_native (stdin); - stdout_fd = GNUNET_DISK_get_handle_from_native (stdout); - read_task_id = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, - stdin_fd, - &read_task, - NULL); - GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); -} - - -/** - * Signal handler called for SIGCHLD. - */ -static void -sighandler_child_death () -{ - static char c; - int old_errno; /* back-up errno */ - - old_errno = errno; - GNUNET_break ( - 1 == - GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe, - GNUNET_DISK_PIPE_END_WRITE), - &c, - sizeof(c))); - errno = old_errno; -} - - -/** - * Main function - * - * @param argc the number of command line arguments - * @param argv command line arg array - * @return return code - */ -int -main (int argc, char **argv) -{ - struct GNUNET_SIGNAL_Context *shc_chld; - struct GNUNET_GETOPT_CommandLineOption options[] = - { GNUNET_GETOPT_OPTION_END }; - int ret; - - GNUNET_log_setup ("gnunet-helper-cmds", - "DEBUG", - NULL); - status = GNUNET_OK; - if (NULL == - (sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE))) - { - GNUNET_break (0); - return 1; - } - shc_chld = - GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); - ret = GNUNET_PROGRAM_run (argc, - argv, - "gnunet-helper-cmds", - "Helper for starting a local interpreter loop", - options, - &run, - NULL); - GNUNET_SIGNAL_handler_uninstall (shc_chld); - shc_chld = NULL; - GNUNET_DISK_pipe_close (sigpipe); - if (GNUNET_OK != ret) - return 1; - return (GNUNET_OK == status) ? 0 : 1; -} - - -/* end of gnunet-helper-testbed.c */ diff --git a/src/testbed/netjail_exec.sh b/src/testbed/netjail_exec.sh index 3e5d39c1c..532f4711c 100755 --- a/src/testbed/netjail_exec.sh +++ b/src/testbed/netjail_exec.sh @@ -13,4 +13,4 @@ NODE=$(netjail_print_name "N" $N $M) -netjail_node_exec_without_fds $NODE $3 +netjail_node_exec_without_fds $NODE $3 $4 $5 $1 $2 diff --git a/src/testbed/plugin_testcmd.c b/src/testbed/plugin_testcmd.c index 90e4a90a1..6f28e102d 100644 --- a/src/testbed/plugin_testcmd.c +++ b/src/testbed/plugin_testcmd.c @@ -26,21 +26,32 @@ #include "platform.h" #include "gnunet_testing_ng_lib.h" #include "gnunet_util_lib.h" -#include "gnunet_testing_plugin.h" - - +#include "gnunet_testbed_ng_service.h" +unsigned int are_all_peers_started; +static void +all_peers_started () +{ + are_all_peers_started = GNUNET_YES; +} static void -start_testcase () +start_testcase (TESTBED_CMD_HELPER_write_cb write_message, char *router_ip, + char *node_ip) { struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); + are_all_peers_started = GNUNET_NO; + struct GNUNET_TESTING_Command commands[] = { GNUNET_TESTING_cmd_hello_world_birth ("hello-world-birth-0", &now), GNUNET_TESTING_cmd_hello_world ("hello-world-0","hello-world-birth-0",""), + GNUNET_TESTING_cmd_send_peer_ready ("send-peer-ready-1", + write_message), + GNUNET_TESTING_cmd_block_until_all_peers_started ("block-1", + &are_all_peers_started), GNUNET_TESTING_cmd_end () }; diff --git a/src/testbed/testbed_api.h b/src/testbed/testbed_api.h index ea78a14ff..9a54ca36c 100644 --- a/src/testbed/testbed_api.h +++ b/src/testbed/testbed_api.h @@ -40,7 +40,7 @@ /** * Cmds Helper binary name */ -#define HELPER_CMDS_BINARY "gnunet-helper-cmds" +#define HELPER_CMDS_BINARY "gnunet-cmds-helper" /** @@ -185,7 +185,6 @@ struct OperationContext typedef void (*TESTBED_opcq_empty_cb) (void *cls); - /** * Handle to interact with a GNUnet testbed controller. Each * controller has at least one master handle which is created when the diff --git a/src/testbed/testbed_api_cmd_block_until_all_peers_started.c b/src/testbed/testbed_api_cmd_block_until_all_peers_started.c new file mode 100644 index 000000000..fc872311d --- /dev/null +++ b/src/testbed/testbed_api_cmd_block_until_all_peers_started.c @@ -0,0 +1,102 @@ +/* + This file is part of GNUnet + Copyright (C) 2021 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 testing_api_cmd_block_until_all_peers_started.c + * @brief cmd to block the interpreter loop until all peers started. + * @author t3sserakt + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_testing_ng_lib.h" + +struct BlockState +{ + unsigned int *all_peers_started; +}; + + +static int +block_until_all_peers_started_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + return GNUNET_OK; +} + + +static void +block_until_all_peers_started_cleanup (void *cls, + const struct GNUNET_TESTING_Command *cmd) +{ + struct BlockState *bs = cls; + + GNUNET_free (bs); +} + + +static void +block_until_all_peers_started_run (void *cls, + const struct GNUNET_TESTING_Command *cmd, + struct GNUNET_TESTING_Interpreter *is) +{ +} + + +static int +block_until_all_peers_started_finish (void *cls, + GNUNET_SCHEDULER_TaskCallback cont, + void *cont_cls) +{ + struct BlockState *bs = cls; + unsigned int *ret = bs->all_peers_started; + + return *ret; +} + + +/** + * Create command. + * + * @param label name for command. + * @return command. + */ +struct GNUNET_TESTING_Command +GNUNET_TESTING_cmd_block_until_all_peers_started (const char *label, + unsigned int * + all_peers_started) +{ + struct BlockState *bs; + + bs = GNUNET_new (struct BlockState); + bs->all_peers_started = all_peers_started; + + struct GNUNET_TESTING_Command cmd = { + .cls = bs, + .label = label, + .run = &block_until_all_peers_started_run, + .finish = &block_until_all_peers_started_finish, + .cleanup = &block_until_all_peers_started_cleanup, + .traits = &block_until_all_peers_started_traits + }; + + return cmd; +} diff --git a/src/testbed/testbed_api_cmd_netjail_start.c b/src/testbed/testbed_api_cmd_netjail_start.c index 320537a61..1e37d5475 100644 --- a/src/testbed/testbed_api_cmd_netjail_start.c +++ b/src/testbed/testbed_api_cmd_netjail_start.c @@ -59,6 +59,9 @@ netjail_start_cleanup (void *cls, { struct NetJailState *ns = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "netjail_start_cleanup!\n"); + if (NULL != ns->cwh) { GNUNET_wait_child_cancel (ns->cwh); @@ -74,6 +77,7 @@ netjail_start_cleanup (void *cls, GNUNET_OS_process_destroy (ns->start_proc); ns->start_proc = NULL; } + GNUNET_free (ns); } @@ -108,6 +112,8 @@ child_completed_callback (void *cls, } else { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Child completed with an error!\n"); ns->finished = GNUNET_SYSERR; } GNUNET_OS_process_destroy (ns->start_proc); diff --git a/src/testbed/testbed_api_cmd_netjail_start_testbed.c b/src/testbed/testbed_api_cmd_netjail_start_testbed.c index dc8196e94..585825cbc 100644 --- a/src/testbed/testbed_api_cmd_netjail_start_testbed.c +++ b/src/testbed/testbed_api_cmd_netjail_start_testbed.c @@ -28,13 +28,36 @@ #include "gnunet_testbed_ng_service.h" #include "testbed_api.h" #include "testbed_api_hosts.h" +#include "testbed_helper.h" #define NETJAIL_EXEC_SCRIPT "./netjail_exec.sh" +struct HelperMessage; + +struct HelperMessage +{ + + struct HelperMessage *next; + + struct HelperMessage *prev; + + /** + * Size of the original message. + */ + uint16_t bytes_msg; + + /* Followed by @e bytes_msg of msg.*/ +}; + + struct NetJailState { + struct HelperMessage *hp_messages_head; + + struct HelperMessage *hp_messages_tail; + /** * The process handle */ @@ -64,6 +87,8 @@ struct NetJailState unsigned int number_of_testbeds_started; + unsigned int number_of_peers_started; + /** * The host where the controller is running */ @@ -112,7 +137,7 @@ netjail_exec_traits (void *cls, { struct NetJailState *ns = cls; struct GNUNET_HELPER_Handle **helper = ns->helper; - struct GNUNET_TESTBED_Host **hosts = ns->host; + struct HelperMessage *hp_messages_head = ns->hp_messages_head; struct GNUNET_TESTING_Trait traits[] = { @@ -123,8 +148,8 @@ netjail_exec_traits (void *cls, }, { .index = 1, - .trait_name = "hosts", - .ptr = (const void *) hosts, + .trait_name = "hp_msgs_head", + .ptr = (const void *) hp_messages_head, }, GNUNET_TESTING_trait_end () }; @@ -162,13 +187,14 @@ GNUNET_TESTBED_get_trait_helper_handles (const struct * @return #GNUNET_OK on success. */ int -GNUNET_TESTBED_get_trait_hosts (const struct - GNUNET_TESTING_Command *cmd, - struct GNUNET_TESTBED_Host ***hosts) +GNUNET_TESTBED_get_trait_helper_messages (const struct + GNUNET_TESTING_Command *cmd, + struct HelperMessage *** + hp_messages_head) { return cmd->traits (cmd->cls, - (const void **) hosts, - "hosts", + (const void **) hp_messages_head, + "hp_msgs_head", (unsigned int) 1); } @@ -214,15 +240,32 @@ helper_mst (void *cls, const struct GNUNET_MessageHeader *message) { struct TestbedCount *tbc = cls; struct NetJailState *ns = tbc->ns; - struct GNUNET_TESTBED_Host *host = ns->host[tbc->count - 1]; + struct HelperMessage *hp_msg; + + if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY == ntohs (message->type)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "helper_mst tbc->count: %d\n", + tbc->count); + // GNUNET_TESTBED_extract_cfg (host, message); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received message from helper.\n"); + ns->number_of_testbeds_started++; + } + else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED == ntohs ( + message->type)) + { + ns->number_of_peers_started++; + } + else + { + hp_msg = GNUNET_new (struct HelperMessage); + hp_msg->bytes_msg = message->size; + memcpy (&hp_msg[1], message, message->size); + GNUNET_CONTAINER_DLL_insert (ns->hp_messages_head, ns->hp_messages_tail, + hp_msg); + } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "helper_mst tbc->count: %d\n", - tbc->count); - GNUNET_TESTBED_extract_cfg (host, message); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received message from helper.\n"); - ns->number_of_testbeds_started++; return GNUNET_OK; } @@ -235,6 +278,32 @@ exp_cb (void *cls) } +static struct GNUNET_CMDS_HelperInit * +create_helper_init_msg_ (char *m_char, + char *n_char, + const char *plugin_name) +{ + struct GNUNET_CMDS_HelperInit *msg; + uint16_t plugin_name_len; + uint16_t msg_size; + + GNUNET_assert (NULL != plugin_name); + plugin_name_len = strlen (plugin_name); + msg_size = sizeof(struct GNUNET_CMDS_HelperInit) + plugin_name_len; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "msg_size: %d \n", + msg_size); + msg = GNUNET_malloc (msg_size); + msg->header.size = htons (msg_size); + msg->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT); + msg->plugin_name_size = htons (plugin_name_len); + GNUNET_memcpy ((char *) &msg[1], + plugin_name, + plugin_name_len); + return msg; +} + + static void start_testbed (struct NetJailState *ns, struct GNUNET_CONFIGURATION_Handle *config, @@ -242,13 +311,15 @@ start_testbed (struct NetJailState *ns, struct char *m_char) { struct GNUNET_CONFIGURATION_Handle *cfg; - struct GNUNET_TESTBED_HelperInit *msg; + struct GNUNET_CMDS_HelperInit *msg; struct TestbedCount *tbc; char *const script_argv[] = {NETJAIL_EXEC_SCRIPT, - m_char, n_char, + m_char, GNUNET_OS_get_libexec_binary_path ( HELPER_CMDS_BINARY), + ns->global_n, + ns->local_m, NULL}; unsigned int m = atoi (m_char); unsigned int n = atoi (n_char); @@ -291,7 +362,9 @@ start_testbed (struct NetJailState *ns, struct struct GNUNET_HELPER_Handle *helper = ns->helper[tbc->count - 1]; - msg = GNUNET_TESTBED_create_helper_init_msg_ ("127.0.0.1", NULL, config); + msg = create_helper_init_msg_ (m_char, + n_char, + "libgnunet_plugin_testcmd"); GNUNET_array_append (ns->msg, ns->n_msg, &msg->header); GNUNET_array_append (ns->shandle, ns->n_shandle, GNUNET_HELPER_send ( @@ -300,6 +373,10 @@ start_testbed (struct NetJailState *ns, struct GNUNET_NO, &clear_msg, tbc)); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Message send!\n"); + if (NULL == ns->shandle[tbc->count - 1]) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -348,14 +425,49 @@ netjail_start_finish (void *cls, { unsigned int ret = GNUNET_NO; struct NetJailState *ns = cls; + unsigned int total_number = atoi (ns->local_m) * atoi (ns->global_n); + struct GNUNET_CMDS_PEER_STARTED *reply; + size_t msg_length; + struct GNUNET_HELPER_Handle *helper; + struct TestbedCount *tbc; - if (ns->number_of_testbeds_started == atoi (ns->local_m) * atoi ( - ns->global_n)) + if (ns->number_of_testbeds_started == total_number) { - ret = GNUNET_YES; - cont (cont_cls); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "All helper started!\n"); + /* ret = GNUNET_YES; + cont (cont_cls);*/ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "All helpers started!\n"); + } + + if (ns->number_of_peers_started == total_number) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "All peers started!\n"); + + for (int i = 1; i <= atoi (ns->global_n); i++) { + for (int j = 1; j <= atoi (ns->local_m); j++) + { + tbc = GNUNET_new (struct TestbedCount); + tbc->ns = ns; + tbc->count = (j - 1) * atoi (ns->local_m) + i + atoi (ns->global_n) + * atoi (ns->local_m); + helper = ns->helper[tbc->count - 1]; + msg_length = sizeof(struct GNUNET_CMDS_ALL_PEERS_STARTED); + reply = GNUNET_new (struct GNUNET_CMDS_ALL_PEERS_STARTED); + reply->header.type = htons ( + GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED); + reply->header.size = htons ((uint16_t) msg_length); + + GNUNET_array_append (ns->msg, ns->n_msg, &reply->header); + + GNUNET_array_append (ns->shandle, ns->n_shandle, GNUNET_HELPER_send ( + helper, + &reply->header, + GNUNET_NO, + &clear_msg, + tbc)); + } + } } return ret; } diff --git a/src/testbed/testbed_api_cmd_send_peer_ready.c b/src/testbed/testbed_api_cmd_send_peer_ready.c new file mode 100644 index 000000000..8a82b23a8 --- /dev/null +++ b/src/testbed/testbed_api_cmd_send_peer_ready.c @@ -0,0 +1,102 @@ +/* + This file is part of GNUnet + Copyright (C) 2021 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 testing_api_cmd_send_peer_ready.c + * @brief cmd to send a helper message if peer is ready. + * @author t3sserakt + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_testing_ng_lib.h" + + +struct SendPeerReadyState +{ + TESTBED_CMD_HELPER_write_cb write_message; + + struct GNUNET_CMDS_PEER_STARTED *reply; +}; + + +static int +send_peer_ready_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + return GNUNET_OK; +} + + +static void +send_peer_ready_cleanup (void *cls, + const struct GNUNET_TESTING_Command *cmd) +{ + struct SendPeerReadyState *sprs = cls; + + GNUNET_free (sprs->reply); + GNUNET_free (sprs); +} + + +static void +send_peer_ready_run (void *cls, + const struct GNUNET_TESTING_Command *cmd, + struct GNUNET_TESTING_Interpreter *is) +{ + /*struct SendPeerReadyState *sprs = cls; + struct GNUNET_CMDS_PEER_STARTED *reply; + size_t msg_length; + + msg_length = sizeof(struct GNUNET_CMDS_PEER_STARTED); + reply = GNUNET_new (struct GNUNET_CMDS_PEER_STARTED); + reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED); + reply->header.size = htons ((uint16_t) msg_length); + sprs->reply = reply; + sprs->write_message ((struct GNUNET_MessageHeader *) reply, msg_length);*/ +} + + +/** + * Create command. + * + * @param label name for command. + * @return command. + */ +struct GNUNET_TESTING_Command +GNUNET_TESTING_cmd_send_peer_ready (const char *label, + TESTBED_CMD_HELPER_write_cb write_message) +{ + struct SendPeerReadyState *sprs; + + sprs = GNUNET_new (struct SendPeerReadyState); + sprs->write_message = write_message; + + struct GNUNET_TESTING_Command cmd = { + .cls = sprs, + .label = label, + .run = &send_peer_ready_run, + .cleanup = &send_peer_ready_cleanup, + .traits = &send_peer_ready_traits + }; + + return cmd; +} diff --git a/src/testbed/testbed_helper.h b/src/testbed/testbed_helper.h index 817ad559d..84059fef2 100644 --- a/src/testbed/testbed_helper.h +++ b/src/testbed/testbed_helper.h @@ -84,6 +84,52 @@ struct GNUNET_TESTBED_HelperReply * un-compressed */ }; +/** + * Initialization message for gnunet-cmds-testbed to start cmd binary. + */ +struct GNUNET_CMDS_HelperInit +{ + /** + * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT + */ + struct GNUNET_MessageHeader header; + + /** + * + */ + uint16_t plugin_name_size GNUNET_PACKED; + + /* Followed by plugin name of the plugin running the test case. This is not NULL + * terminated */ +}; + +/** + * Reply message from cmds helper process + */ +struct GNUNET_CMDS_HelperReply +{ + /** + * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY + */ + struct GNUNET_MessageHeader header; +}; + +struct GNUNET_CMDS_PEER_STARTED +{ + /** + * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED + */ + struct GNUNET_MessageHeader header; +}; + +struct GNUNET_CMDS_ALL_PEERS_STARTED +{ + /** + * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED + */ + struct GNUNET_MessageHeader header; +}; + GNUNET_NETWORK_STRUCT_END #endif /* end of testbed_helper.h */ diff --git a/src/testing/testing_api_cmd_start_peer.c b/src/testing/testing_api_cmd_start_peer.c new file mode 100644 index 000000000..0f8c618b8 --- /dev/null +++ b/src/testing/testing_api_cmd_start_peer.c @@ -0,0 +1,296 @@ +/* + This file is part of GNUnet + Copyright (C) 2021 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 testing_api_cmd_start_peer.c + * @brief cmd to start a peer. + * @author t3sserakt + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_testing_ng_lib.h" + + +struct StartPeerState +{ + /** + * Receive callback + */ + struct GNUNET_MQ_MessageHandler *handlers; + + const char *cfgname; + + /** + * Peer's configuration + */ + struct GNUNET_CONFIGURATION_Handle *cfg; + + struct GNUNET_TESTING_Peer *peer; + + /** + * Peer identity + */ + struct GNUNET_PeerIdentity id; + + /** + * Peer's transport service handle + */ + struct GNUNET_TRANSPORT_CoreHandle *th; + + /** + * Application handle + */ + struct GNUNET_TRANSPORT_ApplicationHandle *ah; + + /** + * Peer's PEERSTORE Handle + */ + struct GNUNET_PEERSTORE_Handle *ph; + + /** + * Hello get task + */ + struct GNUNET_SCHEDULER_Task *rh_task; + + /** + * 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; + + char *m; + + char *n; + + unsigned int finished; +}; + + +static void +retrieve_hello (void *cls); + +static void +hello_iter_cb (void *cb_cls, + const struct GNUNET_PEERSTORE_Record *record, + const char *emsg) +{ + struct StartPeerState *sps = cb_cls; + if (NULL == record) + { + sps->pic = NULL; + sps->rh_task = GNUNET_SCHEDULER_add_now (retrieve_hello, p); + return; + } + // Check record type et al? + sps->hello_size = record->value_size; + sps->hello = GNUNET_malloc (sps->hello_size); + memcpy (sps->hello, record->value, sps->hello_size); + p->hello[p->hello_size - 1] = '\0'; + + GNUNET_PEERSTORE_iterate_cancel (sps->pic); + sps->pic = NULL; + sps->finished = GNUNET_YES; +} + + +static void +retrieve_hello (void *cls) +{ + struct StartPeerState *sps = cls; + sps->rh_task = NULL; + sps->pic = GNUNET_PEERSTORE_iterate (sps->ph, + "transport", + &sps->id, + GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY, + hello_iter_cb, + sps); + +} + +static int +start_peer_finish (void *cls, + GNUNET_SCHEDULER_TaskCallback cont, + void *cont_cls) +{ + struct StartPeerState *sps = cls; + + return sps->finished; +} + + +static void +start_peer_run (void *cls, + const struct GNUNET_TESTING_Command *cmd, + struct GNUNET_TESTING_Interpreter *is) +{ + struct StartPeerState *sps = cls; + char *emsg = NULL; + struct GNUNET_PeerIdentity dummy; + + if (GNUNET_NO == GNUNET_DISK_file_test (sps->cfgname)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "File not found: `%s'\n", + cfgname); + return NULL; + } + + if (NULL != handlers) + { + for (i = 0; NULL != handlers[i].cb; i++) + ; + sps->handlers = GNUNET_new_array (i + 1, + struct GNUNET_MQ_MessageHandler); + GNUNET_memcpy (sps->handlers, + handlers, + i * sizeof(struct GNUNET_MQ_MessageHandler)); + } + sps->cfg = GNUNET_CONFIGURATION_create (); + GNUNET_assert (GNUNET_OK == + GNUNET_CONFIGURATION_load (sps->cfg, sps->cfgname)); + if (GNUNET_SYSERR == + GNUNET_TESTING_configuration_create (tl_system, + sps->cfg)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Testing library failed to create unique configuration based on `%s'\n", + sps->cfgname); + GNUNET_CONFIGURATION_destroy (sps->cfg); + GNUNET_TESTING_interpreter_fail (); + } + + sps->peer = GNUNET_TESTING_peer_configure (tth->tl_system, + p->cfg, + p->no, + NULL, + &emsg); + if (NULL == sps->peer) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Testing library failed to create unique configuration based on `%s': `%s'\n", + cfgname, + emsg); + GNUNET_free (emsg); + GNUNET_TESTING_interpreter_fail (); + } + + 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_free (emsg); + GNUNET_TESTING_interpreter_fail (); + } + + memset (&dummy, + '\0', + sizeof(dummy)); + GNUNET_TESTING_peer_get_identity (sps->peer, + &sps->id); + if (0 == memcmp (&dummy, + &sps->id, + sizeof(struct GNUNET_PeerIdentity))) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Testing library failed to obtain peer identity for peer %s_%s\n", + p->no); + GNUNET_free (emsg); + GNUNET_TESTING_interpreter_fail (); + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Peer %u configured with identity `%s'\n", + p->no, + GNUNET_i2s_full (&p->id)); + sps->th = GNUNET_TRANSPORT_core_connect (p->cfg, + NULL, + handlers, + p, + ¬ify_connect, + ¬ify_disconnect); + if (NULL == sps->th) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to transport service for peer `%s': `%s'\n", + cfgname, + emsg); + GNUNET_free (emsg); + GNUNET_TESTING_interpreter_fail (); + } + sps->ph = GNUNET_PEERSTORE_connect (p->cfg); + if (NULL == sps->th) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to peerstore service for peer `%s': `%s'\n", + cfgname, + emsg); + GNUNET_free (emsg); + GNUNET_TESTING_interpreter_fail (); + } + sps->ah = GNUNET_TRANSPORT_application_init (p->cfg); + if (NULL == sps->ah) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Failed to initialize the TRANSPORT application suggestion client handle for peer `%s': `%s'\n", + cfgname, + emsg); + GNUNET_free (emsg); + GNUNET_TESTING_interpreter_fail (); + } + p->rh_task = GNUNET_SCHEDULER_add_now (retrieve_hello, p); +} + + +/** + * Create command. + * + * @param label name for command. + * @return command. + */ +struct GNUNET_TESTING_Command +GNUNET_TESTING_cmd_start_peer (const char *label, + char *m, + char *n) +{ + struct StartPeerState *sps; + + sps = GNUNET_new (struct StartPeerState); + sps->m = m; + sps->n = n; + + struct GNUNET_TESTING_Command cmd = { + .cls = sps, + .label = label, + .run = &start_peer_run, + .cleanup = &start_peer_cleanup, + .traits = &start_peer_traits + }; + + return cmd; +} diff --git a/src/testing/testing_api_cmd_system_create.c b/src/testing/testing_api_cmd_system_create.c new file mode 100644 index 000000000..ad0aa4f90 --- /dev/null +++ b/src/testing/testing_api_cmd_system_create.c @@ -0,0 +1,110 @@ +/* + This file is part of GNUnet + Copyright (C) 2021 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 testing_api_cmd_system_create.c + * @brief cmd to create a testing system handle. + * @author t3sserakt + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_testing_ng_lib.h" + +struct TestSystemState +{ + struct GNUNET_TESTING_System *test_system; +}; + + +static void +system_create_run (void *cls, + const struct GNUNET_TESTING_Command *cmd, + struct GNUNET_TESTING_Interpreter *is) +{ + struct TestSystemState *tss = cls; + + tss->test_system = GNUNET_TESTING_system_create (tss->testdir, + NULL, + NULL, + NULL); +} + +static int +system_create_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct TestSystemState *tss = cls; + struct GNUNET_TESTING_System *test_system = tss->test_system; + + struct GNUNET_TESTING_Trait traits[] = { + { + .index = 0, + .trait_name = "test_system", + .ptr = (const void *) test_system, + }, + GNUNET_TESTING_trait_end () + }; + + return GNUNET_TESTING_get_trait (traits, + ret, + trait, + index); +} + + +int +GNUNET_TESTING_get_trait_test_system (const struct + GNUNET_TESTING_Command *cmd, + struct GNUNET_TESTING_System **test_system) +{ + return cmd->traits (cmd->cls, + (const void **) test_system, + "test_system", + (unsigned int) 0); +} + + +/** + * Create command. + * + * @param label name for command. + * @return command. + */ +struct GNUNET_TESTING_Command +GNUNET_TESTING_cmd_system_create (const char *label, + const char *testdir) +{ + struct TestSystemState *tss; + + tss = GNUNET_new (struct TestSystemState); + tss->testdir = testdir; + + struct GNUNET_TESTING_Command cmd = { + .cls = tss, + .label = label, + .run = &system_create_run, + .cleanup = &system_create_cleanup, + .traits = &system_create_traits + }; + + return cmd; +} diff --git a/src/testing/testing_api_loop.c b/src/testing/testing_api_loop.c index 49ed48063..7b7dc010a 100644 --- a/src/testing/testing_api_loop.c +++ b/src/testing/testing_api_loop.c @@ -332,6 +332,9 @@ GNUNET_TESTING_interpreter_fail () if (GNUNET_SYSERR == is->result) return; /* ignore, we already failed! */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "interpreter_fail!\n"); + if (NULL != cmd) { while (GNUNET_TESTING_cmd_is_batch (cmd)) diff --git a/src/transport/transport-testing.c b/src/transport/transport-testing.c index a7ee563d7..00c4a08dd 100644 --- a/src/transport/transport-testing.c +++ b/src/transport/transport-testing.c @@ -463,7 +463,7 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_free (emsg); return NULL; } - GNUNET_free (emsg); + if (GNUNET_OK != GNUNET_TESTING_peer_start (p->peer)) { LOG (GNUNET_ERROR_TYPE_ERROR, @@ -508,6 +508,7 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct cfgname, emsg); GNUNET_TRANSPORT_TESTING_stop_peer (p); + GNUNET_free (emsg); return NULL; } p->ats = GNUNET_ATS_connectivity_init (p->cfg); @@ -518,6 +519,7 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct cfgname, emsg); GNUNET_TRANSPORT_TESTING_stop_peer (p); + GNUNET_free (emsg); return NULL; } p->ghh = GNUNET_TRANSPORT_hello_get (p->cfg, diff --git a/src/transport/transport-testing2.c b/src/transport/transport-testing2.c index 482aaf4d0..6d41ec098 100644 --- a/src/transport/transport-testing2.c +++ b/src/transport/transport-testing2.c @@ -478,7 +478,7 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_free (emsg); return NULL; } - GNUNET_free (emsg); + if (GNUNET_OK != GNUNET_TESTING_peer_start (p->peer)) { LOG (GNUNET_ERROR_TYPE_ERROR, @@ -520,6 +520,7 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct cfgname, emsg); GNUNET_TRANSPORT_TESTING_stop_peer (p); + GNUNET_free (emsg); return NULL; } p->ats = GNUNET_ATS_connectivity_init (p->cfg); @@ -530,6 +531,7 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct cfgname, emsg); GNUNET_TRANSPORT_TESTING_stop_peer (p); + GNUNET_free (emsg); return NULL; } p->ph = GNUNET_PEERSTORE_connect (p->cfg); diff --git a/src/util/child_management.c b/src/util/child_management.c index 11fde4a61..3afd682b9 100644 --- a/src/util/child_management.c +++ b/src/util/child_management.c @@ -29,6 +29,11 @@ #include "gnunet_util_lib.h" #include "gnunet_child_management_lib.h" +/** + * Generic logging shortcut + */ +#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__) + /** * Struct which defines a Child Wait handle @@ -87,7 +92,7 @@ maint_child_death (void *cls) (void) cls; sig_task = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received SIGCHLD.\n"); /* drain pipe */ @@ -193,6 +198,9 @@ GNUNET_wait_child (struct GNUNET_OS_Process *proc, { struct GNUNET_ChildWaitHandle *cwh; + LOG (GNUNET_ERROR_TYPE_ERROR, + "Adding child!\n"); + child_management_start (); cwh = GNUNET_new (struct GNUNET_ChildWaitHandle); cwh->proc = proc; @@ -216,9 +224,12 @@ GNUNET_wait_child (struct GNUNET_OS_Process *proc, void GNUNET_wait_child_cancel (struct GNUNET_ChildWaitHandle *cwh) { - GNUNET_CONTAINER_DLL_remove (cwh_head, - cwh_tail, - cwh); + if ((NULL != cwh_head)) + { + GNUNET_CONTAINER_DLL_remove (cwh_head, + cwh_tail, + cwh); + } if (NULL == cwh_head) { child_management_done (); -- cgit v1.2.3