gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

commit 21c4b14e7e9a5f113b2c190b0223ca95074125b1
parent f5c99c11e752667d6c07d16568ae16a782b48e4c
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Fri, 13 Oct 2023 18:19:48 +0200

Delete more subsystems not required after tng

Diffstat:
Mconfigure.ac | 2--
Msrc/Makefile.am | 5+----
Dsrc/fragmentation/.gitignore | 2--
Dsrc/fragmentation/Makefile.am | 42------------------------------------------
Dsrc/fragmentation/defragmentation.c | 590-------------------------------------------------------------------------------
Dsrc/fragmentation/fragmentation.c | 527-------------------------------------------------------------------------------
Dsrc/fragmentation/fragmentation.h | 87-------------------------------------------------------------------------------
Dsrc/fragmentation/meson.build | 22----------------------
Dsrc/fragmentation/test_fragmentation.c | 303-------------------------------------------------------------------------------
Dsrc/fragmentation/test_fragmentation_data.conf | 5-----
Dsrc/fragmentation/test_fragmentation_parallel.c | 254-------------------------------------------------------------------------------
Dsrc/integration-tests/.gitignore | 10----------
Dsrc/integration-tests/Makefile.am | 90-------------------------------------------------------------------------------
Dsrc/integration-tests/confs/c_bootstrap_server.conf | 92-------------------------------------------------------------------------------
Dsrc/integration-tests/confs/c_nat_client.conf | 73-------------------------------------------------------------------------
Dsrc/integration-tests/confs/c_no_nat_client.conf | 105-------------------------------------------------------------------------------
Dsrc/integration-tests/confs/c_no_nat_client_2.conf | 119-------------------------------------------------------------------------------
Dsrc/integration-tests/confs/test_defaults.conf | 76----------------------------------------------------------------------------
Dsrc/integration-tests/gnunet_pyexpect.py.in | 94-------------------------------------------------------------------------------
Dsrc/integration-tests/gnunet_testing.py.in | 381-------------------------------------------------------------------------------
Dsrc/integration-tests/hostkeys/c_bootstrap_server | 2--
Dsrc/integration-tests/hostkeys/c_nat_client | 2--
Dsrc/integration-tests/hostkeys/c_no_nat_client | 2--
Dsrc/integration-tests/hostkeys/c_no_nat_client_2 | 2--
Dsrc/integration-tests/test_integration_bootstrap_and_connect.py.in | 212-------------------------------------------------------------------------------
Dsrc/integration-tests/test_integration_clique.py.in | 236-------------------------------------------------------------------------------
Dsrc/integration-tests/test_integration_disconnect.py.in | 215-------------------------------------------------------------------------------
Dsrc/integration-tests/test_integration_disconnect_nat.py.in | 223-------------------------------------------------------------------------------
Dsrc/integration-tests/test_integration_reconnect.py.in | 237-------------------------------------------------------------------------------
Dsrc/integration-tests/test_integration_reconnect_nat.py.in | 237-------------------------------------------------------------------------------
Dsrc/testbed-logger/.gitignore | 2--
Dsrc/testbed-logger/Makefile.am | 55-------------------------------------------------------
Dsrc/testbed-logger/gnunet-service-testbed-logger.c | 236-------------------------------------------------------------------------------
Dsrc/testbed-logger/meson.build | 34----------------------------------
Dsrc/testbed-logger/test_testbed_logger_api.c | 277-------------------------------------------------------------------------------
Dsrc/testbed-logger/test_testbed_logger_api.conf | 7-------
Dsrc/testbed-logger/testbed-logger.conf.in | 127-------------------------------------------------------------------------------
Dsrc/testbed-logger/testbed_logger_api.c | 338-------------------------------------------------------------------------------
Dsrc/testbed/.gitignore | 37-------------------------------------
Dsrc/testbed/Makefile.am | 401-------------------------------------------------------------------------------
Dsrc/testbed/barriers.README.org | 95-------------------------------------------------------------------------------
Dsrc/testbed/buildvars.py.in | 34----------------------------------
Dsrc/testbed/generate-underlay-topology.c | 407-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-daemon-latency-logger.c | 322-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-daemon-testbed-blacklist.c | 254-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-daemon-testbed-underlay.c | 481-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-helper-testbed-valgrind.patch | 21---------------------
Dsrc/testbed/gnunet-helper-testbed.c | 613-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-test-barriers.c | 152-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed.c | 981-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed.h | 899-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed_barriers.c | 929-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed_barriers.h | 128-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed_cache.c | 270-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed_connectionpool.c | 1045-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed_connectionpool.h | 172-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed_cpustatus.c | 664-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed_links.c | 1468-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed_links.h | 209-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed_meminfo.c | 279-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed_meminfo.h | 55-------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed_oc.c | 1997-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-service-testbed_peers.c | 1552-------------------------------------------------------------------------------
Dsrc/testbed/gnunet-testbed-profiler.c | 323-------------------------------------------------------------------------------
Dsrc/testbed/gnunet_mpi_test.c | 108-------------------------------------------------------------------------------
Dsrc/testbed/meson.build | 129-------------------------------------------------------------------------------
Dsrc/testbed/misc.supp | 49-------------------------------------------------
Dsrc/testbed/overlay_topology.txt | 5-----
Dsrc/testbed/profile-testbed.patch | 43-------------------------------------------
Dsrc/testbed/sample.job | 16----------------
Dsrc/testbed/sample_hosts.txt | 7-------
Dsrc/testbed/test-underlay.sqlite | 0
Dsrc/testbed/test_gnunet_helper_testbed.c | 255-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api.c | 515-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api.conf | 1-
Dsrc/testbed/test_testbed_api_2peers_1controller.c | 540-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_3peers_3controllers.c | 964-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_barriers.c | 234-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_barriers.conf.in | 103-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_barriers.h | 4----
Dsrc/testbed/test_testbed_api_controllerlink.c | 881-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_hosts.c | 183-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_operations.c | 568-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_peer_reconfiguration.c | 194-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_peers_manage_services.c | 216-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_sd.c | 111-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_statistics.c | 205-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_statistics.conf | 9---------
Dsrc/testbed/test_testbed_api_template.conf | 49-------------------------------------------------
Dsrc/testbed/test_testbed_api_test.c | 251-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_test_timeout.c | 126-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_test_timeout.conf | 5-----
Dsrc/testbed/test_testbed_api_testbed_run.c | 242-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_testbed_run_topology2dtorus.conf | 5-----
Dsrc/testbed/test_testbed_api_testbed_run_topologyclique.conf | 4----
Dsrc/testbed/test_testbed_api_testbed_run_topologyfromfile.conf | 5-----
Dsrc/testbed/test_testbed_api_testbed_run_topologyline.conf | 4----
Dsrc/testbed/test_testbed_api_testbed_run_topologyrandom.conf | 5-----
Dsrc/testbed/test_testbed_api_testbed_run_topologyring.conf | 4----
Dsrc/testbed/test_testbed_api_testbed_run_topologyscalefree.conf | 6------
Dsrc/testbed/test_testbed_api_testbed_run_topologysmallworld.conf | 5-----
Dsrc/testbed/test_testbed_api_testbed_run_topologysmallworldring.conf | 5-----
Dsrc/testbed/test_testbed_api_testbed_run_topologystar.conf | 4----
Dsrc/testbed/test_testbed_api_topology.c | 189-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_api_topology_clique.c | 185-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_underlay.c | 174-------------------------------------------------------------------------------
Dsrc/testbed/test_testbed_underlay.conf.in | 13-------------
Dsrc/testbed/testbed.conf.in | 116-------------------------------------------------------------------------------
Dsrc/testbed/testbed.h | 866-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api.c | 2427------------------------------------------------------------------------------
Dsrc/testbed/testbed_api.h | 521-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_barriers.c | 253-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_hosts.c | 1521-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_hosts.h | 227-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_operations.c | 1379-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_operations.h | 233-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_peers.c | 961-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_peers.h | 311-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_sd.c | 213-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_sd.h | 81-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_services.c | 291------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_statistics.c | 435-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_test.c | 175-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_testbed.c | 1467-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_topology.c | 1598-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_topology.h | 115-------------------------------------------------------------------------------
Dsrc/testbed/testbed_api_underlay.c | 260-------------------------------------------------------------------------------
Dsrc/testbed/testbed_helper.h | 89-------------------------------------------------------------------------------
Dsrc/testbed/valgrind-zlib.supp | 6------
Dsrc/testbed/x64_misc.supp | 34----------------------------------
130 files changed, 1 insertion(+), 39310 deletions(-)

diff --git a/configure.ac b/configure.ac @@ -1248,7 +1248,6 @@ src/dhtu/Makefile src/dns/Makefile src/dns/dns.conf src/exit/Makefile -src/fragmentation/Makefile src/fs/Makefile src/fs/fs.conf src/gns/Makefile @@ -1260,7 +1259,6 @@ src/identity/Makefile src/identity/identity.conf src/include/Makefile src/include/gnunet_config.h -src/integration-tests/Makefile src/json/Makefile src/hostlist/Makefile src/namecache/Makefile diff --git a/src/Makefile.am b/src/Makefile.am @@ -1,7 +1,6 @@ # This Makefile.am is in the public domain TESTING = testing -#TESTBED = testbed-logger testbed if HAVE_EXPERIMENTAL EXP_DIR = \ @@ -52,7 +51,6 @@ SUBDIRS = \ peerstore \ nat \ nat-auto \ - fragmentation \ transport \ core \ nse \ @@ -83,5 +81,4 @@ SUBDIRS = \ secretsharing \ reclaim \ messenger \ - $(EXP_DIR) \ - integration-tests + $(EXP_DIR) diff --git a/src/fragmentation/.gitignore b/src/fragmentation/.gitignore @@ -1,2 +0,0 @@ -test_fragmentation -test_fragmentation_parallel diff --git a/src/fragmentation/Makefile.am b/src/fragmentation/Makefile.am @@ -1,42 +0,0 @@ -# This Makefile.am is in the public domain -AM_CPPFLAGS = -I$(top_srcdir)/src/include - -if USE_COVERAGE - AM_CFLAGS = --coverage -endif - -lib_LTLIBRARIES = libgnunetfragmentation.la - -libgnunetfragmentation_la_SOURCES = \ - fragmentation.c fragmentation.h \ - defragmentation.c -libgnunetfragmentation_la_LIBADD = -lm \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(LTLIBINTL) -libgnunetfragmentation_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) \ - -version-info 2:0:0 - -check_PROGRAMS = \ - test_fragmentation \ - test_fragmentation_parallel - -if ENABLE_TEST_RUN -AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; -TESTS = $(check_PROGRAMS) -endif - -test_fragmentation_SOURCES = \ - test_fragmentation.c -test_fragmentation_LDADD = \ - libgnunetfragmentation.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_fragmentation_parallel_SOURCES = \ - test_fragmentation_parallel.c -test_fragmentation_parallel_LDADD = \ - libgnunetfragmentation.la \ - $(top_builddir)/src/util/libgnunetutil.la - -EXTRA_DIST = test_fragmentation_data.conf diff --git a/src/fragmentation/defragmentation.c b/src/fragmentation/defragmentation.c @@ -1,590 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2009, 2011 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file src/fragmentation/defragmentation.c - * @brief library to help defragment messages - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_fragmentation_lib.h" -#include "fragmentation.h" - -/** - * Timestamps for fragments. - */ -struct FragTimes -{ - /** - * The time the fragment was received. - */ - struct GNUNET_TIME_Absolute time; - - /** - * Number of the bit for the fragment (in [0,..,63]). - */ - unsigned int bit; -}; - - -/** - * Information we keep for one message that is being assembled. Note - * that we keep the context around even after the assembly is done to - * handle 'stray' messages that are received 'late'. A message - * context is ONLY discarded when the queue gets too big. - */ -struct MessageContext -{ - /** - * This is a DLL. - */ - struct MessageContext *next; - - /** - * This is a DLL. - */ - struct MessageContext *prev; - - /** - * Associated defragmentation context. - */ - struct GNUNET_DEFRAGMENT_Context *dc; - - /** - * Pointer to the assembled message, allocated at the - * end of this struct. - */ - const struct GNUNET_MessageHeader *msg; - - /** - * Last time we received any update for this message - * (least-recently updated message will be discarded - * if we hit the queue size). - */ - struct GNUNET_TIME_Absolute last_update; - - /** - * Task scheduled for transmitting the next ACK to the - * other peer. - */ - struct GNUNET_SCHEDULER_Task *ack_task; - - /** - * When did we receive which fragment? Used to calculate - * the time we should send the ACK. - */ - struct FragTimes frag_times[64]; - - /** - * Which fragments have we gotten yet? bits that are 1 - * indicate missing fragments. - */ - uint64_t bits; - - /** - * Unique ID for this message. - */ - uint32_t fragment_id; - - /** - * Which 'bit' did the last fragment we received correspond to? - */ - unsigned int last_bit; - - /** - * For the current ACK round, which is the first relevant - * offset in @e frag_times? - */ - unsigned int frag_times_start_offset; - - /** - * Which offset would we write the next frag value into - * in the @e frag_times array? All smaller entries are valid. - */ - unsigned int frag_times_write_offset; - - /** - * Total size of the message that we are assembling. - */ - uint16_t total_size; - - /** - * Was the last fragment we got a duplicate? - */ - int16_t last_duplicate; -}; - - -/** - * Defragmentation context (one per connection). - */ -struct GNUNET_DEFRAGMENT_Context -{ - /** - * For statistics. - */ - struct GNUNET_STATISTICS_Handle *stats; - - /** - * Head of list of messages we're defragmenting. - */ - struct MessageContext *head; - - /** - * Tail of list of messages we're defragmenting. - */ - struct MessageContext *tail; - - /** - * Closure for @e proc and @e ackp. - */ - void *cls; - - /** - * Function to call with defragmented messages. - */ - GNUNET_FRAGMENT_MessageProcessor proc; - - /** - * Function to call with acknowledgements. - */ - GNUNET_DEFRAGMENT_AckProcessor ackp; - - /** - * Running average of the latency (delay between messages) for this - * connection. - */ - struct GNUNET_TIME_Relative latency; - - /** - * num_msgs how many fragmented messages - * to we defragment at most at the same time? - */ - unsigned int num_msgs; - - /** - * Current number of messages in the 'struct MessageContext' - * DLL (smaller or equal to 'num_msgs'). - */ - unsigned int list_size; - - /** - * Maximum message size for each fragment. - */ - uint16_t mtu; -}; - - -/** - * Create a defragmentation context. - * - * @param stats statistics context - * @param mtu the maximum message size for each fragment - * @param num_msgs how many fragmented messages - * to we defragment at most at the same time? - * @param cls closure for @a proc and @a ackp - * @param proc function to call with defragmented messages - * @param ackp function to call with acknowledgements (to send - * back to the other side) - * @return the defragmentation context - */ -struct GNUNET_DEFRAGMENT_Context * -GNUNET_DEFRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, - uint16_t mtu, unsigned int num_msgs, - void *cls, - GNUNET_FRAGMENT_MessageProcessor proc, - GNUNET_DEFRAGMENT_AckProcessor ackp) -{ - struct GNUNET_DEFRAGMENT_Context *dc; - - dc = GNUNET_new (struct GNUNET_DEFRAGMENT_Context); - dc->stats = stats; - dc->cls = cls; - dc->proc = proc; - dc->ackp = ackp; - dc->num_msgs = num_msgs; - dc->mtu = mtu; - dc->latency = GNUNET_TIME_UNIT_SECONDS; /* start with likely overestimate */ - return dc; -} - - -/** - * Destroy the given defragmentation context. - * - * @param dc defragmentation context - */ -void -GNUNET_DEFRAGMENT_context_destroy (struct GNUNET_DEFRAGMENT_Context *dc) -{ - struct MessageContext *mc; - - while (NULL != (mc = dc->head)) - { - GNUNET_CONTAINER_DLL_remove (dc->head, dc->tail, mc); - dc->list_size--; - if (NULL != mc->ack_task) - { - GNUNET_SCHEDULER_cancel (mc->ack_task); - mc->ack_task = NULL; - } - GNUNET_free (mc); - } - GNUNET_assert (0 == dc->list_size); - GNUNET_free (dc); -} - - -/** - * Send acknowledgement to the other peer now. - * - * @param cls the message context - */ -static void -send_ack (void *cls) -{ - struct MessageContext *mc = cls; - struct GNUNET_DEFRAGMENT_Context *dc = mc->dc; - struct FragmentAcknowledgement fa; - - mc->ack_task = NULL; - fa.header.size = htons (sizeof(struct FragmentAcknowledgement)); - fa.header.type = htons (GNUNET_MESSAGE_TYPE_FRAGMENT_ACK); - fa.fragment_id = htonl (mc->fragment_id); - fa.bits = GNUNET_htonll (mc->bits); - GNUNET_STATISTICS_update (mc->dc->stats, - _ ("# acknowledgements sent for fragment"), - 1, - GNUNET_NO); - mc->last_duplicate = GNUNET_NO; /* clear flag */ - dc->ackp (dc->cls, - mc->fragment_id, - &fa.header); -} - - -/** - * This function is from the GNU Scientific Library, linear/fit.c, - * Copyright (C) 2000 Brian Gough - */ -static void -gsl_fit_mul (const double *x, const size_t xstride, const double *y, - const size_t ystride, const size_t n, double *c1, double *cov_11, - double *sumsq) -{ - double m_x = 0, m_y = 0, m_dx2 = 0, m_dxdy = 0; - - size_t i; - - for (i = 0; i < n; i++) - { - m_x += (x[i * xstride] - m_x) / (i + 1.0); - m_y += (y[i * ystride] - m_y) / (i + 1.0); - } - - for (i = 0; i < n; i++) - { - const double dx = x[i * xstride] - m_x; - const double dy = y[i * ystride] - m_y; - - m_dx2 += (dx * dx - m_dx2) / (i + 1.0); - m_dxdy += (dx * dy - m_dxdy) / (i + 1.0); - } - - /* In terms of y = b x */ - - { - double s2 = 0, d2 = 0; - double b = (m_x * m_y + m_dxdy) / (m_x * m_x + m_dx2); - - *c1 = b; - - /* Compute chi^2 = \sum (y_i - b * x_i)^2 */ - - for (i = 0; i < n; i++) - { - const double dx = x[i * xstride] - m_x; - const double dy = y[i * ystride] - m_y; - const double d = (m_y - b * m_x) + dy - b * dx; - - d2 += d * d; - } - - s2 = d2 / (n - 1.0); /* chisq per degree of freedom */ - - *cov_11 = s2 * 1.0 / (n * (m_x * m_x + m_dx2)); - - *sumsq = d2; - } -} - - -/** - * Estimate the latency between messages based on the most recent - * message time stamps. - * - * @param mc context with time stamps - * @return average delay between time stamps (based on least-squares fit) - */ -static struct GNUNET_TIME_Relative -estimate_latency (struct MessageContext *mc) -{ - struct FragTimes *first; - size_t total = mc->frag_times_write_offset - mc->frag_times_start_offset; - double x[total]; - double y[total]; - size_t i; - double c1; - double cov11; - double sumsq; - struct GNUNET_TIME_Relative ret; - - first = &mc->frag_times[mc->frag_times_start_offset]; - GNUNET_assert (total > 1); - for (i = 0; i < total; i++) - { - x[i] = (double) i; - y[i] = (double) (first[i].time.abs_value_us - first[0].time.abs_value_us); - } - gsl_fit_mul (x, 1, y, 1, total, &c1, &cov11, &sumsq); - c1 += sqrt (sumsq); /* add 1 std dev */ - ret.rel_value_us = (uint64_t) c1; - if (0 == ret.rel_value_us) - ret = GNUNET_TIME_UNIT_MICROSECONDS; /* always at least 1 */ - return ret; -} - - -/** - * Discard the message context that was inactive for the longest time. - * - * @param dc defragmentation context - */ -static void -discard_oldest_mc (struct GNUNET_DEFRAGMENT_Context *dc) -{ - struct MessageContext *old; - struct MessageContext *pos; - - old = NULL; - pos = dc->head; - while (NULL != pos) - { - if ((old == NULL) || - (old->last_update.abs_value_us > pos->last_update.abs_value_us)) - old = pos; - pos = pos->next; - } - GNUNET_assert (NULL != old); - GNUNET_CONTAINER_DLL_remove (dc->head, dc->tail, old); - dc->list_size--; - if (NULL != old->ack_task) - { - GNUNET_SCHEDULER_cancel (old->ack_task); - old->ack_task = NULL; - } - GNUNET_free (old); -} - - -/** - * We have received a fragment. Process it. - * - * @param dc the context - * @param msg the message that was received - * @return #GNUNET_OK on success, - * #GNUNET_NO if this was a duplicate, - * #GNUNET_SYSERR on error - */ -int -GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, - const struct GNUNET_MessageHeader *msg) -{ - struct MessageContext *mc; - const struct FragmentHeader *fh; - uint16_t msize; - uint16_t foff; - uint32_t fid; - char *mbuf; - unsigned int bit; - struct GNUNET_TIME_Absolute now; - struct GNUNET_TIME_Relative delay; - unsigned int bc; - unsigned int b; - unsigned int n; - unsigned int num_fragments; - int duplicate; - int last; - - if (ntohs (msg->size) < sizeof(struct FragmentHeader)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (ntohs (msg->size) > dc->mtu) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - fh = (const struct FragmentHeader *) msg; - msize = ntohs (fh->total_size); - if (msize < sizeof(struct GNUNET_MessageHeader)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - fid = ntohl (fh->fragment_id); - foff = ntohs (fh->offset); - if (foff >= msize) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (0 != (foff % (dc->mtu - sizeof(struct FragmentHeader)))) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - GNUNET_STATISTICS_update (dc->stats, - _ ("# fragments received"), - 1, - GNUNET_NO); - num_fragments = (ntohs (msg->size) + dc->mtu - sizeof(struct FragmentHeader) - - 1) / (dc->mtu - sizeof(struct FragmentHeader)); - last = 0; - for (mc = dc->head; NULL != mc; mc = mc->next) - if (mc->fragment_id > fid) - last++; - - mc = dc->head; - while ((NULL != mc) && (fid != mc->fragment_id)) - mc = mc->next; - bit = foff / (dc->mtu - sizeof(struct FragmentHeader)); - if (bit * (dc->mtu - sizeof(struct FragmentHeader)) + ntohs (msg->size) - - sizeof(struct FragmentHeader) > msize) - { - /* payload extends past total message size */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if ((NULL != mc) && (msize != mc->total_size)) - { - /* inconsistent message size */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - now = GNUNET_TIME_absolute_get (); - if (NULL == mc) - { - mc = GNUNET_malloc (sizeof(struct MessageContext) + msize); - mc->msg = (const struct GNUNET_MessageHeader *) &mc[1]; - mc->dc = dc; - mc->total_size = msize; - mc->fragment_id = fid; - mc->last_update = now; - n = (msize + dc->mtu - sizeof(struct FragmentHeader) - 1) / (dc->mtu - - sizeof(struct - FragmentHeader)); - if (n == 64) - mc->bits = UINT64_MAX; /* set all 64 bit */ - else - mc->bits = (1LLU << n) - 1; /* set lowest 'bits' bit */ - if (dc->list_size >= dc->num_msgs) - discard_oldest_mc (dc); - GNUNET_CONTAINER_DLL_insert (dc->head, - dc->tail, - mc); - dc->list_size++; - } - - /* copy data to 'mc' */ - if (0 != (mc->bits & (1LLU << bit))) - { - mc->bits -= 1LLU << bit; - mbuf = (char *) &mc[1]; - GNUNET_memcpy (&mbuf[bit * (dc->mtu - sizeof(struct FragmentHeader))], - &fh[1], - ntohs (msg->size) - sizeof(struct FragmentHeader)); - mc->last_update = now; - if (bit < mc->last_bit) - mc->frag_times_start_offset = mc->frag_times_write_offset; - mc->last_bit = bit; - mc->frag_times[mc->frag_times_write_offset].time = now; - mc->frag_times[mc->frag_times_write_offset].bit = bit; - mc->frag_times_write_offset++; - duplicate = GNUNET_NO; - } - else - { - duplicate = GNUNET_YES; - GNUNET_STATISTICS_update (dc->stats, - _ ("# duplicate fragments received"), - 1, - GNUNET_NO); - } - - /* count number of missing fragments after the current one */ - bc = 0; - for (b = bit; b < 64; b++) - if (0 != (mc->bits & (1LLU << b))) - bc++; - else - bc = 0; - - /* notify about complete message */ - if ((GNUNET_NO == duplicate) && - (0 == mc->bits)) - { - GNUNET_STATISTICS_update (dc->stats, - _ ("# messages defragmented"), - 1, - GNUNET_NO); - /* message complete, notify! */ - dc->proc (dc->cls, mc->msg); - } - /* send ACK */ - if (mc->frag_times_write_offset - mc->frag_times_start_offset > 1) - { - dc->latency = estimate_latency (mc); - } - delay = GNUNET_TIME_relative_saturating_multiply (dc->latency, - bc + 1); - if ((last + fid == num_fragments) || - (0 == mc->bits) || - (GNUNET_YES == duplicate)) - { - /* message complete or duplicate or last missing fragment in - linear sequence; ACK now! */ - delay = GNUNET_TIME_UNIT_ZERO; - } - if (NULL != mc->ack_task) - GNUNET_SCHEDULER_cancel (mc->ack_task); - mc->ack_task = GNUNET_SCHEDULER_add_delayed (delay, - &send_ack, - mc); - if (GNUNET_YES == duplicate) - { - mc->last_duplicate = GNUNET_YES; - return GNUNET_NO; - } - return GNUNET_YES; -} - - -/* end of defragmentation.c */ diff --git a/src/fragmentation/fragmentation.c b/src/fragmentation/fragmentation.c @@ -1,527 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2009-2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file src/fragmentation/fragmentation.c - * @brief library to help fragment messages - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_protocols.h" -#include "fragmentation.h" - - -/** - * Absolute minimum delay we impose between sending and expecting ACK to arrive. - */ -#define MIN_ACK_DELAY GNUNET_TIME_relative_multiply ( \ - GNUNET_TIME_UNIT_MILLISECONDS, 1) - - -/** - * Fragmentation context. - */ -struct GNUNET_FRAGMENT_Context -{ - /** - * Statistics to use. - */ - struct GNUNET_STATISTICS_Handle *stats; - - /** - * Tracker for flow control. - */ - struct GNUNET_BANDWIDTH_Tracker *tracker; - - /** - * Current expected delay for ACKs. - */ - struct GNUNET_TIME_Relative ack_delay; - - /** - * Current expected delay between messages. - */ - struct GNUNET_TIME_Relative msg_delay; - - /** - * Next allowed transmission time. - */ - struct GNUNET_TIME_Absolute delay_until; - - /** - * Time we transmitted the last message of the last round. - */ - struct GNUNET_TIME_Absolute last_round; - - /** - * Message to fragment (allocated at the end of this struct). - */ - const struct GNUNET_MessageHeader *msg; - - /** - * Function to call for transmissions. - */ - GNUNET_FRAGMENT_MessageProcessor proc; - - /** - * Closure for @e proc. - */ - void *proc_cls; - - /** - * Bitfield, set to 1 for each unacknowledged fragment. - */ - uint64_t acks; - - /** - * Bitfield with all possible bits for @e acks (used to mask the - * ack we get back). - */ - uint64_t acks_mask; - - /** - * Task performing work for the fragmenter. - */ - struct GNUNET_SCHEDULER_Task *task; - - /** - * Our fragmentation ID. (chosen at random) - */ - uint32_t fragment_id; - - /** - * Round-robin selector for the next transmission. - */ - unsigned int next_transmission; - - /** - * How many rounds of transmission have we completed so far? - */ - unsigned int num_rounds; - - /** - * How many transmission have we completed in this round? - */ - unsigned int num_transmissions; - - /** - * #GNUNET_YES if we called @e proc and are now waiting for #GNUNET_FRAGMENT_context_transmission_done() - */ - int8_t proc_busy; - - /** - * #GNUNET_YES if we are waiting for an ACK. - */ - int8_t wack; - - /** - * Target fragment size. - */ - uint16_t mtu; -}; - - -/** - * Convert an ACK message to a printable format suitable for logging. - * - * @param ack message to print - * @return ack in human-readable format - */ -const char * -GNUNET_FRAGMENT_print_ack (const struct GNUNET_MessageHeader *ack) -{ - static char buf[128]; - const struct FragmentAcknowledgement *fa; - - if (sizeof(struct FragmentAcknowledgement) != - htons (ack->size)) - return "<malformed ack>"; - fa = (const struct FragmentAcknowledgement *) ack; - GNUNET_snprintf (buf, - sizeof(buf), - "%u-%llX", - ntohl (fa->fragment_id), - (unsigned long long) GNUNET_ntohll (fa->bits)); - return buf; -} - - -/** - * Transmit the next fragment to the other peer. - * - * @param cls the `struct GNUNET_FRAGMENT_Context` - */ -static void -transmit_next (void *cls) -{ - struct GNUNET_FRAGMENT_Context *fc = cls; - char msg[fc->mtu]; - const char *mbuf; - struct FragmentHeader *fh; - struct GNUNET_TIME_Relative delay; - unsigned int bit; - size_t size; - size_t fsize; - int wrap; - - fc->task = NULL; - GNUNET_assert (GNUNET_NO == fc->proc_busy); - if (0 == fc->acks) - return; /* all done */ - /* calculate delay */ - wrap = 0; - while (0 == (fc->acks & (1LLU << fc->next_transmission))) - { - fc->next_transmission = (fc->next_transmission + 1) % 64; - wrap |= (0 == fc->next_transmission); - } - bit = fc->next_transmission; - size = ntohs (fc->msg->size); - if (bit == size / (fc->mtu - sizeof(struct FragmentHeader))) - fsize = - (size % (fc->mtu - sizeof(struct FragmentHeader))) - + sizeof(struct FragmentHeader); - else - fsize = fc->mtu; - if (NULL != fc->tracker) - delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker, - fsize); - else - delay = GNUNET_TIME_UNIT_ZERO; - if (delay.rel_value_us > 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Fragmentation logic delays transmission of next fragment by %s\n", - GNUNET_STRINGS_relative_time_to_string (delay, - GNUNET_YES)); - fc->task = GNUNET_SCHEDULER_add_delayed (delay, - &transmit_next, - fc); - return; - } - fc->next_transmission = (fc->next_transmission + 1) % 64; - wrap |= (0 == fc->next_transmission); - while (0 == (fc->acks & (1LLU << fc->next_transmission))) - { - fc->next_transmission = (fc->next_transmission + 1) % 64; - wrap |= (0 == fc->next_transmission); - } - - /* assemble fragmentation message */ - mbuf = (const char *) &fc[1]; - fh = (struct FragmentHeader *) msg; - fh->header.size = htons (fsize); - fh->header.type = htons (GNUNET_MESSAGE_TYPE_FRAGMENT); - fh->fragment_id = htonl (fc->fragment_id); - fh->total_size = fc->msg->size; /* already in big-endian */ - fh->offset = htons ((fc->mtu - sizeof(struct FragmentHeader)) * bit); - GNUNET_memcpy (&fh[1], &mbuf[bit * (fc->mtu - sizeof(struct FragmentHeader))], - fsize - sizeof(struct FragmentHeader)); - if (NULL != fc->tracker) - GNUNET_BANDWIDTH_tracker_consume (fc->tracker, fsize); - GNUNET_STATISTICS_update (fc->stats, - _ ("# fragments transmitted"), - 1, - GNUNET_NO); - if (0 != fc->last_round.abs_value_us) - GNUNET_STATISTICS_update (fc->stats, - _ ("# fragments retransmitted"), - 1, - GNUNET_NO); - - /* select next message to calculate delay */ - bit = fc->next_transmission; - size = ntohs (fc->msg->size); - if (bit == size / (fc->mtu - sizeof(struct FragmentHeader))) - fsize = size % (fc->mtu - sizeof(struct FragmentHeader)); - else - fsize = fc->mtu; - if (NULL != fc->tracker) - delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker, - fsize); - else - delay = GNUNET_TIME_UNIT_ZERO; - if (fc->num_rounds < 64) - delay = GNUNET_TIME_relative_max (delay, - GNUNET_TIME_relative_saturating_multiply - (fc->msg_delay, - (1ULL << fc->num_rounds))); - else - delay = GNUNET_TIME_UNIT_FOREVER_REL; - if (wrap) - { - /* full round transmitted wait 2x delay for ACK before going again */ - fc->num_rounds++; - delay = GNUNET_TIME_relative_saturating_multiply (fc->ack_delay, 2); - /* never use zero, need some time for ACK always */ - delay = GNUNET_TIME_relative_max (MIN_ACK_DELAY, delay); - fc->wack = GNUNET_YES; - fc->last_round = GNUNET_TIME_absolute_get (); - GNUNET_STATISTICS_update (fc->stats, - _ ("# fragments wrap arounds"), - 1, - GNUNET_NO); - } - fc->proc_busy = GNUNET_YES; - fc->delay_until = GNUNET_TIME_relative_to_absolute (delay); - fc->num_transmissions++; - fc->proc (fc->proc_cls, - &fh->header); -} - - -/** - * Create a fragmentation context for the given message. - * Fragments the message into fragments of size @a mtu or - * less. Calls @a proc on each un-acknowledged fragment, - * using both the expected @a msg_delay between messages and - * acknowledgements and the given @a tracker to guide the - * frequency of calls to @a proc. - * - * @param stats statistics context - * @param mtu the maximum message size for each fragment - * @param tracker bandwidth tracker to use for flow control (can be NULL) - * @param msg_delay initial delay to insert between fragment transmissions - * based on previous messages - * @param ack_delay expected delay between fragment transmission - * and ACK based on previous messages - * @param msg the message to fragment - * @param proc function to call for each fragment to transmit - * @param proc_cls closure for @a proc - * @return the fragmentation context - */ -struct GNUNET_FRAGMENT_Context * -GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, - uint16_t mtu, - struct GNUNET_BANDWIDTH_Tracker *tracker, - struct GNUNET_TIME_Relative msg_delay, - struct GNUNET_TIME_Relative ack_delay, - const struct GNUNET_MessageHeader *msg, - GNUNET_FRAGMENT_MessageProcessor proc, - void *proc_cls) -{ - struct GNUNET_FRAGMENT_Context *fc; - size_t size; - uint64_t bits; - - GNUNET_STATISTICS_update (stats, - _ ("# messages fragmented"), - 1, - GNUNET_NO); - GNUNET_assert (mtu >= 1024 + sizeof(struct FragmentHeader)); - size = ntohs (msg->size); - GNUNET_STATISTICS_update (stats, - _ ("# total size of fragmented messages"), - size, GNUNET_NO); - GNUNET_assert (size >= sizeof(struct GNUNET_MessageHeader)); - fc = GNUNET_malloc (sizeof(struct GNUNET_FRAGMENT_Context) + size); - fc->stats = stats; - fc->mtu = mtu; - fc->tracker = tracker; - fc->ack_delay = ack_delay; - fc->msg_delay = msg_delay; - fc->msg = (const struct GNUNET_MessageHeader *) &fc[1]; - fc->proc = proc; - fc->proc_cls = proc_cls; - fc->fragment_id = - GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, - UINT32_MAX); - GNUNET_memcpy (&fc[1], msg, size); - bits = - (size + mtu - sizeof(struct FragmentHeader) - 1) / (mtu - - sizeof(struct - FragmentHeader)); - GNUNET_assert (bits <= 64); - if (bits == 64) - fc->acks_mask = UINT64_MAX; /* set all 64 bit */ - else - fc->acks_mask = (1LLU << bits) - 1; /* set lowest 'bits' bit */ - fc->acks = fc->acks_mask; - fc->task = GNUNET_SCHEDULER_add_now (&transmit_next, fc); - return fc; -} - - -/** - * Continuation to call from the 'proc' function after the fragment - * has been transmitted (and hence the next fragment can now be - * given to proc). - * - * @param fc fragmentation context - */ -void -GNUNET_FRAGMENT_context_transmission_done (struct GNUNET_FRAGMENT_Context *fc) -{ - GNUNET_assert (fc->proc_busy == GNUNET_YES); - fc->proc_busy = GNUNET_NO; - GNUNET_assert (fc->task == NULL); - fc->task = - GNUNET_SCHEDULER_add_at (fc->delay_until, - &transmit_next, - fc); -} - - -/** - * Process an acknowledgement message we got from the other - * side (to control re-transmits). - * - * @param fc fragmentation context - * @param msg acknowledgement message we received - * @return #GNUNET_OK if this ack completes the work of the 'fc' - * (all fragments have been received); - * #GNUNET_NO if more messages are pending - * #GNUNET_SYSERR if this ack is not valid for this fc - */ -int -GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc, - const struct GNUNET_MessageHeader *msg) -{ - const struct FragmentAcknowledgement *fa; - uint64_t abits; - struct GNUNET_TIME_Relative ndelay; - unsigned int ack_cnt; - unsigned int snd_cnt; - unsigned int i; - - if (sizeof(struct FragmentAcknowledgement) != ntohs (msg->size)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - fa = (const struct FragmentAcknowledgement *) msg; - if (ntohl (fa->fragment_id) != fc->fragment_id) - return GNUNET_SYSERR; /* not our ACK */ - abits = GNUNET_ntohll (fa->bits); - if ((GNUNET_YES == fc->wack) && - (0 != fc->num_transmissions)) - { - /* normal ACK, can update running average of delay... */ - fc->wack = GNUNET_NO; - ndelay = GNUNET_TIME_absolute_get_duration (fc->last_round); - fc->ack_delay.rel_value_us = - (ndelay.rel_value_us / fc->num_transmissions + 3 - * fc->ack_delay.rel_value_us) / 4; - /* calculate ratio msg sent vs. msg acked */ - ack_cnt = 0; - snd_cnt = 0; - for (i = 0; i < 64; i++) - { - if (1 == (fc->acks_mask & (1ULL << i))) - { - snd_cnt++; - if (0 == (abits & (1ULL << i))) - ack_cnt++; - } - } - if (0 == ack_cnt) - { - /* complete loss */ - fc->msg_delay = GNUNET_TIME_relative_saturating_multiply (fc->msg_delay, - snd_cnt); - } - else if (snd_cnt > ack_cnt) - { - /* some loss, slow down proportionally */ - fc->msg_delay.rel_value_us = ((fc->msg_delay.rel_value_us * ack_cnt) - / snd_cnt); - } - else if (snd_cnt == ack_cnt) - { - fc->msg_delay.rel_value_us = - (ndelay.rel_value_us / fc->num_transmissions + 3 - * fc->msg_delay.rel_value_us) / 5; - } - fc->num_transmissions = 0; - fc->msg_delay = GNUNET_TIME_relative_min (fc->msg_delay, - GNUNET_TIME_UNIT_SECONDS); - fc->ack_delay = GNUNET_TIME_relative_min (fc->ack_delay, - GNUNET_TIME_UNIT_SECONDS); - } - GNUNET_STATISTICS_update (fc->stats, - _ ("# fragment acknowledgements received"), - 1, - GNUNET_NO); - if (abits != (fc->acks & abits)) - { - /* ID collision or message reordering, count! This should be rare! */ - GNUNET_STATISTICS_update (fc->stats, - _ ("# bits removed from fragmentation ACKs"), 1, - GNUNET_NO); - } - fc->acks = abits & fc->acks_mask; - if (0 != fc->acks) - { - /* more to transmit, do so right now (if tracker permits...) */ - if (fc->task != NULL) - { - /* schedule next transmission now, no point in waiting... */ - GNUNET_SCHEDULER_cancel (fc->task); - fc->task = GNUNET_SCHEDULER_add_now (&transmit_next, fc); - } - else - { - /* only case where there is no task should be if we're waiting - * for the right to transmit again (proc_busy set to YES) */ - GNUNET_assert (GNUNET_YES == fc->proc_busy); - } - return GNUNET_NO; - } - - /* all done */ - GNUNET_STATISTICS_update (fc->stats, - _ ("# fragmentation transmissions completed"), - 1, - GNUNET_NO); - if (NULL != fc->task) - { - GNUNET_SCHEDULER_cancel (fc->task); - fc->task = NULL; - } - return GNUNET_OK; -} - - -/** - * Destroy the given fragmentation context (stop calling 'proc', free - * resources). - * - * @param fc fragmentation context - * @param msg_delay where to store average delay between individual message transmissions the - * last message (OUT only) - * @param ack_delay where to store average delay between transmission and ACK for the - * last message, set to FOREVER if the message was not fully transmitted (OUT only) - */ -void -GNUNET_FRAGMENT_context_destroy (struct GNUNET_FRAGMENT_Context *fc, - struct GNUNET_TIME_Relative *msg_delay, - struct GNUNET_TIME_Relative *ack_delay) -{ - if (fc->task != NULL) - GNUNET_SCHEDULER_cancel (fc->task); - if (NULL != ack_delay) - *ack_delay = fc->ack_delay; - if (NULL != msg_delay) - *msg_delay = GNUNET_TIME_relative_saturating_multiply (fc->msg_delay, - fc->num_rounds); - GNUNET_free (fc); -} - - -/* end of fragmentation.c */ diff --git a/src/fragmentation/fragmentation.h b/src/fragmentation/fragmentation.h @@ -1,87 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2009, 2011 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file src/fragmentation/fragmentation.h - * @brief library to help fragment messages - * @author Christian Grothoff - */ -#ifndef FRAGMENTATION_H -#define FRAGMENTATION_H - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_fragmentation_lib.h" - -GNUNET_NETWORK_STRUCT_BEGIN - -/** - * Header for a message fragment. Followed by the - * original message. - */ -struct FragmentHeader -{ - /** - * Message header. - */ - struct GNUNET_MessageHeader header; - - /** - * Unique fragment ID. - */ - uint32_t fragment_id GNUNET_PACKED; - - /** - * Total message size of the original message. - */ - uint16_t total_size GNUNET_PACKED; - - /** - * Absolute offset (in bytes) of this fragment in the original - * message. Will be a multiple of the MTU. - */ - uint16_t offset GNUNET_PACKED; -}; - - -/** - * Message fragment acknowledgement. - */ -struct FragmentAcknowledgement -{ - /** - * Message header. - */ - struct GNUNET_MessageHeader header; - - /** - * Unique fragment ID. - */ - uint32_t fragment_id GNUNET_PACKED; - - /** - * Bits that are being acknowledged, in big-endian. - * (bits that are set correspond to fragments that - * have not yet been received). - */ - uint64_t bits GNUNET_PACKED; -}; -GNUNET_NETWORK_STRUCT_END - -#endif diff --git a/src/fragmentation/meson.build b/src/fragmentation/meson.build @@ -1,22 +0,0 @@ -libgnunetfragmentation_src = ['fragmentation.c', - 'defragmentation.c'] - -if get_option('monolith') - foreach p : libgnunetfragmentation_src - gnunet_src += 'fragmentation/' + p - endforeach - subdir_done() -endif - -libgnunetfragmentation = library('gnunetfragmentation', - libgnunetfragmentation_src, - soversion: '2', - version: '2.0.0', - dependencies: [m_dep, libgnunetutil_dep, libgnunetstatistics_dep], - include_directories: [incdir, configuration_inc], - install: true, - install_dir: get_option('libdir')) -libgnunetfragmentation_dep = declare_dependency(link_with : libgnunetfragmentation) -pkg.generate(libgnunetfragmentation, url: 'https://www.gnunet.org', - description : 'Provides API for sending and receiving messages that are larger than the MTU of the transport') - diff --git a/src/fragmentation/test_fragmentation.c b/src/fragmentation/test_fragmentation.c @@ -1,303 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2004, 2009 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file fragmentation/test_fragmentation.c - * @brief test for fragmentation.c - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_fragmentation_lib.h" - -#define DETAILS GNUNET_NO - -/** - * Number of messages to transmit (note: each uses ~32k memory!) - */ -#define NUM_MSGS 1000 - -/** - * MTU to force on fragmentation (must be > 1k + 12) - */ -#define MTU 1111 - -/** - * Simulate dropping of 1 out of how many messages? (must be > 1) - */ -#define DROPRATE 15 - -static int ret = 1; - -static unsigned int dups; - -static unsigned int fragc; - -static unsigned int frag_drops; - -static unsigned int acks; - -static unsigned int ack_drops; - -static struct GNUNET_DEFRAGMENT_Context *defrag; - -static struct GNUNET_BANDWIDTH_Tracker trackers[NUM_MSGS]; - -static struct GNUNET_FRAGMENT_Context *frag; - -static struct GNUNET_SCHEDULER_Task *shutdown_task; - -static struct GNUNET_TIME_Relative msg_delay; - -static struct GNUNET_TIME_Relative ack_delay; - - -static void -do_shutdown (void *cls) -{ - ret = 0; - shutdown_task = NULL; - GNUNET_DEFRAGMENT_context_destroy (defrag); - defrag = NULL; - if (NULL != frag) - { - GNUNET_FRAGMENT_context_destroy (frag, &msg_delay, &ack_delay); - frag = NULL; - } - fprintf (stderr, - "\nFinal message-delay: %s\n", - GNUNET_STRINGS_relative_time_to_string (msg_delay, - GNUNET_YES)); - fprintf (stderr, - "Final ack-delay: %s\n", - GNUNET_STRINGS_relative_time_to_string (ack_delay, - GNUNET_YES)); -} - - -static void -proc_msgs (void *cls, const struct GNUNET_MessageHeader *hdr) -{ - static unsigned int total; - unsigned int i; - const char *buf; - -#if DETAILS - fprintf (stderr, "%s", "M! "); /* message complete, good! */ -#endif - buf = (const char *) hdr; - for (i = sizeof(struct GNUNET_MessageHeader); i < ntohs (hdr->size); i++) - GNUNET_assert (buf[i] == (char) i); - total++; -#if ! DETAILS - if (0 == (total % (NUM_MSGS / 100))) - fprintf (stderr, "%s", "."); -#endif - /* tolerate 10% loss, e.g. due to duplicate fragment IDs */ - if ((total >= NUM_MSGS - (NUM_MSGS / 10)) && (ret != 0)) - { - if (NULL == shutdown_task) - shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - } -} - - -/** - * Process fragment (by passing to defrag). - */ -static void -proc_frac (void *cls, const struct GNUNET_MessageHeader *hdr) -{ - struct GNUNET_FRAGMENT_Context **fc = cls; - int ret; - - GNUNET_FRAGMENT_context_transmission_done (*fc); - if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE)) - { - frag_drops++; -#if DETAILS - fprintf (stderr, "%s", "DF "); /* dropped Frag */ -#endif - return; /* random drop */ - } - if (NULL == defrag) - { - fprintf (stderr, "%s", "?E "); /* Error: frag after shutdown!? */ - return; - } - ret = GNUNET_DEFRAGMENT_process_fragment (defrag, hdr); - if (ret == GNUNET_NO) - { -#if DETAILS - fprintf (stderr, "%s", "FF "); /* duplicate fragment */ -#endif - dups++; - } - else if (ret == GNUNET_OK) - { -#if DETAILS - fprintf (stderr, "%s", "F! "); /* good fragment */ -#endif - fragc++; - } -} - - -static void -next_transmission () -{ - static unsigned int i; - struct GNUNET_MessageHeader *msg; - static char buf[MTU + 32 * 1024]; - unsigned int j; - - if (0 == i) - { - for (j = 0; j < sizeof(buf); j++) - buf[j] = (char) j; - } - else - { - GNUNET_FRAGMENT_context_destroy (frag, - &msg_delay, - &ack_delay); - frag = NULL; - } - if (i == NUM_MSGS) - return; -#if DETAILS - fprintf (stderr, "%s", "T! "); /* sending message */ -#endif - msg = (struct GNUNET_MessageHeader *) buf; - msg->type = htons ((uint16_t) i); - msg->size = - htons (sizeof(struct GNUNET_MessageHeader) + (17 * i) % (32 * 1024)); - frag = GNUNET_FRAGMENT_context_create (NULL /* no stats */, - MTU, &trackers[i], - msg_delay, - ack_delay, - msg, - &proc_frac, &frag); - i++; -} - - -/** - * Process ACK (by passing to fragmenter) - */ -static void -proc_acks (void *cls, - uint32_t msg_id, - const struct GNUNET_MessageHeader *hdr) -{ - unsigned int i; - int ret; - - if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE)) - { - ack_drops++; -#if DETAILS - fprintf (stderr, "%s", "DA "); /* dropped ACK */ -#endif - return; /* random drop */ - } - for (i = 0; i < NUM_MSGS; i++) - { - if (NULL == frag) - continue; - ret = GNUNET_FRAGMENT_process_ack (frag, hdr); - if (ret == GNUNET_OK) - { -#if DETAILS - fprintf (stderr, "%s", "GA "); /* good ACK */ -#endif - next_transmission (); - acks++; - return; - } - if (ret == GNUNET_NO) - { -#if DETAILS - fprintf (stderr, "%s", "AA "); /* duplicate ACK */ -#endif - acks++; - return; - } - } -#if DETAILS - fprintf (stderr, "%s", "?A "); /* BAD: ack that nobody feels responsible for... */ -#endif -} - - -/** - * Main function run with scheduler. - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - defrag = GNUNET_DEFRAGMENT_context_create (NULL, MTU, - 3, - NULL, - &proc_msgs, - &proc_acks); - next_transmission (); -} - - -int -main (int argc, char *argv[]) -{ - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - char *const argv_prog[] = { - "test-fragmentation", - "-c", - "test_fragmentation_data.conf", - "-L", - "WARNING", - NULL - }; - unsigned int i; - - msg_delay = GNUNET_TIME_UNIT_MILLISECONDS; - ack_delay = GNUNET_TIME_UNIT_SECONDS; - GNUNET_log_setup ("test-fragmentation", - "WARNING", - NULL); - for (i = 0; i < NUM_MSGS; i++) - GNUNET_BANDWIDTH_tracker_init (&trackers[i], NULL, NULL, - GNUNET_BANDWIDTH_value_init ((i + 1) * 1024), - 100); - GNUNET_PROGRAM_run (5, - argv_prog, - "test-fragmentation", "nohelp", - options, - &run, NULL); - fprintf (stderr, - "\nHad %u good fragments, %u duplicate fragments, %u acks and %u simulated drops of acks\n", - fragc, - dups, - acks, - ack_drops); - return ret; -} diff --git a/src/fragmentation/test_fragmentation_data.conf b/src/fragmentation/test_fragmentation_data.conf @@ -1,5 +0,0 @@ - -[nse] -START_ON_DEMAND = NO - - diff --git a/src/fragmentation/test_fragmentation_parallel.c b/src/fragmentation/test_fragmentation_parallel.c @@ -1,254 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2004, 2009 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file fragmentation/test_fragmentation.c - * @brief test for fragmentation.c - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_fragmentation_lib.h" - -#define DETAILS GNUNET_NO - -/** - * Number of messages to transmit (note: each uses ~32k memory!) - */ -#define NUM_MSGS 500 - -/** - * MTU to force on fragmentation (must be > 1k + 12) - */ -#define MTU 1111 - -/** - * Simulate dropping of 1 out of how many messages? (must be > 1) - */ -#define DROPRATE 5 - -static int ret = 1; - -static unsigned int dups; - -static unsigned int fragc; - -static unsigned int frag_drops; - -static unsigned int acks; - -static unsigned int ack_drops; - -static struct GNUNET_DEFRAGMENT_Context *defrag; - -static struct GNUNET_BANDWIDTH_Tracker trackers[NUM_MSGS]; - -static struct GNUNET_FRAGMENT_Context *frags[NUM_MSGS]; - -static struct GNUNET_SCHEDULER_Task *shutdown_task; - - -static void -do_shutdown (void *cls) -{ - unsigned int i; - - ret = 0; - shutdown_task = NULL; - GNUNET_DEFRAGMENT_context_destroy (defrag); - defrag = NULL; - for (i = 0; i < NUM_MSGS; i++) - { - if (frags[i] == NULL) - continue; - GNUNET_FRAGMENT_context_destroy (frags[i], NULL, NULL); - frags[i] = NULL; - } -} - - -static void -proc_msgs (void *cls, const struct GNUNET_MessageHeader *hdr) -{ - static unsigned int total; - unsigned int i; - const char *buf; - -#if DETAILS - fprintf (stderr, "%s", "!"); /* message complete, good! */ -#endif - buf = (const char *) hdr; - for (i = sizeof(struct GNUNET_MessageHeader); i < ntohs (hdr->size); i++) - GNUNET_assert (buf[i] == (char) i); - total++; -#if ! DETAILS - if (0 == (total % (NUM_MSGS / 100))) - fprintf (stderr, "%s", "."); -#endif - /* tolerate 10% loss, e.g due to duplicate fragment IDs */ - if ((total >= NUM_MSGS - (NUM_MSGS / 10)) && (ret != 0)) - { - if (NULL == shutdown_task) - shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - } -} - - -/** - * Process ACK (by passing to fragmenter) - */ -static void -proc_acks (void *cls, uint32_t msg_id, const struct GNUNET_MessageHeader *hdr) -{ - unsigned int i; - int ret; - - if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE)) - { - ack_drops++; - return; /* random drop */ - } - for (i = 0; i < NUM_MSGS; i++) - { - if (frags[i] == NULL) - continue; - ret = GNUNET_FRAGMENT_process_ack (frags[i], hdr); - if (ret == GNUNET_OK) - { -#if DETAILS - fprintf (stderr, "%s", "@"); /* good ACK */ -#endif - GNUNET_FRAGMENT_context_destroy (frags[i], NULL, NULL); - frags[i] = NULL; - acks++; - return; - } - if (ret == GNUNET_NO) - { -#if DETAILS - fprintf (stderr, "%s", "@"); /* good ACK */ -#endif - acks++; - return; - } - } -#if DETAILS - fprintf (stderr, "%s", "_"); /* BAD: ack that nobody feels responsible for... */ -#endif -} - - -/** - * Process fragment (by passing to defrag). - */ -static void -proc_frac (void *cls, const struct GNUNET_MessageHeader *hdr) -{ - struct GNUNET_FRAGMENT_Context **fc = cls; - int ret; - - GNUNET_FRAGMENT_context_transmission_done (*fc); - if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE)) - { - frag_drops++; - return; /* random drop */ - } - if (NULL == defrag) - { - fprintf (stderr, "%s", "E"); /* Error: frag after shutdown!? */ - return; - } - ret = GNUNET_DEFRAGMENT_process_fragment (defrag, hdr); - if (ret == GNUNET_NO) - { -#if DETAILS - fprintf (stderr, "%s", "?"); /* duplicate fragment */ -#endif - dups++; - } - else if (ret == GNUNET_OK) - { -#if DETAILS - fprintf (stderr, "%s", "."); /* good fragment */ -#endif - fragc++; - } -} - - -/** - * Main function run with scheduler. - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - unsigned int i; - struct GNUNET_MessageHeader *msg; - char buf[MTU + 32 * 1024]; - - defrag = GNUNET_DEFRAGMENT_context_create (NULL, MTU, NUM_MSGS /* enough space for all */ - , NULL, &proc_msgs, &proc_acks); - for (i = 0; i < sizeof(buf); i++) - buf[i] = (char) i; - msg = (struct GNUNET_MessageHeader *) buf; - for (i = 0; i < NUM_MSGS; i++) - { - msg->type = htons ((uint16_t) i); - msg->size = - htons (sizeof(struct GNUNET_MessageHeader) + (17 * i) % (32 * 1024)); - frags[i] = GNUNET_FRAGMENT_context_create (NULL /* no stats */, - MTU, &trackers[i], - GNUNET_TIME_UNIT_MILLISECONDS, - GNUNET_TIME_UNIT_SECONDS, - msg, - &proc_frac, &frags[i]); - } -} - - -int -main (int argc, char *argv[]) -{ - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - char *const argv_prog[] = { - "test-fragmentation", - "-c", - "test_fragmentation_data.conf", - "-L", - "WARNING", - NULL - }; - unsigned int i; - - GNUNET_log_setup ("test-fragmentation", - "WARNING", - NULL); - for (i = 0; i < NUM_MSGS; i++) - GNUNET_BANDWIDTH_tracker_init (&trackers[i], NULL, NULL, - GNUNET_BANDWIDTH_value_init ((i + 1) * 1024), - 100); - GNUNET_PROGRAM_run (5, argv_prog, "test-fragmentation", "nohelp", options, - &run, NULL); - fprintf (stderr, - "\nHad %u good fragments, %u duplicate fragments, %u acks and %u simulated drops of acks\n", - fragc, dups, acks, ack_drops); - return ret; -} diff --git a/src/integration-tests/.gitignore b/src/integration-tests/.gitignore @@ -1,10 +0,0 @@ -gnunet_testing.py -gnunet_pyexpect.py -gnunet_pyexpect.pyc -gnunet_testing.pyc -test_integration_bootstrap_and_connect.py -test_integration_clique.py -test_integration_disconnect_nat.py -test_integration_disconnect.py -test_integration_reconnect_nat.py -test_integration_reconnect.py diff --git a/src/integration-tests/Makefile.am b/src/integration-tests/Makefile.am @@ -1,90 +0,0 @@ -# This Makefile.am is in the public domain -AM_CPPFLAGS = -I$(top_srcdir)/src/include - -if USE_COVERAGE - AM_CFLAGS = --coverage -O0 - XLIB = -lgcov -endif - -noinst_SCRIPTS = \ - gnunet_testing.py \ - gnunet_pyexpect.py - -if HAVE_PYTHON -check_SCRIPTS = \ - # test_integration_bootstrap_and_connect.py \ - # test_integration_disconnect.py \ - # test_integration_disconnect_nat.py \ - # test_integration_reconnect.py \ - # test_integration_reconnect_nat.py -# test_integration_clique.py -endif - - -if ENABLE_TEST_RUN -AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; -TESTS = \ - $(check_SCRIPTS) -endif - -SUFFIXES = .py.in .py -.py.in.py: - $(AWK) -v bdir="$(bindir)" -v py="$(PYTHON)" -v awkay="$(AWK_BINARY)" -v pfx="$(prefix)" -v prl="$(PERL)" -v sysconfdirectory="$(sysconfdir)" -v pkgdatadirectory="$(pkgdatadir)" -f $(top_srcdir)/bin/dosubst.awk < $(srcdir)/$< > $@ - chmod +x $@ - -gnunet_testing.py: gnunet_testing.py.in Makefile - $(AWK) -v bdir="$(bindir)" -v py="$(PYTHON)" -v awkay="$(AWK_BINARY)" -v pfx="$(prefix)" -v prl="$(PERL)" -v sysconfdirectory="$(sysconfdir)" -v pkgdatadirectory="$(pkgdatadir)" -f $(top_srcdir)/bin/dosubst.awk < $(srcdir)/gnunet_testing.py.in > gnunet_testing.py - chmod +x gnunet_testing.py - -gnunet_pyexpect.py: gnunet_pyexpect.py.in Makefile - $(AWK) -v bdir="$(bindir)" -v py="$(PYTHON)" -v awkay="$(AWK_BINARY)" -v pfx="$(prefix)" -v prl="$(PERL)" -v sysconfdirectory="$(sysconfdir)" -v pkgdatadirectory="$(pkgdatadir)" -f $(top_srcdir)/bin/dosubst.awk < $(srcdir)/gnunet_pyexpect.py.in > gnunet_pyexpect.py - chmod +x gnunet_pyexpect.py - -test_integration_bootstrap_and_connect.py: test_integration_bootstrap_and_connect.py.in Makefile - $(AWK) -v bdir="$(bindir)" -v py="$(PYTHON)" -v awkay="$(AWK_BINARY)" -v pfx="$(prefix)" -v prl="$(PERL)" -v sysconfdirectory="$(sysconfdir)" -v pkgdatadirectory="$(pkgdatadir)" -f $(top_srcdir)/bin/dosubst.awk < $(srcdir)/test_integration_bootstrap_and_connect.py.in > test_integration_bootstrap_and_connect.py - chmod +x test_integration_bootstrap_and_connect.py - -test_integration_disconnect.py: test_integration_disconnect.py.in Makefile - $(AWK) -v bdir="$(bindir)" -v py="$(PYTHON)" -v awkay="$(AWK_BINARY)" -v pfx="$(prefix)" -v prl="$(PERL)" -v sysconfdirectory="$(sysconfdir)" -v pkgdatadirectory="$(pkgdatadir)" -f $(top_srcdir)/bin/dosubst.awk < $(srcdir)/test_integration_disconnect.py.in > test_integration_disconnect.py - chmod +x test_integration_disconnect.py - -test_integration_disconnect_nat.py: test_integration_disconnect_nat.py.in Makefile - $(AWK) -v bdir="$(bindir)" -v py="$(PYTHON)" -v awkay="$(AWK_BINARY)" -v pfx="$(prefix)" -v prl="$(PERL)" -v sysconfdirectory="$(sysconfdir)" -v pkgdatadirectory="$(pkgdatadir)" -f $(top_srcdir)/bin/dosubst.awk < $(srcdir)/test_integration_disconnect_nat.py.in > test_integration_disconnect_nat.py - chmod +x test_integration_disconnect_nat.py - -test_integration_reconnect.py: test_integration_reconnect.py.in Makefile - $(AWK) -v bdir="$(bindir)" -v py="$(PYTHON)" -v awkay="$(AWK_BINARY)" -v pfx="$(prefix)" -v prl="$(PERL)" -v sysconfdirectory="$(sysconfdir)" -v pkgdatadirectory="$(pkgdatadir)" -f $(top_srcdir)/bin/dosubst.awk < $(srcdir)/test_integration_reconnect.py.in > test_integration_reconnect.py - chmod +x test_integration_reconnect.py - -test_integration_reconnect_nat.py: test_integration_reconnect_nat.py.in Makefile - $(AWK) -v bdir="$(bindir)" -v py="$(PYTHON)" -v awkay="$(AWK_BINARY)" -v pfx="$(prefix)" -v prl="$(PERL)" -v sysconfdirectory="$(sysconfdir)" -v pkgdatadirectory="$(pkgdatadir)" -f $(top_srcdir)/bin/dosubst.awk < $(srcdir)/test_integration_reconnect_nat.py.in > test_integration_reconnect_nat.py - chmod +x test_integration_reconnect_nat.py - -test_integration_clique.py: test_integration_clique.py.in Makefile - $(AWK) -v bdir="$(bindir)" -v py="$(PYTHON)" -v awkay="$(AWK_BINARY)" -v pfx="$(prefix)" -v prl="$(PERL)" -v sysconfdirectory="$(sysconfdir)" -v pkgdatadirectory="$(pkgdatadir)" -f $(top_srcdir)/bin/dosubst.awk < $(srcdir)/test_integration_clique.py.in > test_integration_clique.py - chmod +x test_integration_clique.py - - -EXTRA_DIST = \ - gnunet_testing.py.in \ - gnunet_pyexpect.py.in \ - test_integration_bootstrap_and_connect.py.in \ - test_integration_disconnect.py.in \ - test_integration_disconnect_nat.py.in \ - test_integration_reconnect.py.in \ - test_integration_reconnect_nat.py.in \ - test_integration_clique.py.in \ - confs/test_defaults.conf \ - confs/c_bootstrap_server.conf \ - confs/c_nat_client.conf \ - confs/c_no_nat_client_2.conf \ - confs/c_no_nat_client.conf \ - hostkeys/c_bootstrap_server \ - hostkeys/c_no_nat_client \ - hostkeys/c_no_nat_client_2 \ - hostkeys/c_nat_client - -CLEANFILES = \ - $(check_SCRIPTS) \ - gnunet_pyexpect.py \ - gnunet_testing.py diff --git a/src/integration-tests/confs/c_bootstrap_server.conf b/src/integration-tests/confs/c_bootstrap_server.conf @@ -1,92 +0,0 @@ -@INLINE@ test_defaults.conf - -[PATHS] -GNUNET_TEST_HOME = $GNUNET_TMP/c_bootstrap_server/ - -[PEER] -PRIVATE_KEY = hostkeys/c_bootstrap_server - - -[transport] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-transport-8 -PORT = 20011 -PLUGINS = tcp - -[transport-tcp] -PORT = 20010 -ADVERTISED_PORT = 20010 - -[hostlist] -OPTIONS = -p -SERVERs = - -[nat] -BEHIND_NAT = NO -DISABLEV6 = NO -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-nat-4 -PORT = 20070 - -[nat-auto] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-natauto-4 -PORT = 20076 - -[arm] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-arm-4 -PORT = 20004 - -[dns] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dns-5 - -[core] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-core-3 -PORT = 20003 - -[ats] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-ats-9 -PORT = 20012 - -[cadet] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-cadet-13 -PORT = 20016 - -[datastore] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-datastore-11 -PORT = 20014 - -[resolver] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-resolver-14 -PORT = 20017 - -[dht] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dht-1 -PORT = 20000 - -[nat] -BEHIND_NAT = NO - -[fs] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-fs-6 -PORT = 20005 - -[gns] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-gns-15 -PORT = 20018 - -[dv] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dv-16 -PORT = 20019 - -[vpn] -UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-vpn-15 - -[peerinfo] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-peerinfo-10 -PORT = 20013 - -[statistics] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-statistics-2 -PORT = 20001 - -[nse] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-nse-12 -PORT = 20015 diff --git a/src/integration-tests/confs/c_nat_client.conf b/src/integration-tests/confs/c_nat_client.conf @@ -1,72 +0,0 @@ -@INLINE@ test_defaults.conf - -[PATHS] -GNUNET_TEST_HOME = $GNUNET_TMP/c_nat_client/ - -[PEER] -PRIVATE_KEY = hostkeys/c_nat_client - - -[transport] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-transport-50 -PORT = 20065 -PLUGINS = tcp - -[transport-tcp] -PORT = 0 -ADVERTISED_PORT = 20064 - -[transport-udp] -PORT = 0 - -[hostlist] -SERVERS = http://localhost:8080/ - -[nat] -BEHIND_NAT = YES -DISABLEV6 = NO -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-nat-46 -PORT = 20071 - -[nat-auto] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-natauto-46 -PORT = 20077 - -[arm] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-arm-46 -PORT = 20058 - -[core] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-core-45 -PORT = 20057 - -[ats] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-ats-51 -PORT = 20066 - -[datastore] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-datastore-53 -PORT = 20068 - -[resolver] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-resolver-56 -PORT = 20071 - -[dht] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dht-43 -PORT = 20054 - -[fs] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-fs-48 -PORT = 20059 - -[dv] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dv-b_nat_c-1 - -[peerinfo] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-peerinfo-52 -PORT = 20067 - -[nse] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-nse-54 -PORT = 20069 -\ No newline at end of file diff --git a/src/integration-tests/confs/c_no_nat_client.conf b/src/integration-tests/confs/c_no_nat_client.conf @@ -1,105 +0,0 @@ -@INLINE@ test_defaults.conf - -[PATHS] -GNUNET_TEST_HOME = $GNUNET_TMP/c_no_nat_client/ - -[PEER] -PRIVATE_KEY = hostkeys/c_no_nat_client - -[transport] -PLUGINS = tcp -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-transport-22 -PORT = 20029 - -[transport-tcp] -PORT = 20028 -ADVERTISED_PORT = 20028 - -[hostlist] -SERVERS = http://localhost:8080/ - -[nat] -BEHIND_NAT = NO -DISABLEV6 = NO -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-nat-18 -PORT = 20072 - -[nat-auto] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-natauto-18 -PORT = 20074 - -[arm] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-arm-18 -PORT = 20022 - -[namestore] -START_ON_DEMAND = YES - -[dns] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dns-19 - -[consensus] -START_ON_DEMAND = YES - -[core] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-core-17 -PORT = 20021 - -[ats] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-ats-23 -WAN_QUOTA_IN = 64 KiB -WAN_QUOTA_OUT = 64 KiB -PORT = 20030 - -[cadet] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-cadet-27 -PORT = 20034 - -[datastore] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-datastore-25 -PORT = 20032 - -[resolver] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-resolver-28 -PORT = 20035 - -[dht] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dht-15 -PORT = 20018 - -[dhtcache] -DATABASE = heap -QUOTA = 50 MB - -[gnunet-nat-server] -PORT = 20020 - -[fs] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-fs-20 -PORT = 20023 - -[vpn] -UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-vpn-29 - -[dv] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dv-b_no_nat_c-1 - -[peerinfo] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-peerinfo-24 -PORT = 20031 - -[statistics] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-statistics-16 -PORT = 20019 - -[nse] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-nse-26 -PORT = 20033 - -[gns] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-gns-35 -PORT = 20038 - -[dv] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dv-36 -PORT = 20039 diff --git a/src/integration-tests/confs/c_no_nat_client_2.conf b/src/integration-tests/confs/c_no_nat_client_2.conf @@ -1,119 +0,0 @@ -@INLINE@ test_defaults.conf - -[PATHS] -GNUNET_TEST_HOME = $GNUNET_TMP/c_no_nat_client_2/ - -[PEER] -PRIVATE_KEY = hostkeys/c_no_nat_client_2 - - -[transport] -PLUGINS = tcp -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-transport-22 -PORT = 20039 - -[transport-tcp] -PORT = 20038 -ADVERTISED_PORT = 20038 - -[transport-udp] -PORT = 20027 -BROADCAST_INTERVAL = 30 s - -[hostlist] -SERVERS = http://localhost:8080/ - -[nat] -BEHIND_NAT = NO -DISABLEV6 = NO -PORT = 20073 -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-nat-18 - -[nat-auto] -PORT = 20075 -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-natauto-18 - - -[arm] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-arm-18 -PORT = 20022 - -[namestore] -START_ON_DEMAND = YES - -[dns] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dns-19 - -[consensus] -START_ON_DEMAND = YES - -[lockmanager] -START_ON_DEMAND = YES - -[core] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-core-17 -PORT = 20021 - -[ats] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-ats-23 -WAN_QUOTA_IN = 64 KiB -WAN_QUOTA_OUT = 64 KiB -PORT = 20030 - -[cadet] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-cadet-27 -PORT = 20034 - -[datastore] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-datastore-25 -PORT = 20032 - -[resolver] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-resolver-28 -PORT = 20035 - -[dht] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dht-15 -PORT = 20018 - -[dhtcache] -DATABASE = heap -QUOTA = 50 MB - -[gnunet-nat-server] -PORT = 20020 - -[fs] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-fs-20 -PORT = 20023 - -[vpn] -UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-vpn-29 - -[dv] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dv-b_no_nat_c-1 - -[peerinfo] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-peerinfo-24 -USE_INCLUDED_HELLOS = YES -PORT = 20031 - -[statistics] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-statistics-16 -PORT = 20019 - -[template] -PORT = 20024 -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-template-21 - -[nse] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-nse-26 -PORT = 20033 - -[gns] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-gns-35 -PORT = 20038 - -[dv] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dv-36 -PORT = 20039 diff --git a/src/integration-tests/confs/test_defaults.conf b/src/integration-tests/confs/test_defaults.conf @@ -1,76 +0,0 @@ -@INLINE@ ../../../contrib/conf/gnunet/no_forcestart.conf -@INLINE@ ../../../contrib/conf/gnunet/no_autostart_above_core.conf - -[fs] -IMMEDIATE_START = YES - -[datastore] -START_ON_DEMAND = YES - -[dht] -START_ON_DEMAND = YES - -[nse] -START_ON_DEMAND = YES - -[cadet] -START_ON_DEMAND = YES - -[hostlist] -IMMEDIATE_START = YES - -[topology] -IMMEDIATE_START = YES - -[peerinfo] -USE_INCLUDED_HELLOS = NO - -[transport-tcp] -USE_LOCALADDR = YES - -[transport-udp] -BROADCAST = NO -BROADCAST_RECEIVE = no -USE_LOCALADDR = YES - -[nat] -BEHIND_NAT = NO -EXTERNAL_ADDRESS = 127.0.0.1 -INTERNAL_ADDRESS = 127.0.0.1 -BINDTO = 127.0.0.1 -RETURN_LOCAL_ADDRESSES = YES - -[hostlist] -SERVERS = - -[dns] -UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dns-47 -ACCEPT_FROM = 127.0.0.1; -ACCEPT_FROM6 = ::1; -PROVIDE_EXIT = NO - -[ats] -WAN_QUOTA_IN = unlimited -WAN_QUOTA_OUT = unlimited -ATS_MIN_INTERVAL = 15000 -ATS_EXEC_INTERVAL = 30000 - -[datastore] -UNIX_MATCH_UID = YES -QUOTA = 100 MB -BLOOMFILTER = $GNUNET_TEST_HOME/fs/bloomfilter - -[dhtcache] -DATABASE = sqlite -QUOTA = 1 MB - -[fs] -INDEXDB = $GNUNET_TEST_HOME/idxinfo.lst -IDENTITY_DIR = $GNUNET_TEST_HOME/identities/ -STATE_DIR = $GNUNET_TEST_HOME/persistence/ -UPDATE_DIR = $GNUNET_TEST_HOME/updates/ -TRUST = $GNUNET_TEST_HOME/data/credit/ - -[datacache-mysql] -DATABASE = gnunet -CONFIG = ~/.my.cnf diff --git a/src/integration-tests/gnunet_pyexpect.py.in b/src/integration-tests/gnunet_pyexpect.py.in @@ -1,94 +0,0 @@ -#!@PYTHONEXE@ -# This file is part of GNUnet. -# (C) 2010 Christian Grothoff (and other contributing authors) -# -# 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 <http://www.gnu.org/licenses/>. -# -# SPDX-License-Identifier: AGPL3.0-or-later -# -# Testcase for gnunet-peerinfo - -import os -import re -import subprocess -import sys -import shutil -import time - - -class pexpect(object): - def __init__(self): - super(pexpect, self).__init__() - - def spawn(self, stdin, arglist, *pargs, **kwargs): - env = kwargs.pop('env', None) - if env is None: - env = os.environ.copy() - # This messes up some testcases, disable log redirection - env.pop('GNUNET_FORCE_LOGFILE', None) - self.proc = subprocess.Popen(arglist, *pargs, env=env, **kwargs) - if self.proc is None: - print("Failed to spawn a process {0}".format(arglist)) - sys.exit(1) - if stdin is not None: - self.stdo, self.stde = self.proc.communicate(stdin) - else: - self.stdo, self.stde = self.proc.communicate() - return self.proc - - def expect(self, s, r, flags=0): - stream = self.stdo if s == 'stdout' else self.stde - if isinstance(r, str): - if r == "EOF": - if len(stream) == 0: - return True - else: - print( - "Failed to find `{1}' in {0}, which is `{2}' ({3})". - format(s, r, stream, len(stream)) - ) - sys.exit(2) - raise ValueError( - "Argument `r' should be an instance of re.RegexObject or a special string, but is `{0}'" - .format(r) - ) - m = r.search(stream, flags) - if not m: - print( - "Failed to find `{1}' in {0}, which is is `{2}'".format( - s, r.pattern, stream - ) - ) - sys.exit(2) - stream = stream[m.end():] - if s == 'stdout': - self.stdo = stream - else: - self.stde = stream - return m - - def read(self, s, size=-1): - stream = self.stdo if s == 'stdout' else self.stde - result = "" - if size < 0: - result = stream - new_stream = "" - else: - result = stream[0:size] - new_stream = stream[size:] - if s == 'stdout': - self.stdo = new_stream - else: - self.stde = new_stream - return result diff --git a/src/integration-tests/gnunet_testing.py.in b/src/integration-tests/gnunet_testing.py.in @@ -1,381 +0,0 @@ -#!@PYTHONEXE@ -# This file is part of GNUnet. -# (C) 2010, 2017, 2018 Christian Grothoff (and other contributing authors) -# -# 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 <http://www.gnu.org/licenses/>. -# -# SPDX-License-Identifier: AGPL3.0-or-later -# -# Functions for integration testing - -import os -import subprocess -import sys -import shutil -import time -from gnunet_pyexpect import pexpect -import logging - -logger = logging.getLogger() -handler = logging.StreamHandler() -formatter = logging.Formatter( - '%(asctime)s %(name)-12s %(levelname)-8s %(message)s' -) -handler.setFormatter(formatter) -logger.addHandler(handler) -logger.setLevel(logging.DEBUG) - - -class Check(object): - def __init__(self, test): - self.fulfilled = False - self.conditions = list() - self.test = test - - def add(self, condition): - self.conditions.append(condition) - - def run(self): - fulfilled = True - pos = 0 - neg = 0 - for c in self.conditions: - if (False == c.check()): - fulfilled = False - neg += 1 - else: - pos += 1 - return fulfilled - - def run_blocking(self, timeout, pos_cont, neg_cont): - execs = 0 - res = False - while ((False == res) and (execs < timeout)): - res = self.run() - time.sleep(1) - execs += 1 - if ((False == res) and (execs >= timeout)): - logger.debug('Check had timeout after %s seconds', str(timeout)) - neg_cont(self) - elif ((False == res) and (execs < timeout)): - if (None != neg_cont): - neg_cont(self) - else: - if (None != pos_cont): - pos_cont(self) - return res - - def run_once(self, pos_cont, neg_cont): - execs = 0 - res = False - res = self.run() - if ((res == False) and (neg_cont != None)): - neg_cont(self) - if ((res == True) and (pos_cont != None)): - pos_cont(self) - return res - - def evaluate(self, failed_only): - pos = 0 - neg = 0 - for c in self.conditions: - if (False == c.evaluate(failed_only)): - neg += 1 - else: - pos += 1 - logger.debug( - '%s out of %s conditions fulfilled', str(pos), str(pos + neg) - ) - return self.fulfilled - - def reset(self): - self.fulfilled = False - for c in self.conditions: - c.fulfilled = False - - -class Condition(object): - def __init__(self): - self.fulfilled = False - self.type = 'generic' - - def __init__(self, type): - self.fulfilled = False - self.type = type - - def check(self): - return False - - def evaluate(self, failed_only): - if ((self.fulfilled == False) and (failed_only == True)): - logger.debug( - '%s condition for was %s', str(self.type), str(self.fulfilled) - ) - elif (failed_only == False): - logger.debug( - '%s condition for was %s', str(self.type), str(self.fulfilled) - ) - return self.fulfilled - - -class FileExistCondition(Condition): - def __init__(self, file): - self.fulfilled = False - self.type = 'file' - self.file = file - - def check(self): - if (self.fulfilled == False): - res = os.path.isfile(self.file) - if (res == True): - self.fulfilled = True - return True - else: - return False - else: - return True - - def evaluate(self, failed_only): - if ((self.fulfilled == False) and (failed_only == True)): - logger.debug( - '%s confition for file %s was %s', str(self.type), self.file, - str(self.fulfilled) - ) - elif (failed_only == False): - logger.debug( - '%s confition for file %s was %s', str(self.type), self.file, - str(self.fulfilled) - ) - return self.fulfilled - - -class StatisticsCondition(Condition): - def __init__(self, peer, subsystem, name, value): - self.fulfilled = False - self.type = 'statistics' - self.peer = peer - self.subsystem = subsystem - self.name = name - self.value = str(value) - self.result = -1 - - def check(self): - if (self.fulfilled == False): - self.result = self.peer.get_statistics_value( - self.subsystem, self.name - ) - if (self.result == self.value): - self.fulfilled = True - return True - else: - return False - else: - return True - - def evaluate(self, failed_only): - if (self.fulfilled == False): - fail = " FAIL!" - op = " != " - else: - fail = "" - op = " == " - if (((self.fulfilled == False) and (failed_only == True)) - or (failed_only == False)): - logger.debug( - '%s %s condition in subsystem %s: %s: (expected/real value) %s %s %s %s', - self.peer.id[:4].decode("utf-8"), self.peer.cfg, - self.subsystem.ljust(12), self.name.ljust(30), self.value, op, - self.result, fail - ) - return self.fulfilled - - -# Specify two statistic values and check if they are equal -class EqualStatisticsCondition(Condition): - def __init__(self, peer, subsystem, name, peer2, subsystem2, name2): - self.fulfilled = False - self.type = 'equalstatistics' - self.peer = peer - self.subsystem = subsystem - self.name = name - self.result = -1 - self.peer2 = peer2 - self.subsystem2 = subsystem2 - self.name2 = name2 - self.result2 = -1 - - def check(self): - if (self.fulfilled == False): - self.result = self.peer.get_statistics_value( - self.subsystem, self.name - ) - self.result2 = self.peer2.get_statistics_value( - self.subsystem2, self.name2 - ) - if (self.result == self.result2): - self.fulfilled = True - return True - else: - return False - else: - return True - - def evaluate(self, failed_only): - if (((self.fulfilled == False) and (failed_only == True)) - or (failed_only == False)): - logger.debug( - '%s %s %s == %s %s %s %s %s', self.peer.id[:4], - self.subsystem.ljust(12), self.name.ljust(30), self.result, - self.peer2.id[:4], self.subsystem2.ljust(12), - self.name2.ljust(30), self.result2 - ) - return self.fulfilled - - -class Test(object): - def __init__(self, testname, verbose): - self.peers = list() - self.verbose = verbose - self.name = testname - srcdir = "../.." - gnunet_pyexpect_dir = os.path.join(srcdir, "contrib/scripts") - if gnunet_pyexpect_dir not in sys.path: - sys.path.append(gnunet_pyexpect_dir) - self.gnunetarm = '' - self.gnunetstatistics = '' - if os.name == 'posix': - self.gnunetarm = 'gnunet-arm' - self.gnunetstatistics = 'gnunet-statistics' - self.gnunetpeerinfo = 'gnunet-peerinfo' - elif os.name == 'nt': - self.gnunetarm = 'gnunet-arm.exe' - self.gnunetstatistics = 'gnunet-statistics.exe' - self.gnunetpeerinfo = 'gnunet-peerinfo.exe' - if os.name == "nt": - shutil.rmtree(os.path.join(os.getenv("TEMP"), testname), True) - else: - shutil.rmtree("/tmp/" + testname, True) - - def add_peer(self, peer): - self.peers.append(peer) - - def p(self, msg): - if (self.verbose == True): - print(msg) - - -class Peer(object): - def __init__(self, test, cfg_file): - if (False == os.path.isfile(cfg_file)): - # print(("Peer cfg " + cfg_file + ": FILE NOT FOUND")) - logger.debug('Peer cfg %s : FILE NOT FOUND', cfg_file) - self.id = "<NaN>" - self.test = test - self.started = False - self.cfg = cfg_file - - def __del__(self): - if (self.started == True): - # print('ERROR! Peer using cfg ' + self.cfg + ' was not stopped') - logger.debug('ERROR! Peer using cfg %s was not stopped', self.cfg) - ret = self.stop() - if (False == ret): - # print('ERROR! Peer using cfg ' + - # self.cfg + - # ' could not be stopped') - logger.debug( - 'ERROR! Peer using cfg %s could not be stopped', self.cfg - ) - self.started = False - return ret - else: - return False - - def start(self): - os.unsetenv("XDG_CONFIG_HOME") - os.unsetenv("XDG_DATA_HOME") - os.unsetenv("XDG_CACHE_HOME") - self.test.p("Starting peer using cfg " + self.cfg) - try: - server = subprocess.Popen([ - self.test.gnunetarm, '-sq', '-c', self.cfg - ]) - server.communicate() - except OSError: - # print("Can not start peer") - logger.debug('Can not start peer') - self.started = False - return False - self.started = True - test = '' - try: - server = pexpect() - server.spawn( - None, [self.test.gnunetpeerinfo, '-c', self.cfg, '-s'], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT - ) - test = server.read("stdout", 1024) - except OSError: - # print("Can not get peer identity") - logger.debug('Can not get peer identity') - test = (test.split(b'`')[1]) - self.id = test.split(b'\'')[0] - return True - - def stop(self): - if (self.started == False): - return False - self.test.p("Stopping peer using cfg " + self.cfg) - try: - server = subprocess.Popen([ - self.test.gnunetarm, '-eq', '-c', self.cfg - ]) - server.communicate() - except OSError: - # print("Can not stop peer") - logger.debug('Can not stop peer') - return False - self.started = False - return True - - def get_statistics_value(self, subsystem, name): - server = pexpect() - server.spawn( - None, [ - self.test.gnunetstatistics, '-c', self.cfg, '-q', '-n', name, - '-s', subsystem - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT - ) - # server.expect ("stdout", re.compile (r"")) - test = server.read("stdout", 10240) - tests = test.partition(b'\n') - # On W32 GNUnet outputs with \r\n, rather than \n - if os.name == 'nt' and tests[1] == b'\n' and tests[0][-1] == b'\r': - tests = (tests[0][:-1], tests[1], tests[2]) - tests = tests[0] - result = tests.decode("utf-8").strip() - logger.debug( - 'running gnunet-statistics %s for %s "/" %s yields %s', self.cfg, - name, subsystem, result - ) - if (result.isdigit() == True): - return result - else: - logger.debug( - 'Invalid statistics value: %s is not a number!', result - ) - return -1 diff --git a/src/integration-tests/hostkeys/c_bootstrap_server b/src/integration-tests/hostkeys/c_bootstrap_server @@ -1 +0,0 @@ -«´\{€ìº–„âÒq@AP­³­”I$Õ1Šrî˜ -\ No newline at end of file diff --git a/src/integration-tests/hostkeys/c_nat_client b/src/integration-tests/hostkeys/c_nat_client @@ -1 +0,0 @@ -äÅ»ªP yÑûc½q‰®j[U1úúÑÕГæ¿aŽl -\ No newline at end of file diff --git a/src/integration-tests/hostkeys/c_no_nat_client b/src/integration-tests/hostkeys/c_no_nat_client @@ -1 +0,0 @@ -;ÇÒå‰ ÜÅhßVCji¾•ŽeÙ?œ€se^-W¹t -\ No newline at end of file diff --git a/src/integration-tests/hostkeys/c_no_nat_client_2 b/src/integration-tests/hostkeys/c_no_nat_client_2 @@ -1 +0,0 @@ -Ĥ×O7†y`öظ‚ø:ŸÌŠá1´RWFtÏÉpÇ -\ No newline at end of file diff --git a/src/integration-tests/test_integration_bootstrap_and_connect.py.in b/src/integration-tests/test_integration_bootstrap_and_connect.py.in @@ -1,212 +0,0 @@ -#!@PYTHONEXE@ -# This file is part of GNUnet. -# (C) 2010, 2018 Christian Grothoff (and other contributing authors) -# -# 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 <http://www.gnu.org/licenses/>. -# -# SPDX-License-Identifier: AGPL3.0-or-later -# -# - -import signal -import sys -import os -import subprocess -import re -import shutil -import time -from gnunet_testing import Peer -from gnunet_testing import Test -from gnunet_testing import Check -from gnunet_testing import Condition -from gnunet_testing import * - -# -# This test tests if a fresh peer bootstraps from a hostlist server and then -# successfully connects to the server -# -# Conditions for successful exit: -# Both peers have 1 connected peer in transport, core, topology, fs - -# -# This test tests if a fresh peer bootstraps from a hostlist server and then -# successfully connects to the server -# -# Conditions for successful exit: -# Both peers have 1 connected peer in transport, core, topology, fs - -# definitions - -testname = "test_integration_bootstrap_and_connect" -verbose = False -check_timeout = 180 - -if os.name == "nt": - tmp = os.getenv("TEMP") - signals = [signal.SIGTERM, signal.SIGINT] -else: - tmp = "/tmp" - signals = [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT] - - -def cleanup_onerror(function, path, excinfo): - import stat - if not os.path.exists(path): - pass - elif not os.access(path, os.W_OK): - # Is the error an access error ? - os.chmod(path, stat.S_IWUSR) - function(path) - else: - raise - - -def cleanup(): - retries = 10 - path = os.path.join(tmp, "c_bootstrap_server") - test.p("Removing " + path) - while ((os.path.exists(path)) and (retries > 0)): - shutil.rmtree((path), False, cleanup_onerror) - time.sleep(1) - retries -= 1 - if (os.path.exists(path)): - test.p("Failed to remove " + path) - - retries = 10 - path = os.path.join(tmp, "c_no_nat_client") - test.p("Removing " + path) - while ((os.path.exists(path)) and (retries > 0)): - shutil.rmtree((path), False, cleanup_onerror) - time.sleep(1) - retries -= 1 - if (os.path.exists(path)): - test.p("Failed to remove " + path) - - -def success_cont(check): - global success - success = True - print('Peers connected successfully') - - -def fail_cont(check): - global success - success = False - print('Peers did not connect') - check.evaluate(True) - - -def check(): - check = Check(test) - check.add(StatisticsCondition(client, 'transport', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'core', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'topology', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'dht', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'fs', '# peers connected', 1)) - - check.add(StatisticsCondition(server, 'transport', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'core', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'topology', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'dht', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'fs', '# peers connected', 1)) - - check.run_blocking(check_timeout, success_cont, fail_cont) - - -# -# Test execution -# - - -def SigHandler(signum=None, frame=None): - global success - global server - global client - - print('Test was aborted!') - if (None != server): - server.stop() - if (None != client): - client.stop() - cleanup() - sys.exit(success) - - -def run(): - global success - global test - global server - global client - - server = None - client = None - success = False - - for sig in signals: - signal.signal(sig, SigHandler) - - test = Test('test_integration_bootstrap_and_connect.py', verbose) - cleanup() - - server = Peer(test, './confs/c_bootstrap_server.conf') - client = Peer(test, './confs/c_no_nat_client.conf') - - if (True != server.start()): - print('Failed to start server') - if (None != server): - server.stop() - if (None != server): - client.stop() - cleanup() - sys.exit(success) - - # Give the server time to start - time.sleep(5) - - if (True != client.start()): - print('Failed to start client') - if (None != server): - server.stop() - if (None != server): - client.stop() - cleanup() - sys.exit(success) - - if ((client.started == True) and (server.started == True)): - test.p('Peers started, running check') - time.sleep(5) - check() - server.stop() - client.stop() - - cleanup() - - if (success == False): - print('Test failed') - return False - else: - return True - - -try: - run() -except (KeyboardInterrupt, SystemExit): - print('Test interrupted') - server.stop() - client.stop() - cleanup() -if (success == False): - sys.exit(1) -else: - sys.exit(0) diff --git a/src/integration-tests/test_integration_clique.py.in b/src/integration-tests/test_integration_clique.py.in @@ -1,236 +0,0 @@ -#!@PYTHONEXE@ -# This file is part of GNUnet. -# (C) 2010, 2018 Christian Grothoff (and other contributing authors) -# -# 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 <http://www.gnu.org/licenses/>. -# -# SPDX-License-Identifier: AGPL3.0-or-later -# -# -# -# This test starts 3 peers (nated, server, no nat)and expects bootstrap -# and a connected clique -# -# Conditions for successful exit: -# Both peers have 2 connected peers in transport, core, topology, fs and dht - -import sys -import signal -import os -import subprocess -import re -import shutil -import time -from gnunet_testing import Peer -from gnunet_testing import Test -from gnunet_testing import Check -from gnunet_testing import Condition -from gnunet_testing import * - -if os.name == "nt": - tmp = os.getenv("TEMP") -else: - tmp = "/tmp" - -# definitions - -testname = "test_integration_clique" -verbose = True -check_timeout = 180 - - -def cleanup_onerror(function, path, excinfo): - import stat - if not os.path.exists(path): - pass - elif not os.access(path, os.W_OK): - # Is the error an access error ? - os.chmod(path, stat.S_IWUSR) - function(path) - else: - raise - - -def cleanup(): - retries = 10 - path = os.path.join(tmp, "c_bootstrap_server") - test.p("Removing " + path) - while ((os.path.exists(path)) and (retries > 0)): - shutil.rmtree((path), False, cleanup_onerror) - time.sleep(1) - retries -= 1 - if (os.path.exists(path)): - test.p("Failed to remove " + path) - retries = 10 - path = os.path.join(tmp, "c_no_nat_client") - test.p("Removing " + path) - while ((os.path.exists(path)) and (retries > 0)): - shutil.rmtree((path), False, cleanup_onerror) - time.sleep(1) - retries -= 1 - if (os.path.exists(path)): - test.p("Failed to remove " + path) - retries = 10 - path = os.path.join(tmp, "c_nat_client") - test.p("Removing " + path) - while ((os.path.exists(path)) and (retries > 0)): - shutil.rmtree((path), False, cleanup_onerror) - time.sleep(1) - retries -= 1 - if (os.path.exists(path)): - test.p("Failed to remove " + path) - - -def success_cont(check): - global success - success = True - print('Connected clique successfully') - - -def fail_cont(check): - global success - success = False - check.evaluate(True) - print('Failed to connect clique') - - -def check_connect(): - check = Check(test) - check.add(StatisticsCondition(client, 'transport', '# peers connected', 2)) - check.add(StatisticsCondition(client, 'core', '# peers connected', 2)) - check.add(StatisticsCondition(client, 'topology', '# peers connected', 2)) - check.add(StatisticsCondition(client, 'dht', '# peers connected', 2)) - check.add(StatisticsCondition(client, 'fs', '# peers connected', 2)) - - check.add( - StatisticsCondition(client_nat, 'transport', '# peers connected', 2) - ) - check.add(StatisticsCondition(client_nat, 'core', '# peers connected', 2)) - check.add( - StatisticsCondition(client_nat, 'topology', '# peers connected', 2) - ) - check.add(StatisticsCondition(client_nat, 'dht', '# peers connected', 2)) - check.add(StatisticsCondition(client_nat, 'fs', '# peers connected', 2)) - - check.add(StatisticsCondition(server, 'transport', '# peers connected', 2)) - check.add(StatisticsCondition(server, 'core', '# peers connected', 2)) - check.add(StatisticsCondition(server, 'topology', '# peers connected', 2)) - check.add(StatisticsCondition(server, 'dht', '# peers connected', 2)) - check.add(StatisticsCondition(server, 'fs', '# peers connected', 2)) - - check.run_blocking(check_timeout, success_cont, fail_cont) - - -# -# Test execution -# - - -def SigHandler(signum=None, frame=None): - global success - global server - global client - global client_nat - - print('Test was aborted!') - if (None != server): - server.stop() - if (None != client): - client.stop() - if (None != client_nat): - client_nat.stop() - cleanup() - sys.exit(success) - - -def run(): - global success - global test - global server - global client - global client_nat - - success = False - server = None - client = None - client_nat = None - test = Test('test_integration_clique', verbose) - cleanup() - - server = Peer(test, './confs/c_bootstrap_server.conf') - if (True != server.start()): - print('Failed to start server') - if (None != server): - server.stop() - cleanup() - sys.exit(success) - - # Server has to settle down - time.sleep(5) - - client = Peer(test, './confs/c_no_nat_client.conf') - if (True != client.start()): - print('Failed to start client') - if (None != server): - server.stop() - if (None != client): - client.stop() - cleanup() - sys.exit(success) - - # Server has to settle down - time.sleep(5) - - client_nat = Peer(test, './confs/c_nat_client.conf') - if (True != client_nat.start()): - print('Failed to start client_nat') - if (None != server): - server.stop() - if (None != client): - client.stop() - if (None != client_nat): - client_nat.stop() - cleanup() - sys.exit(success) - - if ((client.started == True) and (client_nat.started == True) - and (server.started == True)): - test.p('Peers started, running check') - check_connect() - - server.stop() - client.stop() - client_nat.stop() - - cleanup() - - if (success == False): - print('Test failed') - return False - else: - return True - - -try: - run() -except (KeyboardInterrupt, SystemExit): - print('Test interrupted') - server.stop() - client.stop() - client_nat.stop() - cleanup() -if (success == False): - sys.exit(1) -else: - sys.exit(0) diff --git a/src/integration-tests/test_integration_disconnect.py.in b/src/integration-tests/test_integration_disconnect.py.in @@ -1,215 +0,0 @@ -#!@PYTHONEXE@ -# This file is part of GNUnet. -# (C) 2010, 2017 Christian Grothoff (and other contributing authors) -# -# 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 <http://www.gnu.org/licenses/>. -# -# SPDX-License-Identifier: AGPL3.0-or-later -# -# - -import sys -import signal -import os -import subprocess -import re -import shutil -import time -from gnunet_testing import Peer -from gnunet_testing import Test -from gnunet_testing import Check -from gnunet_testing import Condition -from gnunet_testing import * - -# -# This test tests if a fresh peer bootstraps from a hostlist server and then -# successfully connects to the server. When both peers are connected -# in transport, core, topology, fs, the server is shutdown -# -# Conditions for successful exit: -# Client peer has 0 connected peer in transport, core, topology, dht, fs - -#definitions - -testname = "test_integration_disconnect" -verbose = True -check_timeout = 180 - -if os.name == "nt": - tmp = os.getenv("TEMP") - signals = [signal.SIGTERM, signal.SIGINT] -else: - tmp = "/tmp" - signals = [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT] - - -def cleanup_onerror(function, path, excinfo): - import stat - if not os.path.exists(path): - pass - elif not os.access(path, os.W_OK): - # Is the error an access error ? - os.chmod(path, stat.S_IWUSR) - function(path) - else: - raise - - -def cleanup(): - shutil.rmtree( - os.path.join(tmp, "c_bootstrap_server"), False, cleanup_onerror - ) - shutil.rmtree(os.path.join(tmp, "c_no_nat_client"), False, cleanup_onerror) - - -def success_disconnect_cont(check): - print('Peers disconnected successfully') - global success - success = True - - -def fail_disconnect_cont(check): - global success - success = False - print('Peers failed to disconnect') - check.evaluate(True) - - -def check_disconnect(): - test.p('Shutting down bootstrap server') - server.stop() - check = Check(test) - check.add(StatisticsCondition(client, 'transport', '# peers connected', 0)) - check.add(StatisticsCondition(client, 'core', '# peers connected', 0)) - check.add(StatisticsCondition(client, 'topology', '# peers connected', 0)) - check.add(StatisticsCondition(client, 'dht', '# peers connected', 0)) - check.add(StatisticsCondition(client, 'fs', '# peers connected', 0)) - check.run_blocking( - check_timeout, success_disconnect_cont, fail_disconnect_cont - ) - - -def success_connect_cont(check): - print('Peers connected successfully') - check_disconnect() - - -def fail_connect_cont(check): - global success - success = False - print('Peers failed to connected!') - check.evaluate(True) - - -def check_connect(): - check = Check(test) - check.add(StatisticsCondition(server, 'transport', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'core', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'topology', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'dht', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'fs', '# peers connected', 1)) - - check.add(StatisticsCondition(client, 'transport', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'core', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'topology', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'dht', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'fs', '# peers connected', 1)) - - check.run_blocking(check_timeout, success_connect_cont, fail_connect_cont) - - -# -# Test execution -# - - -def SigHandler(signum=None, frame=None): - global success - global server - global client - - print('Test was aborted!') - if (None != server): - server.stop() - if (None != client): - client.stop() - cleanup() - sys.exit(success) - - -def run(): - global success - global test - global server - global client - - server = None - client = None - success = False - - for sig in signals: - signal.signal(sig, SigHandler) - - test = Test('test_integration_bootstrap_and_connect.py', verbose) - cleanup() - - server = Peer(test, './confs/c_bootstrap_server.conf') - client = Peer(test, './confs/c_no_nat_client.conf') - - if (True != server.start()): - print('Failed to start server') - if (None != server): - server.stop() - cleanup() - sys.exit(success) - - # Give the server time to start - time.sleep(5) - - if (True != client.start()): - print('Failed to start client') - if (None != server): - server.stop() - if (None != client): - client.stop() - cleanup() - sys.exit(success) - - if ((client.started == True) and (server.started == True)): - test.p('Peers started, running check') - time.sleep(5) - check_connect() - server.stop() - client.stop() - - cleanup() - - if (success == False): - print('Test failed') - return False - else: - return True - - -try: - run() -except (KeyboardInterrupt, SystemExit): - print('Test interrupted') - server.stop() - client.stop() - cleanup() -if (success == False): - sys.exit(1) -else: - sys.exit(0) diff --git a/src/integration-tests/test_integration_disconnect_nat.py.in b/src/integration-tests/test_integration_disconnect_nat.py.in @@ -1,223 +0,0 @@ -#!@PYTHONEXE@ -# This file is part of GNUnet. -# (C) 2010, 2018 Christian Grothoff (and other contributing authors) -# -# 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 <http://www.gnu.org/licenses/>. -# -# SPDX-License-Identifier: AGPL3.0-or-later -# -# - -import sys -import signal -import os -import subprocess -import re -import shutil -import time -from gnunet_testing import Peer -from gnunet_testing import Test -from gnunet_testing import Check -from gnunet_testing import Condition -from gnunet_testing import * - -# -# This test tests if a fresh peer bootstraps from a hostlist server and then -# successfully connects to the server. When both peers are connected -# in transport, core, topology, fs, the server is shutdown -# -# Conditions for successful exit: -# Client peer has 0 connected peer in transport, core, topology, dht, fs - -# definitions - -testname = "test_integration_disconnect" -verbose = True -check_timeout = 180 - -if os.name == "nt": - tmp = os.getenv("TEMP") - signals = [signal.SIGTERM, signal.SIGINT] -else: - tmp = "/tmp" - signals = [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT] - - -def cleanup_onerror(function, path, excinfo): - import stat - if not os.path.exists(path): - pass - elif not os.access(path, os.W_OK): - # Is the error an access error ? - os.chmod(path, stat.S_IWUSR) - function(path) - else: - raise - - -def cleanup(): - shutil.rmtree( - os.path.join(tmp, "c_bootstrap_server"), False, cleanup_onerror - ) - shutil.rmtree(os.path.join(tmp, "c_nat_client"), False, cleanup_onerror) - - -def success_disconnect_cont(check): - print('Peers disconnected successfully') - global success - success = True - - -def fail_disconnect_cont(check): - global success - success = False - print('Peers failed to disconnect') - check.evaluate(True) - - -def check_disconnect(): - global server - global nat_client - test.p('Shutting down nat client') - nat_client.stop() - check = Check(test) - check.add(StatisticsCondition(server, 'transport', '# peers connected', 0)) - check.add(StatisticsCondition(server, 'core', '# peers connected', 0)) - check.add(StatisticsCondition(server, 'topology', '# peers connected', 0)) - check.add(StatisticsCondition(server, 'dht', '# peers connected', 0)) - check.add(StatisticsCondition(server, 'fs', '# peers connected', 0)) - check.run_blocking( - check_timeout, success_disconnect_cont, fail_disconnect_cont - ) - - -def success_connect_cont(check): - print('Peers connected successfully') - check_disconnect() - - -def fail_connect_cont(check): - global success - success = False - print('Peers failed to connected!') - check.evaluate(True) - - -def check_connect(): - global server - global nat_client - check = Check(test) - check.add( - StatisticsCondition(nat_client, 'transport', '# peers connected', 1) - ) - check.add(StatisticsCondition(nat_client, 'core', '# peers connected', 1)) - check.add( - StatisticsCondition(nat_client, 'topology', '# peers connected', 1) - ) - check.add(StatisticsCondition(nat_client, 'dht', '# peers connected', 1)) - check.add(StatisticsCondition(nat_client, 'fs', '# peers connected', 1)) - - check.add(StatisticsCondition(server, 'transport', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'core', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'topology', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'dht', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'fs', '# peers connected', 1)) - - check.run_blocking(check_timeout, success_connect_cont, fail_connect_cont) - - -# -# Test execution -# - - -def SigHandler(signum=None, frame=None): - global success - global server - global nat_client - - print('Test was aborted!') - if (None != server): - server.stop() - if (None != nat_client): - nat_client.stop() - cleanup() - sys.exit(success) - - -def run(): - global success - global test - global server - global nat_client - - server = None - nat_client = None - success = False - - for sig in signals: - signal.signal(sig, SigHandler) - - test = Test('test_integration_bootstrap_and_connect.py', verbose) - cleanup() - - server = Peer(test, './confs/c_bootstrap_server.conf') - nat_client = Peer(test, './confs/c_nat_client.conf') - - if (True != server.start()): - print('Failed to start server') - if (None != server): - server.stop() - cleanup() - sys.exit(success) - - # Give the server time to start - time.sleep(5) - - if (True != nat_client.start()): - print('Failed to start nat_client') - if (None != server): - server.stop() - if (None != nat_client): - nat_client.stop() - cleanup() - sys.exit(success) - - if ((nat_client.started == True) and (server.started == True)): - test.p('Peers started, running check') - time.sleep(5) - check_connect() - server.stop() - nat_client.stop() - - cleanup() - - if (success == False): - print('Test failed') - return False - else: - return True - - -try: - run() -except (KeyboardInterrupt, SystemExit): - print('Test interrupted') - server.stop() - nat_client.stop() - cleanup() -if (success == False): - sys.exit(1) -else: - sys.exit(0) diff --git a/src/integration-tests/test_integration_reconnect.py.in b/src/integration-tests/test_integration_reconnect.py.in @@ -1,237 +0,0 @@ -#!@PYTHONEXE@ -# This file is part of GNUnet. -# (C) 2010, 2017 Christian Grothoff (and other contributing authors) -# -# 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 <http://www.gnu.org/licenses/>. -# -# SPDX-License-Identifier: AGPL3.0-or-later -# -# - -import sys -import os -import subprocess -import re -import shutil -import time -import signal -from gnunet_testing import Peer -from gnunet_testing import Test -from gnunet_testing import Check -from gnunet_testing import Condition -from gnunet_testing import * - -# -# This test tests if a fresh peer bootstraps from a hostlist server and then -# successfully connects to the server. When both peers are connected -# in transport, core, topology, fs, botth peers are shutdown and restarted -# -# Conditions for successful exit: -# Both peers have 1 connected peer in transport, core, topology, fs after restart - -#definitions - -testname = "test_integration_restart" -verbose = True -check_timeout = 180 - -if os.name == "nt": - tmp = os.getenv("TEMP") - signals = [signal.SIGTERM, signal.SIGINT] -else: - tmp = "/tmp" - signals = [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT] - - -def cleanup_onerror(function, path, excinfo): - import stat - if not os.path.exists(path): - pass - elif not os.access(path, os.W_OK): - # Is the error an access error ? - os.chmod(path, stat.S_IWUSR) - function(path) - else: - raise - - -def cleanup(): - retries = 10 - path = os.path.join(tmp, "c_bootstrap_server") - test.p("Removing " + path) - while ((os.path.exists(path)) and (retries > 0)): - shutil.rmtree((path), False, cleanup_onerror) - time.sleep(1) - retries -= 1 - if (os.path.exists(path)): - test.p("Failed to remove " + path) - - retries = 10 - path = os.path.join(tmp, "c_no_nat_client") - test.p("Removing " + path) - while ((os.path.exists(path)) and (retries > 0)): - shutil.rmtree((path), False, cleanup_onerror) - time.sleep(1) - retries -= 1 - if (os.path.exists(path)): - test.p("Failed to remove " + path) - - -def success_restart_cont(check): - global success - print('Peers connected successfully after restart') - server.stop() - client.stop() - success = True - - -def fail_restart_cont(check): - global success - success = False - print('Peers failed to connect after restart') - check.evaluate(True) - - -def success_connect_cont(check): - print('Peers connected successfully') - server.stop() - client.stop() - - time.sleep(5) - - test.p('Restarting client & server') - server.start() - client.start() - - check = Check(test) - check.add(StatisticsCondition(client, 'transport', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'core', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'topology', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'fs', '# peers connected', 1)) - - check.add(StatisticsCondition(server, 'transport', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'core', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'topology', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'fs', '# peers connected', 1)) - - check.run_blocking(check_timeout, success_restart_cont, fail_restart_cont) - - -def fail_connect_cont(check): - global success - success = False - print('Peers failed to connect') - check.evaluate(True) - - -def check_connect(): - check = Check(test) - check.add(StatisticsCondition(client, 'transport', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'core', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'topology', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'fs', '# peers connected', 1)) - - check.add(StatisticsCondition(server, 'transport', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'core', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'topology', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'fs', '# peers connected', 1)) - - check.run_blocking(check_timeout, success_connect_cont, fail_connect_cont) - - -# -# Test execution -# - - -def SigHandler(signum=None, frame=None): - global success - global server - global client - - print('Test was aborted!') - if (None != server): - server.stop() - if (None != client): - client.stop() - cleanup() - sys.exit(success) - - -def run(): - global success - global test - global server - global client - - success = False - server = None - client = None - - for sig in signals: - signal.signal(sig, SigHandler) - - test = Test('test_integration_disconnect', verbose) - cleanup() - server = Peer(test, './confs/c_bootstrap_server.conf') - server.start() - - client = Peer(test, './confs/c_no_nat_client.conf') - client.start() - - if (True != server.start()): - print('Failed to start server') - if (None != server): - server.stop() - if (None != server): - client.stop() - cleanup() - sys.exit(success) - - # Give the server time to start - time.sleep(5) - - if (True != client.start()): - print('Failed to start client') - if (None != server): - server.stop() - if (None != server): - client.stop() - cleanup() - sys.exit(success) - - check_connect() - - server.stop() - client.stop() - cleanup() - - if (success == False): - print('Test failed') - return True - else: - return False - - -try: - run() -except (KeyboardInterrupt, SystemExit): - print('Test interrupted') - server.stop() - client.stop() - cleanup() -if (success == False): - sys.exit(1) -else: - sys.exit(0) diff --git a/src/integration-tests/test_integration_reconnect_nat.py.in b/src/integration-tests/test_integration_reconnect_nat.py.in @@ -1,237 +0,0 @@ -#!@PYTHONEXE@ -# This file is part of GNUnet. -# (C) 2010, 2018 Christian Grothoff (and other contributing authors) -# -# 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 <http://www.gnu.org/licenses/>. -# -# SPDX-License-Identifier: AGPL3.0-or-later -# -# - -import sys -import os -import subprocess -import re -import shutil -import time -import signal -from gnunet_testing import Peer -from gnunet_testing import Test -from gnunet_testing import Check -from gnunet_testing import Condition -from gnunet_testing import * - -# -# This test tests if a fresh peer bootstraps from a hostlist server and then -# successfully connects to the server. When both peers are connected -# in transport, core, topology, fs, botth peers are shutdown and restarted -# -# Conditions for successful exit: -# Both peers have 1 connected peer in transport, core, topology, fs after restart - -# definitions - -testname = "test_integration_restart" -verbose = True -check_timeout = 180 - -if os.name == "nt": - tmp = os.getenv("TEMP") - signals = [signal.SIGTERM, signal.SIGINT] -else: - tmp = "/tmp" - signals = [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT] - - -def cleanup_onerror(function, path, excinfo): - import stat - if not os.path.exists(path): - pass - elif not os.access(path, os.W_OK): - # Is the error an access error ? - os.chmod(path, stat.S_IWUSR) - function(path) - else: - raise - - -def cleanup(): - retries = 10 - path = os.path.join(tmp, "c_bootstrap_server") - test.p("Removing " + path) - while ((os.path.exists(path)) and (retries > 0)): - shutil.rmtree((path), False, cleanup_onerror) - time.sleep(1) - retries -= 1 - if (os.path.exists(path)): - test.p("Failed to remove " + path) - - retries = 10 - path = os.path.join(tmp, "c_nat_client") - test.p("Removing " + path) - while ((os.path.exists(path)) and (retries > 0)): - shutil.rmtree((path), False, cleanup_onerror) - time.sleep(1) - retries -= 1 - if (os.path.exists(path)): - test.p("Failed to remove " + path) - - -def success_restart_cont(check): - global success - print('Peers connected successfully after restart') - server.stop() - client.stop() - success = True - - -def fail_restart_cont(check): - global success - success = False - print('Peers failed to connect after restart') - check.evaluate(True) - - -def success_connect_cont(check): - print('Peers connected successfully') - server.stop() - client.stop() - - time.sleep(5) - - test.p('Restarting client & server') - server.start() - client.start() - - check = Check(test) - check.add(StatisticsCondition(client, 'transport', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'core', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'topology', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'fs', '# peers connected', 1)) - - check.add(StatisticsCondition(server, 'transport', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'core', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'topology', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'fs', '# peers connected', 1)) - - check.run_blocking(check_timeout, success_restart_cont, fail_restart_cont) - - -def fail_connect_cont(check): - global success - success = False - print('Peers failed to connect') - check.evaluate(True) - - -def check_connect(): - check = Check(test) - check.add(StatisticsCondition(client, 'transport', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'core', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'topology', '# peers connected', 1)) - check.add(StatisticsCondition(client, 'fs', '# peers connected', 1)) - - check.add(StatisticsCondition(server, 'transport', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'core', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'topology', '# peers connected', 1)) - check.add(StatisticsCondition(server, 'fs', '# peers connected', 1)) - - check.run_blocking(check_timeout, success_connect_cont, fail_connect_cont) - - -# -# Test execution -# - - -def SigHandler(signum=None, frame=None): - global success - global server - global client - - print('Test was aborted!') - if (None != server): - server.stop() - if (None != client): - client.stop() - cleanup() - sys.exit(success) - - -def run(): - global success - global test - global server - global client - - success = False - server = None - client = None - - for sig in signals: - signal.signal(sig, SigHandler) - - test = Test('test_integration_disconnect', verbose) - cleanup() - server = Peer(test, './confs/c_bootstrap_server.conf') - server.start() - - client = Peer(test, './confs/c_nat_client.conf') - client.start() - - if (True != server.start()): - print('Failed to start server') - if (None != server): - server.stop() - if (None != server): - client.stop() - cleanup() - sys.exit(success) - - # Give the server time to start - time.sleep(5) - - if (True != client.start()): - print('Failed to start client') - if (None != server): - server.stop() - if (None != server): - client.stop() - cleanup() - sys.exit(success) - - check_connect() - - server.stop() - client.stop() - cleanup() - - if (success == False): - print('Test failed') - return True - else: - return False - - -try: - run() -except (KeyboardInterrupt, SystemExit): - print('Test interrupted') - server.stop() - client.stop() - cleanup() -if (success == False): - sys.exit(1) -else: - sys.exit(0) diff --git a/src/testbed-logger/.gitignore b/src/testbed-logger/.gitignore @@ -1,2 +0,0 @@ -gnunet-service-testbed-logger -test_testbed_logger_api diff --git a/src/testbed-logger/Makefile.am b/src/testbed-logger/Makefile.am @@ -1,55 +0,0 @@ -# This Makefile.am is in the public domain -AM_CPPFLAGS = -I$(top_srcdir)/src/include - -if USE_COVERAGE - AM_CFLAGS = --coverage -O0 - XLIB = -lgcov -endif - -libexecdir= $(pkglibdir)/libexec/ - -pkgcfgdir= $(pkgdatadir)/config.d/ - -pkgcfg_DATA = \ - testbed-logger.conf - -libexec_PROGRAMS = \ - gnunet-service-testbed-logger - -gnunet_service_testbed_logger_SOURCES = \ - gnunet-service-testbed-logger.c -gnunet_service_testbed_logger_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la -gnunet_service_testbed_logger_LDFLAGS = \ - $(GN_LIBINTL) - -lib_LTLIBRARIES = \ - libgnunettestbedlogger.la - -libgnunettestbedlogger_la_SOURCES = \ - testbed_logger_api.c -libgnunettestbedlogger_la_LIBADD = $(XLIB) \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(LTLIBINTL) -libgnunettestbedlogger_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) \ - -version-info 0:0:0 - -check_PROGRAMS = \ - test_testbed_logger_api - -if ENABLE_TEST_RUN - AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; - TESTS = \ - test_testbed_logger_api -endif - -test_testbed_logger_api_SOURCES = \ - test_testbed_logger_api.c -test_testbed_logger_api_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - libgnunettestbedlogger.la - -EXTRA_DIST = \ - test_testbed_logger_api.conf diff --git a/src/testbed-logger/gnunet-service-testbed-logger.c b/src/testbed-logger/gnunet-service-testbed-logger.c @@ -1,236 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed-logger/gnunet-service-testbed-logger.c - * @brief service for collecting messages and writing to a file - * @author Sree Harsha Totakura - */ - -#include "platform.h" -#include "gnunet_util_lib.h" - -/** - * Generic logging shorthand - */ -#define LOG(type, ...) \ - GNUNET_log (type, __VA_ARGS__) - -/** - * Debug logging shorthand - */ -#define LOG_DEBUG(...) \ - LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) - -/** - * Handle for buffered writing. - */ -struct GNUNET_BIO_WriteHandle *bio; - -/** - * The number of connections we have - */ -static unsigned int nconn; - -/** - * Are we shutting down? - */ -static int in_shutdown; - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG messages - * - * @param cls client identification of the client - * @param msg the actual message - * @return #GNUNET_OK (they are all always OK) - */ -static int -check_log_msg (void *cls, - const struct GNUNET_MessageHeader *msg) -{ - return GNUNET_OK; -} - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG messages - * - * @param cls client identification of the client - * @param msg the actual message - */ -static void -handle_log_msg (void *cls, - const struct GNUNET_MessageHeader *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - uint16_t ms; - - ms = ntohs (msg->size) - sizeof(struct GNUNET_MessageHeader); - GNUNET_BIO_write (bio, - "testbed-logger-handle-log-msg", - &msg[1], - ms); - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Task to clean up and shutdown nicely - * - * @param cls NULL - */ -static void -shutdown_task (void *cls) -{ - in_shutdown = GNUNET_YES; - if (0 != nconn) - { - /* Delay shutdown if there are active connections */ - GNUNET_SCHEDULER_add_shutdown (&shutdown_task, - NULL); - return; - } - GNUNET_break (GNUNET_OK == - GNUNET_BIO_write_close (bio, NULL)); -} - - -/** - * Callback called when a client connects to the service. - * - * @param cls closure for the service - * @param c the new client that connected to the service - * @param mq the message queue used to send messages to the client - * @return @a c - */ -static void * -client_connect_cb (void *cls, - struct GNUNET_SERVICE_Client *c, - struct GNUNET_MQ_Handle *mq) -{ - /* FIXME: is this really what we want here? */ - GNUNET_SERVICE_client_persist (c); - nconn++; - return c; -} - - -/** - * Callback called when a client disconnected from the service - * - * @param cls closure for the service - * @param c the client that disconnected - * @param internal_cls should be equal to @a c - */ -static void -client_disconnect_cb (void *cls, - struct GNUNET_SERVICE_Client *c, - void *internal_cls) -{ - nconn--; - if (GNUNET_YES == in_shutdown) - GNUNET_SCHEDULER_shutdown (); - GNUNET_assert (c == internal_cls); -} - - -/** - * Testbed setup - * - * @param cls closure - * @param cfg configuration to use - * @param service the initialized service - */ -static void -logger_run (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_SERVICE_Handle *service) -{ - char *dir; - char *fn; - char *hname; - size_t hname_len; - pid_t pid; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, - "TESTBED-LOGGER", - "DIR", - &dir)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "TESTBED-LOGGER", - "DIR"); - GNUNET_SCHEDULER_shutdown (); - return; - } - pid = getpid (); - hname_len = GNUNET_OS_get_hostname_max_length (); - hname = GNUNET_malloc (hname_len); - if (0 != gethostname (hname, - hname_len)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Cannot get hostname. Exiting\n"); - GNUNET_free (hname); - GNUNET_free (dir); - GNUNET_SCHEDULER_shutdown (); - return; - } - GNUNET_asprintf (&fn, - "%s/%.*s_%jd.dat", - dir, - (int) hname_len, - hname, - (intmax_t) pid); - GNUNET_free (hname); - GNUNET_free (dir); - if (NULL == (bio = GNUNET_BIO_write_open_file (fn))) - { - GNUNET_free (fn); - GNUNET_SCHEDULER_shutdown (); - return; - } - GNUNET_free (fn); - GNUNET_SCHEDULER_add_shutdown (&shutdown_task, - NULL); - LOG_DEBUG ("TESTBED-LOGGER startup complete\n"); -} - - -/** - * Define "main" method using service macro. - */ -GNUNET_SERVICE_MAIN - ("testbed-logger", - GNUNET_SERVICE_OPTION_NONE, - &logger_run, - &client_connect_cb, - &client_disconnect_cb, - NULL, - GNUNET_MQ_hd_var_size (log_msg, - GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG, - struct GNUNET_MessageHeader, - NULL), - GNUNET_MQ_handler_end ()); - - -/* end of gnunet-service-testbed-logger.c */ diff --git a/src/testbed-logger/meson.build b/src/testbed-logger/meson.build @@ -1,34 +0,0 @@ -libgnunettestbedlogger_src = ['testbed_logger_api.c'] - -tdata = configuration_data() -tdata.merge_from(cdata) -tdata.set_quoted('prefix', get_option('prefix')) - -configure_file(input : 'testbed-logger.conf.in', - output : 'testbed-logger.conf', - configuration : tdata, - install: true, - install_dir: pkgcfgdir) - - -if get_option('monolith') - subdir_done() -endif - -libgnunettestbedlogger = library('gnunettestbedlogger', - libgnunettestbedlogger_src, - soversion: '0', - version: '0.0.0', - dependencies: [libgnunetutil_dep], - include_directories: [incdir, configuration_inc], - install: true, - install_dir: get_option('libdir')) -libgnunettestbedlogger_dep = declare_dependency(link_with : libgnunettestbedlogger) - - -executable ('gnunet-service-testbed-logger', - ['gnunet-service-testbed-logger.c'], - dependencies: [libgnunetutil_dep], - include_directories: [incdir, configuration_inc], - install:true, - install_dir: get_option('libdir')/'gnunet'/'libexec') diff --git a/src/testbed-logger/test_testbed_logger_api.c b/src/testbed-logger/test_testbed_logger_api.c @@ -1,277 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file testbed-logger/test_testbed_logger_api.c - * @brief testcases for the testbed logger api - * @author Sree Harsha Totakura - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testing_lib.h" -#include "gnunet_testbed_logger_service.h" - -/** - * Generic logging shortcut - */ -#define LOG(kind, ...) \ - GNUNET_log (kind, __VA_ARGS__) - -/** - * Relative time seconds shorthand - */ -#define TIME_REL_SECS(sec) \ - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) - -/** - * Opaque handle for the logging service - */ -static struct GNUNET_TESTBED_LOGGER_Handle *h; - -static struct GNUNET_TESTING_Peer *peer; - -static char *search_dir; - -/** - * Abort task identifier - */ -static struct GNUNET_SCHEDULER_Task *abort_task; -static struct GNUNET_SCHEDULER_Task *write_task; - -static int result; - -#define CANCEL_TASK(task) do { \ - if (NULL != task) \ - { \ - GNUNET_SCHEDULER_cancel (task); \ - task = NULL; \ - } \ -} while (0) - -/** - * shortcut to exit during failure - */ -#define FAIL_TEST(cond, ret) do { \ - if (! (cond)) { \ - GNUNET_break (0); \ - CANCEL_TASK (abort_task); \ - abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); \ - ret; \ - } \ -} while (0) - - -/** - * Shutdown nicely - * - * @param cls NULL - * @param tc the task context - */ -static void -shutdown_now () -{ - CANCEL_TASK (abort_task); - CANCEL_TASK (write_task); - GNUNET_free (search_dir); - if (NULL != h) - GNUNET_TESTBED_LOGGER_disconnect (h); - GNUNET_SCHEDULER_shutdown (); -} - - -static void -do_abort (void *cls) -{ - LOG (GNUNET_ERROR_TYPE_WARNING, - "Aborting\n"); - abort_task = NULL; - shutdown_now (); -} - - -#define BSIZE 1024 - - -/** - * Function called to iterate over a directory. - * - * @param cls closure - * @param filename complete filename (absolute path) - * @return #GNUNET_OK to continue to iterate, - * #GNUNET_NO to stop iteration with no error, - * #GNUNET_SYSERR to abort iteration with error! - */ -static int -iterator_cb (void *cls, - const char *filename) -{ - const char *fn; - size_t len; - uint64_t fs; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Iterator sees file %s\n", - filename); - len = strlen (filename); - fn = filename + len; - if (0 != strcasecmp (".dat", fn - 4)) - return GNUNET_OK; - if (GNUNET_OK != - GNUNET_DISK_file_size (filename, - &fs, - GNUNET_NO, - GNUNET_YES)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Failed to obtain file size for file %s\n", - filename); - return GNUNET_SYSERR; - } - if ((BSIZE * 2) != fs) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Unexpected file size for file %s\n", - filename); - /* The file size should be equal to what we - have written */ - return GNUNET_SYSERR; - } - result = GNUNET_OK; - return GNUNET_OK; -} - - -/** - * Functions of this type are called to notify a successful - * transmission of the message to the logger service - * - * @param cls the closure given to GNUNET_TESTBED_LOGGER_send() - * @param size the amount of data sent - */ -static void -flush_comp (void *cls, - size_t size) -{ - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Flush running\n"); - FAIL_TEST (&write_task == cls, - return ); - FAIL_TEST ((BSIZE * 2) == size, - return ); - FAIL_TEST (GNUNET_OK == - GNUNET_TESTING_peer_stop (peer), - return ); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Peer stopped, scanning %s\n", - search_dir); - FAIL_TEST (GNUNET_SYSERR != - GNUNET_DISK_directory_scan (search_dir, - &iterator_cb, - NULL), - return ); - shutdown_now (); -} - - -static void -do_write (void *cls) -{ - static int i; - char buf[BSIZE]; - - write_task = NULL; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Write task running\n"); - if (0 == i) - write_task = GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (1), - &do_write, - NULL); - (void) memset (buf, i, BSIZE); - GNUNET_TESTBED_LOGGER_write (h, - buf, - BSIZE); - if (0 == i++) - return; - GNUNET_TESTBED_LOGGER_flush (h, - &flush_comp, - &write_task); -} - - -/** - * Signature of the 'main' function for a (single-peer) testcase that - * is run using #GNUNET_TESTING_peer_run(). - * - * @param cls closure - * @param cfg configuration of the peer that was started - * @param peer identity of the peer that was created - */ -static void -test_main (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Peer *p) -{ - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Connecting to logger\n"); - FAIL_TEST (NULL != (h = GNUNET_TESTBED_LOGGER_connect (cfg)), - return ); - FAIL_TEST (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_filename (cfg, - "testbed-logger", - "dir", - &search_dir), - return ); - peer = p; - write_task = GNUNET_SCHEDULER_add_now (&do_write, - NULL); - abort_task = GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (10), - &do_abort, - NULL); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - int ret; - - result = GNUNET_SYSERR; - GNUNET_log_setup ("test-testbed-logger-api", - "WARNING", - NULL); - GNUNET_DISK_purge_cfg_dir - ("test_testbed_logger_api.conf", - "GNUNET_TEST_HOME"); - ret = GNUNET_TESTING_service_run ("test-testbed-logger", - "testbed-logger", - "test_testbed_logger_api.conf", - &test_main, - NULL); - GNUNET_DISK_purge_cfg_dir - ("test_testbed_logger_api.conf", - "GNUNET_TEST_HOME"); - if (0 != ret) - return 1; - if (GNUNET_OK != result) - return 2; - return 0; -} diff --git a/src/testbed-logger/test_testbed_logger_api.conf b/src/testbed-logger/test_testbed_logger_api.conf @@ -1,6 +0,0 @@ -[testbed-logger] -UNIXPATH=$GNUNET_TMP/testbed-logger.sock -DIR=$GNUNET_TEST_HOME/data - -[PATHS] -GNUNET_TEST_HOME = $GNUNET_TMP/test-testbed/ -\ No newline at end of file diff --git a/src/testbed-logger/testbed-logger.conf.in b/src/testbed-logger/testbed-logger.conf.in @@ -1,127 +0,0 @@ -[testbed] -START_ON_DEMAND = NO -@JAVAPORT@ PORT = 2101 -HOSTNAME = localhost -BINARY = gnunet-service-testbed - -# How long should operations wait? -OPERATION_TIMEOUT = 30 s - -# Set this to the path where the testbed helper is installed. By default the -# helper binary is searched in @prefix@/lib/gnunet/libexec/ -# HELPER_BINARY_PATH = @prefix@/lib/gnunet/libexec/gnunet-helper-testbed - -# Add your local network address here. For example, if you want to run -# testbed on a group of hosts connected to network 192.168.1.0/24, then set -# ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24; -# Multiple network addresses can be given. They should be separated by `;' -ACCEPT_FROM = 127.0.0.1; -ACCEPT_FROM6 = ::1; - -UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-testbed.sock -UNIX_MATCH_UID = YES -UNIX_MATCH_GID = YES - -# How many maximum number of operations can be run in parallel. This number -# should be decreased if the system is getting overloaded and to reduce the load -# exerted by the emulation. -MAX_PARALLEL_OPERATIONS = 1000 -MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 1 - -# What topology should be generated by the helper functions GNUNET_TESTBED_run() -# and GNUNET_TESTBED_test_run(). This option has no effect if testbed is -# initialized with other functions. Valid values can be found at: -# https://gnunet.org/supported-topologies -OVERLAY_TOPOLOGY = NONE - -# Number of random links to be included to the generate the above topology. -# Note that not all topologies require this option and ignore it. Topologies -# requiring this option are RANDOM, SMALL_WORLD and SMALL_WORLD ring. -# OVERLAY_RANDOM_LINKS = - -# This option is required if the OVERLAY_TOPOLOGY is set to FROM_FILE. It is -# ignored for all other topologies. This option should contain the path to -# the file containing the topology information. The format of the file is -# presented at: https://gnunet.org/topology-file-format -# OVERLAY_TOPOLOGY_FILE = /path/to/topology-file - -# The following options are required if the OVERLAY_TOPOLOGY is set to -# SCALE_FREE. They are ignored in all other cases. -# The number of maximum peers which can connect to a peer -SCALE_FREE_TOPOLOGY_CAP = 70 -# The minimum number of peers which a peer has to connect -SCALE_FREE_TOPOLOGY_M = 5 - -# How many maximum number of handles to peers' services should be kept open at -# any time. This number also keeps a check on the number of open descriptors as -# opening a service connection results in opening a file descriptor. -MAX_PARALLEL_SERVICE_CONNECTIONS = 256 - -# Size of the internal testbed cache. It is used to cache handles to peers -# while trying to connect them. -CACHE_SIZE = 30 - -# Maximum number of file descriptors a testbed controller is permitted to keep -# open. -MAX_OPEN_FDS = 512 - -# How long should we wait for testbed to setup while using helper functions -# GNUNET_TESTBED_test_run() and GNUNET_TESTBED_run() -SETUP_TIMEOUT = 5 m - -# Where should testbed write load statistics data -# STATS_DIR = /tmp/load - -# What services should be shared among peers. -# Format is "[<service:share>] [<service:share>] ...". The shared services are -# started standalone without any other peer services or a hostkey. For this -# reason, only services which doesn't depend on other services can only be -# shared. Example: To share peerinfo among every 10 peers. The following spec -# will start 5 peerinfo services when 50 peers are started: -# -# SHARED_SERVICES = peerinfo:10 -# -# To share multiple services -# -# SHARED_SERVICES = service1:n_share1 service2:n_share2 ... -# -# Default is to share no services -SHARED_SERVICES = - - -[testbed-logger] -START_ON_DEMAND = NO -@UNIXONLY@ PORT = 2102 -HOSTNAME = localhost -BINARY = gnunet-service-testbed-logger -UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-gnunet-testbed-logger.sock -DIR = $GNUNET_TMP -UNIX_MATCH_UID = YES -UNIX_MATCH_GID = YES - - -[testbed-barrier] -START_ON_DEMAND = NO -@UNIXONLY@ PORT = 2103 -HOSTNAME = localhost -UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-testbed-barrier.sock -UNIX_MATCH_UID = YES -UNIX_MATCH_GID = YES - - -# This section is related to configuring underlay restrictions to simulate -# connectivity restrictions of NAT boxes -[testbed-underlay] -START_ON_DEMAND = NO -NOARMBIND = YES -BINARY = gnunet-daemon-testbed-underlay -# The sqlite3 database file containing information about what underlay -# restrictions to apply -# DBFILE = - -[latency-logger] -START_ON_DEMAND = NO -NOARMBIND = YES -BINARY = gnunet-daemon-latency-logger -# The sqlite3 database file where the latency values are to be stored -# DBFILE = diff --git a/src/testbed-logger/testbed_logger_api.c b/src/testbed-logger/testbed_logger_api.c @@ -1,338 +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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed-logger/testbed_logger_api.c - * @brief Client-side routines for communicating with the tesbted logger service - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - * @author Christian Grothoff - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_logger_service.h" - -/** - * Generic logging shorthand - */ -#define LOG(kind, ...) \ - GNUNET_log_from (kind, "testbed-logger-api", __VA_ARGS__) - - -/** - * The size of the buffer we fill before sending out the message - */ -#define BUFFER_SIZE (GNUNET_MAX_MESSAGE_SIZE - sizeof(struct \ - GNUNET_MessageHeader)) - -/** - * Connection handle for the logger service - */ -struct GNUNET_TESTBED_LOGGER_Handle -{ - /** - * Client connection - */ - struct GNUNET_MQ_Handle *mq; - - /** - * Flush completion callback - */ - GNUNET_TESTBED_LOGGER_FlushCompletion cb; - - /** - * Closure for @e cb - */ - void *cb_cls; - - /** - * Local buffer for data to be transmitted - */ - char buf[BUFFER_SIZE]; - - /** - * How many bytes in @a buf are in use? - */ - size_t buse; - - /** - * Number of bytes wrote since last flush - */ - size_t bwrote; - - /** - * How long after should we retry sending a message to the service? - */ - struct GNUNET_TIME_Relative retry_backoff; - - /** - * Task to call the flush completion callback - */ - struct GNUNET_SCHEDULER_Task *flush_completion_task; - - /** - * Number of entries in the MQ. - */ - unsigned int mq_len; -}; - - -/** - * Task to call the flush completion notification - * - * @param cls the logger handle - */ -static void -call_flush_completion (void *cls) -{ - struct GNUNET_TESTBED_LOGGER_Handle *h = cls; - GNUNET_TESTBED_LOGGER_FlushCompletion cb; - void *cb_cls; - size_t bw; - - h->flush_completion_task = NULL; - bw = h->bwrote; - h->bwrote = 0; - cb = h->cb; - h->cb = NULL; - cb_cls = h->cb_cls; - h->cb_cls = NULL; - if (NULL != cb) - cb (cb_cls, bw); -} - - -/** - * Schedule the flush completion notification task - * - * @param h logger handle - */ -static void -trigger_flush_notification (struct GNUNET_TESTBED_LOGGER_Handle *h) -{ - if (NULL != h->flush_completion_task) - GNUNET_SCHEDULER_cancel (h->flush_completion_task); - h->flush_completion_task - = GNUNET_SCHEDULER_add_now (&call_flush_completion, - h); -} - - -/** - * Send the buffered data to the service - * - * @param h the logger handle - */ -static void -dispatch_buffer (struct GNUNET_TESTBED_LOGGER_Handle *h); - - -/** - * MQ successfully sent a message. - * - * @param cls our handle - */ -static void -notify_sent (void *cls) -{ - struct GNUNET_TESTBED_LOGGER_Handle *h = cls; - - h->mq_len--; - if ((0 == h->mq_len) && - (NULL != h->cb)) - { - if (0 == h->buse) - trigger_flush_notification (h); - else - dispatch_buffer (h); - } -} - - -/** - * Send the buffered data to the service - * - * @param h the logger handle - */ -static void -dispatch_buffer (struct GNUNET_TESTBED_LOGGER_Handle *h) -{ - struct GNUNET_MessageHeader *msg; - struct GNUNET_MQ_Envelope *env; - - env = GNUNET_MQ_msg_extra (msg, - h->buse, - GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG); - GNUNET_memcpy (&msg[1], - h->buf, - h->buse); - h->bwrote += h->buse; - h->buse = 0; - h->mq_len++; - GNUNET_MQ_notify_sent (env, - &notify_sent, - h); - GNUNET_MQ_send (h->mq, - env); -} - - -/** - * We got disconnected from the logger. Stop logging. - * - * @param cls the `struct GNUNET_TESTBED_LOGGER_Handle` - * @param error error code - */ -static void -mq_error_handler (void *cls, - enum GNUNET_MQ_Error error) -{ - struct GNUNET_TESTBED_LOGGER_Handle *h = cls; - - GNUNET_break (0); - GNUNET_MQ_destroy (h->mq); - h->mq = NULL; -} - - -/** - * Connect to the testbed logger service - * - * @param cfg configuration to use - * @return the handle which can be used for sending data to the service; NULL - * upon any error - */ -struct GNUNET_TESTBED_LOGGER_Handle * -GNUNET_TESTBED_LOGGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_TESTBED_LOGGER_Handle *h; - - h = GNUNET_new (struct GNUNET_TESTBED_LOGGER_Handle); - h->mq = GNUNET_CLIENT_connect (cfg, - "testbed-logger", - NULL, - &mq_error_handler, - h); - if (NULL == h->mq) - { - GNUNET_free (h); - return NULL; - } - return h; -} - - -/** - * Disconnect from the logger service. - * - * @param h the logger handle - */ -void -GNUNET_TESTBED_LOGGER_disconnect (struct GNUNET_TESTBED_LOGGER_Handle *h) -{ - if (NULL != h->flush_completion_task) - { - GNUNET_SCHEDULER_cancel (h->flush_completion_task); - h->flush_completion_task = NULL; - } - if (0 != h->mq_len) - LOG (GNUNET_ERROR_TYPE_WARNING, - "Disconnect lost %u logger message[s]\n", - h->mq_len); - if (NULL != h->mq) - { - GNUNET_MQ_destroy (h->mq); - h->mq = NULL; - } - GNUNET_free (h); -} - - -/** - * Send data to be logged to the logger service. The data will be buffered and - * will be sent upon an explicit call to GNUNET_TESTBED_LOGGER_flush() or upon - * exceeding a threshold size. - * - * @param h the logger handle - * @param data the data to send; - * @param size how many bytes of @a data to send - */ -void -GNUNET_TESTBED_LOGGER_write (struct GNUNET_TESTBED_LOGGER_Handle *h, - const void *data, - size_t size) -{ - if (NULL == h->mq) - return; - while (0 != size) - { - size_t fit_size = GNUNET_MIN (size, - BUFFER_SIZE - h->buse); - GNUNET_memcpy (&h->buf[h->buse], - data, - fit_size); - h->buse += fit_size; - data += fit_size; - size -= fit_size; - if (0 != size) - dispatch_buffer (h); - } -} - - -void -GNUNET_TESTBED_LOGGER_flush (struct GNUNET_TESTBED_LOGGER_Handle *h, - GNUNET_TESTBED_LOGGER_FlushCompletion cb, - void *cb_cls) -{ - GNUNET_assert (NULL == h->cb); - h->cb = cb; - h->cb_cls = cb_cls; - if ((NULL == h->mq) || - (0 == h->buse)) - { - trigger_flush_notification (h); - return; - } - dispatch_buffer (h); -} - - -/** - * Cancel notification upon flush. Should only be used when the flush - * completion callback given to GNUNET_TESTBED_LOGGER_flush() is not already - * called. - * - * @param h the logger handle - */ -void -GNUNET_TESTBED_LOGGER_flush_cancel (struct GNUNET_TESTBED_LOGGER_Handle *h) -{ - if (NULL != h->flush_completion_task) - { - GNUNET_SCHEDULER_cancel (h->flush_completion_task); - h->flush_completion_task = NULL; - } - h->cb = NULL; - h->cb_cls = NULL; -} - - -/* End of testbed_logger_api.c */ diff --git a/src/testbed/.gitignore b/src/testbed/.gitignore @@ -1,37 +0,0 @@ -gnunet-testbed-profiler -generate-underlay-topology -gnunet-daemon-latency-logger -gnunet-daemon-testbed-blacklist -gnunet-daemon-testbed-underlay -gnunet-helper-testbed -gnunet-service-testbed -gnunet-service-test-barriers -test_gnunet_helper_testbed -test_testbed_api -test_testbed_api_2peers_1controller -test_testbed_api_3peers_3controllers -test_testbed_api_barriers -test_testbed_api_controllerlink -test_testbed_api_hosts -test_testbed_api_operations -test_testbed_api_peer_reconfiguration -test_testbed_api_peers_manage_services -test_testbed_api_sd -test_testbed_api_statistics -test_testbed_api_test -test_testbed_api_test_timeout -test_testbed_api_testbed_run -test_testbed_api_testbed_run_topology2dtorus -test_testbed_api_testbed_run_topologyclique -test_testbed_api_testbed_run_topologyfromfile -test_testbed_api_testbed_run_topologyline -test_testbed_api_testbed_run_topologyrandom -test_testbed_api_testbed_run_topologyring -test_testbed_api_testbed_run_topologyscalefree -test_testbed_api_testbed_run_topologysmallworld -test_testbed_api_testbed_run_topologysmallworldring -test_testbed_api_testbed_run_topologystar -test_testbed_api_testbed_run_waitforever -test_testbed_api_topology -test_testbed_api_topology_clique -test_testbed_underlay diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am @@ -1,401 +0,0 @@ -# This Makefile.am is in the public domain -AM_CPPFLAGS = -I$(top_srcdir)/src/include - -if USE_COVERAGE - AM_CFLAGS = --coverage -O0 - XLIB = -lgcov -endif - -plugindir = $(libdir)/gnunet - -libexecdir= $(pkglibdir)/libexec/ - -pkgcfgdir= $(pkgdatadir)/config.d/ - -pkgcfg_DATA = \ - testbed.conf - -if HAVE_SQLITE - underlay_daemon = gnunet-daemon-testbed-underlay - latency_logger = gnunet-daemon-latency-logger - generate_underlay = generate-underlay-topology - underlay_testcases = test_testbed_underlay -endif - -libexec_PROGRAMS = \ - gnunet-service-testbed \ - gnunet-helper-testbed \ - gnunet-daemon-testbed-blacklist \ - $(underlay_daemon) \ - $(latency_logger) - -bin_PROGRAMS = \ - gnunet-testbed-profiler - -noinst_PROGRAMS = \ - $(generate_underlay) - -gnunet_service_testbed_SOURCES = \ - gnunet-service-testbed.c gnunet-service-testbed.h \ - gnunet-service-testbed_links.c gnunet-service-testbed_links.h \ - gnunet-service-testbed_peers.c \ - gnunet-service-testbed_cache.c \ - gnunet-service-testbed_oc.c \ - gnunet-service-testbed_cpustatus.c \ - gnunet-service-testbed_meminfo.c gnunet-service-testbed_meminfo.h \ - gnunet-service-testbed_barriers.c gnunet-service-testbed_barriers.h \ - gnunet-service-testbed_connectionpool.c gnunet-service-testbed_connectionpool.h -gnunet_service_testbed_LDADD = $(XLIB) \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/hello/libgnunethello.la \ - $(top_builddir)/src/transport/libgnunettransport.la \ - $(top_builddir)/src/ats/libgnunetats.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - libgnunettestbed.la \ - $(top_builddir)/src/arm/libgnunetarm.la \ - $(LTLIBINTL) $(Z_LIBS) - -gnunet_testbed_profiler_SOURCES = \ - gnunet-testbed-profiler.c -gnunet_testbed_profiler_LDADD = $(XLIB) \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la -gnunet_testbed_profiler_LDFLAGS = \ - $(GN_LIBINTL) - -gnunet_helper_testbed_SOURCES = \ - gnunet-helper-testbed.c -gnunet_helper_testbed_LDADD = $(XLIB) \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - libgnunettestbed.la \ - $(LTLIBINTL) $(Z_LIBS) - -gnunet_daemon_testbed_blacklist_SOURCES = gnunet-daemon-testbed-blacklist.c -gnunet_daemon_testbed_blacklist_LDADD = $(XLIB) \ - $(top_builddir)/src/transport/libgnunettransport.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(LTLIBINTL) - -gnunet_daemon_testbed_underlay_SOURCES = gnunet-daemon-testbed-underlay.c -gnunet_daemon_testbed_underlay_LDADD = $(XLIB) \ - $(top_builddir)/src/transport/libgnunettransport.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(LTLIBINTL) -lsqlite3 - -gnunet_daemon_latency_logger_SOURCES = gnunet-daemon-latency-logger.c -gnunet_daemon_latency_logger_LDADD = $(XLIB) \ - $(top_builddir)/src/ats/libgnunetats.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(LTLIBINTL) -lsqlite3 - -lib_LTLIBRARIES = \ - libgnunettestbed.la - -libgnunettestbed_la_SOURCES = \ - testbed_api.c testbed_api.h testbed.h \ - testbed_api_hosts.c testbed_api_hosts.h testbed_helper.h \ - testbed_api_operations.c testbed_api_operations.h \ - testbed_api_peers.c testbed_api_peers.h \ - testbed_api_services.c \ - testbed_api_statistics.c \ - testbed_api_testbed.c \ - testbed_api_test.c \ - testbed_api_topology.c testbed_api_topology.h \ - testbed_api_sd.c testbed_api_sd.h \ - testbed_api_barriers.c -libgnunettestbed_la_LIBADD = $(XLIB) \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/transport/libgnunettransport.la \ - $(top_builddir)/src/hello/libgnunethello.la \ - -lm $(Z_LIBS) \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/arm/libgnunetarm.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(LTLIBINTL) -libgnunettestbed_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) \ - -version-info 0:0:0 - -generate_underlay_topology_SOURCES = generate-underlay-topology.c -generate_underlay_topology_LDADD = $(XLIB) \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la \ - $(LTLIBINTL) -lsqlite3 - -check_PROGRAMS = \ - test_testbed_api_hosts \ - test_gnunet_helper_testbed \ - test_testbed_api_controllerlink \ - test_testbed_api_2peers_1controller \ - test_testbed_api_3peers_3controllers \ - test_testbed_api \ - test_testbed_api_sd \ - test_testbed_api_operations \ - test_testbed_api_testbed_run \ - test_testbed_api_test \ - test_testbed_api_test_timeout \ - test_testbed_api_peer_reconfiguration \ - test_testbed_api_peers_manage_services \ - test_testbed_api_topology \ - test_testbed_api_topology_clique \ - test_testbed_api_testbed_run_topologyrandom \ - test_testbed_api_testbed_run_topologyline \ - test_testbed_api_testbed_run_topologystar \ - test_testbed_api_testbed_run_topologyclique \ - test_testbed_api_testbed_run_topologyring \ - test_testbed_api_testbed_run_topologysmallworldring \ - test_testbed_api_testbed_run_topology2dtorus \ - test_testbed_api_testbed_run_topologysmallworld \ - test_testbed_api_testbed_run_topologyfromfile \ - test_testbed_api_testbed_run_topologyscalefree \ - test_testbed_api_testbed_run_waitforever \ - test_testbed_api_statistics \ - gnunet-service-test-barriers \ - test_testbed_api_barriers \ - $(underlay_testcases) - -if ENABLE_TEST_RUN - AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; - TESTS = \ - test_testbed_api \ - test_testbed_api_sd \ - test_testbed_api_operations \ - test_testbed_api_hosts \ - test_gnunet_helper_testbed \ - test_testbed_api_2peers_1controller \ - test_testbed_api_controllerlink \ - test_testbed_api_3peers_3controllers \ - test_testbed_api_testbed_run \ - test_testbed_api_test \ - test_testbed_api_test_timeout \ - test_testbed_api_statistics \ - test_testbed_api_peer_reconfiguration \ - test_testbed_api_peers_manage_services \ - test_testbed_api_topology \ - test_testbed_api_topology_clique \ - test_testbed_api_testbed_run_topologyrandom \ - test_testbed_api_testbed_run_topologyline \ - test_testbed_api_testbed_run_topologystar \ - test_testbed_api_testbed_run_topologyclique \ - test_testbed_api_testbed_run_topologyring \ - test_testbed_api_testbed_run_topology2dtorus \ - test_testbed_api_testbed_run_topologysmallworld \ - test_testbed_api_testbed_run_topologysmallworldring \ - test_testbed_api_testbed_run_topologyfromfile \ - test_testbed_api_testbed_run_topologyscalefree \ - test_testbed_api_barriers \ - $(underlay_testcases) -endif - -test_testbed_api_SOURCES = \ - test_testbed_api.c -test_testbed_api_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/arm/libgnunetarm.la \ - libgnunettestbed.la - -test_testbed_api_sd_SOURCES = \ - test_testbed_api_sd.c -test_testbed_api_sd_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_2peers_1controller_SOURCES = \ - test_testbed_api_2peers_1controller.c -test_testbed_api_2peers_1controller_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - libgnunettestbed.la - -test_testbed_api_3peers_3controllers_SOURCES = \ - test_testbed_api_3peers_3controllers.c -test_testbed_api_3peers_3controllers_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - libgnunettestbed.la - -test_testbed_api_operations_SOURCES = \ - test_testbed_api_operations.c -test_testbed_api_operations_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_hosts_SOURCES = \ - test_testbed_api_hosts.c -test_testbed_api_hosts_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_controllerlink_SOURCES = \ - test_testbed_api_controllerlink.c -test_testbed_api_controllerlink_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_testbed_run_SOURCES = \ - test_testbed_api_testbed_run.c -test_testbed_api_testbed_run_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_test_SOURCES = \ - test_testbed_api_test.c -test_testbed_api_test_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_test_timeout_SOURCES = \ - test_testbed_api_test_timeout.c -test_testbed_api_test_timeout_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_topology_SOURCES = \ - test_testbed_api_topology.c -test_testbed_api_topology_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_topology_clique_SOURCES = \ - test_testbed_api_topology_clique.c -test_testbed_api_topology_clique_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_gnunet_helper_testbed_SOURCES = \ - test_gnunet_helper_testbed.c -test_gnunet_helper_testbed_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la \ - $(Z_LIBS) - -test_testbed_api_testbed_run_topologyrandom_SOURCES = \ - test_testbed_api_testbed_run.c -test_testbed_api_testbed_run_topologyrandom_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_testbed_run_topologyline_SOURCES = \ - test_testbed_api_testbed_run.c -test_testbed_api_testbed_run_topologyline_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_testbed_run_topologystar_SOURCES = \ - test_testbed_api_testbed_run.c -test_testbed_api_testbed_run_topologystar_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_testbed_run_topologyclique_SOURCES = \ - test_testbed_api_testbed_run.c -test_testbed_api_testbed_run_topologyclique_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_testbed_run_topologyring_SOURCES = \ - test_testbed_api_testbed_run.c -test_testbed_api_testbed_run_topologyring_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_testbed_run_topologysmallworldring_SOURCES = \ - test_testbed_api_testbed_run.c -test_testbed_api_testbed_run_topologysmallworldring_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_testbed_run_topology2dtorus_SOURCES = \ - test_testbed_api_testbed_run.c -test_testbed_api_testbed_run_topology2dtorus_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_testbed_run_topologysmallworld_SOURCES = \ - test_testbed_api_testbed_run.c -test_testbed_api_testbed_run_topologysmallworld_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_testbed_run_topologyfromfile_SOURCES = \ - test_testbed_api_testbed_run.c -test_testbed_api_testbed_run_topologyfromfile_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_testbed_run_topologyscalefree_SOURCES = \ - test_testbed_api_testbed_run.c -test_testbed_api_testbed_run_topologyscalefree_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_testbed_run_waitforever_SOURCES = \ - test_testbed_api_testbed_run.c -test_testbed_api_testbed_run_waitforever_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_statistics_SOURCES = \ - test_testbed_api_statistics.c -test_testbed_api_statistics_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_peers_manage_services_SOURCES = \ - test_testbed_api_peers_manage_services.c -test_testbed_api_peers_manage_services_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_peer_reconfiguration_SOURCES = \ - test_testbed_api_peer_reconfiguration.c -test_testbed_api_peer_reconfiguration_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_api_barriers_SOURCES = \ - test_testbed_api_barriers.c \ - test_testbed_api_barriers.h -test_testbed_api_barriers_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -gnunet_service_test_barriers_SOURCES = \ - gnunet-service-test-barriers.c \ - test_testbed_api_barriers.h -gnunet_service_test_barriers_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -test_testbed_underlay_SOURCES = \ - test_testbed_underlay.c -test_testbed_underlay_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - libgnunettestbed.la - -EXTRA_DIST = \ - test_testbed_api.conf \ - test_testbed_api_statistics.conf \ - test_testbed_api_test_timeout.conf \ - test_testbed_api_template.conf \ - test_testbed_api_testbed_run_topologyring.conf \ - test_testbed_api_testbed_run_topologystar.conf \ - test_testbed_api_testbed_run_topologyclique.conf \ - test_testbed_api_testbed_run_topologyline.conf \ - test_testbed_api_testbed_run_topologyrandom.conf \ - test_testbed_api_testbed_run_topologysmallworldring.conf \ - test_testbed_api_testbed_run_topology2dtorus.conf \ - test_testbed_api_testbed_run_topologysmallworld.conf \ - test_testbed_api_testbed_run_topologyfromfile.conf \ - test_testbed_api_testbed_run_topologyscalefree.conf \ - test_testbed_api_barriers.conf.in \ - overlay_topology.txt \ - sample_hosts.txt \ - sample.job \ - test_testbed_underlay.conf.in \ - test-underlay.sqlite diff --git a/src/testbed/barriers.README.org b/src/testbed/barriers.README.org @@ -1,95 +0,0 @@ -* Description -The testbed subsystem's barriers API facilitates coordination among the peers -run by the testbed and the experiment driver. The concept is similar to the -barrier synchronisation mechanism found in parallel programming or -multi-threading paradigms - a peer waits at a barrier upon reaching it until the -barrier is reached by a predefined number of peers. This predefined number of -peers required to cross a barrier is also called quorum. We say a peer has -reached a barrier if the peer is waiting for the barrier to be crossed. -Similarly a barrier is said to be reached if the required quorum of peers reach -the barrier. A barrier which is reached is deemed as crossed after all the -peers waiting on it are notified. - -The barriers API provides the following functions: -1) GNUNET_TESTBED_barrier_init(): function to initialise a barrier in the - experiment -2) GNUNET_TESTBED_barrier_cancel(): function to cancel a barrier which has been - initialised before -3) GNUNET_TESTBED_barrier_wait(): function to signal barrier service that the - caller has reached a barrier and is waiting for it to be crossed -4) GNUNET_TESTBED_barrier_wait_cancel(): function to stop waiting for a barrier - to be crossed - -Among the above functions, the first two, namely GNUNET_TESTBED_barrier_init() -and GNUNET_TESTBED_barrier_cacel() are used by experiment drivers. All barriers -should be initialised by the experiment driver by calling -GNUNET_TESTBED_barrier_init(). This function takes a name to identify the -barrier, the quorum required for the barrier to be crossed and a notification -callback for notifying the experiment driver when the barrier is crossed. The -GNUNET_TESTBED_function barrier_cancel() cancels an initialised barrier and -frees the resources allocated for it. This function can be called upon a -initialised barrier before it is crossed. - -The remaining two functions GNUNET_TESTBED_barrier_wait() and -GNUNET_TESTBED_barrier_wait_cancel() are used in the peer's processes. -GNUNET_TESTBED_barrier_wait() connects to the local barrier service running on -the same host the peer is running on and registers that the caller has reached -the barrier and is waiting for the barrier to be crossed. Note that this -function can only be used by peers which are started by testbed as this function -tries to access the local barrier service which is part of the testbed -controller service. Calling GNUNET_TESTBED_barrier_wait() on an uninitialised -barrier results in failure. GNUNET_TESTBED_barrier_wait_cancel() cancels the -notification registered by GNUNET_TESTBED_barrier_wait(). - - -* Implementation -Since barriers involve coordination between experiment driver and peers, the -barrier service in the testbed controller is split into two components. The -first component responds to the message generated by the barrier API used by the -experiment driver (functions GNUNET_TESTBED_barrier_init() and -GNUNET_TESTBED_barrier_cancel()) and the second component to the messages -generated by barrier API used by peers (functions GNUNET_TESTBED_barrier_wait() -and GNUNET_TESTBED_barrier_wait_cancel()). - -Calling GNUNET_TESTBED_barrier_init() sends a BARRIER_INIT message to the master -controller. The master controller then registers a barrier and calls -GNUNET_TESTBED_barrier_init() for each its subcontrollers. In this way barrier -initialisation is propagated to the controller hierarchy. While propagating -initialisation, any errors at a subcontroller such as timeout during further -propagation are reported up the hierarchy back to the experiment driver. - -Similar to GNUNET_TESTBED_barrier_init(), GNUNET_TESTBED_barrier_cancel() -propagates BARRIER_CANCEL message which causes controllers to remove an -initialised barrier. - -The second component is implemented as a separate service in the binary -`gnunet-service-testbed' which already has the testbed controller service. -Although this deviates from the gnunet process architecture of having one -service per binary, it is needed in this case as this component needs access to -barrier data created by the first component. This component responds to -BARRIER_WAIT messages from local peers when they call -GNUNET_TESTBED_barrier_wait(). Upon receiving BARRIER_WAIT message, the service -checks if the requested barrier has been initialised before and if it was not -initialised, an error status is sent through BARRIER_STATUS message to the local -peer and the connection from the peer is terminated. If the barrier is -initialised before, the barrier's counter for reached peers is incremented and a -notification is registered to notify the peer when the barrier is reached. The -connection from the peer is left open. - -When enough peers required to attain the quorum send BARRIER_WAIT messages, the -controller sends a BARRIER_STATUS message to its parent informing that the -barrier is crossed. If the controller has started further subcontrollers, it -delays this message until it receives a similar notification from each of those -subcontrollers. Finally, the barriers API at the experiment driver receives the -BARRIER_STATUS when the barrier is reached at all the controllers. - -The barriers API at the experiment driver responds to the BARRIER_STATUS message -by echoing it back to the master controller and notifying the experiment -controller through the notification callback that a barrier has been crossed. -The echoed BARRIER_STATUS message is propagated by the master controller to the -controller hierarchy. This propagation triggers the notifications registered by -peers at each of the controllers in the hierarchy. Note the difference between -this downward propagation of the BARRIER_STATUS message from its upward -propagation -- the upward propagation is needed for ensuring that the barrier is -reached by all the controllers and the downward propagation is for triggering -that the barrier is crossed. diff --git a/src/testbed/buildvars.py.in b/src/testbed/buildvars.py.in @@ -1,34 +0,0 @@ -# This file is part of GNUnet. -# (C) 2008--2013, 2018 Christian Grothoff (and other contributing authors) -# -# 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 <http://www.gnu.org/licenses/>. -# -# SPDX-License-Identifier: AGPL3.0-or-later - -# file: testbed/buildvars.py -# brief: file for importing variables from build system into python -# author: Sree Harsha Totakura - -import os - -exec_prefix = '@exec_prefix@' -libexecdir = '@libexecdir@' - -if libexecdir.startswith(exec_prefix): - libexecdir = libexecdir[len(exec_prefix):] - -gnunet_prefix = os.environ.get('GNUNET_PREFIX', None) - -if gnunet_prefix and libexecdir.startswith('/'): - libexecdir = os.path.join(gnunet_prefix, libexecdir[1:]) diff --git a/src/testbed/generate-underlay-topology.c b/src/testbed/generate-underlay-topology.c @@ -1,407 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2014 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/generate-underlay-topology.c - * @brief Program to generate a database file containing given underlay topology - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" -#include "testbed_api_topology.h" -#include "sqlite3.h" - -#define LOG(type, ...) GNUNET_log (type, __VA_ARGS__) - - -#define LOG_ERROR(...) LOG (GNUNET_ERROR_TYPE_ERROR, __VA_ARGS__) - -/** - * Log an error message at log-level 'level' that indicates - * a failure of the command 'cmd' on file 'filename' - * with the message given by strerror(errno). - */ -#define LOG_SQLITE(db, msg, level, cmd) \ - do \ - { \ - GNUNET_log_from (level, \ - "sqlite", \ - _ ("`%s' failed at %s:%d with error: %s\n"), \ - cmd, \ - __FILE__, \ - __LINE__, \ - sqlite3_errmsg (db)); \ - if (msg != NULL) \ - GNUNET_asprintf (msg, \ - _ ("`%s' failed at %s:%u with error: %s"), \ - cmd, \ - __FILE__, \ - __LINE__, \ - sqlite3_errmsg (db)); \ - } while (0) - - -/** - * Handle to the sqlite3 database - */ -static struct sqlite3 *db; - -/** - * Prepared statement for inserting link values into db - */ -struct sqlite3_stmt *stmt_insert; - -/** - * The topology to generate - */ -enum GNUNET_TESTBED_TopologyOption topology; - -/** - * The number of peers to include in the topology - */ -static unsigned int num_peers; - -/** - * program result - */ -static int exit_result; - - -/** - * Functions of this type are called to process underlay link - * - * @param cls closure - * @param A offset of first peer - * @param B offset of second peer - * @param bandwidth the bandwidth of the link in bytes per second - * @param latency the latency of link in milliseconds - * @param loss the percentage of messages dropped on the link - * @return GNUNET_OK to continue processing; GNUNET_SYSERR to abort - */ -static int -link_processor (void *cls, - unsigned int A, - unsigned int B, - unsigned int bandwidth, - unsigned int latency, - unsigned int loss) -{ - if ((SQLITE_OK != sqlite3_bind_int (stmt_insert, 1, A)) || - (SQLITE_OK != sqlite3_bind_int (stmt_insert, 2, B)) || - (SQLITE_OK != sqlite3_bind_int (stmt_insert, 3, bandwidth)) || - (SQLITE_OK != sqlite3_bind_int (stmt_insert, 4, latency)) || - (SQLITE_OK != sqlite3_bind_int (stmt_insert, 5, loss))) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_int"); - return GNUNET_SYSERR; - } - if (SQLITE_DONE != sqlite3_step (stmt_insert)) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_step"); - return GNUNET_SYSERR; - } - fprintf (stdout, "%u -> %u\n", A, B); - GNUNET_break (SQLITE_OK == sqlite3_reset (stmt_insert)); - // GNUNET_break (SQLITE_OK == sqlite3_clear_bindings (stmt_insert)); - if ((SQLITE_OK != sqlite3_bind_int (stmt_insert, 1, B)) || - (SQLITE_OK != sqlite3_bind_int (stmt_insert, 2, A))) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_int"); - return GNUNET_SYSERR; - } - if (SQLITE_DONE != sqlite3_step (stmt_insert)) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_step"); - return GNUNET_SYSERR; - } - fprintf (stdout, "%u -> %u\n", B, A); - GNUNET_break (SQLITE_OK == sqlite3_reset (stmt_insert)); - return GNUNET_OK; -} - - -/** - * Open the database file, creating a new database if not existing and setup the - * whitelist table - * - * @param dbfile the database filename - * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure (error message has - * to be printed) - */ -static int -setup_db (const char *dbfile) -{ - const char *query_create = "CREATE TABLE whitelist (" - "id INTEGER," - "oid INTEGER," - "bandwidth INTEGER DEFAULT NULL," - "latency INTEGER DEFAULT NULL," - "loss INTEGER DEFAULT NULL," - " UNIQUE (" - " id," - " oid" - " ) ON CONFLICT IGNORE" - ");"; - const char *query_insert = "INSERT INTO whitelist(" - " id," - " oid," - " bandwidth," - " latency," - " loss" - ") VALUES (" - " ?1," - " ?2," - " ?3," - " ?4," - " ?5);"; - int ret; - - ret = GNUNET_SYSERR; - if (SQLITE_OK != sqlite3_open (dbfile, &db)) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_open"); - goto err_ret; - } - if (0 != sqlite3_exec (db, query_create, NULL, NULL, NULL)) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec"); - fprintf (stderr, - "Error: %d. Perhaps the database `%s' already exits.\n", - sqlite3_errcode (db), - dbfile); - goto err_ret; - } - GNUNET_break (0 == - sqlite3_exec (db, "PRAGMA synchronous = 0;", NULL, NULL, NULL)); - if (SQLITE_OK != - sqlite3_prepare_v2 (db, query_insert, -1, &stmt_insert, NULL)) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2"); - goto err_ret; - } - ret = GNUNET_OK; - -err_ret: - return ret; -} - - -/** - * Main run function. - * - * @param cls NULL - * @param args arguments passed to GNUNET_PROGRAM_run - * @param cfgfile the path to configuration file - * @param cfg the configuration file handle - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - const char *dbfile; - const char *topology_string; - unsigned int arg_uint1; - unsigned int arg_uint2; - const char *arg_str1; - const char *value; - unsigned int argc; - - argc = 0; - arg_uint1 = 0; /* make compilers happy */ - arg_uint2 = 0; /* make compilers happy */ - if (NULL == args) - { - LOG_ERROR (_ ("Need at least 2 arguments\n")); - return; - } - if (NULL == (dbfile = args[argc++])) - { - LOG_ERROR (_ ("Database filename missing\n")); - return; - } - if (GNUNET_OK != setup_db (dbfile)) - return; - if (NULL == (topology_string = args[argc++])) - { - LOG_ERROR (_ ("Topology string missing\n")); - return; - } - if (GNUNET_YES != GNUNET_TESTBED_topology_get_ (&topology, topology_string)) - { - LOG_ERROR (_ ("Invalid topology: %s\n"), topology_string); - return; - } - arg_str1 = NULL; - /* parse for first TOPOOPT. This can either be arg_uint1 or arg_str1 */ - switch (topology) - { - case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: - case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: - case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: - case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: - if (NULL == (value = args[argc++])) - { - LOG_ERROR (_ ("An argument is missing for given topology `%s'\n"), - topology_string); - return; - } - if (-1 == sscanf (value, "%u", &arg_uint1)) - { - LOG_ERROR (_ ("Invalid argument `%s' given as topology argument\n"), - value); - return; - } - break; - - case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: - if (NULL == (arg_str1 = args[argc++])) - { - LOG_ERROR (_ ("Filename argument missing for topology `%s'\n"), - topology_string); - return; - } - break; - - default: - break; - } - /* parse for second TOPOOPT. Only required for SCALE_FREE topology */ - switch (topology) - { - case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: - if (NULL == (value = args[argc++])) - { - LOG_ERROR (_ ("Second argument for topology `%s' is missing\n"), - topology_string); - return; - } - if (-1 == sscanf (value, "%u", &arg_uint2)) - { - LOG_ERROR (_ ("Invalid argument `%s'; expecting unsigned int\n"), value); - return; - } - break; - - default: - break; - } - /* construct topologies */ - switch (topology) - { - case GNUNET_TESTBED_TOPOLOGY_LINE: - case GNUNET_TESTBED_TOPOLOGY_RING: - case GNUNET_TESTBED_TOPOLOGY_STAR: - case GNUNET_TESTBED_TOPOLOGY_CLIQUE: - case GNUNET_TESTBED_TOPOLOGY_2D_TORUS: - GNUNET_TESTBED_underlay_construct_ (num_peers, - link_processor, - NULL, - topology); - break; - - case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: - case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: - case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: - GNUNET_TESTBED_underlay_construct_ (num_peers, - link_processor, - NULL, - topology, - arg_uint1); - break; - - case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: - GNUNET_TESTBED_underlay_construct_ (num_peers, - link_processor, - NULL, - topology, - arg_str1); - break; - - case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: - GNUNET_TESTBED_underlay_construct_ (num_peers, - link_processor, - NULL, - topology, - arg_uint1, - arg_uint2); - break; - - default: - GNUNET_assert (0); - } -} - - -/** - * Main - */ -int -main (int argc, char *const argv[]) -{ - struct GNUNET_GETOPT_CommandLineOption option[] = { - GNUNET_GETOPT_option_uint ('p', - "num-peers", - "COUNT", - gettext_noop ("create COUNT number of peers"), - &num_peers), - GNUNET_GETOPT_OPTION_END - }; - - int ret; - - exit_result = GNUNET_SYSERR; - ret = GNUNET_PROGRAM_run ( - argc, - argv, - "gnunet-underlay-topology", - _ ( - "Generates SQLite3 database representing a given underlay topology.\n" - "Usage: gnunet-underlay-topology [OPTIONS] db-filename TOPO [TOPOOPTS]\n" - "The following options are available for TOPO followed by TOPOOPTS if applicable:\n" - "\t LINE\n" - "\t RING\n" - "\t RANDOM <num_rnd_links>\n" - "\t SMALL_WORLD <num_rnd_links>\n" - "\t SMALL_WORLD_RING <num_rnd_links>\n" - "\t CLIQUE\n" - "\t 2D_TORUS\n" - "\t SCALE_FREE <cap> <m>\n" - "\t FROM_FILE <filename>\n" - "TOPOOPTS:\n" - "\t num_rnd_links: The number of random links\n" - "\t cap: the maximum number of links a node can have\n" - "\t m: the number of links a node should have while joining the network\n" - "\t filename: the path of the file which contains topology information\n" - "NOTE: the format of the above file is described here: https://www.gnunet.org/content/topology-file-format\n"), - option, - &run, - NULL); - if (NULL != stmt_insert) - sqlite3_finalize (stmt_insert); - if (NULL != db) - GNUNET_break (SQLITE_OK == sqlite3_close (db)); - if ((GNUNET_OK != ret) || (GNUNET_OK != exit_result)) - return 1; - return 0; -} diff --git a/src/testbed/gnunet-daemon-latency-logger.c b/src/testbed/gnunet-daemon-latency-logger.c @@ -1,322 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2014 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-daemon-latency-logger.c - * @brief log latency values from neighbour connections into an SQLite database - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_ats_service.h" -#include <sqlite3.h> - - -/** - * Logging shorthand - */ -#define LOG(type, ...) \ - GNUNET_log (type, __VA_ARGS__) - -/** - * Debug logging shorthand - */ -#define DEBUG(...) \ - LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) - -/** - * Log an error message at log-level 'level' that indicates - * a failure of the command 'cmd' on file 'filename' - * with the message given by strerror(errno). - */ -#define LOG_SQLITE(db, msg, level, cmd) \ - do { \ - GNUNET_log_from (level, "sqlite", _ ( \ - "`%s' failed at %s:%d with error: %s\n"), \ - cmd, __FILE__, __LINE__, sqlite3_errmsg (db)); \ - if (msg != NULL) \ - GNUNET_asprintf (msg, _ ("`%s' failed at %s:%u with error: %s"), cmd, \ - __FILE__, __LINE__, sqlite3_errmsg (db)); \ - } while (0) - - -/** - * Entry type to be used in the map to store old latency values - */ -struct Entry -{ - /** - * The peer's identity - */ - struct GNUNET_PeerIdentity id; - - /** - * The last known value for latency. - * FIXME: type! - */ - unsigned int latency; -}; - - -/** - * Handle to the map used to store old latency values for peers - */ -static struct GNUNET_CONTAINER_MultiPeerMap *map; - -/** - * The SQLite database handle - */ -static struct sqlite3 *db; - -/** - * Handle to the ATS performance subsystem - */ -static struct GNUNET_ATS_PerformanceHandle *ats; - -/** - * Prepared statement for inserting values into the database table - */ -static struct sqlite3_stmt *stmt_insert; - - -/** - * @ingroup hashmap - * Iterator over hash map entries. - * - * @param cls closure - * @param key current public key - * @param value value in the hash map - * @return #GNUNET_YES if we should continue to - * iterate, - * #GNUNET_NO if not. - */ -static int -free_iterator (void *cls, - const struct GNUNET_PeerIdentity *key, - void *value) -{ - struct Entry *e = cls; - - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_remove (map, key, e)); - GNUNET_free (e); - return GNUNET_YES; -} - - -/** - * Shutdown - * - * @param cls NULL - * @return - */ -static void -do_shutdown (void *cls) -{ - GNUNET_ATS_performance_done (ats); - ats = NULL; - if (NULL != stmt_insert) - { - sqlite3_finalize (stmt_insert); - stmt_insert = NULL; - } - GNUNET_break (SQLITE_OK == sqlite3_close (db)); - db = NULL; - if (NULL != map) - { - GNUNET_assert (GNUNET_SYSERR != - GNUNET_CONTAINER_multipeermap_iterate (map, free_iterator, - NULL)); - GNUNET_CONTAINER_multipeermap_destroy (map); - map = NULL; - } -} - - -/** - * Signature of a function that is called with QoS information about an address. - * - * @param cls closure - * @param address the address - * @param address_active #GNUNET_YES if this address is actively used - * to maintain a connection to a peer; - * #GNUNET_NO if the address is not actively used; - * #GNUNET_SYSERR if this address is no longer available for ATS - * @param bandwidth_out assigned outbound bandwidth for the connection - * @param bandwidth_in assigned inbound bandwidth for the connection - * @param prop performance data for the address (as far as known) - */ -static void -addr_info_cb (void *cls, - const struct GNUNET_HELLO_Address *address, - int address_active, - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, - const struct GNUNET_ATS_Properties *prop) -{ - static const char *query_insert = - "INSERT INTO ats_info(" - " id," - " val," - " timestamp" - ") VALUES (" - " ?1," - " ?2," - " datetime('now')" - ");"; - struct Entry *entry; - int latency; /* FIXME: type!? */ - - if (NULL == address) - { - /* ATS service temporarily disconnected */ - return; - } - - GNUNET_assert (NULL != db); - if (GNUNET_YES != address_active) - return; - latency = (int) prop->delay.rel_value_us; - entry = NULL; - if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (map, - &address->peer)) - { - entry = GNUNET_CONTAINER_multipeermap_get (map, &address->peer); - GNUNET_assert (NULL != entry); - if (latency == entry->latency) - return; - } - if (NULL == stmt_insert) - { - if (SQLITE_OK != sqlite3_prepare_v2 (db, query_insert, -1, &stmt_insert, - NULL)) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2"); - goto err_shutdown; - } - } - if ((SQLITE_OK != sqlite3_bind_text (stmt_insert, 1, - GNUNET_i2s (&address->peer), -1, - SQLITE_STATIC)) || - (SQLITE_OK != sqlite3_bind_int (stmt_insert, 2, latency))) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_text"); - goto err_shutdown; - } - if (SQLITE_DONE != sqlite3_step (stmt_insert)) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_step"); - goto err_shutdown; - } - if (SQLITE_OK != sqlite3_reset (stmt_insert)) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_insert"); - goto err_shutdown; - } - if (NULL == entry) - { - entry = GNUNET_new (struct Entry); - entry->id = address->peer; - GNUNET_CONTAINER_multipeermap_put (map, - &entry->id, entry, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); - } - entry->latency = latency; - return; - -err_shutdown: - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * 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 c configuration - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - const char *query_create = - "CREATE TABLE ats_info (" - "id TEXT," - "val INTEGER," - "timestamp NUMERIC" - ");"; - char *dbfile; - - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "LATENCY-LOGGER", - "DBFILE", - &dbfile)) - { - GNUNET_break (0); - return; - } - if (SQLITE_OK != sqlite3_open (dbfile, &db)) - { - if (NULL != db) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_open_v2"); - GNUNET_break (SQLITE_OK == sqlite3_close (db)); - } - else - LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot open sqlite file %s\n", dbfile); - GNUNET_free (dbfile); - return; - } - if (0 != sqlite3_exec (db, query_create, NULL, NULL, NULL)) - DEBUG ("SQLite Error: %d. Perhaps the database `%s' already exits.\n", - sqlite3_errcode (db), dbfile); - DEBUG ("Opened database %s\n", dbfile); - GNUNET_free (dbfile); - dbfile = NULL; - ats = GNUNET_ATS_performance_init (c, &addr_info_cb, NULL); - map = GNUNET_CONTAINER_multipeermap_create (30, GNUNET_YES); - GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); -} - - -/** - * Execution entry point - */ -int -main (int argc, char *const *argv) -{ - static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - int ret; - - if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) - return 2; - ret = - (GNUNET_OK == - GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-latency-logger", - _ ( - "Daemon to log latency values of connections to neighbours"), - options, &run, NULL)) ? 0 : 1; - GNUNET_free_nz ((void *) argv); - return ret; -} diff --git a/src/testbed/gnunet-daemon-testbed-blacklist.c b/src/testbed/gnunet-daemon-testbed-blacklist.c @@ -1,254 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - - -/** - * @file testbed/gnunet-daemon-testbed-blacklist.c - * @brief daemon to restrict incoming connections from other peers at the - * transport layer of a peer - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_transport_service.h" - - -/** - * Logging shorthand - */ -#define LOG(type, ...) \ - GNUNET_log (type, __VA_ARGS__) - -/** - * Debug logging shorthand - */ -#define DEBUG(...) \ - LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) - -/** - * Allow access from the peers read from the whitelist - */ -#define ACCESS_ALLOW 1 - -/** - * Deny access from the peers read from the blacklist - */ -#define ACCESS_DENY 0 - -/** - * The map to store the peer identities to allow/deny - */ -static struct GNUNET_CONTAINER_MultiPeerMap *map; - -/** - * The array of peer identities we read from whitelist/blacklist - */ -static struct GNUNET_PeerIdentity *ilist; - -/** - * The blacklist handle we obtain from transport when we register ourselves for - * access control - */ -static struct GNUNET_TRANSPORT_Blacklist *bh; - -/** - * Are we allowing or denying access from peers - */ -static int mode; - - -/** - * Cleaup and destroy the map - */ -static void -cleanup_map () -{ - if (NULL != map) - { - GNUNET_CONTAINER_multipeermap_destroy (map); - map = NULL; - } -} - - -/** - * Shutdown task to cleanup our resources and exit. - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - cleanup_map (); - if (NULL != bh) - GNUNET_TRANSPORT_blacklist_cancel (bh); -} - - -/** - * Function that decides if a connection is acceptable or not. - * - * @param cls closure - * @param pid peer to approve or disapproave - * @return GNUNET_OK if the connection is allowed, GNUNET_SYSERR if not - */ -static int -check_access (void *cls, const struct GNUNET_PeerIdentity *pid) -{ - int contains; - - if (NULL != map) - contains = GNUNET_CONTAINER_multipeermap_contains (map, pid); - else - contains = GNUNET_NO; - if (ACCESS_DENY == mode) - return (contains) ? GNUNET_SYSERR : GNUNET_OK; - return (contains) ? GNUNET_OK : GNUNET_SYSERR; -} - - -/** - * Setup the access control by reading the given file containing peer identities - * and then establishing blacklist handler with the peer's transport service - * - * @param fname the filename to read the list of peer identities - * @param cfg the configuration for connecting to the peer's transport service - */ -static void -setup_ac (const char *fname, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - uint64_t fsize; - unsigned int npeers; - unsigned int cnt; - - GNUNET_assert (GNUNET_OK != - GNUNET_DISK_file_size (fname, &fsize, GNUNET_NO, - GNUNET_YES)); - if (0 != (fsize % sizeof(struct GNUNET_PeerIdentity))) - { - GNUNET_break (0); - return; - } - npeers = fsize / sizeof(struct GNUNET_PeerIdentity); - if (0 != npeers) - { - map = GNUNET_CONTAINER_multipeermap_create (npeers, GNUNET_YES); - ilist = GNUNET_malloc_large (fsize); - GNUNET_assert (fsize == GNUNET_DISK_fn_read (fname, ilist, fsize)); - } - for (cnt = 0; cnt < npeers; cnt++) - { - if (GNUNET_SYSERR == - GNUNET_CONTAINER_multipeermap_put (map, &ilist[cnt], - &ilist[cnt], - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) - { - cleanup_map (); - GNUNET_free (ilist); - return; - } - } - GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); - bh = GNUNET_TRANSPORT_blacklist (cfg, &check_access, 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 c configuration - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - char *shome; - char *fname; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (c, - "PATHS", - "GNUNET_HOME", - &shome)) - { - GNUNET_break (0); - return; - } - GNUNET_asprintf (&fname, - "%s/whitelist", - shome); - if (GNUNET_YES == GNUNET_DISK_file_test (fname)) - { - mode = ACCESS_ALLOW; - setup_ac (fname, c); - GNUNET_free (shome); - GNUNET_free (fname); - return; - } - GNUNET_free (fname); - GNUNET_asprintf (&fname, - "%s/blacklist", - shome); - if (GNUNET_YES == GNUNET_DISK_file_test (fname)) - { - mode = ACCESS_DENY; - setup_ac (shome, c); - } - GNUNET_free (shome); - GNUNET_free (fname); -} - - -/** - * The main function. - * - * @param argc number of arguments from the command line - * @param argv command line arguments - * @return 0 ok, 1 on error - */ -int -main (int argc, char *const *argv) -{ - static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - int ret; - - if (GNUNET_OK != - GNUNET_STRINGS_get_utf8_args (argc, argv, - &argc, &argv)) - return 2; - ret = - (GNUNET_OK == - GNUNET_PROGRAM_run (argc, argv, - "gnunet-daemon-testbed-blacklist", - _ ( - "Daemon to restrict incoming transport layer connections during testbed deployments"), - options, &run, NULL)) ? 0 : 1; - GNUNET_free_nz ((void *) argv); - return ret; -} diff --git a/src/testbed/gnunet-daemon-testbed-underlay.c b/src/testbed/gnunet-daemon-testbed-underlay.c @@ -1,481 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - - -/** - * @file testbed/gnunet-daemon-testbed-blacklist.c - * @brief daemon to restrict incoming connections from other peers at the - * transport layer of a peer - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_transport_service.h" -#include "gnunet_transport_manipulation_service.h" -#include "gnunet_ats_service.h" -#include "gnunet_testing_lib.h" -#include <sqlite3.h> - -/** - * Logging shorthand - */ -#define LOG(type, ...) \ - GNUNET_log (type, __VA_ARGS__) - -/** - * Debug logging shorthand - */ -#define DEBUG(...) \ - LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) - -/** - * Log an error message at log-level 'level' that indicates - * a failure of the command 'cmd' on file 'filename' - * with the message given by strerror(errno). - */ -#define LOG_SQLITE(db, msg, level, cmd) \ - do { \ - GNUNET_log_from (level, "sqlite", _ ( \ - "`%s' failed at %s:%d with error: %s\n"), \ - cmd, __FILE__, __LINE__, sqlite3_errmsg (db)); \ - if (msg != NULL) \ - GNUNET_asprintf (msg, _ ("`%s' failed at %s:%u with error: %s"), cmd, \ - __FILE__, __LINE__, sqlite3_errmsg (db)); \ - } while (0) - - -/** - * The map to store the peer identities to allow/deny - */ -static struct GNUNET_CONTAINER_MultiPeerMap *map; - -/** - * The database connection - */ -static struct sqlite3 *db; - -/** - * The blacklist handle we obtain from transport when we register ourselves for - * access control - */ -static struct GNUNET_TRANSPORT_Blacklist *bh; - -/** - * The hostkeys file - */ -struct GNUNET_DISK_FileHandle *hostkeys_fd; - -/** - * The hostkeys map - */ -static struct GNUNET_DISK_MapHandle *hostkeys_map; - -/** - * The hostkeys data - */ -static void *hostkeys_data; - -/** - * Handle to the transport service. This is used for setting link metrics - */ -static struct GNUNET_TRANSPORT_ManipulationHandle *transport; - -/** - * The number of hostkeys in the hostkeys array - */ -static unsigned int num_hostkeys; - - -/** - * @ingroup hashmap - * Iterator over hash map entries. - * - * @param cls closure - * @param key current key code - * @param value value in the hash map - * @return #GNUNET_YES if we should continue to - * iterate, - * #GNUNET_NO if not. - */ -static int -iterator (void *cls, const struct GNUNET_PeerIdentity *key, void *value) -{ - GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (map, key, - value)); - return GNUNET_YES; -} - - -/** - * Cleaup and destroy the map - */ -static void -cleanup_map () -{ - if (NULL != map) - { - GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multipeermap_iterate (map, - & - iterator, - NULL)); - GNUNET_CONTAINER_multipeermap_destroy (map); - map = NULL; - } -} - - -/** - * Function that decides if a connection is acceptable or not. - * - * @param cls closure - * @param pid peer to approve or disapproave - * @return GNUNET_OK if the connection is allowed, GNUNET_SYSERR if not - */ -static int -check_access (void *cls, const struct GNUNET_PeerIdentity *pid) -{ - int contains; - - GNUNET_assert (NULL != map); - contains = GNUNET_CONTAINER_multipeermap_contains (map, pid); - if (GNUNET_YES == contains) - { - DEBUG ("Permitting `%s'\n", GNUNET_i2s (pid)); - return GNUNET_OK; - } - DEBUG ("Not permitting `%s'\n", GNUNET_i2s (pid)); - return GNUNET_SYSERR; -} - - -static int -get_identity (unsigned int offset, - struct GNUNET_PeerIdentity *id) -{ - struct GNUNET_CRYPTO_EddsaPrivateKey private_key; - - if (offset >= num_hostkeys) - return GNUNET_SYSERR; - GNUNET_memcpy (&private_key, - hostkeys_data + (offset * GNUNET_TESTING_HOSTKEYFILESIZE), - GNUNET_TESTING_HOSTKEYFILESIZE); - GNUNET_CRYPTO_eddsa_key_get_public (&private_key, - &id->public_key); - return GNUNET_OK; -} - - -/** - * Whilelist entry - */ -struct WhiteListRow -{ - /** - * Next ptr - */ - struct WhiteListRow *next; - - /** - * The offset where to find the hostkey for the peer - */ - unsigned int id; - - /** - * Latency to be assigned to the link - */ - int latency; -}; - - -/** - * Function to load keys - */ -static int -load_keys (const struct GNUNET_CONFIGURATION_Handle *c) -{ - char *data_dir; - char *idfile; - uint64_t fsize; - - data_dir = NULL; - idfile = NULL; - fsize = 0; - data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); - GNUNET_asprintf (&idfile, "%s/testing_hostkeys.ecc", data_dir); - GNUNET_free (data_dir); - data_dir = NULL; - if (GNUNET_OK != - GNUNET_DISK_file_size (idfile, &fsize, GNUNET_YES, GNUNET_YES)) - { - GNUNET_free (idfile); - return GNUNET_SYSERR; - } - if (0 != (fsize % GNUNET_TESTING_HOSTKEYFILESIZE)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Incorrect hostkey file format: %s\n"), idfile); - GNUNET_free (idfile); - return GNUNET_SYSERR; - } - hostkeys_fd = GNUNET_DISK_file_open (idfile, GNUNET_DISK_OPEN_READ, - GNUNET_DISK_PERM_NONE); - if (NULL == hostkeys_fd) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", idfile); - GNUNET_free (idfile); - return GNUNET_SYSERR; - } - GNUNET_free (idfile); - idfile = NULL; - hostkeys_data = GNUNET_DISK_file_map (hostkeys_fd, - &hostkeys_map, - GNUNET_DISK_MAP_TYPE_READ, - fsize); - if (NULL == hostkeys_data) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "mmap"); - return GNUNET_SYSERR; - } - num_hostkeys = fsize / GNUNET_TESTING_HOSTKEYFILESIZE; - return GNUNET_OK; -} - - -/** - * Function to unload keys - */ -static void -unload_keys () -{ - if (NULL != hostkeys_map) - { - GNUNET_assert (NULL != hostkeys_data); - GNUNET_DISK_file_unmap (hostkeys_map); - hostkeys_map = NULL; - hostkeys_data = NULL; - } - if (NULL != hostkeys_fd) - { - GNUNET_DISK_file_close (hostkeys_fd); - hostkeys_fd = NULL; - } -} - - -/** - * Shutdown task to cleanup our resources and exit. - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - if (NULL != transport) - { - GNUNET_TRANSPORT_manipulation_disconnect (transport); - transport = NULL; - } - cleanup_map (); - unload_keys (); - if (NULL != bh) - GNUNET_TRANSPORT_blacklist_cancel (bh); -} - - -/** - * Function to read whitelist rows from the database - * - * @param db the database connection - * @param pid the identity of this peer - * @param wl_rows where to store the retrieved whitelist rows - * @return GNUNET_SYSERR upon error OR the number of rows retrieved - */ -static int -db_read_whitelist (struct sqlite3 *db, int pid, struct WhiteListRow **wl_rows) -{ - static const char *query_wl = - "SELECT oid, latency FROM whitelist WHERE (id == ?);"; - struct sqlite3_stmt *stmt_wl; - struct WhiteListRow *lr; - int nrows; - int ret; - - if (SQLITE_OK != (ret = sqlite3_prepare_v2 (db, query_wl, -1, &stmt_wl, - NULL))) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2"); - return GNUNET_SYSERR; - } - if (SQLITE_OK != (ret = sqlite3_bind_int (stmt_wl, 1, pid))) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_int"); - sqlite3_finalize (stmt_wl); - return GNUNET_SYSERR; - } - nrows = 0; - do - { - ret = sqlite3_step (stmt_wl); - if (SQLITE_ROW != ret) - break; - nrows++; - lr = GNUNET_new (struct WhiteListRow); - lr->id = sqlite3_column_int (stmt_wl, 0); - lr->latency = sqlite3_column_int (stmt_wl, 1); - lr->next = *wl_rows; - *wl_rows = lr; - } - while (1); - sqlite3_finalize (stmt_wl); - return nrows; -} - - -/** - * 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 c configuration - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - char *dbfile; - struct WhiteListRow *wl_head; - struct WhiteListRow *wl_entry; - struct GNUNET_PeerIdentity identity; - struct GNUNET_ATS_Properties prop; - struct GNUNET_TIME_Relative delay; - unsigned long long pid; - unsigned int nrows; - int ret; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (c, "TESTBED", - "PEERID", &pid)) - { - GNUNET_break (0); - return; - } - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, - "TESTBED-UNDERLAY", - "DBFILE", - &dbfile)) - { - GNUNET_break (0); - return; - } - if (SQLITE_OK != (ret = sqlite3_open_v2 (dbfile, &db, SQLITE_OPEN_READONLY, - NULL))) - { - if (NULL != db) - { - LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_open_v2"); - GNUNET_break (SQLITE_OK == sqlite3_close (db)); - } - else - LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot open sqlite file %s\n", dbfile); - GNUNET_free (dbfile); - return; - } - DEBUG ("Opened database %s\n", dbfile); - GNUNET_free (dbfile); - dbfile = NULL; - wl_head = NULL; - if (GNUNET_OK != load_keys (c)) - goto close_db; - - transport = GNUNET_TRANSPORT_manipulation_connect (c); - if (NULL == transport) - { - GNUNET_break (0); - return; - } - /* read and process whitelist */ - nrows = 0; - wl_head = NULL; - nrows = db_read_whitelist (db, pid, &wl_head); - if ((GNUNET_SYSERR == nrows) || (0 == nrows)) - { - GNUNET_TRANSPORT_manipulation_disconnect (transport); - goto close_db; - } - map = GNUNET_CONTAINER_multipeermap_create (nrows, GNUNET_NO); - while (NULL != (wl_entry = wl_head)) - { - wl_head = wl_entry->next; - delay.rel_value_us = wl_entry->latency; - memset (&prop, 0, sizeof(prop)); - GNUNET_assert (GNUNET_OK == get_identity (wl_entry->id, &identity)); - GNUNET_break (GNUNET_OK == - GNUNET_CONTAINER_multipeermap_put (map, &identity, &identity, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); - DEBUG ("Setting %u ms latency to peer `%s'\n", - wl_entry->latency, - GNUNET_i2s (&identity)); - GNUNET_TRANSPORT_manipulation_set (transport, - &identity, - &prop, - delay, - delay); - GNUNET_free (wl_entry); - } - bh = GNUNET_TRANSPORT_blacklist (c, &check_access, NULL); - GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); - -close_db: - GNUNET_break (SQLITE_OK == sqlite3_close (db)); -} - - -/** - * The main function. - * - * @param argc number of arguments from the command line - * @param argv command line arguments - * @return 0 ok, 1 on error - */ -int -main (int argc, char *const *argv) -{ - static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - int ret; - - if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) - return 2; -#ifdef SQLITE_CONFIG_MMAP_SIZE - (void) sqlite3_config (SQLITE_CONFIG_MMAP_SIZE, 512000, 256000000); -#endif - ret = - (GNUNET_OK == - GNUNET_PROGRAM_run (argc, argv, "testbed-underlay", - _ - ( - "Daemon to restrict underlay network in testbed deployments"), - options, &run, NULL)) ? 0 : 1; - GNUNET_free_nz ((void *) argv); - return ret; -} diff --git a/src/testbed/gnunet-helper-testbed-valgrind.patch b/src/testbed/gnunet-helper-testbed-valgrind.patch @@ -1,21 +0,0 @@ -Index: gnunet-helper-testbed.c -=================================================================== ---- gnunet-helper-testbed.c (revision 32320) -+++ gnunet-helper-testbed.c (working copy) -@@ -462,7 +462,15 @@ - testbed = - GNUNET_OS_start_process (PIPE_CONTROL, - GNUNET_OS_INHERIT_STD_ERR /*verbose? */ , NULL, -- NULL, binary, "gnunet-service-testbed", "-c", -+ NULL, "valgrind", -+ "valgrind", -+ "--leak-check=full", -+ "--show-reachable=yes", -+ "--suppressions=$HOME/gnunet/src/util/util.supp", -+ "--suppressions=$HOME/gnunet/src/testbed/misc.supp", -+ "--suppressions=$HOME/gnunet/src/testbed/valgrind-zlib.supp", -+ "--suppressions=$HOME/gnunet/src/testbed/x64_misc.supp", -+ binary, "-c", - config, NULL); - GNUNET_free (binary); - GNUNET_free (config); diff --git a/src/testbed/gnunet-helper-testbed.c b/src/testbed/gnunet-helper-testbed.c @@ -1,613 +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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-helper-testbed.c - * @brief Helper binary that is started from a remote controller to start - * gnunet-service-testbed. This binary also receives configuration - * from the remove controller which is put in a temporary location - * with ports and paths fixed so that gnunet-service-testbed runs - * without any hurdles. - * - * 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 testbed crashed. In case of events 1 and 2 - * the helper kills the testbed service. When testbed crashed (event - * 3), the helper should send a SIGTERM to its own process group; this - * behaviour will help terminate any child processes (peers) testbed - * has started and prevents them from leaking and running forever. - * - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - - -#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 <zlib.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__) - - -/** - * 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; -}; - - -/** - * 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; - -/** - * The process handle to the testbed service - */ -static struct GNUNET_OS_Process *testbed; - -/** - * 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 != testbed) - { - LOG_DEBUG ("Killing testbed\n"); - GNUNET_break (0 == GNUNET_OS_process_kill (testbed, GNUNET_TERM_SIG)); - } - 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 != testbed) - { - GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (testbed)); - GNUNET_OS_process_destroy (testbed); - testbed = 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]; - enum GNUNET_OS_ProcessStatusType type; - unsigned long code; - int ret; - - 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"); - if (NULL == testbed) - { - GNUNET_break (0); - return; - } - GNUNET_break (GNUNET_SYSERR != - (ret = GNUNET_OS_process_status (testbed, &type, &code))); - if (GNUNET_NO != ret) - { - GNUNET_OS_process_destroy (testbed); - testbed = NULL; - /* Send SIGTERM to our process group */ - if (0 != kill (0, GNUNET_TERM_SIG)) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "signal"); - GNUNET_SCHEDULER_shutdown (); /* Couldn't send the signal, we shutdown frowning */ - } - return; - } - 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-service-testbed"); - { - 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; - } - testbed = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR /*verbose? */, - NULL, - NULL, - NULL, - binary, - "gnunet-service-testbed", - "-c", - config, - NULL); - GNUNET_free (binary); - GNUNET_free (config); - if (NULL == testbed) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Error starting gnunet-service-testbed -- exiting\n"); - GNUNET_CONFIGURATION_destroy (cfg); - goto error; - } - 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 testbed 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; - - 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-testbed", - "Helper for starting gnunet-service-testbed", - 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/gnunet-service-test-barriers.c b/src/testbed/gnunet-service-test-barriers.c @@ -1,152 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-service-test-barriers.c - * @brief Daemon acting as a service for testing testbed barriers. It is - * started as a peer service and waits for a barrier to be crossed. - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" -#include "test_testbed_api_barriers.h" - -/** - * logging short hand - */ -#define LOG(type, ...) \ - GNUNET_log (type, __VA_ARGS__); - -/** - * Our barrier wait handle - */ -static struct GNUNET_TESTBED_BarrierWaitHandle *wh; - -static struct GNUNET_SCHEDULER_Task *tt; - - -/** - * Dummy task callback to keep us running forever - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - if (NULL != wh) - { - GNUNET_TESTBED_barrier_wait_cancel (wh); - wh = NULL; - } - if (NULL != tt) - { - GNUNET_SCHEDULER_cancel (tt); - tt = NULL; - } -} - - -/** - * Functions of this type are to be given as acallback argument to - * GNUNET_TESTBED_barrier_wait(). The callback will be called when the barrier - * corresponding given in GNUNET_TESTBED_barrier_wait() is crossed or cancelled. - * - * @param cls NULL - * @param name the barrier name - * @param status #GNUNET_SYSERR in case of error while waiting for the barrier; - * #GNUNET_OK if the barrier is crossed - */ -static void -barrier_wait_cb (void *cls, - const char *name, - int status) -{ - GNUNET_break (NULL == cls); - wh = NULL; - GNUNET_break (GNUNET_OK == status); -} - - -/** - * Task to wait for the barrier - * - * @param cls NULL - * @return - */ -static void -do_wait (void *cls) -{ - tt = NULL; - wh = GNUNET_TESTBED_barrier_wait (TEST_BARRIER_NAME, - &barrier_wait_cb, - NULL); - GNUNET_break (NULL != wh); -} - - -/** - * Main run function. - * - * @param cls NULL - * @param args arguments passed to GNUNET_PROGRAM_run - * @param cfgfile the path to configuration file - * @param config the configuration file handle - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - unsigned int rsec; - - rsec = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, - 10); - tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply ( - GNUNET_TIME_UNIT_SECONDS, - rsec), - &do_wait, - NULL); - GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); -} - - -/** - * Main - */ -int -main (int argc, char **argv) -{ - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - int ret; - - ret = - GNUNET_PROGRAM_run (argc, argv, - "test-barriers", - "nohelp", - options, - &run, - NULL); - return ret; -} diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c @@ -1,981 +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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-service-testbed.c - * @brief implementation of the TESTBED service - * @author Sree Harsha Totakura - */ - -#include "platform.h" -#include "gnunet-service-testbed.h" -#include "gnunet-service-testbed_barriers.h" -#include "gnunet-service-testbed_connectionpool.h" - -/***********/ -/* Globals */ -/***********/ - -/** - * Our configuration - */ -struct GNUNET_CONFIGURATION_Handle *GST_config; - -/** - * The master context; generated with the first INIT message - */ -struct Context *GST_context; - -/** - * Array of hosts - */ -struct GNUNET_TESTBED_Host **GST_host_list; - -/** - * DLL head for forwarded operation contexts - */ -struct ForwardedOperationContext *fopcq_head; - -/** - * DLL tail for forwarded operation contexts - */ -struct ForwardedOperationContext *fopcq_tail; - -/** - * Operation queue for open file descriptors - */ -struct OperationQueue *GST_opq_openfds; - -/** - * Timeout for operations which may take some time - */ -struct GNUNET_TIME_Relative GST_timeout; - -/** - * The size of the host list - */ -unsigned int GST_host_list_size; - -/** - * The size of the peer list - */ -unsigned int GST_peer_list_size; - - -/***********************************/ -/* Local definitions and variables */ -/***********************************/ - -/** - * Our hostname; we give this to all the peers we start - */ -static char *hostname; - - -/** - * Function to add a host to the current list of known hosts - * - * @param host the host to add - * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure due to host-id - * already in use - */ -static int -host_list_add (struct GNUNET_TESTBED_Host *host) -{ - uint32_t host_id; - - host_id = GNUNET_TESTBED_host_get_id_ (host); - if (GST_host_list_size <= host_id) - GST_array_grow_large_enough (GST_host_list, GST_host_list_size, host_id); - if (NULL != GST_host_list[host_id]) - { - LOG_DEBUG ("A host with id: %u already exists\n", host_id); - return GNUNET_SYSERR; - } - GST_host_list[host_id] = host; - return GNUNET_OK; -} - - -/** - * Send operation failure message to client - * - * @param client the client to which the failure message has to be sent to - * @param operation_id the id of the failed operation - * @param emsg the error message; can be NULL - */ -void -GST_send_operation_fail_msg (struct GNUNET_SERVICE_Client *client, - uint64_t operation_id, - const char *emsg) -{ - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_OperationFailureEventMessage *msg; - uint16_t emsg_len; - - emsg_len = (NULL == emsg) ? 0 : strlen (emsg) + 1; - env = GNUNET_MQ_msg_extra (msg, - emsg_len, - GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT); - msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED); - msg->operation_id = GNUNET_htonll (operation_id); - GNUNET_memcpy (&msg[1], - emsg, - emsg_len); - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), - env); -} - - -/** - * Function to send generic operation success message to given client - * - * @param client the client to send the message to - * @param operation_id the id of the operation which was successful - */ -void -GST_send_operation_success_msg (struct GNUNET_SERVICE_Client *client, - uint64_t operation_id) -{ - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg; - - env = GNUNET_MQ_msg (msg, - GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS); - msg->operation_id = GNUNET_htonll (operation_id); - msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED); - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), - env); -} - - -/** - * Callback which will be called after a host registration succeeded or failed - * - * @param cls the handle to the slave at which the registration is completed - * @param emsg the error message; NULL if host registration is successful - */ -static void -hr_completion (void *cls, - const char *emsg); - - -/** - * Attempts to register the next host in the host registration queue - * - * @param slave the slave controller whose host registration queue is checked - * for host registrations - */ -static void -register_next_host (struct Slave *slave) -{ - struct HostRegistration *hr; - - hr = slave->hr_dll_head; - GNUNET_assert (NULL != hr); - GNUNET_assert (NULL == slave->rhandle); - LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering host %u at %u\n", - GNUNET_TESTBED_host_get_id_ (hr->host), - GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); - slave->rhandle - = GNUNET_TESTBED_register_host (slave->controller, - hr->host, - hr_completion, - slave); -} - - -/** - * Callback which will be called to after a host registration succeeded or failed - * - * @param cls the handle to the slave at which the registration is completed - * @param emsg the error message; NULL if host registration is successful - */ -static void -hr_completion (void *cls, - const char *emsg) -{ - struct Slave *slave = cls; - struct HostRegistration *hr; - - slave->rhandle = NULL; - hr = slave->hr_dll_head; - GNUNET_assert (NULL != hr); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Registering host %u at %u successful\n", - GNUNET_TESTBED_host_get_id_ (hr->host), - GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); - GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, - slave->hr_dll_tail, - hr); - if (NULL != hr->cb) - hr->cb (hr->cb_cls, - emsg); - GNUNET_free (hr); - if (NULL != slave->hr_dll_head) - register_next_host (slave); -} - - -/** - * Adds a host registration's request to a slave's registration queue - * - * @param slave the slave controller at which the given host has to be - * registered - * @param cb the host registration completion callback - * @param cb_cls the closure for the host registration completion callback - * @param host the host which has to be registered - */ -void -GST_queue_host_registration (struct Slave *slave, - GNUNET_TESTBED_HostRegistrationCompletion cb, - void *cb_cls, - struct GNUNET_TESTBED_Host *host) -{ - struct HostRegistration *hr; - int call_register; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Queueing host registration for host %u at %u\n", - GNUNET_TESTBED_host_get_id_ (host), - GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); - hr = GNUNET_new (struct HostRegistration); - hr->cb = cb; - hr->cb_cls = cb_cls; - hr->host = host; - call_register = (NULL == slave->hr_dll_head) ? GNUNET_YES : GNUNET_NO; - GNUNET_CONTAINER_DLL_insert_tail (slave->hr_dll_head, - slave->hr_dll_tail, - hr); - if (GNUNET_YES == call_register) - register_next_host (slave); -} - - -/** - * Callback to relay the reply msg of a forwarded operation back to the client - * - * @param cls ForwardedOperationContext - * @param msg the message to relay - */ -void -GST_forwarded_operation_reply_relay (void *cls, - const struct GNUNET_MessageHeader *msg) -{ - struct ForwardedOperationContext *fopc = cls; - struct GNUNET_MQ_Envelope *env; - - LOG_DEBUG ("Relaying message with type: %u, size: %u\n", - ntohs (msg->type), - ntohs (msg->size)); - env = GNUNET_MQ_msg_copy (msg); - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (fopc->client), - env); - GNUNET_SCHEDULER_cancel (fopc->timeout_task); - GNUNET_CONTAINER_DLL_remove (fopcq_head, - fopcq_tail, - fopc); - GNUNET_free (fopc); -} - - -void -GST_forwarded_operation_timeout (void *cls) -{ - struct ForwardedOperationContext *fopc = cls; - - fopc->timeout_task = NULL; - GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "A forwarded operation has timed out\n"); - GST_send_operation_fail_msg (fopc->client, - fopc->operation_id, - "A forwarded operation has timed out"); - GNUNET_CONTAINER_DLL_remove (fopcq_head, - fopcq_tail, - fopc); - GNUNET_free (fopc); -} - - -/** - * Parse service sharing specification line. - * Format is "[<service:share>] [<service:share>] ..." - * - * @param ss_str the spec string to be parsed - * @param cfg the configuration to use for shared services - * @return an array suitable to pass to GNUNET_TESTING_system_create(). NULL - * upon empty service sharing specification. - */ -static struct GNUNET_TESTING_SharedService * -parse_shared_services (char *ss_str, - struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_TESTING_SharedService ss; - struct GNUNET_TESTING_SharedService *slist; - char service[256]; - char *arg; - unsigned int n; - -#define GROW_SS \ - do { \ - GNUNET_array_grow (slist, n, n + 1); \ - GNUNET_memcpy (&slist[n - 1], &ss, \ - sizeof(struct GNUNET_TESTING_SharedService)); \ - } while (0) - - slist = NULL; - n = 0; - ss.cfg = cfg; - for (; NULL != (arg = strtok (ss_str, " ")); ss_str = NULL) - { - ss.service = NULL; - ss.share = 0; - if (2 != sscanf (arg, "%255[^:]:%u", - service, - &ss.share)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Ignoring shared service spec: %s", - arg); - continue; - } - LOG_DEBUG ("Will be sharing %s service among %u peers\n", - service, - ss.share); - ss.service = GNUNET_strdup (service); - GROW_SS; - } - if (NULL != slist) - { - /* Add trailing NULL block */ - (void) memset (&ss, - 0, - sizeof(struct GNUNET_TESTING_SharedService)); - GROW_SS; - } - return slist; -#undef GROW_SS -} - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_INIT messages - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a message is well-formed - */ -static int -check_init (void *cls, - const struct GNUNET_TESTBED_InitMessage *msg) -{ - const char *controller_hostname; - uint16_t msize; - - msize = ntohs (msg->header.size) - sizeof(struct GNUNET_TESTBED_InitMessage); - controller_hostname = (const char *) &msg[1]; - if ('\0' != controller_hostname[msize - 1]) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_INIT messages - * - * @param cls identification of the client - * @param msg the actual message - */ -static void -handle_init (void *cls, - const struct GNUNET_TESTBED_InitMessage *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct GNUNET_TESTBED_Host *host; - const char *controller_hostname; - char *ss_str; - struct GNUNET_TESTING_SharedService *ss; - unsigned int cnt; - - if (NULL != GST_context) - { - LOG_DEBUG ("We are being connected to laterally\n"); - GNUNET_SERVICE_client_continue (client); - return; - } - controller_hostname = (const char *) &msg[1]; - ss_str = NULL; - ss = NULL; - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (GST_config, - "TESTBED", - "SHARED_SERVICES", - &ss_str)) - { - ss = parse_shared_services (ss_str, - GST_config); - GNUNET_free (ss_str); - ss_str = NULL; - } - GST_context = GNUNET_new (struct Context); - GST_context->client = client; - GST_context->host_id = ntohl (msg->host_id); - GST_context->master_ip = GNUNET_strdup (controller_hostname); - LOG_DEBUG ("Our IP: %s\n", - GST_context->master_ip); - GST_context->system - = GNUNET_TESTING_system_create ("testbed", - GST_context->master_ip, - hostname, - ss); - if (NULL != ss) - { - for (cnt = 0; NULL != ss[cnt].service; cnt++) - { - ss_str = (char *) ss[cnt].service; - GNUNET_free (ss_str); - } - GNUNET_free (ss); - ss = NULL; - } - host = - GNUNET_TESTBED_host_create_with_id (GST_context->host_id, - GST_context->master_ip, - NULL, - GST_config, - 0); - host_list_add (host); - LOG_DEBUG ("Created master context with host ID: %u\n", - GST_context->host_id); - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a message is well-formed - */ -static int -check_add_host (void *cls, - const struct GNUNET_TESTBED_AddHostMessage *msg) -{ - uint16_t username_length; - uint16_t hostname_length; - uint16_t msize; - - msize = ntohs (msg->header.size) - sizeof(struct - GNUNET_TESTBED_AddHostMessage); - username_length = ntohs (msg->username_length); - hostname_length = ntohs (msg->hostname_length); - /* msg must contain hostname */ - if ((msize <= username_length) || - (0 == hostname_length)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - /* msg must contain configuration */ - if (msize <= username_length + hostname_length) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages - * - * @param cls identification of the client - * @param msg the actual message - */ -static void -handle_add_host (void *cls, - const struct GNUNET_TESTBED_AddHostMessage *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct GNUNET_TESTBED_Host *host; - struct GNUNET_TESTBED_HostConfirmedMessage *reply; - struct GNUNET_CONFIGURATION_Handle *host_cfg; - char *username; - char *hostname; - char *emsg; - const void *ptr; - uint32_t host_id; - uint16_t username_length; - uint16_t hostname_length; - struct GNUNET_MQ_Envelope *env; - - username_length = ntohs (msg->username_length); - hostname_length = ntohs (msg->hostname_length); - username = NULL; - hostname = NULL; - ptr = &msg[1]; - if (0 != username_length) - { - username = GNUNET_malloc (username_length + 1); - GNUNET_strlcpy (username, ptr, username_length + 1); - ptr += username_length; - } - hostname = GNUNET_malloc (hostname_length + 1); - GNUNET_strlcpy (hostname, ptr, hostname_length + 1); - if (NULL == (host_cfg = GNUNET_TESTBED_extract_config_ (&msg->header))) - { - GNUNET_free (username); - GNUNET_free (hostname); - GNUNET_break_op (0); - GNUNET_SERVICE_client_drop (client); - return; - } - host_id = ntohl (msg->host_id); - LOG_DEBUG ("Received ADDHOST %u message\n", host_id); - LOG_DEBUG ("-------host id: %u\n", host_id); - LOG_DEBUG ("-------hostname: %s\n", hostname); - if (NULL != username) - LOG_DEBUG ("-------username: %s\n", username); - else - LOG_DEBUG ("-------username: <not given>\n"); - LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port)); - host = GNUNET_TESTBED_host_create_with_id (host_id, - hostname, - username, - host_cfg, - ntohs (msg->ssh_port)); - GNUNET_free (username); - GNUNET_free (hostname); - GNUNET_CONFIGURATION_destroy (host_cfg); - if (NULL == host) - { - GNUNET_break_op (0); - GNUNET_SERVICE_client_drop (client); - return; - } - if (GNUNET_OK != host_list_add (host)) - { - /* We are unable to add a host */ - emsg = "A host exists with given host-id"; - LOG_DEBUG ("%s: %u", - emsg, - host_id); - GNUNET_TESTBED_host_destroy (host); - env = GNUNET_MQ_msg_extra (reply, - strlen (emsg) + 1, - GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS); - GNUNET_memcpy (&reply[1], - emsg, - strlen (emsg) + 1); - } - else - { - LOG_DEBUG ("Added host %u at %u\n", - host_id, - GST_context->host_id); - env = GNUNET_MQ_msg (reply, - GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS); - } - reply->host_id = htonl (host_id); - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), - env); - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages - * - * @param cls identification of the client - * @param msg the actual message - */ -static void -handle_slave_get_config (void *cls, - const struct - GNUNET_TESTBED_SlaveGetConfigurationMessage *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct Slave *slave; - struct GNUNET_TESTBED_SlaveConfiguration *reply; - const struct GNUNET_CONFIGURATION_Handle *cfg; - struct GNUNET_MQ_Envelope *env; - char *config; - char *xconfig; - size_t config_size; - size_t xconfig_size; - uint64_t op_id; - uint32_t slave_id; - - slave_id = ntohl (msg->slave_id); - op_id = GNUNET_ntohll (msg->operation_id); - if ((GST_slave_list_size <= slave_id) || - (NULL == GST_slave_list[slave_id])) - { - /* FIXME: Add forwardings for this type of message here.. */ - GST_send_operation_fail_msg (client, - op_id, - "Slave not found"); - GNUNET_SERVICE_client_continue (client); - return; - } - slave = GST_slave_list[slave_id]; - GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ ( - GST_host_list[slave->host_id]))); - config = GNUNET_CONFIGURATION_serialize (cfg, - &config_size); - /* FIXME: maybe we want to transmit the delta to the default here? */ - xconfig_size = GNUNET_TESTBED_compress_config_ (config, - config_size, - &xconfig); - GNUNET_free (config); - GNUNET_assert (xconfig_size + sizeof(struct - GNUNET_TESTBED_SlaveConfiguration) <= - UINT16_MAX); - GNUNET_assert (xconfig_size <= UINT16_MAX); - env = GNUNET_MQ_msg_extra (reply, - xconfig_size, - GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION); - reply->slave_id = msg->slave_id; - reply->operation_id = msg->operation_id; - reply->config_size = htons ((uint16_t) config_size); - GNUNET_memcpy (&reply[1], - xconfig, - xconfig_size); - GNUNET_free (xconfig); - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), - env); - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Clears the forwarded operations queue - */ -void -GST_clear_fopcq () -{ - struct ForwardedOperationContext *fopc; - - while (NULL != (fopc = fopcq_head)) - { - GNUNET_CONTAINER_DLL_remove (fopcq_head, - fopcq_tail, - fopc); - GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc); - if (NULL != fopc->timeout_task) - GNUNET_SCHEDULER_cancel (fopc->timeout_task); - switch (fopc->type) - { - case OP_PEER_CREATE: - GNUNET_free (fopc->cls); - break; - - case OP_SHUTDOWN_PEERS: - { - struct HandlerContext_ShutdownPeers *hc = fopc->cls; - - GNUNET_assert (0 < hc->nslaves); - hc->nslaves--; - if (0 == hc->nslaves) - GNUNET_free (hc); - } - break; - - case OP_PEER_START: - case OP_PEER_STOP: - case OP_PEER_DESTROY: - case OP_PEER_INFO: - case OP_OVERLAY_CONNECT: - case OP_LINK_CONTROLLERS: - case OP_GET_SLAVE_CONFIG: - case OP_MANAGE_SERVICE: - case OP_PEER_RECONFIGURE: - break; - - case OP_FORWARDED: - GNUNET_assert (0); - } - ; - GNUNET_free (fopc); - } -} - - -/** - * Task to clean up and shutdown nicely - * - * @param cls NULL - */ -static void -shutdown_task (void *cls) -{ - uint32_t id; - - LOG_DEBUG ("Shutting down testbed service\n"); - /* cleanup any remaining forwarded operations */ - GST_clear_fopcq (); - GST_free_lcf (); - GST_free_mctxq (); - GST_free_occq (); - GST_free_roccq (); - GST_free_nccq (); - GST_neighbour_list_clean (); - GST_free_prcq (); - /* Clear peer list */ - GST_destroy_peers (); - /* Clear route list */ - GST_route_list_clear (); - /* Clear GST_slave_list */ - GST_slave_list_clear (); - /* Clear host list */ - for (id = 0; id < GST_host_list_size; id++) - if (NULL != GST_host_list[id]) - GNUNET_TESTBED_host_destroy (GST_host_list[id]); - GNUNET_free (GST_host_list); - if (NULL != GST_context) - { - GNUNET_free (GST_context->master_ip); - if (NULL != GST_context->system) - GNUNET_TESTING_system_destroy (GST_context->system, - GNUNET_YES); - GNUNET_free (GST_context); - GST_context = NULL; - } - GNUNET_free (hostname); - /* Free hello cache */ - GST_cache_clear (); - GST_connection_pool_destroy (); - GNUNET_TESTBED_operation_queue_destroy_ (GST_opq_openfds); - GST_opq_openfds = NULL; - GST_stats_destroy (); - GST_barriers_destroy (); - GNUNET_CONFIGURATION_destroy (GST_config); -} - - -/** - * Callback for client connect - * - * @param cls NULL - * @param client the client which has disconnected - * @param mq queue for sending messages to @a client - * @return @a client - */ -static void * -client_connect_cb (void *cls, - struct GNUNET_SERVICE_Client *client, - struct GNUNET_MQ_Handle *mq) -{ - return client; -} - - -/** - * Callback for client disconnect - * - * @param cls NULL - * @param client the client which has disconnected - * @param app_ctx should match @a client - */ -static void -client_disconnect_cb (void *cls, - struct GNUNET_SERVICE_Client *client, - void *app_ctx) -{ - struct ForwardedOperationContext *fopc; - struct ForwardedOperationContext *fopcn; - - GNUNET_assert (client == app_ctx); - GST_notify_client_disconnect_oc (client); - GST_link_notify_disconnect (client); - GST_notify_client_disconnect_peers (client); - for (fopc = fopcq_head; NULL != fopc; fopc = fopcn) - { - fopcn = fopc->next; - if (fopc->client == client) - { - /* handle as if it were a timeout */ - GNUNET_SCHEDULER_cancel (fopc->timeout_task); - GST_forwarded_operation_timeout (fopc); - } - } - if (NULL == GST_context) - return; - if (client == GST_context->client) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Master client disconnected\n"); - GST_context->client = NULL; - /* should not be needed as we're terminated by failure to read - * from stdin, but if stdin fails for some reason, this shouldn't - * hurt for now --- might need to revise this later if we ever - * decide that master connections might be temporarily down - * for some reason */// GNUNET_SCHEDULER_shutdown (); - } -} - - -/** - * Testbed setup - * - * @param cls closure - * @param cfg configuration to use - * @param service the initialized server - */ -static void -testbed_run (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_SERVICE_Handle *service) -{ - char *logfile; - unsigned long long num; - - LOG_DEBUG ("Starting testbed\n"); - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED", "LOG_FILE", - &logfile)) - { - GNUNET_break (GNUNET_OK == - GNUNET_log_setup ("testbed", - "DEBUG", - logfile)); - GNUNET_free (logfile); - } - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number (cfg, - "testbed", - "CACHE_SIZE", - &num)); - GST_cache_init ((unsigned int) num); - GST_connection_pool_init ((unsigned int) num); - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number (cfg, - "testbed", - "MAX_OPEN_FDS", - &num)); - GST_opq_openfds = GNUNET_TESTBED_operation_queue_create_ ( - OPERATION_QUEUE_TYPE_FIXED, - (unsigned int) num); - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_time (cfg, - "testbed", - "OPERATION_TIMEOUT", - &GST_timeout)); - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (cfg, - "testbed", - "HOSTNAME", - &hostname)); - GST_config = GNUNET_CONFIGURATION_dup (cfg); - GNUNET_SCHEDULER_add_shutdown (&shutdown_task, - NULL); - LOG_DEBUG ("Testbed startup complete\n"); - GST_stats_init (GST_config); - GST_barriers_init (GST_config); -} - - -/** - * Define "main" method using service macro. - */ -GNUNET_SERVICE_MAIN - ("testbed", - GNUNET_SERVICE_OPTION_NONE, - &testbed_run, - &client_connect_cb, - &client_disconnect_cb, - NULL, - GNUNET_MQ_hd_var_size (init, - GNUNET_MESSAGE_TYPE_TESTBED_INIT, - struct GNUNET_TESTBED_InitMessage, - NULL), - GNUNET_MQ_hd_var_size (add_host, - GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, - struct GNUNET_TESTBED_AddHostMessage, - NULL), - GNUNET_MQ_hd_fixed_size (slave_get_config, - GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION, - struct GNUNET_TESTBED_SlaveGetConfigurationMessage, - NULL), - GNUNET_MQ_hd_fixed_size (link_controllers, - GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, - struct GNUNET_TESTBED_ControllerLinkRequest, - NULL), - GNUNET_MQ_hd_var_size (remote_overlay_connect, - GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT, - struct GNUNET_TESTBED_RemoteOverlayConnectMessage, - NULL), - GNUNET_MQ_hd_fixed_size (overlay_connect, - GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT, - struct GNUNET_TESTBED_OverlayConnectMessage, - NULL), - GNUNET_MQ_hd_var_size (peer_create, - GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER, - struct GNUNET_TESTBED_PeerCreateMessage, - NULL), - GNUNET_MQ_hd_fixed_size (peer_destroy, - GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER, - struct GNUNET_TESTBED_PeerDestroyMessage, - NULL), - GNUNET_MQ_hd_fixed_size (peer_start, - GNUNET_MESSAGE_TYPE_TESTBED_START_PEER, - struct GNUNET_TESTBED_PeerStartMessage, - NULL), - GNUNET_MQ_hd_fixed_size (peer_stop, - GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER, - struct GNUNET_TESTBED_PeerStopMessage, - NULL), - GNUNET_MQ_hd_fixed_size (peer_get_config, - GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION, - struct GNUNET_TESTBED_PeerGetConfigurationMessage, - NULL), - GNUNET_MQ_hd_var_size (manage_peer_service, - GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE, - struct GNUNET_TESTBED_ManagePeerServiceMessage, - NULL), - GNUNET_MQ_hd_fixed_size (shutdown_peers, - GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS, - struct GNUNET_TESTBED_ShutdownPeersMessage, - NULL), - GNUNET_MQ_hd_var_size (peer_reconfigure, - GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER, - struct GNUNET_TESTBED_PeerReconfigureMessage, - NULL), - GNUNET_MQ_hd_var_size (barrier_init, - GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT, - struct GNUNET_TESTBED_BarrierInit, - NULL), - GNUNET_MQ_hd_var_size (barrier_cancel, - GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL, - struct GNUNET_TESTBED_BarrierCancel, - NULL), - GNUNET_MQ_hd_var_size (barrier_status, - GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, - struct GNUNET_TESTBED_BarrierStatusMsg, - NULL), - GNUNET_MQ_handler_end ()); - - -/* end of gnunet-service-testbed.c */ diff --git a/src/testbed/gnunet-service-testbed.h b/src/testbed/gnunet-service-testbed.h @@ -1,899 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-service-testbed.h - * @brief data structures shared amongst components of TESTBED service - * @author Sree Harsha Totakura - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" -#include "gnunet_transport_service.h" -#include "gnunet_core_service.h" - -#include "testbed.h" -#include "testbed_api.h" -#include "testbed_api_operations.h" -#include "testbed_api_hosts.h" -#include "gnunet_testing_lib.h" -#include "gnunet-service-testbed_links.h" - - -/** - * Generic logging - */ -#define LOG(kind, ...) \ - GNUNET_log (kind, __VA_ARGS__) - -/** - * Debug logging - */ -#define LOG_DEBUG(...) \ - LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) - -/** - * By how much should the arrays lists grow - */ -#define LIST_GROW_STEP 10 - - -/** - * A routing entry - */ -struct Route -{ - /** - * destination host - */ - uint32_t dest; - - /** - * The destination host is reachable thru - */ - uint32_t thru; -}; - - -/** - * Context information for operations forwarded to subcontrollers - */ -struct ForwardedOperationContext -{ - /** - * The next pointer for DLL - */ - struct ForwardedOperationContext *next; - - /** - * The prev pointer for DLL - */ - struct ForwardedOperationContext *prev; - - /** - * The generated operation context - */ - struct OperationContext *opc; - - /** - * The client to which we have to reply - */ - struct GNUNET_SERVICE_Client *client; - - /** - * Closure pointer - */ - void *cls; - - /** - * Task ID for the timeout task - */ - struct GNUNET_SCHEDULER_Task *timeout_task; - - /** - * The id of the operation that has been forwarded - */ - uint64_t operation_id; - - /** - * The type of the operation which is forwarded - */ - enum OperationType type; -}; - - -/** - * A DLL of host registrations to be made - */ -struct HostRegistration -{ - /** - * next registration in the DLL - */ - struct HostRegistration *next; - - /** - * previous registration in the DLL - */ - struct HostRegistration *prev; - - /** - * The callback to call after this registration's status is available - */ - GNUNET_TESTBED_HostRegistrationCompletion cb; - - /** - * The closure for the above callback - */ - void *cb_cls; - - /** - * The host that has to be registered - */ - struct GNUNET_TESTBED_Host *host; -}; - - -/** - * Context information used while linking controllers - */ -struct LinkControllersContext -{ - /** - * The client which initiated the link controller operation - */ - struct GNUNET_SERVICE_Client *client; - - /** - * The ID of the operation - */ - uint64_t operation_id; -}; - - -/** - * A peer - */ -struct Peer -{ - union - { - struct - { - /** - * The peer handle from testing API - */ - struct GNUNET_TESTING_Peer *peer; - - /** - * The modified (by GNUNET_TESTING_peer_configure) configuration this - * peer is configured with - */ - struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Is the peer running - */ - int is_running; - } local; - - struct - { - /** - * The slave this peer is started through - */ - struct Slave *slave; - - /** - * The id of the remote host this peer is running on - */ - uint32_t remote_host_id; - } remote; - } details; - - /** - * Is this peer locally created? - */ - int is_remote; - - /** - * Our local reference id for this peer - */ - uint32_t id; - - /** - * References to peers are using in forwarded overlay contexts and remote - * overlay connect contexts. A peer can only be destroyed after all such - * contexts are destroyed. For this, we maintain a reference counter. When we - * use a peer in any such context, we increment this counter. We decrement it - * when we are destroying these contexts - */ - uint32_t reference_cnt; - - /** - * While destroying a peer, due to the fact that there could be references to - * this peer, we delay the peer destroy to a further time. We do this by using - * this flag to destroy the peer while destroying a context in which this peer - * has been used. When the flag is set to 1 and reference_cnt = 0 we destroy - * the peer - */ - uint32_t destroy_flag; -}; - - -/** - * The main context information associated with the client which started us - */ -struct Context -{ - /** - * The client handle associated with this context - */ - struct GNUNET_SERVICE_Client *client; - - /** - * The network address of the master controller - */ - char *master_ip; - - /** - * The TESTING system handle for starting peers locally - */ - struct GNUNET_TESTING_System *system; - - /** - * Our host id according to this context - */ - uint32_t host_id; -}; - - -/** - * The structure for identifying a shared service - */ -struct SharedService -{ - /** - * The name of the shared service - */ - char *name; - - /** - * Number of shared peers per instance of the shared service - */ - uint32_t num_shared; - - /** - * Number of peers currently sharing the service - */ - uint32_t num_sharing; -}; - - -struct RegisteredHostContext; - - -/** - * Context information to used during operations which forward the overlay - * connect message - */ -struct ForwardedOverlayConnectContext -{ - /** - * next ForwardedOverlayConnectContext in the DLL - */ - struct ForwardedOverlayConnectContext *next; - - /** - * previous ForwardedOverlayConnectContext in the DLL - */ - struct ForwardedOverlayConnectContext *prev; - - /** - * Which host does this FOCC belong to? - */ - struct RegisteredHostContext *rhc; - - /** - * A copy of the original overlay connect message - */ - struct GNUNET_MessageHeader *orig_msg; - - /** - * The client handle - */ - struct GNUNET_SERVICE_Client *client; - - /** - * The id of the operation which created this context information - */ - uint64_t operation_id; - - /** - * the id of peer 1 - */ - uint32_t peer1; - - /** - * The id of peer 2 - */ - uint32_t peer2; - - /** - * Id of the host where peer2 is running - */ - uint32_t peer2_host_id; -}; - - -/** - * This context information will be created for each host that is registered at - * slave controllers during overlay connects. - */ -struct RegisteredHostContext -{ - /** - * The host which is being registered - */ - struct GNUNET_TESTBED_Host *reg_host; - - /** - * The host of the controller which has to connect to the above rhost - */ - struct GNUNET_TESTBED_Host *host; - - /** - * Head of the ForwardedOverlayConnectContext DLL - */ - struct ForwardedOverlayConnectContext *focc_dll_head; - - /** - * Tail of the ForwardedOverlayConnectContext DLL - */ - struct ForwardedOverlayConnectContext *focc_dll_tail; - - /** - * Enumeration of states for this context - */ - enum RHCState - { - /** - * The initial state - */ - RHC_INIT = 0, - - /** - * State where we attempt to do the overlay connection again - */ - RHC_DONE - } state; -}; - - -/** - * Context data for #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS handler - */ -struct HandlerContext_ShutdownPeers -{ - /** - * The number of slave we expect to hear from since we forwarded the - * #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS message to them - */ - unsigned int nslaves; - - /** - * Did we observe a timeout with respect to this operation at any of the - * slaves - */ - int timeout; -}; - - -/** - * Our configuration - */ -extern struct GNUNET_CONFIGURATION_Handle *GST_config; - -/** - * The master context; generated with the first INIT message - */ -extern struct Context *GST_context; - -/** - * DLL head for forwarded operation contexts - */ -extern struct ForwardedOperationContext *fopcq_head; - -/** - * DLL tail for forwarded operation contexts - */ -extern struct ForwardedOperationContext *fopcq_tail; - -/** - * A list of peers we know about - */ -extern struct Peer **GST_peer_list; - -/** - * Array of hosts - */ -extern struct GNUNET_TESTBED_Host **GST_host_list; - -/** - * Operation queue for open file descriptors - */ -extern struct OperationQueue *GST_opq_openfds; - -/** - * Timeout for operations which may take some time - */ -extern struct GNUNET_TIME_Relative GST_timeout; - -/** - * The size of the peer list - */ -extern unsigned int GST_peer_list_size; - -/** - * The current number of peers running locally under this controller - */ -extern unsigned int GST_num_local_peers; - -/** - * The size of the host list - */ -extern unsigned int GST_host_list_size; - -/** - * The directory where to store load statistics data - */ -extern char *GST_stats_dir; - -/** - * Condition to check if host id is valid - */ -#define VALID_HOST_ID(id) \ - (((id) < GST_host_list_size) && (NULL != GST_host_list[id])) - -/** - * Condition to check if peer id is valid - */ -#define VALID_PEER_ID(id) \ - (((id) < GST_peer_list_size) && (NULL != GST_peer_list[id])) - - -/** - * Similar to GNUNET_array_grow(); however instead of calling GNUNET_array_grow() - * several times we call it only once. The array is also made to grow in steps - * of LIST_GROW_STEP. - * - * @param ptr the array pointer to grow - * @param size the size of array - * @param accommodate_size the size which the array has to accommdate; after - * this call the array will be big enough to accommdate sizes up to - * accommodate_size - */ -#define GST_array_grow_large_enough(ptr, size, accommodate_size) \ - do \ - { \ - unsigned int growth_size; \ - GNUNET_assert (size <= accommodate_size); \ - growth_size = size; \ - while (growth_size <= accommodate_size) \ - growth_size += LIST_GROW_STEP; \ - GNUNET_array_grow (ptr, size, growth_size); \ - GNUNET_assert (size > accommodate_size); \ - } while (0) - - -/** - * Function to destroy a peer - * - * @param peer the peer structure to destroy - */ -void -GST_destroy_peer (struct Peer *peer); - - -/** - * Stops and destroys all peers - */ -void -GST_destroy_peers (void); - - -/** - * Finds the route with directly connected host as destination through which - * the destination host can be reached - * - * @param host_id the id of the destination host - * @return the route with directly connected destination host; NULL if no route - * is found - */ -struct Route * -GST_find_dest_route (uint32_t host_id); - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_overlay_connect (void *cls, - const struct GNUNET_TESTBED_OverlayConnectMessage *msg); - - -/** - * Adds a host registration's request to a slave's registration queue - * - * @param slave the slave controller at which the given host has to be - * registered - * @param cb the host registration completion callback - * @param cb_cls the closure for the host registration completion callback - * @param host the host which has to be registered - */ -void -GST_queue_host_registration (struct Slave *slave, - GNUNET_TESTBED_HostRegistrationCompletion cb, - void *cb_cls, struct GNUNET_TESTBED_Host *host); - - -/** - * Callback to relay the reply msg of a forwarded operation back to the client - * - * @param cls ForwardedOperationContext - * @param msg the message to relay - */ -void -GST_forwarded_operation_reply_relay (void *cls, - const struct GNUNET_MessageHeader *msg); - - -/** - * Task to free resources when forwarded operation has been timed out. - * - * @param cls the ForwardedOperationContext - */ -void -GST_forwarded_operation_timeout (void *cls); - - -/** - * Clears the forwarded operations queue - */ -void -GST_clear_fopcq (void); - - -/** - * Send operation failure message to client - * - * @param client the client to which the failure message has to be sent to - * @param operation_id the id of the failed operation - * @param emsg the error message; can be NULL - */ -void -GST_send_operation_fail_msg (struct GNUNET_SERVICE_Client *client, - uint64_t operation_id, - const char *emsg); - - -/** - * Notify OC subsystem that @a client disconnected. - * - * @param client the client that disconnected - */ -void -GST_notify_client_disconnect_oc (struct GNUNET_SERVICE_Client *client); - - -/** - * Notify peers subsystem that @a client disconnected. - * - * @param client the client that disconnected - */ -void -GST_notify_client_disconnect_peers (struct GNUNET_SERVICE_Client *client); - - -/** - * Function to send generic operation success message to given client - * - * @param client the client to send the message to - * @param operation_id the id of the operation which was successful - */ -void -GST_send_operation_success_msg (struct GNUNET_SERVICE_Client *client, - uint64_t operation_id); - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_remote_overlay_connect (void *cls, - const struct - GNUNET_TESTBED_RemoteOverlayConnectMessage *msg); - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_remote_overlay_connect (void *cls, - const struct - GNUNET_TESTBED_RemoteOverlayConnectMessage *msg); - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_peer_create (void *cls, - const struct GNUNET_TESTBED_PeerCreateMessage *msg); - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_peer_create (void *cls, - const struct GNUNET_TESTBED_PeerCreateMessage *msg); - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_peer_destroy (void *cls, - const struct GNUNET_TESTBED_PeerDestroyMessage *msg); - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_START_PEER messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_peer_start (void *cls, - const struct GNUNET_TESTBED_PeerStartMessage *msg); - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_peer_stop (void *cls, - const struct GNUNET_TESTBED_PeerStopMessage *msg); - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_peer_get_config (void *cls, - const struct - GNUNET_TESTBED_PeerGetConfigurationMessage *msg); - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_shutdown_peers (void *cls, - const struct GNUNET_TESTBED_ShutdownPeersMessage *msg); - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE message - * - * @param cls identification of client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_manage_peer_service (void *cls, - const struct - GNUNET_TESTBED_ManagePeerServiceMessage *msg); - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE messages - * - * @param cls identification of client - * @param msg the actual message - */ -void -handle_manage_peer_service (void *cls, - const struct - GNUNET_TESTBED_ManagePeerServiceMessage *msg); - - -/** - * Check #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_peer_reconfigure (void *cls, - const struct - GNUNET_TESTBED_PeerReconfigureMessage *msg); - - -/** - * Handler for #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. - * Should stop the peer asynchronously, destroy it and create it again with the - * new configuration. - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_peer_reconfigure (void *cls, - const struct - GNUNET_TESTBED_PeerReconfigureMessage *msg); - - -/** - * Frees the ManageServiceContext queue - */ -void -GST_free_mctxq (void); - - -/** - * Cleans up the queue used for forwarding link controllers requests - */ -void -GST_free_lcf (void); - - -/** - * Cleans up the route list - */ -void -GST_route_list_clear (void); - - -/** - * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext - * - * @param rhc the RegisteredHostContext - */ -void -GST_process_next_focc (struct RegisteredHostContext *rhc); - - -/** - * Cleans up ForwardedOverlayConnectContext - * - * @param focc the ForwardedOverlayConnectContext to cleanup - */ -void -GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc); - - -/** - * Clears all pending overlay connect contexts in queue - */ -void -GST_free_occq (void); - - -/** - * Clears all pending remote overlay connect contexts in queue - */ -void -GST_free_roccq (void); - - -/** - * Cleans up the Peer reconfigure context list - */ -void -GST_free_prcq (void); - - -/** - * Initializes the cache - * - * @param size the size of the cache - */ -void -GST_cache_init (unsigned int size); - - -/** - * Clear cache - */ -void -GST_cache_clear (void); - - -/** - * Looks up in the hello cache and returns the HELLO of the given peer - * - * @param peer_id the index of the peer whose HELLO has to be looked up - * @return the HELLO message; NULL if not found - */ -const struct GNUNET_MessageHeader * -GST_cache_lookup_hello (const unsigned int peer_id); - - -/** - * Caches the HELLO of the given peer. Updates the HELLO if it was already - * cached before - * - * @param peer_id the peer identity of the peer whose HELLO has to be cached - * @param hello the HELLO message - */ -void -GST_cache_add_hello (const unsigned int peer_id, - const struct GNUNET_MessageHeader *hello); - - -/** - * Initialize logging CPU and IO statisticfs. Checks the configuration for - * "STATS_DIR" and logs to a file in that directory. The file is name is - * generated from the hostname and the process's PID. - */ -void -GST_stats_init (const struct GNUNET_CONFIGURATION_Handle *cfg); - - -/** - * Shutdown the status calls module. - */ -void -GST_stats_destroy (void); - -/* End of gnunet-service-testbed.h */ diff --git a/src/testbed/gnunet-service-testbed_barriers.c b/src/testbed/gnunet-service-testbed_barriers.c @@ -1,929 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-service-testbed_barriers.c - * @brief barrier handling at the testbed controller - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet-service-testbed.h" -#include "gnunet-service-testbed_barriers.h" -#include "testbed_api.h" - - -/** - * timeout for outgoing message transmissions in seconds - */ -#define MESSAGE_SEND_TIMEOUT(s) \ - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, s) - - -/** - * Test to see if local peers have reached the required quorum of a barrier - */ -#define LOCAL_QUORUM_REACHED(barrier) \ - ((barrier->quorum * GST_num_local_peers) <= (barrier->nreached * 100)) - - -#ifdef LOG -#undef LOG -#endif - -/** - * Logging shorthand - */ -#define LOG(kind, ...) \ - GNUNET_log_from (kind, "testbed-barriers", __VA_ARGS__) - - -/** - * Barrier - */ -struct Barrier; - - -/** - * Context to be associated with each client - */ -struct ClientCtx -{ - /** - * The barrier this client is waiting for - */ - struct Barrier *barrier; - - /** - * DLL next ptr - */ - struct ClientCtx *next; - - /** - * DLL prev ptr - */ - struct ClientCtx *prev; - - /** - * The client handle - */ - struct GNUNET_SERVICE_Client *client; -}; - - -/** - * Wrapper around Barrier handle - */ -struct WBarrier -{ - /** - * DLL next pointer - */ - struct WBarrier *next; - - /** - * DLL prev pointer - */ - struct WBarrier *prev; - - /** - * The local barrier associated with the creation of this wrapper - */ - struct Barrier *barrier; - - /** - * Handle to the slave controller where this wrapper creates a barrier - */ - struct GNUNET_TESTBED_Controller *controller; - - /** - * The barrier handle from API - */ - struct GNUNET_TESTBED_Barrier *hbarrier; - - /** - * Has this barrier been crossed? - */ - uint8_t reached; -}; - - -/** - * Barrier - */ -struct Barrier -{ - /** - * The hashcode of the barrier name - */ - struct GNUNET_HashCode hash; - - /** - * The client handle to the master controller - */ - struct GNUNET_SERVICE_Client *mc; - - /** - * The name of the barrier - */ - char *name; - - /** - * DLL head for the list of clients waiting for this barrier - */ - struct ClientCtx *head; - - /** - * DLL tail for the list of clients waiting for this barrier - */ - struct ClientCtx *tail; - - /** - * DLL head for the list of barrier handles - */ - struct WBarrier *whead; - - /** - * DLL tail for the list of barrier handles - */ - struct WBarrier *wtail; - - /** - * Identifier for the timeout task - */ - struct GNUNET_SCHEDULER_Task *tout_task; - - /** - * The status of this barrier - */ - enum GNUNET_TESTBED_BarrierStatus status; - - /** - * Number of barriers wrapped in the above DLL - */ - unsigned int num_wbarriers; - - /** - * Number of wrapped barriers reached so far - */ - unsigned int num_wbarriers_reached; - - /** - * Number of wrapped barrier initialised so far - */ - unsigned int num_wbarriers_inited; - - /** - * Number of peers which have reached this barrier - */ - unsigned int nreached; - - /** - * Number of slaves we have initialised this barrier - */ - unsigned int nslaves; - - /** - * Quorum percentage to be reached - */ - uint8_t quorum; -}; - - -/** - * Hashtable handle for storing initialised barriers - */ -static struct GNUNET_CONTAINER_MultiHashMap *barrier_map; - -/** - * Service context - */ -static struct GNUNET_SERVICE_Handle *ctx; - - -/** - * Function to remove a barrier from the barrier map and cleanup resources - * occupied by a barrier - * - * @param barrier the barrier handle - */ -static void -remove_barrier (struct Barrier *barrier) -{ - struct ClientCtx *ctx; - - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (barrier_map, - &barrier->hash, - barrier)); - while (NULL != (ctx = barrier->head)) - { - GNUNET_CONTAINER_DLL_remove (barrier->head, - barrier->tail, - ctx); - ctx->barrier = NULL; - } - GNUNET_free (barrier->name); - GNUNET_free (barrier); -} - - -/** - * Cancels all subcontroller barrier handles - * - * @param barrier the local barrier - */ -static void -cancel_wrappers (struct Barrier *barrier) -{ - struct WBarrier *wrapper; - - while (NULL != (wrapper = barrier->whead)) - { - GNUNET_TESTBED_barrier_cancel (wrapper->hbarrier); - GNUNET_CONTAINER_DLL_remove (barrier->whead, - barrier->wtail, - wrapper); - GNUNET_free (wrapper); - } -} - - -/** - * Send a status message about a barrier to the given client - * - * @param client the client to send the message to - * @param name the barrier name - * @param status the status of the barrier - * @param emsg the error message; should be non-NULL for - * status=GNUNET_TESTBED_BARRIERSTATUS_ERROR - */ -static void -send_client_status_msg (struct GNUNET_SERVICE_Client *client, - const char *name, - enum GNUNET_TESTBED_BarrierStatus status, - const char *emsg) -{ - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_BarrierStatusMsg *msg; - size_t name_len; - size_t err_len; - - GNUNET_assert ((NULL == emsg) || - (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status)); - name_len = strlen (name) + 1; - err_len = ((NULL == emsg) ? 0 : (strlen (emsg) + 1)); - env = GNUNET_MQ_msg_extra (msg, - name_len + err_len, - GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS); - msg->status = htons (status); - msg->name_len = htons ((uint16_t) name_len - 1); - GNUNET_memcpy (msg->data, - name, - name_len); - GNUNET_memcpy (msg->data + name_len, - emsg, - err_len); - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), - env); -} - - -/** - * Sends a barrier failed message - * - * @param barrier the corresponding barrier - * @param emsg the error message; should be non-NULL for - * status=GNUNET_TESTBED_BARRIERSTATUS_ERROR - */ -static void -send_barrier_status_msg (struct Barrier *barrier, - const char *emsg) -{ - GNUNET_assert (0 != barrier->status); - send_client_status_msg (barrier->mc, - barrier->name, - barrier->status, - emsg); -} - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT messages. - * - * @param cls identification of the client - * @param msg the actual message - */ -static int -check_barrier_wait (void *cls, - const struct GNUNET_TESTBED_BarrierWait *msg) -{ - return GNUNET_OK; /* always well-formed */ -} - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT messages. This - * message should come from peers or a shared helper service using the - * testbed-barrier client API (@see gnunet_testbed_barrier_service.h) - * - * This handler is queued in the main service and will handle the messages sent - * either from the testbed driver or from a high level controller - * - * @param cls identification of the client - * @param msg the actual message - */ -static void -handle_barrier_wait (void *cls, - const struct GNUNET_TESTBED_BarrierWait *msg) -{ - struct ClientCtx *client_ctx = cls; - struct Barrier *barrier; - char *name; - struct GNUNET_HashCode key; - size_t name_len; - uint16_t msize; - - msize = ntohs (msg->header.size); - if (NULL == barrier_map) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (client_ctx->client); - return; - } - name_len = msize - sizeof(struct GNUNET_TESTBED_BarrierWait); - name = GNUNET_malloc (name_len + 1); - name[name_len] = '\0'; - GNUNET_memcpy (name, - msg->name, - name_len); - LOG_DEBUG ("Received BARRIER_WAIT for barrier `%s'\n", - name); - GNUNET_CRYPTO_hash (name, - name_len, - &key); - GNUNET_free (name); - if (NULL == (barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, &key))) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (client_ctx->client); - return; - } - if (NULL != client_ctx->barrier) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (client_ctx->client); - return; - } - client_ctx->barrier = barrier; - GNUNET_CONTAINER_DLL_insert_tail (barrier->head, - barrier->tail, - client_ctx); - barrier->nreached++; - if ((barrier->num_wbarriers_reached == barrier->num_wbarriers) && - (LOCAL_QUORUM_REACHED (barrier))) - { - barrier->status = GNUNET_TESTBED_BARRIERSTATUS_CROSSED; - send_barrier_status_msg (barrier, - NULL); - } - GNUNET_SERVICE_client_continue (client_ctx->client); -} - - -/** - * Function called when a client connects to the testbed-barrier service. - * - * @param cls NULL - * @param client the connecting client - * @param mq queue to talk to @a client - * @return our `struct ClientCtx` - */ -static void * -connect_cb (void *cls, - struct GNUNET_SERVICE_Client *client, - struct GNUNET_MQ_Handle *mq) -{ - struct ClientCtx *client_ctx; - - LOG_DEBUG ("Client connected to testbed-barrier service\n"); - client_ctx = GNUNET_new (struct ClientCtx); - client_ctx->client = client; - return client_ctx; -} - - -/** - * Functions with this signature are called whenever a client - * is disconnected on the network level. - * - * @param cls closure - * @param client identification of the client; NULL - * for the last call when the server is destroyed - */ -static void -disconnect_cb (void *cls, - struct GNUNET_SERVICE_Client *client, - void *app_ctx) -{ - struct ClientCtx *client_ctx = app_ctx; - struct Barrier *barrier = client_ctx->barrier; - - if (NULL != barrier) - { - GNUNET_CONTAINER_DLL_remove (barrier->head, - barrier->tail, - client_ctx); - client_ctx->barrier = NULL; - } - GNUNET_free (client_ctx); - LOG_DEBUG ("Client disconnected from testbed-barrier service\n"); -} - - -/** - * Function to initialise barriers component - * - * @param cfg the configuration to use for initialisation - */ -void -GST_barriers_init (struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_MQ_MessageHandler message_handlers[] = { - GNUNET_MQ_hd_var_size (barrier_wait, - GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT, - struct GNUNET_TESTBED_BarrierWait, - NULL), - GNUNET_MQ_handler_end () - }; - - LOG_DEBUG ("Launching testbed-barrier service\n"); - barrier_map = GNUNET_CONTAINER_multihashmap_create (3, - GNUNET_YES); - ctx = GNUNET_SERVICE_start ("testbed-barrier", - cfg, - &connect_cb, - &disconnect_cb, - NULL, - message_handlers); -} - - -/** - * Iterator over hash map entries. - * - * @param cls closure - * @param key current key code - * @param value value in the hash map - * @return #GNUNET_YES if we should continue to - * iterate, - * #GNUNET_NO if not. - */ -static int -barrier_destroy_iterator (void *cls, - const struct GNUNET_HashCode *key, - void *value) -{ - struct Barrier *barrier = value; - - GNUNET_assert (NULL != barrier); - cancel_wrappers (barrier); - remove_barrier (barrier); - return GNUNET_YES; -} - - -/** - * Function to stop the barrier service - */ -void -GST_barriers_destroy () -{ - GNUNET_assert (NULL != barrier_map); - GNUNET_assert (GNUNET_SYSERR != - GNUNET_CONTAINER_multihashmap_iterate (barrier_map, - & - barrier_destroy_iterator, - NULL)); - GNUNET_CONTAINER_multihashmap_destroy (barrier_map); - GNUNET_assert (NULL != ctx); - GNUNET_SERVICE_stop (ctx); -} - - -/** - * Functions of this type are to be given as callback argument to - * GNUNET_TESTBED_barrier_init(). The callback will be called when status - * information is available for the barrier. - * - * @param cls the closure given to GNUNET_TESTBED_barrier_init() - * @param name the name of the barrier - * @param b_ the barrier handle - * @param status status of the barrier; #GNUNET_OK if the barrier is crossed; - * #GNUNET_SYSERR upon error - * @param emsg if the status were to be #GNUNET_SYSERR, this parameter has the - * error message - */ -static void -wbarrier_status_cb (void *cls, - const char *name, - struct GNUNET_TESTBED_Barrier *b_, - enum GNUNET_TESTBED_BarrierStatus status, - const char *emsg) -{ - struct WBarrier *wrapper = cls; - struct Barrier *barrier = wrapper->barrier; - - GNUNET_assert (b_ == wrapper->hbarrier); - switch (status) - { - case GNUNET_TESTBED_BARRIERSTATUS_ERROR: - LOG (GNUNET_ERROR_TYPE_ERROR, - "Initialising barrier `%s' failed at a sub-controller: %s\n", - barrier->name, - (NULL != emsg) ? emsg : "NULL"); - cancel_wrappers (barrier); - if (NULL == emsg) - emsg = "Initialisation failed at a sub-controller"; - barrier->status = GNUNET_TESTBED_BARRIERSTATUS_ERROR; - send_barrier_status_msg (barrier, emsg); - return; - - case GNUNET_TESTBED_BARRIERSTATUS_CROSSED: - if (GNUNET_TESTBED_BARRIERSTATUS_INITIALISED != barrier->status) - { - GNUNET_break_op (0); - return; - } - barrier->num_wbarriers_reached++; - if ((barrier->num_wbarriers_reached == barrier->num_wbarriers) - && (LOCAL_QUORUM_REACHED (barrier))) - { - barrier->status = GNUNET_TESTBED_BARRIERSTATUS_CROSSED; - send_barrier_status_msg (barrier, NULL); - } - return; - - case GNUNET_TESTBED_BARRIERSTATUS_INITIALISED: - if (0 != barrier->status) - { - GNUNET_break_op (0); - return; - } - barrier->num_wbarriers_inited++; - if (barrier->num_wbarriers_inited == barrier->num_wbarriers) - { - barrier->status = GNUNET_TESTBED_BARRIERSTATUS_INITIALISED; - send_barrier_status_msg (barrier, NULL); - } - return; - } -} - - -/** - * Function called upon timeout while waiting for a response from the - * subcontrollers to barrier init message - * - * @param cls barrier - */ -static void -fwd_tout_barrier_init (void *cls) -{ - struct Barrier *barrier = cls; - - cancel_wrappers (barrier); - barrier->status = GNUNET_TESTBED_BARRIERSTATUS_ERROR; - send_barrier_status_msg (barrier, - "Timedout while propagating barrier initialisation\n"); - remove_barrier (barrier); -} - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_barrier_init (void *cls, - const struct GNUNET_TESTBED_BarrierInit *msg) -{ - return GNUNET_OK; /* always well-formed */ -} - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. This - * message should always come from a parent controller or the testbed API if we - * are the root controller. - * - * This handler is queued in the main service and will handle the messages sent - * either from the testbed driver or from a high level controller - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_barrier_init (void *cls, - const struct GNUNET_TESTBED_BarrierInit *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - char *name; - struct Barrier *barrier; - struct Slave *slave; - struct WBarrier *wrapper; - struct GNUNET_HashCode hash; - size_t name_len; - unsigned int cnt; - uint16_t msize; - - if (NULL == GST_context) - { - GNUNET_break_op (0); - GNUNET_SERVICE_client_drop (client); - return; - } - if (client != GST_context->client) - { - GNUNET_break_op (0); - GNUNET_SERVICE_client_drop (client); - return; - } - msize = ntohs (msg->header.size); - name_len = (size_t) msize - sizeof(struct GNUNET_TESTBED_BarrierInit); - name = GNUNET_malloc (name_len + 1); - GNUNET_memcpy (name, msg->name, name_len); - GNUNET_CRYPTO_hash (name, name_len, &hash); - LOG_DEBUG ("Received BARRIER_INIT for barrier `%s'\n", - name); - if (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (barrier_map, - &hash)) - { - send_client_status_msg (client, - name, - GNUNET_TESTBED_BARRIERSTATUS_ERROR, - "A barrier with the same name already exists"); - GNUNET_free (name); - GNUNET_SERVICE_client_continue (client); - return; - } - barrier = GNUNET_new (struct Barrier); - barrier->hash = hash; - barrier->quorum = msg->quorum; - barrier->name = name; - barrier->mc = client; - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (barrier_map, - &barrier->hash, - barrier, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); - GNUNET_SERVICE_client_continue (client); - /* Propagate barrier init to subcontrollers */ - for (cnt = 0; cnt < GST_slave_list_size; cnt++) - { - if (NULL == (slave = GST_slave_list[cnt])) - continue; - if (NULL == slave->controller) - { - GNUNET_break (0); /* May happen when we are connecting to the controller */ - continue; - } - wrapper = GNUNET_new (struct WBarrier); - wrapper->barrier = barrier; - wrapper->controller = slave->controller; - GNUNET_CONTAINER_DLL_insert_tail (barrier->whead, - barrier->wtail, - wrapper); - barrier->num_wbarriers++; - wrapper->hbarrier = GNUNET_TESTBED_barrier_init_ (wrapper->controller, - barrier->name, - barrier->quorum, - &wbarrier_status_cb, - wrapper, - GNUNET_NO); - } - if (NULL == barrier->whead) /* No further propagation */ - { - barrier->status = GNUNET_TESTBED_BARRIERSTATUS_INITIALISED; - LOG_DEBUG ( - "Sending GNUNET_TESTBED_BARRIERSTATUS_INITIALISED for barrier `%s'\n", - barrier->name); - send_barrier_status_msg (barrier, NULL); - } - else - barrier->tout_task = GNUNET_SCHEDULER_add_delayed (MESSAGE_SEND_TIMEOUT ( - 30), - &fwd_tout_barrier_init, - barrier); -} - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_barrier_cancel (void *cls, - const struct GNUNET_TESTBED_BarrierCancel *msg) -{ - return GNUNET_OK; /* all are well-formed */ -} - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. This - * message should always come from a parent controller or the testbed API if we - * are the root controller. - * - * This handler is queued in the main service and will handle the messages sent - * either from the testbed driver or from a high level controller - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_barrier_cancel (void *cls, - const struct GNUNET_TESTBED_BarrierCancel *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - char *name; - struct Barrier *barrier; - struct GNUNET_HashCode hash; - size_t name_len; - uint16_t msize; - - if (NULL == GST_context) - { - GNUNET_break_op (0); - GNUNET_SERVICE_client_drop (client); - return; - } - if (client != GST_context->client) - { - GNUNET_break_op (0); - GNUNET_SERVICE_client_drop (client); - return; - } - msize = ntohs (msg->header.size); - name_len = msize - sizeof(struct GNUNET_TESTBED_BarrierCancel); - name = GNUNET_malloc (name_len + 1); - GNUNET_memcpy (name, - msg->name, - name_len); - LOG_DEBUG ("Received BARRIER_CANCEL for barrier `%s'\n", - name); - GNUNET_CRYPTO_hash (name, - name_len, - &hash); - if (GNUNET_NO == - GNUNET_CONTAINER_multihashmap_contains (barrier_map, - &hash)) - { - GNUNET_break_op (0); - GNUNET_free (name); - GNUNET_SERVICE_client_drop (client); - return; - } - barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, - &hash); - GNUNET_assert (NULL != barrier); - cancel_wrappers (barrier); - remove_barrier (barrier); - GNUNET_free (name); - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_barrier_status (void *cls, - const struct GNUNET_TESTBED_BarrierStatusMsg *msg) -{ - uint16_t msize; - uint16_t name_len; - const char *name; - enum GNUNET_TESTBED_BarrierStatus status; - - msize = ntohs (msg->header.size) - sizeof(*msg); - status = ntohs (msg->status); - if (GNUNET_TESTBED_BARRIERSTATUS_CROSSED != status) - { - GNUNET_break_op (0); /* current we only expect BARRIER_CROSSED - status message this way */ - return GNUNET_SYSERR; - } - name = msg->data; - name_len = ntohs (msg->name_len); - if ((name_len + 1) != msize) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if ('\0' != name[name_len]) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. - * This handler is queued in the main service and will handle the messages sent - * either from the testbed driver or from a high level controller - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_barrier_status (void *cls, - const struct GNUNET_TESTBED_BarrierStatusMsg *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct Barrier *barrier; - struct ClientCtx *client_ctx; - struct WBarrier *wrapper; - const char *name; - struct GNUNET_HashCode key; - uint16_t name_len; - struct GNUNET_MQ_Envelope *env; - - if (NULL == GST_context) - { - GNUNET_break_op (0); - GNUNET_SERVICE_client_drop (client); - return; - } - if (client != GST_context->client) - { - GNUNET_break_op (0); - GNUNET_SERVICE_client_drop (client); - return; - } - name = msg->data; - name_len = ntohs (msg->name_len); - LOG_DEBUG ("Received BARRIER_STATUS for barrier `%s'\n", - name); - GNUNET_CRYPTO_hash (name, - name_len, - &key); - barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, - &key); - if (NULL == barrier) - { - GNUNET_break_op (0); - GNUNET_SERVICE_client_drop (client); - return; - } - GNUNET_SERVICE_client_continue (client); - for (client_ctx = barrier->head; NULL != client_ctx; client_ctx = - client_ctx->next) /* Notify peers */ - { - env = GNUNET_MQ_msg_copy (&msg->header); - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client_ctx->client), - env); - } - /** - * The wrapper barriers do not echo the barrier status, so we have to do it - * here - */ - for (wrapper = barrier->whead; NULL != wrapper; wrapper = wrapper->next) - { - GNUNET_TESTBED_queue_message_ (wrapper->controller, - GNUNET_copy_message (&msg->header)); - } -} - - -/* end of gnunet-service-testbed_barriers.c */ diff --git a/src/testbed/gnunet-service-testbed_barriers.h b/src/testbed/gnunet-service-testbed_barriers.h @@ -1,128 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-service-testbed_barriers.h - * @brief Interface for the barrier initialisation handler routine - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#ifndef GNUNET_SERVER_TESTBED_BARRIERS_H_ -#define GNUNET_SERVER_TESTBED_BARRIERS_H_ - -/** - * Function to initialise barriers component - * - * @param cfg the configuration to use for initialisation - */ -void -GST_barriers_init (struct GNUNET_CONFIGURATION_Handle *cfg); - - -/** - * Function to stop the barrier service - */ -void -GST_barriers_destroy (void); - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_barrier_init (void *cls, - const struct GNUNET_TESTBED_BarrierInit *msg); - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. This - * message should always come from a parent controller or the testbed API if we - * are the root controller. - * - * This handler is queued in the main service and will handle the messages sent - * either from the testbed driver or from a high level controller - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_barrier_init (void *cls, - const struct GNUNET_TESTBED_BarrierInit *msg); - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_barrier_cancel (void *cls, - const struct GNUNET_TESTBED_BarrierCancel *msg); - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. This - * message should always come from a parent controller or the testbed API if we - * are the root controller. - * - * This handler is queued in the main service and will handle the messages sent - * either from the testbed driver or from a high level controller - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_barrier_cancel (void *cls, - const struct GNUNET_TESTBED_BarrierCancel *msg); - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_barrier_status (void *cls, - const struct GNUNET_TESTBED_BarrierStatusMsg *msg); - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. - * This handler is queued in the main service and will handle the messages sent - * either from the testbed driver or from a high level controller - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_barrier_status (void *cls, - const struct GNUNET_TESTBED_BarrierStatusMsg *msg); - -#endif /* GNUNET_SERVER_TESTBED_BARRIERS_H_ */ - -/* end of gnunet-service-testbed_barriers.h */ diff --git a/src/testbed/gnunet-service-testbed_cache.c b/src/testbed/gnunet-service-testbed_cache.c @@ -1,270 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-service-testbed_cache.c - * @brief testbed cache implementation - * @author Sree Harsha Totakura - */ -#include "platform.h" -#include "gnunet-service-testbed.h" - -/** - * Redefine LOG with a changed log component string - */ -#ifdef LOG -#undef LOG -#endif -#define LOG(kind, ...) \ - GNUNET_log_from (kind, "testbed-cache", __VA_ARGS__) - - -/** - * Cache entry - */ -struct CacheEntry -{ - /** - * DLL next ptr for least recently used cache entries - */ - struct CacheEntry *next; - - /** - * DLL prev ptr for least recently used cache entries - */ - struct CacheEntry *prev; - - /** - * The HELLO message - */ - struct GNUNET_MessageHeader *hello; - - /** - * The id of the peer this entry corresponds to - */ - unsigned int peer_id; -}; - - -/** - * Hashmap to maintain cache - */ -static struct GNUNET_CONTAINER_MultiHashMap32 *cache; - -/** - * DLL head for least recently used cache entries; least recently used - * cache items are at the head. The cache enties are added to this queue when - * their demand becomes zero. They are removed from the queue when they are - * needed by any operation. - */ -static struct CacheEntry *cache_head; - -/** - * DLL tail for least recently used cache entries; recently used cache - * items are at the tail.The cache enties are added to this queue when - * their demand becomes zero. They are removed from the queue when they are - * needed by any operation. - */ -static struct CacheEntry *cache_tail; - -/** - * Maximum number of elements to cache - */ -static unsigned int cache_size; - - -/** - * Looks up in the cache and returns the entry - * - * @param peer_id the peer identity of the peer whose corresponding entry has to - * be looked up - * @return the HELLO message; NULL if not found - */ -static struct CacheEntry * -cache_lookup (unsigned int peer_id) -{ - struct CacheEntry *entry; - - GNUNET_assert (NULL != cache); - entry = GNUNET_CONTAINER_multihashmap32_get (cache, peer_id); - if (NULL == entry) - return NULL; - GNUNET_CONTAINER_DLL_remove (cache_head, cache_tail, entry); - GNUNET_CONTAINER_DLL_insert_tail (cache_head, cache_tail, entry); - return entry; -} - - -/** - * Free the resources occupied by a cache entry - * - * @param entry the cache entry to free - */ -static void -free_entry (struct CacheEntry *entry) -{ - GNUNET_CONTAINER_DLL_remove (cache_head, cache_tail, entry); - GNUNET_free (entry->hello); - GNUNET_free (entry); -} - - -/** - * Creates a new cache entry and then puts it into the cache's hashtable. - * - * @param peer_id the index of the peer to tag the newly created entry - * @return the newly created entry - */ -static struct CacheEntry * -add_entry (unsigned int peer_id) -{ - struct CacheEntry *entry; - - GNUNET_assert (NULL != cache); - if (cache_size == GNUNET_CONTAINER_multihashmap32_size (cache)) - { - /* remove the LRU head */ - entry = cache_head; - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap32_remove (cache, (uint32_t) - entry->peer_id, - entry)); - free_entry (entry); - } - entry = GNUNET_new (struct CacheEntry); - entry->peer_id = peer_id; - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap32_put (cache, - (uint32_t) peer_id, - entry, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); - GNUNET_CONTAINER_DLL_insert_tail (cache_head, cache_tail, entry); - return entry; -} - - -/** - * Iterator over hash map entries. - * - * @param cls closure - * @param key current key - * @param value value in the hash map - * @return GNUNET_YES if we should continue to - * iterate, - * GNUNET_NO if not. - */ -static int -cache_clear_iterator (void *cls, uint32_t key, void *value) -{ - struct CacheEntry *entry = value; - - GNUNET_assert (NULL != entry); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap32_remove (cache, key, value)); - free_entry (entry); - return GNUNET_YES; -} - - -/** - * Clear cache - */ -void -GST_cache_clear () -{ - if (NULL != cache) - { - GNUNET_CONTAINER_multihashmap32_iterate (cache, &cache_clear_iterator, - NULL); - GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (cache)); - GNUNET_CONTAINER_multihashmap32_destroy (cache); - cache = NULL; - } - cache_size = 0; - cache_head = NULL; - cache_tail = NULL; -} - - -/** - * Initializes the cache - * - * @param size the size of the cache - */ -void -GST_cache_init (unsigned int size) -{ - if (0 == size) - return; - cache_size = size; - cache = GNUNET_CONTAINER_multihashmap32_create (cache_size); -} - - -/** - * Looks up in the hello cache and returns the HELLO of the given peer - * - * @param peer_id the index of the peer whose HELLO has to be looked up - * @return the HELLO message; NULL if not found - */ -const struct GNUNET_MessageHeader * -GST_cache_lookup_hello (const unsigned int peer_id) -{ - struct CacheEntry *entry; - - LOG_DEBUG ("Looking up HELLO for peer %u\n", peer_id); - if (NULL == cache) - { - LOG_DEBUG ("Caching disabled\n"); - return NULL; - } - entry = cache_lookup (peer_id); - if (NULL == entry) - return NULL; - if (NULL != entry->hello) - LOG_DEBUG ("HELLO found for peer %u\n", peer_id); - return entry->hello; -} - - -/** - * Caches the HELLO of the given peer. Updates the HELLO if it was already - * cached before - * - * @param peer_id the peer identity of the peer whose HELLO has to be cached - * @param hello the HELLO message - */ -void -GST_cache_add_hello (const unsigned int peer_id, - const struct GNUNET_MessageHeader *hello) -{ - struct CacheEntry *entry; - - if (NULL == cache) - return; - entry = cache_lookup (peer_id); - if (NULL == entry) - entry = add_entry (peer_id); - GNUNET_free (entry->hello); - entry->hello = GNUNET_copy_message (hello); -} - - -/* end of gnunet-service-testbed_hc.c */ diff --git a/src/testbed/gnunet-service-testbed_connectionpool.c b/src/testbed/gnunet-service-testbed_connectionpool.c @@ -1,1045 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--2015 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-service-testbed_connectionpool.c - * @brief connection pooling for connections to peers' services - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet-service-testbed.h" -#include "gnunet-service-testbed_connectionpool.h" -#include "testbed_api_operations.h" -#include "gnunet_transport_service.h" - -/** - * Redefine LOG with a changed log component string - */ -#ifdef LOG -#undef LOG -#endif -#define LOG(kind, ...) \ - GNUNET_log_from (kind, "testbed-connectionpool", __VA_ARGS__) - - -/** - * Time to expire a cache entry - */ -#define CACHE_EXPIRY \ - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) - - -/** - * The request handle for obtaining a pooled connection - */ -struct GST_ConnectionPool_GetHandle; - - -/** - * A pooled connection - */ -struct PooledConnection -{ - /** - * Next ptr for placing this object in the DLL of least recently used pooled - * connections - */ - struct PooledConnection *next; - - /** - * Prev ptr for placing this object in the DLL of the least recently used - * pooled connections - */ - struct PooledConnection *prev; - - /** - * The transport handle to the peer corresponding to this entry; can be NULL - */ - struct GNUNET_TRANSPORT_CoreHandle *handle_transport; - - /** - * The core handle to the peer corresponding to this entry; can be NULL - */ - struct GNUNET_CORE_Handle *handle_core; - - /** - * The ATS handle to the peer correspondign to this entry; can be NULL. - */ - struct GNUNET_ATS_ConnectivityHandle *handle_ats_connectivity; - - /** - * The operation handle for transport handle - */ - struct GNUNET_TESTBED_Operation *op_transport; - - /** - * The operation handle for core handle - */ - struct GNUNET_TESTBED_Operation *op_core; - - /** - * The operation handle for ATS handle - */ - struct GNUNET_TESTBED_Operation *op_ats_connectivity; - - /** - * The peer identity of this peer. Will be set upon opening a connection to - * the peers CORE service. Will be NULL until then and after the CORE - * connection is closed - */ - struct GNUNET_PeerIdentity *peer_identity; - - /** - * The configuration of the peer. Should be not NULL as long as the - * core_handle or transport_handle are valid - */ - struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * DLL head for the queue to serve notifications when a peer is connected - */ - struct GST_ConnectionPool_GetHandle *head_notify; - - /** - * DLL tail for the queue to serve notifications when a peer is connected - */ - struct GST_ConnectionPool_GetHandle *tail_notify; - - /** - * DLL head for the queue of #GST_ConnectionPool_GetHandle requests that are - * waiting for this connection to be opened - */ - struct GST_ConnectionPool_GetHandle *head_waiting; - - /** - * DLL tail for the queue of #GST_ConnectionPool_GetHandle requests that are - * waiting for this connection to be opened - */ - struct GST_ConnectionPool_GetHandle *tail_waiting; - - /** - * The task to expire this connection from the connection pool - */ - struct GNUNET_SCHEDULER_Task *expire_task; - - /** - * The task to notify a waiting #GST_ConnectionPool_GetHandle object - */ - struct GNUNET_SCHEDULER_Task *notify_task; - - /** - * Number of active requests using this pooled connection - */ - unsigned int demand; - - /** - * Is this entry in LRU - */ - int in_lru; - - /** - * Is this entry present in the connection pool - */ - int in_pool; - - /** - * The index of this peer - */ - uint32_t index; -}; - - -/** - * The request handle for obtaining a pooled connection - */ -struct GST_ConnectionPool_GetHandle -{ - /** - * The next ptr for inclusion in the notification DLLs. At first the object - * is placed in the waiting DLL of the corresponding #PooledConnection - * object. After the handle is opened it is moved to the notification DLL if - * @p connect_notify_cb and @p target are not NULL - */ - struct GST_ConnectionPool_GetHandle *next; - - /** - * The prev ptr for inclusion in the notification DLLs - */ - struct GST_ConnectionPool_GetHandle *prev; - - /** - * The pooled connection object this handle corresponds to - */ - struct PooledConnection *entry; - - /** - * The cache callback to call when a handle is available - */ - GST_connection_pool_connection_ready_cb cb; - - /** - * The closure for the above callback - */ - void *cb_cls; - - /** - * The peer identity of the target peer. When this target peer is connected, - * call the notify callback - */ - const struct GNUNET_PeerIdentity *target; - - /** - * The callback to be called for serving notification that the target peer is - * connected - */ - GST_connection_pool_peer_connect_notify connect_notify_cb; - - /** - * The closure for the notify callback - */ - void *connect_notify_cb_cls; - - /** - * The service we want to connect to - */ - enum GST_ConnectionPool_Service service; - - /** - * Did we call the pool_connection_ready_cb already? - */ - int connection_ready_called; - - /** - * Are we waiting for any peer connect notifications? - */ - int notify_waiting; -}; - - -/** - * A hashmap for quickly finding connections in the connection pool - */ -static struct GNUNET_CONTAINER_MultiHashMap32 *map; - -/** - * DLL head for maitaining the least recently used #PooledConnection objects. - * The head is the least recently used object. - */ -static struct PooledConnection *head_lru; - -/** - * DLL tail for maitaining the least recently used #PooledConnection objects - */ -static struct PooledConnection *tail_lru; - -/** - * DLL head for maintaining #PooledConnection objects that are not added into - * the connection pool as it was full at the time the object's creation - * FIXME - */ -static struct PooledConnection *head_not_pooled; - -/** - * DLL tail for maintaining #PooledConnection objects that are not added into - * the connection pool as it was full at the time the object's creation - */ -static struct PooledConnection *tail_not_pooled; - -/** - * The maximum number of entries that can be present in the connection pool - */ -static unsigned int max_size; - - -/** - * Cancel the expiration task of the give #PooledConnection object - * - * @param entry the #PooledConnection object - */ -static void -expire_task_cancel (struct PooledConnection *entry); - - -/** - * Destroy a #PooledConnection object - * - * @param entry the #PooledConnection object - */ -static void -destroy_pooled_connection (struct PooledConnection *entry) -{ - GNUNET_assert ((NULL == entry->head_notify) && (NULL == entry->tail_notify)); - GNUNET_assert ((NULL == entry->head_waiting) && - (NULL == entry->tail_waiting)); - GNUNET_assert (0 == entry->demand); - expire_task_cancel (entry); - if (entry->in_lru) - GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry); - if (entry->in_pool) - GNUNET_assert ( - GNUNET_OK == - GNUNET_CONTAINER_multihashmap32_remove (map, entry->index, entry)); - if (NULL != entry->notify_task) - { - GNUNET_SCHEDULER_cancel (entry->notify_task); - entry->notify_task = NULL; - } - LOG_DEBUG ("Cleaning up handles of a pooled connection\n"); - if (NULL != entry->handle_transport) - GNUNET_assert (NULL != entry->op_transport); - if (NULL != entry->op_transport) - { - GNUNET_TESTBED_operation_done (entry->op_transport); - entry->op_transport = NULL; - } - if (NULL != entry->handle_ats_connectivity) - GNUNET_assert (NULL != entry->op_ats_connectivity); - if (NULL != entry->op_ats_connectivity) - { - GNUNET_TESTBED_operation_done (entry->op_ats_connectivity); - entry->op_ats_connectivity = NULL; - } - if (NULL != entry->op_core) - { - GNUNET_TESTBED_operation_done (entry->op_core); - entry->op_core = NULL; - } - GNUNET_assert (NULL == entry->handle_core); - GNUNET_assert (NULL == entry->handle_ats_connectivity); - GNUNET_assert (NULL == entry->handle_transport); - GNUNET_CONFIGURATION_destroy (entry->cfg); - GNUNET_free (entry); -} - - -/** - * Expire a #PooledConnection object - * - * @param cls the #PooledConnection object - */ -static void -expire (void *cls) -{ - struct PooledConnection *entry = cls; - - entry->expire_task = NULL; - destroy_pooled_connection (entry); -} - - -/** - * Cancel the expiration task of the give #PooledConnection object - * - * @param entry the #PooledConnection object - */ -static void -expire_task_cancel (struct PooledConnection *entry) -{ - if (NULL != entry->expire_task) - { - GNUNET_SCHEDULER_cancel (entry->expire_task); - entry->expire_task = NULL; - } -} - - -/** - * Function to add a #PooledConnection object into LRU and begin the expiry task - * - * @param entry the #PooledConnection object - */ -static void -add_to_lru (struct PooledConnection *entry) -{ - GNUNET_assert (0 == entry->demand); - GNUNET_assert (! entry->in_lru); - GNUNET_CONTAINER_DLL_insert_tail (head_lru, tail_lru, entry); - entry->in_lru = GNUNET_YES; - GNUNET_assert (NULL == entry->expire_task); - entry->expire_task = - GNUNET_SCHEDULER_add_delayed (CACHE_EXPIRY, &expire, entry); -} - - -/** - * Function to find a #GST_ConnectionPool_GetHandle which is waiting for one of - * the handles in given entry which are now available. - * - * @param entry the pooled connection whose active list has to be searched - * @param head the starting list element in the GSTCacheGetHandle where the - * search has to be begin - * @return a suitable GSTCacheGetHandle whose handle ready notify callback - * hasn't been called yet. NULL if no such suitable GSTCacheGetHandle - * is found - */ -static struct GST_ConnectionPool_GetHandle * -search_waiting (const struct PooledConnection *entry, - struct GST_ConnectionPool_GetHandle *head) -{ - struct GST_ConnectionPool_GetHandle *gh; - - for (gh = head; NULL != gh; gh = gh->next) - { - switch (gh->service) - { - case GST_CONNECTIONPOOL_SERVICE_CORE: - if (NULL == entry->handle_core) - continue; - if (NULL == entry->peer_identity) - continue; /* CORE connection isn't ready yet */ - break; - - case GST_CONNECTIONPOOL_SERVICE_TRANSPORT: - if (NULL == entry->handle_transport) - continue; - break; - - case GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY: - if (NULL == entry->handle_ats_connectivity) - continue; - break; - } - break; - } - return gh; -} - - -/** - * A handle in the #PooledConnection object pointed by @a cls is ready and there - * is a #GST_ConnectionPool_GetHandle object waiting in the waiting list. This - * function retrieves that object and calls the handle ready callback. It - * further schedules itself if there are similar waiting objects which can be - * notified. - * - * @param cls the #PooledConnection object - */ -static void -connection_ready (void *cls) -{ - struct PooledConnection *entry = cls; - struct GST_ConnectionPool_GetHandle *gh; - struct GST_ConnectionPool_GetHandle *gh_next; - - GNUNET_assert (NULL != entry->notify_task); - entry->notify_task = NULL; - gh = search_waiting (entry, entry->head_waiting); - GNUNET_assert (NULL != gh); - gh_next = NULL; - if (NULL != gh->next) - gh_next = search_waiting (entry, gh->next); - GNUNET_CONTAINER_DLL_remove (entry->head_waiting, - entry->tail_waiting, - gh); - gh->connection_ready_called = 1; - if (NULL != gh_next) - entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready, - entry); - if ((NULL != gh->target) && (NULL != gh->connect_notify_cb)) - { - GNUNET_CONTAINER_DLL_insert_tail (entry->head_notify, - entry->tail_notify, - gh); - gh->notify_waiting = 1; - } - LOG_DEBUG ("Connection ready to %u for handle type %u\n", - (unsigned int) entry->index, - gh->service); - gh->cb (gh->cb_cls, - entry->handle_core, - entry->handle_transport, - entry->handle_ats_connectivity, - entry->peer_identity, - entry->cfg); -} - - -/** - * Function called from peer connect notify callbacks from CORE and TRANSPORT - * connections. This function calls the pending peer connect notify callbacks - * which are queued in an entry. - * - * @param cls the #PooledConnection object - * @param peer the peer that connected - * @param service the service where this notification has originated - */ -static void -peer_connect_notify_cb (void *cls, - const struct GNUNET_PeerIdentity *peer, - const enum GST_ConnectionPool_Service service) -{ - struct PooledConnection *entry = cls; - struct GST_ConnectionPool_GetHandle *gh; - struct GST_ConnectionPool_GetHandle *gh_next; - GST_connection_pool_peer_connect_notify cb; - void *cb_cls; - - for (gh = entry->head_notify; NULL != gh;) - { - GNUNET_assert (NULL != gh->target); - GNUNET_assert (NULL != gh->connect_notify_cb); - GNUNET_assert (gh->connection_ready_called); - if (service != gh->service) - { - gh = gh->next; - continue; - } - if (0 != memcmp (gh->target, peer, sizeof(struct GNUNET_PeerIdentity))) - { - gh = gh->next; - continue; - } - cb = gh->connect_notify_cb; - cb_cls = gh->connect_notify_cb_cls; - gh_next = gh->next; - GNUNET_CONTAINER_DLL_remove (entry->head_notify, entry->tail_notify, gh); - gh->notify_waiting = 0; - LOG_DEBUG ("Peer connected to peer %u at service %u\n", - entry->index, - gh->service); - gh = gh_next; - cb (cb_cls, peer); - } -} - - -/** - * Function called to notify transport users that another - * peer connected to us. - * - * @param cls the #PooledConnection object - * @param peer the peer that connected - * @param mq queue for sending data to @a peer - * @return NULL - */ -static void * -transport_peer_connect_notify_cb (void *cls, - const struct GNUNET_PeerIdentity *peer, - struct GNUNET_MQ_Handle *mq) -{ - struct PooledConnection *entry = cls; - - peer_connect_notify_cb (entry, peer, GST_CONNECTIONPOOL_SERVICE_TRANSPORT); - return NULL; -} - - -/** - * Function called when resources for opening a connection to TRANSPORT are - * available. - * - * @param cls the #PooledConnection object - */ -static void -opstart_get_handle_transport (void *cls) -{ - struct PooledConnection *entry = cls; - - GNUNET_assert (NULL != entry); - LOG_DEBUG ("Opening a transport connection to peer %u\n", entry->index); - entry->handle_transport = - GNUNET_TRANSPORT_core_connect (entry->cfg, - NULL, - NULL, - entry, - &transport_peer_connect_notify_cb, - NULL, - NULL); - if (NULL == entry->handle_transport) - { - GNUNET_break (0); - return; - } - if (0 == entry->demand) - return; - if (NULL != entry->notify_task) - return; - if (NULL != search_waiting (entry, entry->head_waiting)) - { - entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready, entry); - return; - } -} - - -/** - * Function called when the operation responsible for opening a TRANSPORT - * connection is marked as done. - * - * @param cls the cache entry - */ -static void -oprelease_get_handle_transport (void *cls) -{ - struct PooledConnection *entry = cls; - - if (NULL == entry->handle_transport) - return; - GNUNET_TRANSPORT_core_disconnect (entry->handle_transport); - entry->handle_transport = NULL; -} - - -/** - * Method called whenever a given peer connects at CORE level - * - * @param cls the #PooledConnection object - * @param peer peer identity this notification is about - * @param mq message queue for talking to @a peer - * @return peer - */ -static void * -core_peer_connect_cb (void *cls, - const struct GNUNET_PeerIdentity *peer, - struct GNUNET_MQ_Handle *mq) -{ - struct PooledConnection *entry = cls; - - peer_connect_notify_cb (entry, peer, GST_CONNECTIONPOOL_SERVICE_CORE); - return (void *) peer; -} - - -/** - * Function called after #GNUNET_CORE_connect() has succeeded (or failed - * for good). Note that the private key of the peer is intentionally - * not exposed here; if you need it, your process should try to read - * the private key file directly (which should work if you are - * authorized...). Implementations of this function must not call - * #GNUNET_CORE_disconnect() (other than by scheduling a new task to - * do this later). - * - * @param cls the #PooledConnection object - * @param my_identity ID of this peer, NULL if we failed - */ -static void -core_startup_cb (void *cls, - const struct GNUNET_PeerIdentity *my_identity) -{ - struct PooledConnection *entry = cls; - - if (NULL == my_identity) - { - GNUNET_break (0); - return; - } - GNUNET_assert (NULL == entry->peer_identity); - entry->peer_identity = GNUNET_new (struct GNUNET_PeerIdentity); - *entry->peer_identity = *my_identity; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Established CORE connection for peer %s (%u)\n", - GNUNET_i2s (my_identity), - (unsigned int) entry->index); - if (0 == entry->demand) - return; - if (NULL != entry->notify_task) - return; - if (NULL != search_waiting (entry, entry->head_waiting)) - { - entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready, entry); - return; - } -} - - -/** - * Function called when resources for opening a connection to CORE are - * available. - * - * @param cls the #PooledConnection object - */ -static void -opstart_get_handle_core (void *cls) -{ - struct PooledConnection *entry = cls; - - GNUNET_assert (NULL != entry); - LOG_DEBUG ("Opening a CORE connection to peer %u\n", entry->index); - entry->handle_core = - GNUNET_CORE_connect (entry->cfg, - entry, /* closure */ - &core_startup_cb, /* core startup notify */ - &core_peer_connect_cb, /* peer connect notify */ - NULL, /* peer disconnect notify */ - NULL); -} - - -/** - * Function called when the operation responsible for opening a CORE - * connection is marked as done. - * - * @param cls the #PooledConnection object - */ -static void -oprelease_get_handle_core (void *cls) -{ - struct PooledConnection *entry = cls; - - if (NULL == entry->handle_core) - return; - GNUNET_CORE_disconnect (entry->handle_core); - entry->handle_core = NULL; - GNUNET_free (entry->peer_identity); - entry->peer_identity = NULL; -} - - -/** - * Function called when resources for opening a connection to ATS are - * available. - * - * @param cls the #PooledConnection object - */ -static void -opstart_get_handle_ats_connectivity (void *cls) -{ - struct PooledConnection *entry = cls; - - entry->handle_ats_connectivity = GNUNET_ATS_connectivity_init (entry->cfg); -} - - -/** - * Function called when the operation responsible for opening a ATS - * connection is marked as done. - * - * @param cls the #PooledConnection object - */ -static void -oprelease_get_handle_ats_connectivity (void *cls) -{ - struct PooledConnection *entry = cls; - - if (NULL == entry->handle_ats_connectivity) - return; - GNUNET_ATS_connectivity_done (entry->handle_ats_connectivity); - entry->handle_ats_connectivity = NULL; -} - - -/** - * This function will be called for every #PooledConnection object in @p map - * - * @param cls NULL - * @param key current key code - * @param value the #PooledConnection object - * @return #GNUNET_YES if we should continue to - * iterate, - * #GNUNET_NO if not. - */ -static int -cleanup_iterator (void *cls, uint32_t key, void *value) -{ - struct PooledConnection *entry = value; - - GNUNET_assert (NULL != entry); - destroy_pooled_connection (entry); - return GNUNET_YES; -} - - -/** - * Initialise the connection pool. - * - * @param size the size of the connection pool. Each entry in the connection - * pool can handle a connection to each of the services enumerated in - * #GST_ConnectionPool_Service - */ -void -GST_connection_pool_init (unsigned int size) -{ - max_size = size; - if (0 == max_size) - return; - GNUNET_assert (NULL == map); - map = GNUNET_CONTAINER_multihashmap32_create (((size * 3) / 4) + 1); -} - - -/** - * Cleanup the connection pool - */ -void -GST_connection_pool_destroy () -{ - struct PooledConnection *entry; - - if (NULL != map) - { - GNUNET_assert ( - GNUNET_SYSERR != - GNUNET_CONTAINER_multihashmap32_iterate (map, &cleanup_iterator, NULL)); - GNUNET_CONTAINER_multihashmap32_destroy (map); - map = NULL; - } - while (NULL != (entry = head_lru)) - { - GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry); - destroy_pooled_connection (entry); - } - GNUNET_assert (NULL == head_not_pooled); -} - - -/** - * Get a connection handle to @a service. If the connection is opened before - * and the connection handle is present in the connection pool, it is returned - * through @a cb. @a peer_id is used for the lookup in the connection pool. If - * the connection handle is not present in the connection pool, a new connection - * handle is opened for the @a service using @a cfg. Additionally, @a target, - * @a connect_notify_cb can be specified to get notified when @a target is - * connected at @a service. - * - * @note @a connect_notify_cb will not be called if @a target is - * already connected @a service level. Use - * GNUNET_TRANSPORT_check_peer_connected() or a similar function from the - * respective @a service's API to check if the target peer is already connected - * or not. @a connect_notify_cb will be called only once or never (in case @a - * target cannot be connected or is already connected). - * - * @param peer_id the index of the peer - * @param cfg the configuration with which the transport handle has to be - * created if it was not present in the cache - * @param service the service of interest - * @param cb the callback to notify when the transport handle is available - * @param cb_cls the closure for @a cb - * @param target the peer identify of the peer whose connection to our TRANSPORT - * subsystem will be notified through the @a connect_notify_cb. Can be - * NULL - * @param connect_notify_cb the callback to call when the @a target peer is - * connected. This callback will only be called once or never again (in - * case the target peer cannot be connected). Can be NULL - * @param connect_notify_cb_cls the closure for @a connect_notify_cb - * @return the handle which can be used cancel or mark that the handle is no - * longer being used - */ -struct GST_ConnectionPool_GetHandle * -GST_connection_pool_get_handle ( - unsigned int peer_id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - enum GST_ConnectionPool_Service service, - GST_connection_pool_connection_ready_cb cb, - void *cb_cls, - const struct GNUNET_PeerIdentity *target, - GST_connection_pool_peer_connect_notify connect_notify_cb, - void *connect_notify_cb_cls) -{ - struct GST_ConnectionPool_GetHandle *gh; - struct PooledConnection *entry; - struct GNUNET_TESTBED_Operation *op; - void *handle; - uint32_t peer_id32; - - peer_id32 = (uint32_t) peer_id; - handle = NULL; - entry = NULL; - if (NULL != map) - entry = GNUNET_CONTAINER_multihashmap32_get (map, peer_id32); - if (NULL != entry) - { - if (entry->in_lru) - { - GNUNET_assert (0 == entry->demand); - expire_task_cancel (entry); - GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry); - entry->in_lru = GNUNET_NO; - } - switch (service) - { - case GST_CONNECTIONPOOL_SERVICE_TRANSPORT: - handle = entry->handle_transport; - if (NULL != handle) - LOG_DEBUG ("Found TRANSPORT handle for peer %u\n", - entry->index); - break; - case GST_CONNECTIONPOOL_SERVICE_CORE: - handle = entry->handle_core; - if (NULL != handle) - LOG_DEBUG ("Found CORE handle for peer %u\n", - entry->index); - break; - case GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY: - handle = entry->handle_ats_connectivity; - if (NULL != handle) - LOG_DEBUG ("Found ATS CONNECTIVITY handle for peer %u\n", - entry->index); - break; - } - } - else - { - entry = GNUNET_new (struct PooledConnection); - entry->index = peer_id32; - if ((NULL != map) && - (GNUNET_CONTAINER_multihashmap32_size (map) < max_size)) - { - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap32_put ( - map, - entry->index, - entry, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); - entry->in_pool = GNUNET_YES; - } - else - { - GNUNET_CONTAINER_DLL_insert_tail (head_not_pooled, - tail_not_pooled, - entry); - } - entry->cfg = GNUNET_CONFIGURATION_dup (cfg); - } - entry->demand++; - gh = GNUNET_new (struct GST_ConnectionPool_GetHandle); - gh->entry = entry; - gh->cb = cb; - gh->cb_cls = cb_cls; - gh->target = target; - gh->connect_notify_cb = connect_notify_cb; - gh->connect_notify_cb_cls = connect_notify_cb_cls; - gh->service = service; - GNUNET_CONTAINER_DLL_insert (entry->head_waiting, - entry->tail_waiting, - gh); - if (NULL != handle) - { - if (NULL == entry->notify_task) - { - if (NULL != search_waiting (entry, entry->head_waiting)) - entry->notify_task = - GNUNET_SCHEDULER_add_now (&connection_ready, entry); - } - return gh; - } - op = NULL; - switch (gh->service) - { - case GST_CONNECTIONPOOL_SERVICE_TRANSPORT: - if (NULL != entry->op_transport) - return gh; /* Operation pending */ - op = GNUNET_TESTBED_operation_create_ (entry, - &opstart_get_handle_transport, - &oprelease_get_handle_transport); - entry->op_transport = op; - break; - - case GST_CONNECTIONPOOL_SERVICE_CORE: - if (NULL != entry->op_core) - return gh; /* Operation pending */ - op = GNUNET_TESTBED_operation_create_ (entry, - &opstart_get_handle_core, - &oprelease_get_handle_core); - entry->op_core = op; - break; - - case GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY: - if (NULL != entry->op_ats_connectivity) - return gh; /* Operation pending */ - op = - GNUNET_TESTBED_operation_create_ (entry, - &opstart_get_handle_ats_connectivity, - &oprelease_get_handle_ats_connectivity); - entry->op_ats_connectivity = op; - break; - } - GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, op); - GNUNET_TESTBED_operation_begin_wait_ (op); - return gh; -} - - -/** - * Relinquish a #GST_ConnectionPool_GetHandle object. If the connection - * associated with the object is currently being used by other - * #GST_ConnectionPool_GetHandle objects, it is left in the connection pool. If - * no other objects are using the connection and the connection pool is not full - * then it is placed in a LRU queue. If the connection pool is full, then - * connections from the LRU queue are evicted and closed to create place for - * this connection. If the connection pool if full and the LRU queue is empty, - * then the connection is closed. - * - * @param gh the handle - */ -void -GST_connection_pool_get_handle_done (struct GST_ConnectionPool_GetHandle *gh) -{ - struct PooledConnection *entry; - - if (NULL == gh) - return; - entry = gh->entry; - LOG_DEBUG ("Cleaning up get handle %p for service %u, peer %u\n", - gh, - gh->service, - entry->index); - if (! gh->connection_ready_called) - { - GNUNET_CONTAINER_DLL_remove (entry->head_waiting, entry->tail_waiting, gh); - if ((NULL == search_waiting (entry, entry->head_waiting)) && - (NULL != entry->notify_task)) - { - GNUNET_SCHEDULER_cancel (entry->notify_task); - entry->notify_task = NULL; - } - } - if (gh->notify_waiting) - { - GNUNET_CONTAINER_DLL_remove (entry->head_notify, entry->tail_notify, gh); - gh->notify_waiting = 0; - } - GNUNET_free (gh); - gh = NULL; - GNUNET_assert (! entry->in_lru); - if (! entry->in_pool) - GNUNET_CONTAINER_DLL_remove (head_not_pooled, tail_not_pooled, entry); - if (NULL != map) - { - if (GNUNET_YES == - GNUNET_CONTAINER_multihashmap32_contains (map, entry->index)) - goto unallocate; - if (GNUNET_CONTAINER_multihashmap32_size (map) == max_size) - { - if (NULL == head_lru) - goto unallocate; - destroy_pooled_connection (head_lru); - } - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap32_put ( - map, - entry->index, - entry, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - entry->in_pool = GNUNET_YES; - } - -unallocate: - GNUNET_assert (0 < entry->demand); - entry->demand--; - if (0 != entry->demand) - return; - if (entry->in_pool) - { - add_to_lru (entry); - return; - } - destroy_pooled_connection (entry); -} diff --git a/src/testbed/gnunet-service-testbed_connectionpool.h b/src/testbed/gnunet-service-testbed_connectionpool.h @@ -1,172 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--2015 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-service-testbed_connectionpool.h - * @brief Interface for connection pooling subroutines - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ -#include "gnunet_ats_service.h" -#include "gnunet_core_service.h" -#include "gnunet_transport_service.h" - -/** - * The request handle for obtaining a pooled connection - */ -struct GST_ConnectionPool_GetHandle; - - -/** - * The type of service - */ -enum GST_ConnectionPool_Service -{ - /** - * Transport service - */ - GST_CONNECTIONPOOL_SERVICE_TRANSPORT = 1, - - /** - * Core service - */ - GST_CONNECTIONPOOL_SERVICE_CORE, - - /** - * ATS service - */ - GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY -}; - - -/** - * Initialise the connection pool. - * - * @param size the size of the connection pool. Each entry in the connection - * pool can handle a connection to each of the services enumerated in - * #GST_ConnectionPool_Service - */ -void -GST_connection_pool_init (unsigned int size); - - -/** - * Cleanup the connection pool - */ -void -GST_connection_pool_destroy (void); - -/** - * Functions of this type are called when the needed handle is available for - * usage. These functions are to be registered with the function - * GST_connection_pool_get_handle(). The corresponding handles will be set upon - * success. If they are not set, then it signals an error while opening the - * handles. - * - * @param cls the closure passed to GST_connection_pool_get_handle() - * @param ch the handle to CORE. Can be NULL if it is not requested - * @param th the handle to TRANSPORT. Can be NULL if it is not requested - * @param ac the handle to ATS, can be NULL if it is not requested - * @param peer_id the identity of the peer. Will be NULL if ch is NULL. In other - * cases, its value being NULL means that CORE connection has failed. - * @param cfg configuration of the peer - */ -typedef void (*GST_connection_pool_connection_ready_cb) ( - void *cls, - struct GNUNET_CORE_Handle *ch, - struct GNUNET_TRANSPORT_CoreHandle *th, - struct GNUNET_ATS_ConnectivityHandle *ac, - const struct GNUNET_PeerIdentity *peer_id, - const struct GNUNET_CONFIGURATION_Handle *cfg); - - -/** - * Callback to notify when the target peer given to - * GST_connection_pool_get_handle() is connected. - * - * @param cls the closure given to GST_connection_pool_get_handle() for this - * callback - * @param target the peer identity of the target peer - */ -typedef void (*GST_connection_pool_peer_connect_notify) ( - void *cls, - const struct GNUNET_PeerIdentity *target); - - -/** - * Get a connection handle to @a service. If the connection is opened before - * and the connection handle is present in the connection pool, it is returned - * through @a cb. @a peer_id is used for the lookup in the connection pool. If - * the connection handle is not present in the connection pool, a new connection - * handle is opened for the @a service using @a cfg. Additionally, @a target, - * @a connect_notify_cb can be specified to get notified when @a target is - * connected at @a service. - * - * @note @a connect_notify_cb will not be called if @a target is - * already connected @a service level. Use - * GNUNET_TRANSPORT_check_peer_connected() or a similar function from the - * respective @a service's API to check if the target peer is already connected - * or not. @a connect_notify_cb will be called only once or never (in case @a - * target cannot be connected or is already connected). - * - * @param peer_id the index of the peer - * @param cfg the configuration with which the transport handle has to be - * created if it was not present in the cache - * @param service the service of interest - * @param cb the callback to notify when the transport handle is available - * @param cb_cls the closure for @a cb - * @param target the peer identify of the peer whose connection to our TRANSPORT - * subsystem will be notified through the @a connect_notify_cb. Can be - * NULL - * @param connect_notify_cb the callback to call when the @a target peer is - * connected. This callback will only be called once or never again (in - * case the target peer cannot be connected). Can be NULL - * @param connect_notify_cb_cls the closure for @a connect_notify_cb - * @return the handle which can be used cancel or mark that the handle is no - * longer being used - */ -struct GST_ConnectionPool_GetHandle * -GST_connection_pool_get_handle ( - unsigned int peer_id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - enum GST_ConnectionPool_Service service, - GST_connection_pool_connection_ready_cb cb, - void *cb_cls, - const struct GNUNET_PeerIdentity *target, - GST_connection_pool_peer_connect_notify connect_notify_cb, - void *connect_notify_cb_cls); - - -/** - * Relinquish a #GST_ConnectionPool_GetHandle object. If the connection - * associated with the object is currently being used by other - * #GST_ConnectionPool_GetHandle objects, it is left in the connection pool. If - * no other objects are using the connection and the connection pool is not full - * then it is placed in a LRU queue. If the connection pool is full, then - * connections from the LRU queue are evicted and closed to create place for - * this connection. If the connection pool if full and the LRU queue is empty, - * then the connection is closed. - * - * @param gh the handle - */ -void -GST_connection_pool_get_handle_done (struct GST_ConnectionPool_GetHandle *gh); - - -/* End of gnunet-service-testbed_connectionpool.h */ diff --git a/src/testbed/gnunet-service-testbed_cpustatus.c b/src/testbed/gnunet-service-testbed_cpustatus.c @@ -1,664 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-service-testbed_cpustatus.c - * @brief calls to determine current CPU load - * @author Tzvetan Horozov - * @author Christian Grothoff - * @author Igor Wronsky - * @author Alex Harper (OS X portion) - * @author Sree Harsha Totakura - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet-service-testbed_meminfo.h" - -#if SOLARIS -#if HAVE_KSTAT_H -#include <kstat.h> -#endif -#if HAVE_SYS_SYSINFO_H -#include <sys/sysinfo.h> -#endif -#if HAVE_KVM_H -#include <kvm.h> -#endif -#endif -#ifdef BSD -#if HAVE_KVM_H -#include <kvm.h> -#endif -#endif - -#ifdef OSX -#include <mach/mach.h> - -static processor_cpu_load_info_t prev_cpu_load; -#endif - -#define DEBUG_STATUSCALLS GNUNET_NO - -#ifdef __linux__ -static FILE *proc_stat; -#endif - -/** - * Current CPU load, as percentage of CPU cycles not idle or - * blocked on IO. - */ -static int currentCPULoad; - -static double agedCPULoad = -1; - -/** - * Current IO load, as percentage of CPU cycles blocked on IO. - */ -static int currentIOLoad; - -static double agedIOLoad = -1; - - -/** - * handle to the file to write the load statistics to - */ -struct GNUNET_BIO_WriteHandle *bw; - -struct GNUNET_SCHEDULER_Task *sample_load_task_id; - - -#ifdef OSX -static int -initMachCpuStats () -{ - unsigned int cpu_count; - processor_cpu_load_info_t cpu_load; - mach_msg_type_number_t cpu_msg_count; - kern_return_t kret; - int i, j; - - kret = host_processor_info (mach_host_self (), - PROCESSOR_CPU_LOAD_INFO, - &cpu_count, - (processor_info_array_t *) &cpu_load, - &cpu_msg_count); - if (kret != KERN_SUCCESS) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "host_processor_info failed."); - return GNUNET_SYSERR; - } - prev_cpu_load = GNUNET_malloc (cpu_count * sizeof(*prev_cpu_load)); - for (i = 0; i < cpu_count; i++) - { - for (j = 0; j < CPU_STATE_MAX; j++) - { - prev_cpu_load[i].cpu_ticks[j] = cpu_load[i].cpu_ticks[j]; - } - } - vm_deallocate (mach_task_self (), - (vm_address_t) cpu_load, - (vm_size_t) (cpu_msg_count * sizeof(*cpu_load))); - return GNUNET_OK; -} - - -#endif - -/** - * Update the currentCPU and currentIO load (and on Linux, memory) values. - * - * Before its first invocation the method initStatusCalls() must be called. - * If there is an error the method returns -1. - */ -static int -updateUsage () -{ - currentIOLoad = -1; - currentCPULoad = -1; -#ifdef __linux__ - /* under linux, first try %idle/usage using /proc/stat; - if that does not work, disable /proc/stat for the future - by closing the file and use the next-best method. */ - if (proc_stat != NULL) - { - static unsigned long long last_cpu_results[5] = { 0, 0, 0, 0, 0 }; - static int have_last_cpu = GNUNET_NO; - int ret; - char line[256]; - unsigned long long user_read, system_read, nice_read, idle_read, - iowait_read; - unsigned long long user, system, nice, idle, iowait; - unsigned long long usage_time = 0, total_time = 1; - - /* Get the first line with the data */ - rewind (proc_stat); - fflush (proc_stat); - if (NULL == fgets (line, 256, proc_stat)) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, - "fgets", "/proc/stat"); - proc_stat = NULL; /* don't try again */ - } - else - { - iowait_read = 0; - ret = sscanf (line, "%*s %llu %llu %llu %llu %llu", - &user_read, - &system_read, &nice_read, &idle_read, &iowait_read); - if (ret < 4) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, - "fgets-sscanf", "/proc/stat"); - fclose (proc_stat); - proc_stat = NULL; /* don't try again */ - have_last_cpu = GNUNET_NO; - } - else - { - /* Store the current usage */ - user = user_read - last_cpu_results[0]; - system = system_read - last_cpu_results[1]; - nice = nice_read - last_cpu_results[2]; - idle = idle_read - last_cpu_results[3]; - iowait = iowait_read - last_cpu_results[4]; - /* Calculate the % usage */ - usage_time = user + system + nice; - total_time = usage_time + idle + iowait; - if ((total_time > 0) && (have_last_cpu == GNUNET_YES)) - { - currentCPULoad = (int) (100L * usage_time / total_time); - if (ret > 4) - currentIOLoad = (int) (100L * iowait / total_time); - else - currentIOLoad = -1; /* 2.4 kernel */ - } - /* Store the values for the next calculation */ - last_cpu_results[0] = user_read; - last_cpu_results[1] = system_read; - last_cpu_results[2] = nice_read; - last_cpu_results[3] = idle_read; - last_cpu_results[4] = iowait_read; - have_last_cpu = GNUNET_YES; - return GNUNET_OK; - } - } - } -#endif - -#ifdef OSX - { - unsigned int cpu_count; - processor_cpu_load_info_t cpu_load; - mach_msg_type_number_t cpu_msg_count; - unsigned long long t_sys, t_user, t_nice, t_idle, t_total; - unsigned long long t_idle_all, t_total_all; - kern_return_t kret; - int i, j; - - t_idle_all = t_total_all = 0; - kret = host_processor_info (mach_host_self (), PROCESSOR_CPU_LOAD_INFO, - &cpu_count, - (processor_info_array_t *) &cpu_load, - &cpu_msg_count); - if (kret == KERN_SUCCESS) - { - for (i = 0; i < cpu_count; i++) - { - if (cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM] >= - prev_cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM]) - { - t_sys = cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM] - - prev_cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM]; - } - else - { - t_sys = cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM] - + (ULONG_MAX - prev_cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM] - + 1); - } - - if (cpu_load[i].cpu_ticks[CPU_STATE_USER] >= - prev_cpu_load[i].cpu_ticks[CPU_STATE_USER]) - { - t_user = cpu_load[i].cpu_ticks[CPU_STATE_USER] - - prev_cpu_load[i].cpu_ticks[CPU_STATE_USER]; - } - else - { - t_user = cpu_load[i].cpu_ticks[CPU_STATE_USER] - + (ULONG_MAX - prev_cpu_load[i].cpu_ticks[CPU_STATE_USER] - + 1); - } - - if (cpu_load[i].cpu_ticks[CPU_STATE_NICE] >= - prev_cpu_load[i].cpu_ticks[CPU_STATE_NICE]) - { - t_nice = cpu_load[i].cpu_ticks[CPU_STATE_NICE] - - prev_cpu_load[i].cpu_ticks[CPU_STATE_NICE]; - } - else - { - t_nice = cpu_load[i].cpu_ticks[CPU_STATE_NICE] - + (ULONG_MAX - prev_cpu_load[i].cpu_ticks[CPU_STATE_NICE] - + 1); - } - - if (cpu_load[i].cpu_ticks[CPU_STATE_IDLE] >= - prev_cpu_load[i].cpu_ticks[CPU_STATE_IDLE]) - { - t_idle = cpu_load[i].cpu_ticks[CPU_STATE_IDLE] - - prev_cpu_load[i].cpu_ticks[CPU_STATE_IDLE]; - } - else - { - t_idle = cpu_load[i].cpu_ticks[CPU_STATE_IDLE] - + (ULONG_MAX - prev_cpu_load[i].cpu_ticks[CPU_STATE_IDLE] - + 1); - } - t_total = t_sys + t_user + t_nice + t_idle; - t_idle_all += t_idle; - t_total_all += t_total; - } - for (i = 0; i < cpu_count; i++) - { - for (j = 0; j < CPU_STATE_MAX; j++) - { - prev_cpu_load[i].cpu_ticks[j] = cpu_load[i].cpu_ticks[j]; - } - } - if (t_total_all > 0) - currentCPULoad = 100 - (100 * t_idle_all) / t_total_all; - else - currentCPULoad = -1; - vm_deallocate (mach_task_self (), - (vm_address_t) cpu_load, - (vm_size_t) (cpu_msg_count * sizeof(*cpu_load))); - currentIOLoad = -1; /* FIXME-OSX! */ - return GNUNET_OK; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "host_processor_info failed."); - return GNUNET_SYSERR; - } - } -#endif - /* try kstat (Solaris only) */ -#if SOLARIS && HAVE_KSTAT_H && HAVE_SYS_SYSINFO_H - { - static long long last_idlecount; - static long long last_totalcount; - static int kstat_once; /* if open fails, don't keep - trying */ - kstat_ctl_t *kc; - kstat_t *khelper; - long long idlecount; - long long totalcount; - long long deltaidle; - long long deltatotal; - - if (kstat_once == 1) - goto ABORT_KSTAT; - kc = kstat_open (); - if (kc == NULL) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kstat_close"); - goto ABORT_KSTAT; - } - - idlecount = 0; - totalcount = 0; - for (khelper = kc->kc_chain; khelper != NULL; khelper = khelper->ks_next) - { - cpu_stat_t stats; - - if (0 != strncmp (khelper->ks_name, "cpu_stat", strlen ("cpu_stat"))) - continue; - if (khelper->ks_data_size > sizeof(cpu_stat_t)) - continue; /* better save then sorry! */ - if (-1 != kstat_read (kc, khelper, &stats)) - { - idlecount += stats.cpu_sysinfo.cpu[CPU_IDLE]; - totalcount - += stats.cpu_sysinfo.cpu[CPU_IDLE] - + stats.cpu_sysinfo.cpu[CPU_USER] - + stats.cpu_sysinfo.cpu[CPU_KERNEL] - + stats.cpu_sysinfo.cpu[CPU_WAIT]; - } - } - if (0 != kstat_close (kc)) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kstat_close"); - if ((idlecount == 0) && (totalcount == 0)) - goto ABORT_KSTAT; /* no stats found => abort */ - deltaidle = idlecount - last_idlecount; - deltatotal = totalcount - last_totalcount; - if ((deltatotal > 0) && (last_totalcount > 0)) - { - currentCPULoad = (unsigned int) (100.0 * deltaidle / deltatotal); - if (currentCPULoad > 100) - currentCPULoad = 100; /* odd */ - if (currentCPULoad < 0) - currentCPULoad = 0; /* odd */ - currentCPULoad = 100 - currentCPULoad; /* computed idle-load before! */ - } - else - currentCPULoad = -1; - currentIOLoad = -1; /* FIXME-SOLARIS! */ - last_idlecount = idlecount; - last_totalcount = totalcount; - return GNUNET_OK; -ABORT_KSTAT: - kstat_once = 1; /* failed, don't try again */ - return GNUNET_SYSERR; - } -#endif - - /* insert methods better than getloadavg for - other platforms HERE! */ - - /* ok, maybe we have getloadavg on this platform */ -#if HAVE_GETLOADAVG - { - static int warnOnce = 0; - double loadavg; - if (1 != getloadavg (&loadavg, 1)) - { - /* only warn once, if there is a problem with - getloadavg, we're going to hit it frequently... */ - if (warnOnce == 0) - { - warnOnce = 1; - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "getloadavg"); - } - return GNUNET_SYSERR; - } - else - { - /* success with getloadavg */ - currentCPULoad = (int) (100 * loadavg); - currentIOLoad = -1; /* FIXME */ - return GNUNET_OK; - } - } -#endif - - /* loadaverage not defined and no platform - specific alternative defined - => default: error - */ - return GNUNET_SYSERR; -} - - -/** - * Update load values (if enough time has expired), - * including computation of averages. Code assumes - * that lock has already been obtained. - */ -static void -updateAgedLoad () -{ - static struct GNUNET_TIME_Absolute lastCall; - struct GNUNET_TIME_Relative age; - - age = GNUNET_TIME_absolute_get_duration (lastCall); - if ((agedCPULoad == -1) - || (age.rel_value_us > 500000)) - { - /* use smoothing, but do NOT update lastRet at frequencies higher - than 500ms; this makes the smoothing (mostly) independent from - the frequency at which getCPULoad is called (and we don't spend - more time measuring CPU than actually computing something). */ - lastCall = GNUNET_TIME_absolute_get (); - updateUsage (); - if (currentCPULoad == -1) - { - agedCPULoad = -1; - } - else - { - if (agedCPULoad == -1) - { - agedCPULoad = currentCPULoad; - } - else - { - /* for CPU, we don't do the 'fast increase' since CPU is much - more jitterish to begin with */ - agedCPULoad = (agedCPULoad * 31 + currentCPULoad) / 32; - } - } - if (currentIOLoad == -1) - { - agedIOLoad = -1; - } - else - { - if (agedIOLoad == -1) - { - agedIOLoad = currentIOLoad; - } - else - { - /* for IO, we don't do the 'fast increase' since IO is much - more jitterish to begin with */ - agedIOLoad = (agedIOLoad * 31 + currentIOLoad) / 32; - } - } - } -} - - -/** - * Get the load of the CPU relative to what is allowed. - * @return the CPU load as a percentage of allowed - * (100 is equivalent to full load) - */ -static int -cpu_get_load () -{ - updateAgedLoad (); - return (int) agedCPULoad; -} - - -/** - * Get the load of the CPU relative to what is allowed. - * @return the CPU load as a percentage of allowed - * (100 is equivalent to full load) - */ -static int -disk_get_load () -{ - updateAgedLoad (); - return (int) agedIOLoad; -} - - -/** - * Get the percentage of memory used - * - * @return the percentage of memory used - */ -static unsigned int -mem_get_usage () -{ - double percentage; - - meminfo (); - percentage = (((double) kb_main_used) / ((double) kb_main_total) * 100.0); - return (unsigned int) percentage; -} - - -#ifdef __linux__ -#include <dirent.h> -/** - * Returns the number of processes - * - * @return the number of processes - */ -static unsigned int -get_nproc () -{ - DIR *dir; - struct dirent *ent; - unsigned int nproc; - - dir = opendir ("/proc"); - if (NULL == dir) - return 0; - nproc = 0; - while (NULL != (ent = readdir (dir))) - { - if ((*ent->d_name > '0') && (*ent->d_name <= '9')) - nproc++; - } - closedir (dir); - return nproc; -} - - -#endif - - -static void -sample_load_task (void *cls) -{ - struct GNUNET_TIME_Absolute now; - char *str; - int nbs; - int ld_cpu; - int ld_disk; - unsigned int mem_usage; - unsigned int nproc; - - sample_load_task_id = NULL; - ld_cpu = cpu_get_load (); - ld_disk = disk_get_load (); - if ((-1 == ld_cpu) || (-1 == ld_disk)) - goto reschedule; - mem_usage = mem_get_usage (); -#ifdef __linux__ - nproc = get_nproc (); -#else - nproc = 0; -#endif - now = GNUNET_TIME_absolute_get (); - nbs = GNUNET_asprintf (&str, "%llu %d %d %u %u\n", now.abs_value_us / 1000LL - / 1000LL, - ld_cpu, ld_disk, mem_usage, nproc); - if (0 < nbs) - { - GNUNET_BIO_write (bw, "sample load task", str, nbs); - } - else - GNUNET_break (0); - GNUNET_free (str); - -reschedule: - sample_load_task_id = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, - &sample_load_task, NULL); -} - - -/** - * Initialize logging CPU and IO statisticfs. Checks the configuration for - * "STATS_DIR" and logs to a file in that directory. The file is name is - * generated from the hostname and the process's PID. - */ -void -GST_stats_init (const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - char *hostname; - char *stats_dir; - char *fn; - size_t len; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, "testbed", - "STATS_DIR", &stats_dir)) - return; - len = GNUNET_OS_get_hostname_max_length (); - hostname = GNUNET_malloc (len); - if (0 != gethostname (hostname, len)) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "gethostname"); - GNUNET_free (stats_dir); - GNUNET_free (hostname); - return; - } - fn = NULL; - (void) GNUNET_asprintf (&fn, "%s/%.*s-%jd.dat", stats_dir, (int)len, - hostname, (intmax_t) getpid ()); - GNUNET_free (stats_dir); - GNUNET_free (hostname); - if (NULL == (bw = GNUNET_BIO_write_open_file (fn))) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ ("Cannot open %s for writing load statistics. " - "Not logging load statistics\n"), fn); - GNUNET_free (fn); - return; - } - GNUNET_free (fn); - sample_load_task_id = GNUNET_SCHEDULER_add_now (&sample_load_task, NULL); -#ifdef __linux__ - proc_stat = fopen ("/proc/stat", "r"); - if (NULL == proc_stat) - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, - "fopen", "/proc/stat"); -#elif OSX - initMachCpuStats (); -#endif - updateUsage (); /* initialize */ -} - - -/** - * Shutdown the status calls module. - */ -void -GST_stats_destroy () -{ - if (NULL == bw) - return; -#ifdef __linux__ - if (proc_stat != NULL) - { - fclose (proc_stat); - proc_stat = NULL; - } -#elif OSX - GNUNET_free (prev_cpu_load); -#endif - if (NULL != sample_load_task_id) - { - GNUNET_SCHEDULER_cancel (sample_load_task_id); - sample_load_task_id = NULL; - } - GNUNET_break (GNUNET_OK == GNUNET_BIO_write_close (bw, NULL)); - bw = NULL; -} - - -/* end of cpustatus.c */ diff --git a/src/testbed/gnunet-service-testbed_links.c b/src/testbed/gnunet-service-testbed_links.c @@ -1,1468 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-service-testbed_links.c - * @brief TESTBED service components that deals with starting slave controllers - * and establishing lateral links between controllers - * @author Sree Harsha Totakura - */ - -#include "platform.h" -#include "gnunet-service-testbed.h" - -/** - * Redefine LOG with a changed log component string - */ -#ifdef LOG -#undef LOG -#endif -#define LOG(kind, ...) \ - GNUNET_log_from (kind, "testbed-links", __VA_ARGS__) - -/** - * The event mask for the events we listen from sub-controllers - */ -#define EVENT_MASK (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED) - - -/** - * States of LCFContext - */ -enum LCFContextState -{ - /** - * The Context has been initialized; Nothing has been done on it - */ - INIT, - - /** - * Delegated host has been registered at the forwarding controller - */ - DELEGATED_HOST_REGISTERED, - - /** - * The slave host has been registered at the forwarding controller - */ - SLAVE_HOST_REGISTERED, - - /** - * The context has been finished (may have error) - */ - FINISHED -}; - - -/** - * Link controllers request forwarding context - */ -struct LCFContext -{ - /** - * The LCFContext - */ - struct LCFContext *next; - - /** - * The LCFContext - */ - struct LCFContext *prev; - - /** - * The gateway which will pass the link message to delegated host - */ - struct Slave *gateway; - - /** - * The client which has asked to perform this operation - */ - struct GNUNET_SERVICE_Client *client; - - /** - * Handle for operations which are forwarded while linking controllers - */ - struct GNUNET_TESTBED_Operation *op; - - /** - * The timeout task - */ - struct GNUNET_SCHEDULER_Task *timeout_task; - - /** - * The id of the operation which created this context - */ - uint64_t operation_id; - - /** - * should the slave controller start the delegated controller? - */ - int is_subordinate; - - /** - * The state of this context - */ - enum LCFContextState state; - - /** - * The delegated host - */ - uint32_t delegated_host_id; - - /** - * The slave host - */ - uint32_t slave_host_id; -}; - - -/** - * Notification context to be used to notify when connection to the neighbour's - * controller is opened - */ -struct NeighbourConnectNotification -{ - /** - * DLL next for inclusion in neighbour's list of notification requests - */ - struct NeighbourConnectNotification *next; - - /** - * DLL prev - */ - struct NeighbourConnectNotification *prev; - - /** - * The neighbour - */ - struct Neighbour *n; - - /** - * The notification callback to call when we are connect to neighbour - */ - GST_NeighbourConnectNotifyCallback cb; - - /** - * The closure for the above callback - */ - void *cb_cls; -}; - - -/** - * A connected controller which is not our child - */ -struct Neighbour -{ - /** - * The controller handle - */ - struct GNUNET_TESTBED_Controller *controller; - - /** - * Operation handle for opening a lateral connection to another controller. - * Will be NULL if the slave controller is started by this controller - */ - struct GNUNET_TESTBED_Operation *conn_op; - - /** - * DLL head for the list of notification requests - */ - struct NeighbourConnectNotification *nl_head; - - /** - * DLL tail for the list of notification requests - */ - struct NeighbourConnectNotification *nl_tail; - - /** - * Task id for the task to call notifications from the notification list - */ - struct GNUNET_SCHEDULER_Task *notify_task; - - /** - * How many references are present currently to this neighbour's connection - */ - unsigned int reference_cnt; - - /** - * Is the conn_op inactivated? - */ - unsigned int inactive; - - /** - * The id of the host this controller is running on - */ - uint32_t host_id; -}; - - -/** - * The neighbour list - */ -static struct Neighbour **neighbour_list; - -/** - * The size of the neighbour list - */ -static unsigned int neighbour_list_size; - - -/** - * Context information for establishing a link to neighbour (Used is - * GST_handle_link_controllers() - */ -struct NeighbourConnectCtxt -{ - /** - * DLL next for inclusion in the corresponding context list - */ - struct NeighbourConnectCtxt *next; - - /** - * DLL tail - */ - struct NeighbourConnectCtxt *prev; - - /** - * The neighbour to whom connection should be made - */ - struct Neighbour *n; - - /** - * The client requesting the connection - */ - struct GNUNET_SERVICE_Client *client; - - /** - * Task to be run upon timeout - */ - struct GNUNET_SCHEDULER_Task *timeout_task; - - /** - * The notification handle associated with the neighbour's connection request - */ - struct NeighbourConnectNotification *nh; - - /** - * The id of the link-controllers operation responsible for creating this - * context - */ - uint64_t op_id; -}; - -/** - * DLL head for the list of neighbour connect contexts - */ -struct NeighbourConnectCtxt *ncc_head; - -/** - * DLL tail for the list of neighbour connect contexts - */ -struct NeighbourConnectCtxt *ncc_tail; - -/** - * A list of directly linked neighbours - */ -struct Slave **GST_slave_list; - -/** - * The size of directly linked neighbours list - */ -unsigned int GST_slave_list_size; - -/** - * A list of routes - */ -static struct Route **route_list; - -/** - * The LCF queue - */ -static struct LCFContext *lcf_head; - -/** - * The tail for the LCF queue - */ -static struct LCFContext *lcf_tail; - -/** - * The lcf_task handle - */ -static struct GNUNET_SCHEDULER_Task *lcf_proc_task_id; - -/** - * The size of the route list - */ -static unsigned int route_list_size; - - -/** - * Adds a slave to the slave array - * - * @param slave the slave controller to add - */ -static void -slave_list_add (struct Slave *slave) -{ - if (slave->host_id >= GST_slave_list_size) - GST_array_grow_large_enough (GST_slave_list, - GST_slave_list_size, - slave->host_id); - GNUNET_assert (NULL == GST_slave_list[slave->host_id]); - GST_slave_list[slave->host_id] = slave; -} - - -/** - * Clean up all forwarded operation overlay context matching the - * client given in @a cls. - * - * @param cls a `struct GNUNET_SERVICE_Client *` to match - * @param key unused - * @param value the `struct RegisteredHostContext` to search for @a cls - * @return #GNUNET_OK (continue iterating) - */ -static int -drop_client_entries (void *cls, - const struct GNUNET_HashCode *key, - void *value) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct RegisteredHostContext *rhc = value; - struct ForwardedOverlayConnectContext *focc; - struct ForwardedOverlayConnectContext *foccn; - - for (focc = rhc->focc_dll_head; NULL != focc; focc = foccn) - { - foccn = focc->next; - if (focc->client == client) - GST_cleanup_focc (focc); - } - return GNUNET_OK; -} - - -/** - * Adds a route to the route list - * - * @param route the route to add - */ -static void -route_list_add (struct Route *route) -{ - if (route->dest >= route_list_size) - GST_array_grow_large_enough (route_list, route_list_size, route->dest); - GNUNET_assert (NULL == route_list[route->dest]); - route_list[route->dest] = route; -} - - -/** - * Add a neighbour to the neighbour list. Grows the neighbour list - * automatically. - * - * @param n the neighbour to add - */ -static void -neighbour_list_add (struct Neighbour *n) -{ - if (n->host_id >= neighbour_list_size) - GST_array_grow_large_enough (neighbour_list, neighbour_list_size, - n->host_id); - GNUNET_assert (NULL == neighbour_list[n->host_id]); - neighbour_list[n->host_id] = n; -} - - -/** - * Cleans up the route list - */ -void -GST_route_list_clear () -{ - unsigned int id; - - for (id = 0; id < route_list_size; id++) - if (NULL != route_list[id]) - GNUNET_free (route_list[id]); - GNUNET_free (route_list); - route_list = NULL; -} - - -/** - * Iterator for freeing hash map entries in a slave's reghost_map - * - * @param cls handle to the slave - * @param key current key code - * @param value value in the hash map - * @return #GNUNET_YES if we should continue to iterate, - * #GNUNET_NO if not. - */ -static int -reghost_free_iterator (void *cls, - const struct GNUNET_HashCode *key, - void *value) -{ - struct Slave *slave = cls; - struct RegisteredHostContext *rhc = value; - struct ForwardedOverlayConnectContext *focc; - - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (slave->reghost_map, key, - value)); - while (NULL != (focc = rhc->focc_dll_head)) - GST_cleanup_focc (focc); - GNUNET_free (value); - return GNUNET_YES; -} - - -/** - * Kill a #Slave object - * - * @param slave the #Slave object - */ -static void -kill_slave (struct Slave *slave) -{ - struct HostRegistration *hr_entry; - - while (NULL != (hr_entry = slave->hr_dll_head)) - { - GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, slave->hr_dll_tail, - hr_entry); - GNUNET_free (hr_entry); - } - if (NULL != slave->rhandle) - GNUNET_TESTBED_cancel_registration (slave->rhandle); - GNUNET_assert (GNUNET_SYSERR != - GNUNET_CONTAINER_multihashmap_iterate (slave->reghost_map, - reghost_free_iterator, - slave)); - GNUNET_CONTAINER_multihashmap_destroy (slave->reghost_map); - if (NULL != slave->controller) - GNUNET_TESTBED_controller_disconnect (slave->controller); - if (NULL != slave->controller_proc) - { - LOG_DEBUG ("Stopping a slave\n"); - GNUNET_TESTBED_controller_kill_ (slave->controller_proc); - } -} - - -/** - * Destroy a #Slave object - * - * @param slave the #Slave object - */ -static void -destroy_slave (struct Slave *slave) -{ - if (NULL != slave->controller_proc) - { - GNUNET_TESTBED_controller_destroy_ (slave->controller_proc); - LOG_DEBUG ("Slave stopped\n"); - } - GST_slave_list[slave->host_id] = NULL; - GNUNET_free (slave); -} - - -/** - * Cleans up the slave list - */ -void -GST_slave_list_clear () -{ - struct Slave *slave; - unsigned int id; - - for (id = 0; id < GST_slave_list_size; id++) - { - slave = GST_slave_list[id]; - if (NULL == slave) - continue; - kill_slave (slave); - } - for (id = 0; id < GST_slave_list_size; id++) - { - slave = GST_slave_list[id]; - if (NULL == slave) - continue; - destroy_slave (slave); - } - GNUNET_free (GST_slave_list); - GST_slave_list = NULL; -} - - -/** - * Finds the route with directly connected host as destination through which - * the destination host can be reached - * - * @param host_id the id of the destination host - * @return the route with directly connected destination host; NULL if no route - * is found - */ -struct Route * -GST_find_dest_route (uint32_t host_id) -{ - struct Route *route; - - if (route_list_size <= host_id) - return NULL; - while (NULL != (route = route_list[host_id])) - { - if (route->thru == GST_context->host_id) - break; - host_id = route->thru; - } - return route; -} - - -/** - * Function to send a failure response for controller link operation - * - * @param client the client to send the message to - * @param operation_id the operation ID of the controller link request - * @param cfg the configuration with which the delegated controller is started. - * Can be NULL if the delegated controller is not started but just - * linked to. - * @param emsg set to an error message explaining why the controller link - * failed. Setting this to NULL signifies success. !This should be - * NULL if cfg is set! - */ -static void -send_controller_link_response (struct GNUNET_SERVICE_Client *client, - uint64_t operation_id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *emsg) -{ - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_ControllerLinkResponse *msg; - char *xconfig; - size_t config_size; - size_t xconfig_size; - uint16_t msize; - - GNUNET_assert ((NULL == cfg) || (NULL == emsg)); - xconfig = NULL; - xconfig_size = 0; - config_size = 0; - msize = 0; - if (NULL != cfg) - { - xconfig = GNUNET_TESTBED_compress_cfg_ (cfg, - &config_size, - &xconfig_size); - msize += xconfig_size; - } - if (NULL != emsg) - msize += strlen (emsg); - env = GNUNET_MQ_msg_extra (msg, - msize, - GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT); - if (NULL == emsg) - msg->success = htons (GNUNET_YES); - msg->operation_id = GNUNET_htonll (operation_id); - msg->config_size = htons ((uint16_t) config_size); - if (NULL != xconfig) - { - GNUNET_memcpy (&msg[1], - xconfig, - xconfig_size); - GNUNET_free (xconfig); - } - if (NULL != emsg) - GNUNET_memcpy (&msg[1], - emsg, - strlen (emsg)); - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), - env); -} - - -/** - * The Link Controller forwarding task - * - * @param cls the LCFContext - */ -static void -lcf_proc_task (void *cls); - - -/** - * Completion callback for host registrations while forwarding Link Controller messages - * - * @param cls the LCFContext - * @param emsg the error message; NULL if host registration is successful - */ -static void -lcf_proc_cc (void *cls, - const char *emsg) -{ - struct LCFContext *lcf = cls; - - GNUNET_assert (NULL == lcf_proc_task_id); - switch (lcf->state) - { - case INIT: - if (NULL != emsg) - goto registration_error; - lcf->state = DELEGATED_HOST_REGISTERED; - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); - break; - - case DELEGATED_HOST_REGISTERED: - if (NULL != emsg) - goto registration_error; - lcf->state = SLAVE_HOST_REGISTERED; - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); - break; - - default: - GNUNET_assert (0); /* Shouldn't reach here */ - } - return; - -registration_error: - LOG (GNUNET_ERROR_TYPE_WARNING, - "Host registration failed with message: %s\n", - emsg); - lcf->state = FINISHED; - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, - lcf); -} - - -/** - * The Link Controller forwarding task - * - * @param cls the LCFContext - */ -static void -lcf_proc_task (void *cls); - - -/** - * Task to free resources when forwarded link controllers has been timedout - * - * @param cls the LCFContext - */ -static void -lcf_forwarded_operation_timeout (void *cls) -{ - struct LCFContext *lcf = cls; - - lcf->timeout_task = NULL; - // GST_forwarded_operation_timeout (lcf->fopc, tc); - LOG (GNUNET_ERROR_TYPE_WARNING, - "A forwarded controller link operation has timed out\n"); - send_controller_link_response (lcf->client, - lcf->operation_id, - NULL, - "A forwarded controller link operation has timed out\n"); - GNUNET_assert (NULL == lcf_proc_task_id); - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, - lcf); -} - - -/** - * The Link Controller forwarding task - * - * @param cls the LCFContext - */ -static void -lcf_proc_task (void *cls) -{ - struct LCFContext *lcf = cls; - - lcf_proc_task_id = NULL; - switch (lcf->state) - { - case INIT: - if (GNUNET_NO == - GNUNET_TESTBED_is_host_registered_ (GST_host_list - [lcf->delegated_host_id], - lcf->gateway->controller)) - { - GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf, - GST_host_list[lcf->delegated_host_id]); - } - else - { - lcf->state = DELEGATED_HOST_REGISTERED; - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); - } - break; - - case DELEGATED_HOST_REGISTERED: - if (GNUNET_NO == - GNUNET_TESTBED_is_host_registered_ (GST_host_list[lcf->slave_host_id], - lcf->gateway->controller)) - { - GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf, - GST_host_list[lcf->slave_host_id]); - } - else - { - lcf->state = SLAVE_HOST_REGISTERED; - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); - } - break; - - case SLAVE_HOST_REGISTERED: - lcf->op = GNUNET_TESTBED_controller_link (lcf, - lcf->gateway->controller, - GST_host_list[lcf-> - delegated_host_id], - GST_host_list[lcf->slave_host_id], - lcf->is_subordinate); - lcf->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, - &lcf_forwarded_operation_timeout, - lcf); - lcf->state = FINISHED; - break; - - case FINISHED: - if (NULL != lcf->op) - GNUNET_TESTBED_operation_done (lcf->op); - GNUNET_CONTAINER_DLL_remove (lcf_head, - lcf_tail, - lcf); - GNUNET_free (lcf); - if (NULL != lcf_head) - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, - lcf_head); - } -} - - -/** - * Callback for event from slave controllers - * - * @param cls NULL - * @param event information about the event - */ -static void -slave_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) -{ - struct LCFContext *lcf; - - /* We currently only get here when working on LCFContexts */ - GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type); - lcf = event->op_cls; - GNUNET_assert (lcf->op == event->op); - GNUNET_TESTBED_operation_done (lcf->op); - lcf->op = NULL; - GNUNET_assert (FINISHED == lcf->state); - GNUNET_assert (NULL != lcf->timeout_task); - GNUNET_SCHEDULER_cancel (lcf->timeout_task); - if (NULL == event->details.operation_finished.emsg) - send_controller_link_response (lcf->client, lcf->operation_id, - GNUNET_TESTBED_host_get_cfg_ - (GST_host_list[lcf->delegated_host_id]), - NULL); - else - send_controller_link_response (lcf->client, lcf->operation_id, - NULL, - event->details.operation_finished.emsg); - GNUNET_assert (NULL == lcf_proc_task_id); - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); - return; -} - - -/** - * Callback to signal successful startup of the controller process - * - * @param cls the handle to the slave whose status is to be found here - * @param cfg the configuration with which the controller has been started; - * NULL if status is not #GNUNET_OK - * @param status #GNUNET_OK if the startup is successful; #GNUNET_SYSERR if not, - * GNUNET_TESTBED_controller_stop() shouldn't be called in this case - */ -static void -slave_status_cb (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg, - int status) -{ - struct Slave *slave = cls; - struct LinkControllersContext *lcc; - - lcc = slave->lcc; - if (GNUNET_SYSERR == status) - { - slave->controller_proc = NULL; - /* Stop all link controller forwarding tasks since we shutdown here anyway - and as these tasks they depend on the operation queues which are created - through GNUNET_TESTBED_controller_connect() and in kill_slave() we call - the destructor function GNUNET_TESTBED_controller_disconnect() */ - GST_free_lcf (); - kill_slave (slave); - destroy_slave (slave); - slave = NULL; - LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected slave shutdown\n"); - GNUNET_SCHEDULER_shutdown (); /* We too shutdown */ - goto clean_lcc; - } - slave->controller = - GNUNET_TESTBED_controller_connect (GST_host_list[slave->host_id], - EVENT_MASK, &slave_event_cb, - slave); - if (NULL != slave->controller) - { - send_controller_link_response (lcc->client, lcc->operation_id, cfg, NULL); - } - else - { - send_controller_link_response (lcc->client, lcc->operation_id, NULL, - "Could not connect to delegated controller"); - kill_slave (slave); - destroy_slave (slave); - slave = NULL; - } - -clean_lcc: - if (NULL != lcc) - { - if (NULL != lcc->client) - { - GNUNET_SERVICE_client_continue (lcc->client); - lcc->client = NULL; - } - GNUNET_free (lcc); - } - if (NULL != slave) - slave->lcc = NULL; -} - - -/** - * Trigger notification task if there are notification requests currently - * waiting in the given neighbour. Also activates the neighbour connect operation - * if it was previously inactivated so that the connection to the neighbour can - * be re-used - * - * @param n the neighbour - */ -static void -trigger_notifications (struct Neighbour *n); - - -/** - * Task to call the notification queued in the notifications list of the given - * neighbour - * - * @param cls the neighbour - */ -static void -neighbour_connect_notify_task (void *cls) -{ - struct Neighbour *n = cls; - struct NeighbourConnectNotification *h; - - GNUNET_assert (NULL != (h = n->nl_head)); - GNUNET_assert (NULL != n->notify_task); - n->notify_task = NULL; - GNUNET_assert (NULL != n->controller); - GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h); - trigger_notifications (n); - h->cb (h->cb_cls, n->controller); - GNUNET_free (h); -} - - -/** - * Trigger notification task if there are notification requests currently - * waiting in the given neighbour. Also activates the neighbour connect operation - * if it was previously inactivated so that the connection to the neighbour can - * be re-used - * - * @param n the neighbour - */ -static void -trigger_notifications (struct Neighbour *n) -{ - GNUNET_assert (NULL != n->conn_op); - if (NULL == n->nl_head) - return; - if (NULL == n->controller) - return; - if (NULL != n->notify_task) - return; - if (1 == n->inactive) - { - GNUNET_assert (0 == n->reference_cnt); - GNUNET_TESTBED_operation_activate_ (n->conn_op); - n->inactive = 0; - } - n->reference_cnt++; - n->notify_task = - GNUNET_SCHEDULER_add_now (&neighbour_connect_notify_task, n); -} - - -/** - * Callback to be called when the neighbour connect operation is started. The - * connection to the neighbour is opened here and any pending notifications are - * trigger. - * - * @param cls the neighbour - */ -static void -opstart_neighbour_conn (void *cls) -{ - struct Neighbour *n = cls; - - GNUNET_assert (NULL != n->conn_op); - GNUNET_assert (NULL == n->controller); - LOG_DEBUG ("Opening connection to controller on host %u\n", n->host_id); - n->controller = GNUNET_TESTBED_controller_connect (GST_host_list[n->host_id], - EVENT_MASK, - &slave_event_cb, - NULL); - trigger_notifications (n); -} - - -/** - * Callback to be called when the neighbour connect operation is released - * - * @param cls the neighbour - */ -static void -oprelease_neighbour_conn (void *cls) -{ - struct Neighbour *n = cls; - - GNUNET_assert (0 == n->reference_cnt); - GNUNET_assert (NULL == n->notify_task); - GNUNET_assert (NULL == n->nl_head); - if (NULL != n->controller) - { - LOG_DEBUG ("Closing connection to controller on host %u\n", n->host_id); - GNUNET_TESTBED_controller_disconnect (n->controller); - n->controller = NULL; - } - n->conn_op = NULL; - n->inactive = 0; -} - - -/** - * Try to open a connection to the given neighbour. If the connection is open - * already, then it is re-used. If not, the request is queued in the operation - * queues responsible for bounding the total number of file descriptors. The - * actual connection will happen when the operation queue marks the - * corresponding operation as active. - * - * @param n the neighbour to open a connection to - * @param cb the notification callback to call when the connection is opened - * @param cb_cls the closure for the above callback - */ -struct NeighbourConnectNotification * -GST_neighbour_get_connection (struct Neighbour *n, - GST_NeighbourConnectNotifyCallback cb, - void *cb_cls) -{ - struct NeighbourConnectNotification *h; - - GNUNET_assert (NULL != cb); - LOG_DEBUG ("Attempting to get connection to controller on host %u\n", - n->host_id); - h = GNUNET_new (struct NeighbourConnectNotification); - h->n = n; - h->cb = cb; - h->cb_cls = cb_cls; - GNUNET_CONTAINER_DLL_insert_tail (n->nl_head, n->nl_tail, h); - if (NULL == n->conn_op) - { - GNUNET_assert (NULL == n->controller); - n->conn_op = GNUNET_TESTBED_operation_create_ (n, &opstart_neighbour_conn, - &oprelease_neighbour_conn); - GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, n->conn_op); - GNUNET_TESTBED_operation_begin_wait_ (n->conn_op); - return h; - } - trigger_notifications (n); - return h; -} - - -/** - * Cancel the request for opening a connection to the neighbour - * - * @param h the notification handle - */ -void -GST_neighbour_get_connection_cancel (struct NeighbourConnectNotification *h) -{ - struct Neighbour *n; - int cleanup_task; - - n = h->n; - cleanup_task = (h == n->nl_head) ? GNUNET_YES : GNUNET_NO; - GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h); - GNUNET_free (h); - if (GNUNET_NO == cleanup_task) - return; - if (NULL == n->notify_task) - return; - GNUNET_assert (0 < n->reference_cnt); - n->reference_cnt--; - GNUNET_SCHEDULER_cancel (n->notify_task); - n->notify_task = NULL; - if (NULL == n->nl_head) - { - if ((0 == n->reference_cnt) && (0 == n->inactive)) - { - n->inactive = 1; - GNUNET_TESTBED_operation_inactivate_ (n->conn_op); - } - return; - } - trigger_notifications (n); -} - - -/** - * Release the connection to the neighbour. The actual connection will be - * closed if connections to other neighbour are waiting (to maintain a bound on - * the total number of connections that are open). - * - * @param n the neighbour whose connection can be closed - */ -void -GST_neighbour_release_connection (struct Neighbour *n) -{ - GNUNET_assert (0 == n->inactive); - GNUNET_assert (0 < n->reference_cnt); - n->reference_cnt--; - if (0 == n->reference_cnt) - { - n->inactive = 1; - GNUNET_TESTBED_operation_inactivate_ (n->conn_op); - } -} - - -/** - * Cleanup neighbour connect contexts - * - * @param ncc the neighbour connect context to cleanup - */ -static void -cleanup_ncc (struct NeighbourConnectCtxt *ncc) -{ - if (NULL != ncc->nh) - GST_neighbour_get_connection_cancel (ncc->nh); - if (NULL != ncc->timeout_task) - GNUNET_SCHEDULER_cancel (ncc->timeout_task); - GNUNET_CONTAINER_DLL_remove (ncc_head, - ncc_tail, - ncc); - GNUNET_free (ncc); -} - - -/** - * Cleans up the neighbour list - */ -void -GST_neighbour_list_clean () -{ - struct Neighbour *n; - unsigned int id; - - for (id = 0; id < neighbour_list_size; id++) - { - if (NULL == (n = neighbour_list[id])) - continue; - if (NULL != n->conn_op) - GNUNET_TESTBED_operation_release_ (n->conn_op); - GNUNET_free (n); - neighbour_list[id] = NULL; - } - GNUNET_free (neighbour_list); -} - - -/** - * Get a neighbour from the neighbour list - * - * @param id the index of the neighbour in the neighbour list - * @return the Neighbour; NULL if the given index in invalid (index greater than - * the list size or neighbour at that index is NULL) - */ -struct Neighbour * -GST_get_neighbour (uint32_t id) -{ - if (neighbour_list_size <= id) - return NULL; - return neighbour_list[id]; -} - - -/** - * Function to cleanup the neighbour connect contexts - */ -void -GST_free_nccq () -{ - while (NULL != ncc_head) - cleanup_ncc (ncc_head); -} - - -/** - * Task to be run upon timeout while attempting to connect to the neighbour - * - * @param cls the NeighbourConnectCtxt created in GST_handle_link_controllers() - */ -static void -timeout_neighbour_connect (void *cls) -{ - struct NeighbourConnectCtxt *ncc = cls; - - ncc->timeout_task = NULL; - send_controller_link_response (ncc->client, - ncc->op_id, - NULL, - "Could not connect to delegated controller"); - cleanup_ncc (ncc); -} - - -/** - * Callback called when a connection to the neighbour is made - * - * @param cls the NeighbourConnectCtxt created in GST_handle_link_controllers() - * @param c the handle the neighbour's controller - */ -static void -neighbour_connect_cb (void *cls, - struct GNUNET_TESTBED_Controller *c) -{ - struct NeighbourConnectCtxt *ncc = cls; - - GNUNET_SCHEDULER_cancel (ncc->timeout_task); - ncc->timeout_task = NULL; - ncc->nh = NULL; - GST_neighbour_release_connection (ncc->n); - send_controller_link_response (ncc->client, - ncc->op_id, - NULL, - NULL); - cleanup_ncc (ncc); -} - - -/** - * Function to create a neighbour and add it into the neighbour list - * - * @param host the host of the neighbour - */ -struct Neighbour * -GST_create_neighbour (struct GNUNET_TESTBED_Host *host) -{ - struct Neighbour *n; - - n = GNUNET_new (struct Neighbour); - n->host_id = GNUNET_TESTBED_host_get_id_ (host); - neighbour_list_add (n); /* just add; connect on-demand */ - return n; -} - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_link_controllers (void *cls, - const struct GNUNET_TESTBED_ControllerLinkRequest *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct LCFContext *lcf; - struct Route *route; - struct Route *new_route; - uint64_t op_id; - uint32_t delegated_host_id; - uint32_t slave_host_id; - - if (NULL == GST_context) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (client); - return; - } - delegated_host_id = ntohl (msg->delegated_host_id); - if (delegated_host_id == GST_context->host_id) - { - GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_WARNING, - "Trying to link ourselves\n"); - GNUNET_SERVICE_client_drop (client); - return; - } - if ((delegated_host_id >= GST_host_list_size) || - (NULL == GST_host_list[delegated_host_id])) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Delegated host %u not registered with us\n", - delegated_host_id); - GNUNET_SERVICE_client_drop (client); - return; - } - slave_host_id = ntohl (msg->slave_host_id); - if ((slave_host_id >= GST_host_list_size) || - (NULL == GST_host_list[slave_host_id])) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Slave host %u not registered with us\n", - slave_host_id); - GNUNET_SERVICE_client_drop (client); - return; - } - if (slave_host_id == delegated_host_id) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Slave and delegated host are same\n"); - GNUNET_SERVICE_client_drop (client); - return; - } - op_id = GNUNET_ntohll (msg->operation_id); - if (slave_host_id == GST_context->host_id) /* Link from us */ - { - struct Slave *slave; - struct LinkControllersContext *lcc; - - if (1 != msg->is_subordinate) - { - struct Neighbour *n; - struct NeighbourConnectCtxt *ncc; - - if ((delegated_host_id < neighbour_list_size) && - (NULL != neighbour_list[delegated_host_id])) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (client); - return; - } - LOG_DEBUG ("Received request to establish a link to host %u\n", - delegated_host_id); - n = GST_create_neighbour (GST_host_list[delegated_host_id]); - ncc = GNUNET_new (struct NeighbourConnectCtxt); - ncc->n = n; - ncc->op_id = op_id; - ncc->client = client; - ncc->nh = GST_neighbour_get_connection (n, - &neighbour_connect_cb, - ncc); - ncc->timeout_task - = GNUNET_SCHEDULER_add_delayed (GST_timeout, - &timeout_neighbour_connect, - ncc); - GNUNET_CONTAINER_DLL_insert_tail (ncc_head, - ncc_tail, - ncc); - GNUNET_SERVICE_client_continue (client); - return; - } - if ((delegated_host_id < GST_slave_list_size) && - (NULL != GST_slave_list[delegated_host_id])) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (client); - return; - } - LOG_DEBUG ("Received request to start and establish a link to host %u\n", - delegated_host_id); - slave = GNUNET_new (struct Slave); - slave->host_id = delegated_host_id; - slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100, - GNUNET_NO); - slave_list_add (slave); - lcc = GNUNET_new (struct LinkControllersContext); - lcc->operation_id = op_id; - lcc->client = client; - slave->lcc = lcc; - slave->controller_proc - = GNUNET_TESTBED_controller_start (GST_context->master_ip, - GST_host_list[slave->host_id], - &slave_status_cb, - slave); - new_route = GNUNET_new (struct Route); - new_route->dest = delegated_host_id; - new_route->thru = GST_context->host_id; - route_list_add (new_route); - return; - } - - /* Route the request */ - if (slave_host_id >= route_list_size) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "No route towards slave host"); - GNUNET_SERVICE_client_drop (client); - return; - } - lcf = GNUNET_new (struct LCFContext); - lcf->delegated_host_id = delegated_host_id; - lcf->slave_host_id = slave_host_id; - route = GST_find_dest_route (slave_host_id); - GNUNET_assert (NULL != route); /* because we add routes carefully */ - GNUNET_assert (route->dest < GST_slave_list_size); - GNUNET_assert (NULL != GST_slave_list[route->dest]); - lcf->is_subordinate = msg->is_subordinate; - lcf->state = INIT; - lcf->operation_id = op_id; - lcf->gateway = GST_slave_list[route->dest]; - lcf->client = client; - if (NULL == lcf_head) - { - GNUNET_assert (NULL == lcf_proc_task_id); - GNUNET_CONTAINER_DLL_insert_tail (lcf_head, - lcf_tail, - lcf); - lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, - lcf); - } - else - { - GNUNET_CONTAINER_DLL_insert_tail (lcf_head, - lcf_tail, - lcf); - } - /* FIXME: Adding a new route should happen after the controllers are linked - * successfully */ - if (1 != msg->is_subordinate) - { - GNUNET_SERVICE_client_continue (client); - return; - } - if ((delegated_host_id < route_list_size) && - (NULL != route_list[delegated_host_id])) - { - GNUNET_break_op (0); /* Are you trying to link delegated host twice - * with is subordinate flag set to GNUNET_YES? */ - GNUNET_SERVICE_client_drop (client); - return; - } - new_route = GNUNET_new (struct Route); - new_route->dest = delegated_host_id; - new_route->thru = route->dest; - route_list_add (new_route); - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Clean up @a client handle if we stored any via #handle_link_controllers(), - * the given client disconnected. - * - * @param client the client that is history - */ -void -GST_link_notify_disconnect (struct GNUNET_SERVICE_Client *client) -{ - struct NeighbourConnectCtxt *ncc; - struct NeighbourConnectCtxt *nccn; - struct LCFContext *lcf; - struct LCFContext *lcfn; - - for (ncc = ncc_head; NULL != ncc; ncc = nccn) - { - nccn = ncc->next; - if (ncc->client == client) - cleanup_ncc (ncc); - } - for (unsigned int i = 0; i < GST_slave_list_size; i++) - { - struct Slave *slave = GST_slave_list[i]; - struct LinkControllersContext *lcc; - - if (NULL == slave) - continue; - GNUNET_CONTAINER_multihashmap_iterate (slave->reghost_map, - &drop_client_entries, - client); - lcc = slave->lcc; - if (NULL == lcc) - continue; - if (lcc->client == client) - { - slave->lcc = NULL; - GNUNET_free (lcc); - } - } - for (lcf = lcf_head; NULL != lcf; lcf = lcfn) - { - lcfn = lcf->next; - if ((NULL != lcf) && - (client == lcf->client)) - { - if (NULL != lcf->op) - GNUNET_TESTBED_operation_done (lcf->op); - GNUNET_CONTAINER_DLL_remove (lcf_head, - lcf_tail, - lcf); - GNUNET_free (lcf); - } - } -} - - -/** - * Cleans up the queue used for forwarding link controllers requests - */ -void -GST_free_lcf () -{ - struct LCFContext *lcf; - - if (NULL != lcf_head) - { - if (NULL != lcf_proc_task_id) - { - GNUNET_SCHEDULER_cancel (lcf_proc_task_id); - lcf_proc_task_id = NULL; - } - } - GNUNET_assert (NULL == lcf_proc_task_id); - for (lcf = lcf_head; NULL != lcf; lcf = lcf_head) - { - if (NULL != lcf->op) - GNUNET_TESTBED_operation_done (lcf->op); - if (NULL != lcf->timeout_task) - GNUNET_SCHEDULER_cancel (lcf->timeout_task); - GNUNET_CONTAINER_DLL_remove (lcf_head, - lcf_tail, - lcf); - GNUNET_free (lcf); - } -} diff --git a/src/testbed/gnunet-service-testbed_links.h b/src/testbed/gnunet-service-testbed_links.h @@ -1,209 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-service-testbed_links.h - * @brief TESTBED service components that deals with starting slave controllers - * and establishing lateral links between controllers - * @author Sree Harsha Totakura - */ - - -/** - * A connected controller which is not our child - */ -struct Neighbour; - - -/** - * Structure representing a connected(directly-linked) controller - */ -struct Slave -{ - /** - * The controller process handle if we had started the controller - */ - struct GNUNET_TESTBED_ControllerProc *controller_proc; - - /** - * The controller handle - */ - struct GNUNET_TESTBED_Controller *controller; - - /** - * handle to lcc which is associated with this slave startup. Should be set to - * NULL when the slave has successfully started up - */ - struct LinkControllersContext *lcc; - - /** - * Head of the host registration DLL - */ - struct HostRegistration *hr_dll_head; - - /** - * Tail of the host registration DLL - */ - struct HostRegistration *hr_dll_tail; - - /** - * The current host registration handle - */ - struct GNUNET_TESTBED_HostRegistrationHandle *rhandle; - - /** - * Hashmap to hold Registered host contexts - */ - struct GNUNET_CONTAINER_MultiHashMap *reghost_map; - - /** - * The id of the host this controller is running on - */ - uint32_t host_id; -}; - -/** - * A list of directly linked neighbours - */ -extern struct Slave **GST_slave_list; - -/** - * The size of directly linked neighbours list - */ -extern unsigned int GST_slave_list_size; - - -/** - * Cleans up the neighbour list - */ -void -GST_neighbour_list_clean (void); - - -/** - * Get a neighbour from the neighbour list - * - * @param id the index of the neighbour in the neighbour list - * @return the Neighbour; NULL if the given index in invalid (index greater than - * the list size or neighbour at that index is NULL) - */ -struct Neighbour * -GST_get_neighbour (uint32_t id); - - -/** - * Function to cleanup the neighbour connect contexts - */ -void -GST_free_nccq (void); - - -/** - * Notification context to be used to notify when connection to the neighbour's - * controller is opened - */ -struct NeighbourConnectNotification; - - -/** - * The notification callback to call when we are connect to neighbour - * - * @param cls the closure given to GST_neighbour_get_connection() - * @param controller the controller handle to the neighbour - */ -typedef void -(*GST_NeighbourConnectNotifyCallback) (void *cls, - struct GNUNET_TESTBED_Controller * - controller); - - -/** - * Try to open a connection to the given neighbour. If the connection is open - * already, then it is re-used. If not, the request is queued in the operation - * queues responsible for bounding the total number of file descriptors. The - * actual connection will happen when the operation queue marks the - * corresponding operation as active. - * - * @param n the neighbour to open a connection to - * @param cb the notification callback to call when the connection is opened - * @param cb_cls the closure for the above callback - */ -struct NeighbourConnectNotification * -GST_neighbour_get_connection (struct Neighbour *n, - GST_NeighbourConnectNotifyCallback cb, - void *cb_cls); - - -/** - * Cancel the request for opening a connection to the neighbour - * - * @param h the notification handle - */ -void -GST_neighbour_get_connection_cancel (struct NeighbourConnectNotification *h); - - -/** - * Release the connection to the neighbour. The actual connection will be - * closed if connections to other neighbour are waiting (to maintain a bound on - * the total number of connections that are open). - * - * @param n the neighbour whose connection can be closed - */ -void -GST_neighbour_release_connection (struct Neighbour *n); - - -/** - * Function to create a neighbour and add it into the neighbour list - * - * @param host the host of the neighbour - */ -struct Neighbour * -GST_create_neighbour (struct GNUNET_TESTBED_Host *host); - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_link_controllers (void *cls, - const struct - GNUNET_TESTBED_ControllerLinkRequest *msg); - - -/** - * Clean up @a client handle if we stored any via #handle_link_controllers(), - * the given client disconnected. - * - * @param client the client that is history - */ -void -GST_link_notify_disconnect (struct GNUNET_SERVICE_Client *client); - - -/** - * Cleans up the slave list - */ -void -GST_slave_list_clear (void); diff --git a/src/testbed/gnunet-service-testbed_meminfo.c b/src/testbed/gnunet-service-testbed_meminfo.c @@ -1,279 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -#include "platform.h" -#include "gnunet_util_lib.h" - -/* - * File for parsing top-level /proc entities. - * Copyright Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com - * Copyright 1998-2003 Albert Cahalan - * June 2003, Fabian Frederick, disk and slab info - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define BAD_OPEN_MESSAGE \ - "Error: /proc must be mounted\n" \ - " To mount /proc at boot you need an /etc/fstab line like:\n" \ - " proc /proc proc defaults\n" \ - " In the meantime, run \"mount proc /proc -t proc\"\n" - -#define STAT_FILE "/proc/stat" -// static int stat_fd = -1; -#define UPTIME_FILE "/proc/uptime" -// static int uptime_fd = -1; -#define LOADAVG_FILE "/proc/loadavg" -// static int loadavg_fd = -1; -#define MEMINFO_FILE "/proc/meminfo" -static int meminfo_fd = -1; -#define VMINFO_FILE "/proc/vmstat" -// static int vminfo_fd = -1; - -// As of 2.6.24 /proc/meminfo seems to need 888 on 64-bit, -// and would need 1258 if the obsolete fields were there. -static char buf[2048]; - -/* This macro opens filename only if necessary and seeks to 0 so - * that successive calls to the functions are more efficient. - * It also reads the current contents of the file into the global buf. - */ -#define FILE_TO_BUF(filename, fd) do { \ - static int local_n; \ - if (fd == -1 && (fd = open (filename, O_RDONLY)) == -1) { \ - fputs (BAD_OPEN_MESSAGE, stderr); \ - fflush (NULL); \ - _exit (102); \ - } \ - lseek (fd, 0L, SEEK_SET); \ - if ((local_n = read (fd, buf, sizeof buf - 1)) < 0) { \ - perror (filename); \ - fflush (NULL); \ - _exit (103); \ - } \ - buf[local_n] = '\0'; \ -} while (0) - - -/***********************************************************************/ -/* - * Copyright 1999 by Albert Cahalan; all rights reserved. - * This file may be used subject to the terms and conditions of the - * GNU Library General Public License Version 2, or any later version - * at your option, as published by the Free Software Foundation. - * This program 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 Library General Public License for more details. - */ - -typedef struct mem_table_struct -{ - const char *name; /* memory type name */ - unsigned long *slot; /* slot in return struct */ -} mem_table_struct; - -static int -compare_mem_table_structs (const void *a, const void *b) -{ - return strcmp (((const mem_table_struct *) a)->name, ((const - mem_table_struct *) b) - -> - name); -} - - -/* example data, following junk, with comments added: - * - * MemTotal: 61768 kB old - * MemFree: 1436 kB old - * MemShared: 0 kB old (now always zero; not calculated) - * Buffers: 1312 kB old - * Cached: 20932 kB old - * Active: 12464 kB new - * Inact_dirty: 7772 kB new - * Inact_clean: 2008 kB new - * Inact_target: 0 kB new - * Inact_laundry: 0 kB new, and might be missing too - * HighTotal: 0 kB - * HighFree: 0 kB - * LowTotal: 61768 kB - * LowFree: 1436 kB - * SwapTotal: 122580 kB old - * SwapFree: 60352 kB old - * Inactive: 20420 kB 2.5.41+ - * Dirty: 0 kB 2.5.41+ - * Writeback: 0 kB 2.5.41+ - * Mapped: 9792 kB 2.5.41+ - * Slab: 4564 kB 2.5.41+ - * Committed_AS: 8440 kB 2.5.41+ - * PageTables: 304 kB 2.5.41+ - * ReverseMaps: 5738 2.5.41+ - * SwapCached: 0 kB 2.5.??+ - * HugePages_Total: 220 2.5.??+ - * HugePages_Free: 138 2.5.??+ - * Hugepagesize: 4096 kB 2.5.??+ - */ - -/* obsolete */ -unsigned long kb_main_shared; -/* old but still kicking -- the important stuff */ -unsigned long kb_main_buffers; -unsigned long kb_main_cached; -unsigned long kb_main_free; -unsigned long kb_main_total; -unsigned long kb_swap_free; -unsigned long kb_swap_total; -/* recently introduced */ -unsigned long kb_high_free; -unsigned long kb_high_total; -unsigned long kb_low_free; -unsigned long kb_low_total; -/* 2.4.xx era */ -unsigned long kb_active; -unsigned long kb_inact_laundry; -unsigned long kb_inact_dirty; -unsigned long kb_inact_clean; -unsigned long kb_inact_target; -unsigned long kb_swap_cached; /* late 2.4 and 2.6+ only */ -/* derived values */ -unsigned long kb_swap_used; -unsigned long kb_main_used; -/* 2.5.41+ */ -unsigned long kb_writeback; -unsigned long kb_slab; -unsigned long nr_reversemaps; -unsigned long kb_committed_as; -unsigned long kb_dirty; -unsigned long kb_inactive; -unsigned long kb_mapped; -unsigned long kb_pagetables; -// seen on a 2.6.x kernel: -static unsigned long kb_vmalloc_chunk; -static unsigned long kb_vmalloc_total; -static unsigned long kb_vmalloc_used; -// seen on 2.6.24-rc6-git12 -static unsigned long kb_anon_pages; -static unsigned long kb_bounce; -static unsigned long kb_commit_limit; -static unsigned long kb_nfs_unstable; -static unsigned long kb_swap_reclaimable; -static unsigned long kb_swap_unreclaimable; - -void -meminfo (void) -{ - char namebuf[16]; /* big enough to hold any row name */ - mem_table_struct findme = { namebuf, NULL }; - mem_table_struct *found; - char *head; - char *tail; - static const mem_table_struct mem_table[] = { - { "Active", &kb_active }, // important - { "AnonPages", &kb_anon_pages }, - { "Bounce", &kb_bounce }, - { "Buffers", &kb_main_buffers }, // important - { "Cached", &kb_main_cached }, // important - { "CommitLimit", &kb_commit_limit }, - { "Committed_AS", &kb_committed_as }, - { "Dirty", &kb_dirty }, // kB version of vmstat nr_dirty - { "HighFree", &kb_high_free }, - { "HighTotal", &kb_high_total }, - { "Inact_clean", &kb_inact_clean }, - { "Inact_dirty", &kb_inact_dirty }, - { "Inact_laundry", &kb_inact_laundry }, - { "Inact_target", &kb_inact_target }, - { "Inactive", &kb_inactive }, // important - { "LowFree", &kb_low_free }, - { "LowTotal", &kb_low_total }, - { "Mapped", &kb_mapped }, // kB version of vmstat nr_mapped - { "MemFree", &kb_main_free }, // important - { "MemShared", &kb_main_shared }, // important, but now gone! - { "MemTotal", &kb_main_total }, // important - { "NFS_Unstable", &kb_nfs_unstable }, - { "PageTables", &kb_pagetables }, // kB version of vmstat nr_page_table_pages - { "ReverseMaps", &nr_reversemaps }, // same as vmstat nr_page_table_pages - { "SReclaimable", &kb_swap_reclaimable }, // "swap reclaimable" (dentry and inode structures) - { "SUnreclaim", &kb_swap_unreclaimable }, - { "Slab", &kb_slab }, // kB version of vmstat nr_slab - { "SwapCached", &kb_swap_cached }, - { "SwapFree", &kb_swap_free }, // important - { "SwapTotal", &kb_swap_total }, // important - { "VmallocChunk", &kb_vmalloc_chunk }, - { "VmallocTotal", &kb_vmalloc_total }, - { "VmallocUsed", &kb_vmalloc_used }, - { "Writeback", &kb_writeback }, // kB version of vmstat nr_writeback - }; - const int mem_table_count = sizeof(mem_table) / sizeof(mem_table_struct); - - FILE_TO_BUF (MEMINFO_FILE, meminfo_fd); - - kb_inactive = ~0UL; - - head = buf; - for (;;) - { - tail = strchr (head, ':'); - if (! tail) - break; - *tail = '\0'; - if (strlen (head) >= sizeof(namebuf)) - { - head = tail + 1; - goto nextline; - } - strcpy (namebuf, head); - found = bsearch (&findme, mem_table, mem_table_count, - sizeof(mem_table_struct), compare_mem_table_structs - ); - head = tail + 1; - if (! found) - goto nextline; - *(found->slot) = (unsigned long) strtoull (head, &tail, 10); -nextline: - tail = strchr (head, '\n'); - if (! tail) - break; - head = tail + 1; - } - if (! kb_low_total) /* low==main except with large-memory support */ - { - kb_low_total = kb_main_total; - kb_low_free = kb_main_free; - } - if (kb_inactive == ~0UL) - { - kb_inactive = kb_inact_dirty + kb_inact_clean + kb_inact_laundry; - } - kb_swap_used = kb_swap_total - kb_swap_free; - kb_main_used = kb_main_total - kb_main_free; -} diff --git a/src/testbed/gnunet-service-testbed_meminfo.h b/src/testbed/gnunet-service-testbed_meminfo.h @@ -1,55 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/* obsolete */ -extern unsigned long kb_main_shared; -/* old but still kicking -- the important stuff */ -extern unsigned long kb_main_buffers; -extern unsigned long kb_main_cached; -extern unsigned long kb_main_free; -extern unsigned long kb_main_total; -extern unsigned long kb_swap_free; -extern unsigned long kb_swap_total; -/* recently introduced */ -extern unsigned long kb_high_free; -extern unsigned long kb_high_total; -extern unsigned long kb_low_free; -extern unsigned long kb_low_total; -/* 2.4.xx era */ -extern unsigned long kb_active; -extern unsigned long kb_inact_laundry; // grrr... -extern unsigned long kb_inact_dirty; -extern unsigned long kb_inact_clean; -extern unsigned long kb_inact_target; -extern unsigned long kb_swap_cached; /* late 2.4+ */ -/* derived values */ -extern unsigned long kb_swap_used; -extern unsigned long kb_main_used; -/* 2.5.41+ */ -extern unsigned long kb_writeback; -extern unsigned long kb_slab; -extern unsigned long nr_reversemaps; -extern unsigned long kb_committed_as; -extern unsigned long kb_dirty; -extern unsigned long kb_inactive; -extern unsigned long kb_mapped; -extern unsigned long kb_pagetables; - -extern void meminfo (void); diff --git a/src/testbed/gnunet-service-testbed_oc.c b/src/testbed/gnunet-service-testbed_oc.c @@ -1,1997 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-service-testbed_oc.c - * @brief code for handling overlay connect operations - * @author Sree Harsha Totakura - */ - -#include "platform.h" -#include "gnunet-service-testbed.h" -#include "gnunet-service-testbed_connectionpool.h" -#include "gnunet_transport_hello_service.h" - -/** - * Redefine LOG with a changed log component string - */ -#ifdef LOG -#undef LOG -#endif -#define LOG(kind, ...) \ - GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__) - - -/** - * Context information for requesting ATS to connect to a peer - */ -struct ConnectivitySuggestContext -{ - /** - * The transport handle obtained from cache. Do NOT close/disconnect. - */ - struct GNUNET_TRANSPORT_CoreHandle *th_; - - /** - * Configuration of the peer from cache. Do not free! - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * The GetCacheHandle for the peer2's transport handle - * (used to offer the HELLO to the peer). - */ - struct GST_ConnectionPool_GetHandle *cgh_p2_th; - - /** - * The GetCacheHandle for the peer2's ATS handle. - */ - struct GST_ConnectionPool_GetHandle *cgh_p2_ats; - - /** - * The ATS handle for the connectivity suggestion. - */ - struct GNUNET_ATS_ConnectivitySuggestHandle *csh; -}; - - -/** - * Types for context information we create for overlay connect requests - */ -enum OverlayConnectContextType -{ - /** - * This type is used if the overlay connection is local i.e. the connection - * has to be made between local peers - */ - OCC_TYPE_LOCAL, - - /** - * Type to be used when the first peer is local and the other peer is on a slave - * controller started by us - */ - OCC_TYPE_REMOTE_SLAVE, - - /** - * Type to be used when the first peer is local and the other peer is on a - * controller which is not started by us. - */ - OCC_TYPE_REMOTE_LATERAL -}; - - -/** - * Context data for operations on second peer in local overlay connection - * contexts - */ -struct LocalPeer2Context -{ - /** - * The handle for offering the HELLO of the first peer to the second - * peer. - */ - struct GNUNET_TRANSPORT_OfferHelloHandle *ohh; - - /** - * The transport ConnectivitySuggestContext - */ - struct ConnectivitySuggestContext tcc; -}; - - -/** - * Context data for operations on second peer in remote overlay connection - * contexts - */ -struct RemotePeer2Context -{ - /** - * Controller of peer 2; If #OCC_TYPE_REMOTE_LATERAL is the type of overlay - * connection then this can be NULL until the connection to the controller is - * established - */ - struct GNUNET_TESTBED_Controller *p2c; - - /** - * Operation context for the suboperation we start to get the identity of the - * second peer - */ - struct OperationContext *opc; - - /** - * Notification handle acquire to connect to a remote controller. Only used - * if the type of overlay connection is #OCC_TYPE_REMOTE_LATERAL. - */ - struct NeighbourConnectNotification *ncn; - - /** - * The neighbour handle. Only used if the type of overlay connection is - * #OCC_TYPE_REMOTE_LATERAL. - */ - struct Neighbour *p2n; -}; - -/** - * Context information for connecting 2 peers in overlay. - */ -struct OverlayConnectContext -{ - /** - * The next pointer for maintaining a DLL of all OverlayConnectContexts - */ - struct OverlayConnectContext *next; - - /** - * The prev pointer for maintaining a DLL of all OverlayConnectContexts - */ - struct OverlayConnectContext *prev; - - /** - * The client which has requested for overlay connection. This is used to send - * either a success of failure message - */ - struct GNUNET_SERVICE_Client *client; - - /** - * the first peer which is to expect an overlay connection from the second peer. - */ - struct Peer *peer; - - /** - * Transport handle of the first peer obtained from cache to get its HELLO. Do - * NOT close/disconnect. - */ - struct GNUNET_TRANSPORT_CoreHandle *p1th_; - - /** - * The #GST_ConnectionPool_GetHandle for the peer1's transport handle - */ - struct GST_ConnectionPool_GetHandle *cgh_p1th; - - /** - * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE - * level peer connects and to get our identity. - */ - struct GST_ConnectionPool_GetHandle *cgh_ch; - - /** - * HELLO of the first peer. This should be sent to the second peer. - */ - struct GNUNET_MessageHeader *hello; - - /** - * Get GetHelloHandle to acquire a HELLO of the first peer - */ - struct GNUNET_TRANSPORT_HelloGetHandle *ghh; - - /** - * The error message we send if this overlay connect operation has timed out - */ - char *emsg; - - /** - * Context information for operations on the second peer - */ - union - { - /** - * Context information to be used if the second peer is local - */ - struct LocalPeer2Context local; - - /** - * Context information to be used if the second peer is remote - */ - struct RemotePeer2Context remote; - } p2ctx; - - /** - * The peer identity of the first peer - */ - struct GNUNET_PeerIdentity peer_identity; - - /** - * The peer identity of the other peer - */ - struct GNUNET_PeerIdentity other_peer_identity; - - /** - * The id of the operation responsible for creating this context - */ - uint64_t op_id; - - /** - * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to - * connect to peer 2 - */ - struct GNUNET_SCHEDULER_Task *send_hello_task; - - /** - * The id of the overlay connect timeout task - */ - struct GNUNET_SCHEDULER_Task *timeout_task; - - /** - * The id of the cleanup task - */ - struct GNUNET_SCHEDULER_Task *cleanup_task; - - /** - * The type of this context information - */ - enum OverlayConnectContextType type; - - /** - * The id of the second peer which has to connect to the first peer - */ - uint32_t other_peer_id; -}; - - -/** - * Context information for remote overlay connect operations. Remote overlay - * connections are used when peers A and B reside on different hosts. In these - * operations the host controller for peer B is asked by the host controller of - * peer A to make peer B connect to peer A by sending the controller of peer B - * the HELLO of peer A. - */ -struct RemoteOverlayConnectCtx -{ - /** - * the next pointer for DLL - */ - struct RemoteOverlayConnectCtx *next; - - /** - * the prev pointer for DLL - */ - struct RemoteOverlayConnectCtx *prev; - - /** - * The peer handle of peer B - */ - struct Peer *peer; - - /** - * Peer A's HELLO - */ - struct GNUNET_MessageHeader *hello; - - /** - * The handle for offering HELLO - */ - struct GNUNET_TRANSPORT_OfferHelloHandle *ohh; - - /** - * The transport try connect context - */ - struct ConnectivitySuggestContext tcc; - - /** - * The peer identity of peer A - */ - struct GNUNET_PeerIdentity a_id; - - /** - * Task for offering HELLO of A to B and doing try_connect - */ - struct GNUNET_SCHEDULER_Task *attempt_connect_task_id; - - /** - * Task to timeout RequestOverlayConnect - */ - struct GNUNET_SCHEDULER_Task *timeout_rocc_task_id; - - /** - * The id of the operation responsible for creating this context - */ - uint64_t op_id; -}; - - -/** - * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown - */ -static struct OverlayConnectContext *occq_head; - -/** - * DLL tail for OverlayConnectContext DLL - */ -static struct OverlayConnectContext *occq_tail; - -/** - * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during - * shutdown - */ -static struct RemoteOverlayConnectCtx *roccq_head; - -/** - * DLL tail for RequectOverlayConnectContext DLL - */ -static struct RemoteOverlayConnectCtx *roccq_tail; - - -/** - * Cleans up ForwardedOverlayConnectContext - * - * @param focc the ForwardedOverlayConnectContext to cleanup - */ -void -GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc) -{ - struct RegisteredHostContext *rhc = focc->rhc; - - GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, - rhc->focc_dll_tail, - focc); - GNUNET_free (focc->orig_msg); - GNUNET_free (focc); -} - - -/** - * Timeout task for cancelling a forwarded overlay connect connect - * - * @param cls the `struct ForwardedOperationContext` - */ -static void -forwarded_overlay_connect_timeout (void *cls) -{ - struct ForwardedOperationContext *fopc = cls; - struct RegisteredHostContext *rhc; - struct ForwardedOverlayConnectContext *focc; - - fopc->timeout_task = NULL; - rhc = fopc->cls; - focc = rhc->focc_dll_head; - LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", - focc->peer1, - focc->peer2); - GST_cleanup_focc (focc); - GST_forwarded_operation_timeout (fopc); - if (NULL != rhc->focc_dll_head) - GST_process_next_focc (rhc); -} - - -/** - * Callback to be called when forwarded overlay connection operation has a reply - * from the sub-controller successful. We have to relay the reply msg back to - * the client - * - * @param cls ForwardedOperationContext - * @param msg the peer create success message - */ -static void -forwarded_overlay_connect_listener (void *cls, - const struct GNUNET_MessageHeader *msg) -{ - struct ForwardedOperationContext *fopc = cls; - struct RegisteredHostContext *rhc; - struct ForwardedOverlayConnectContext *focc; - - rhc = fopc->cls; - GST_forwarded_operation_reply_relay (cls, msg); - focc = rhc->focc_dll_head; - GST_cleanup_focc (focc); - if (NULL != rhc->focc_dll_head) - GST_process_next_focc (rhc); -} - - -/** - * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext - * - * @param rhc the RegisteredHostContext - */ -void -GST_process_next_focc (struct RegisteredHostContext *rhc) -{ - struct ForwardedOperationContext *fopc; - struct ForwardedOverlayConnectContext *focc; - struct Peer *peer; - struct Slave *slave; - - focc = rhc->focc_dll_head; - GNUNET_assert (NULL != focc); - GNUNET_assert (RHC_DONE == rhc->state); - GNUNET_assert (VALID_PEER_ID (focc->peer1)); - peer = GST_peer_list[focc->peer1]; - GNUNET_assert (GNUNET_YES == peer->is_remote); - GNUNET_assert (NULL != (slave = peer->details.remote.slave)); - fopc = GNUNET_new (struct ForwardedOperationContext); - fopc->client = focc->client; - fopc->operation_id = focc->operation_id; - fopc->cls = rhc; - fopc->type = OP_OVERLAY_CONNECT; - fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (slave->controller, - focc->operation_id, - focc->orig_msg, - &forwarded_overlay_connect_listener, - fopc); - GNUNET_free (focc->orig_msg); - focc->orig_msg = NULL; - fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, - & - forwarded_overlay_connect_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, - fopcq_tail, - fopc); -} - - -/** - * Cleans up any used handles in local peer2 context - * - * @param lp2c the local peer2 context information - */ -static void -cleanup_occ_lp2c (struct LocalPeer2Context *lp2c) -{ - if (NULL != lp2c->ohh) - { - GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh); - lp2c->ohh = NULL; - } - if (NULL != lp2c->tcc.cgh_p2_th) - { - GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_th); - lp2c->tcc.cgh_p2_th = NULL; - } - if (NULL != lp2c->tcc.cgh_p2_ats) - { - GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_ats); - lp2c->tcc.cgh_p2_ats = NULL; - } - if (NULL != lp2c->tcc.csh) - { - GNUNET_ATS_connectivity_suggest_cancel (lp2c->tcc.csh); - lp2c->tcc.csh = NULL; - } -} - - -/** - * Cleans up any used handles in remote peer2 context. Relinquishes the - * remote controller connection if it has been established on-demand. - * - * @param rp2c the remote peer2 context information - */ -static void -cleanup_occ_rp2c (struct RemotePeer2Context *rp2c) -{ - if (NULL != rp2c->opc) - { - GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc); - rp2c->opc = NULL; - } - if (NULL != rp2c->ncn) - { - GST_neighbour_get_connection_cancel (rp2c->ncn); - rp2c->ncn = NULL; - } - if ((NULL != rp2c->p2c) && (NULL != rp2c->p2n)) - { - GST_neighbour_release_connection (rp2c->p2n); - rp2c->p2n = NULL; - } -} - - -/** - * Condition for checking if given peer is ready to be destroyed - * - * @param peer the peer to check - */ -#define PEER_EXPIRED(peer) \ - ((GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt)) - -/** - * Cleanup overlay connect context structure - * - * @param occ the overlay connect context - */ -static void -cleanup_occ (struct OverlayConnectContext *occ) -{ - struct Peer *peer2; - - LOG_DEBUG ("0x%llx: Cleaning up occ\n", - (unsigned long long) occ->op_id); - GNUNET_free (occ->emsg); - GNUNET_free (occ->hello); - if (NULL != occ->send_hello_task) - GNUNET_SCHEDULER_cancel (occ->send_hello_task); - if (NULL != occ->cleanup_task) - GNUNET_SCHEDULER_cancel (occ->cleanup_task); - if (NULL != occ->timeout_task) - GNUNET_SCHEDULER_cancel (occ->timeout_task); - if (NULL != occ->cgh_ch) - GST_connection_pool_get_handle_done (occ->cgh_ch); - if (NULL != occ->ghh) - GNUNET_TRANSPORT_hello_get_cancel (occ->ghh); - GST_connection_pool_get_handle_done (occ->cgh_p1th); - GNUNET_assert (NULL != GST_peer_list); - GNUNET_assert (occ->peer->reference_cnt > 0); - occ->peer->reference_cnt--; - if (PEER_EXPIRED (occ->peer)) - GST_destroy_peer (occ->peer); - switch (occ->type) - { - case OCC_TYPE_LOCAL: - peer2 = GST_peer_list[occ->other_peer_id]; - GNUNET_assert (peer2->reference_cnt > 0); - peer2->reference_cnt--; - if (PEER_EXPIRED (peer2)) - GST_destroy_peer (peer2); - cleanup_occ_lp2c (&occ->p2ctx.local); - break; - - case OCC_TYPE_REMOTE_SLAVE: - case OCC_TYPE_REMOTE_LATERAL: - cleanup_occ_rp2c (&occ->p2ctx.remote); - break; - } - GNUNET_CONTAINER_DLL_remove (occq_head, - occq_tail, - occ); - GNUNET_free (occ); -} - - -/** - * Task for cleaning up overlay connect context structure - * - * @param cls the overlay connect context - */ -static void -do_cleanup_occ (void *cls) -{ - struct OverlayConnectContext *occ = cls; - - occ->cleanup_task = NULL; - cleanup_occ (occ); -} - - -/** - * Task which will be run when overlay connect request has been timed out - * - * @param cls the OverlayConnectContext - */ -static void -timeout_overlay_connect (void *cls) -{ - struct OverlayConnectContext *occ = cls; - - GNUNET_assert (NULL != occ->timeout_task); - occ->timeout_task = NULL; - /* LOG (GNUNET_ERROR_TYPE_WARNING, */ - /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */ - /* occ->peer->id, occ->other_peer_id, occ->emsg); */ - GST_send_operation_fail_msg (occ->client, - occ->op_id, - occ->emsg); - cleanup_occ (occ); -} - - -/** - * Notify OC subsystem that @a client disconnected. - * - * @param client the client that disconnected - */ -void -GST_notify_client_disconnect_oc (struct GNUNET_SERVICE_Client *client) -{ - struct ForwardedOperationContext *fopc; - struct ForwardedOperationContext *fopcn; - struct OverlayConnectContext *occ; - struct OverlayConnectContext *occn; - - for (fopc = fopcq_head; NULL != fopc; fopc = fopcn) - { - fopcn = fopc->next; - if (fopc->client == client) - { - GNUNET_SCHEDULER_cancel (fopc->timeout_task); - GST_forwarded_operation_timeout (fopc); - } - } - for (occ = occq_head; NULL != occ; occ = occn) - { - occn = occ->next; - if (occ->client == client) - cleanup_occ (occ); - } - // FIXME: implement clean up for client_keep replacements! -} - - -/** - * FIXME. - */ -static void -send_overlay_connect_success_msg (struct OverlayConnectContext *occ) -{ - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_ConnectionEventMessage *msg; - - LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n", - (unsigned long long) occ->op_id); - env = GNUNET_MQ_msg (msg, - GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT); - msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT); - msg->peer1 = htonl (occ->peer->id); - msg->peer2 = htonl (occ->other_peer_id); - msg->operation_id = GNUNET_htonll (occ->op_id); - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (occ->client), - env); -} - - -/** - * Function called to notify transport users that another - * peer connected to us. - * - * @param cls closure - * @param new_peer the peer that connected - */ -static void -overlay_connect_notify (void *cls, - const struct GNUNET_PeerIdentity *new_peer) -{ - struct OverlayConnectContext *occ = cls; - char *new_peer_str; - char *other_peer_str; - - LOG_DEBUG ("Overlay connect notify\n"); - if (0 == - GNUNET_memcmp (new_peer, - &occ->peer_identity)) - return; - new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer)); - other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); - if (0 != - GNUNET_memcmp (new_peer, - &occ->other_peer_identity)) - { - LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n", - new_peer_str, - other_peer_str); - GNUNET_free (new_peer_str); - GNUNET_free (other_peer_str); - return; - } - GNUNET_free (new_peer_str); - LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n", - (unsigned long long) occ->op_id, - other_peer_str, - GNUNET_i2s (&occ->peer_identity)); - GNUNET_free (other_peer_str); - if (NULL != occ->send_hello_task) - { - GNUNET_SCHEDULER_cancel (occ->send_hello_task); - occ->send_hello_task = NULL; - } - GNUNET_assert (NULL != occ->timeout_task); - GNUNET_SCHEDULER_cancel (occ->timeout_task); - occ->timeout_task = NULL; - switch (occ->type) - { - case OCC_TYPE_LOCAL: - cleanup_occ_lp2c (&occ->p2ctx.local); - break; - - case OCC_TYPE_REMOTE_SLAVE: - case OCC_TYPE_REMOTE_LATERAL: - cleanup_occ_rp2c (&occ->p2ctx.remote); - break; - } - GNUNET_free (occ->emsg); - occ->emsg = NULL; - send_overlay_connect_success_msg (occ); - occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, - occ); -} - - -/** - * Callback from cache with needed ATS handle set - * - * @param cls a `struct OverlayConnectCtx *` - * @param ch the handle to CORE. Can be NULL if it is not requested - * @param th the handle to TRANSPORT. Can be NULL if it is not requested - * @param ac the handle to ATS. Can be NULL if it is not requested - * @param my_identity the identity of our peer - * @param cfg configuration of the peer - */ -static void -occ_cache_get_handle_ats_occ_cb (void *cls, - struct GNUNET_CORE_Handle *ch, - struct GNUNET_TRANSPORT_CoreHandle *th, - struct GNUNET_ATS_ConnectivityHandle *ac, - const struct GNUNET_PeerIdentity *my_identity, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct OverlayConnectContext *occ = cls; - struct LocalPeer2Context *lp2c; - - GNUNET_assert (OCC_TYPE_LOCAL == occ->type); - GNUNET_assert (NULL != occ->timeout_task); - GNUNET_free (occ->emsg); - if (NULL == ac) - { - GNUNET_asprintf (&occ->emsg, - "0x%llx: Failed to connect to ATS of peer with id: %u", - (unsigned long long) occ->op_id, - occ->peer->id); - GNUNET_SCHEDULER_cancel (occ->timeout_task); - occ->timeout_task = - GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, - occ); - return; - } - occ->emsg = NULL; - - GNUNET_asprintf (&occ->emsg, - "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->other_peer_identity)); - - lp2c = &occ->p2ctx.local; - lp2c->tcc.csh = - GNUNET_ATS_connectivity_suggest (ac, - &occ->peer_identity, - 1); -} - - -/** - * Callback from cache with needed ATS handle set - * - * @param cls a `struct RemoteOverlayConnectCtx *` - * @param ch the handle to CORE. Can be NULL if it is not requested - * @param th the handle to TRANSPORT. Can be NULL if it is not requested - * @param ac the handle to ATS. Can be NULL if it is not requested - * @param my_identity the identity of our peer - */ -static void -occ_cache_get_handle_ats_rocc_cb (void *cls, - struct GNUNET_CORE_Handle *ch, - struct GNUNET_TRANSPORT_CoreHandle *th, - struct GNUNET_ATS_ConnectivityHandle *ac, - const struct GNUNET_PeerIdentity *my_identity, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct RemoteOverlayConnectCtx *rocc = cls; - - rocc->tcc.csh = - GNUNET_ATS_connectivity_suggest (ac, - &rocc->a_id, - 1); -} - - -/** - * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to - * peer 1. - * - * @param cls the OverlayConnectContext - */ -static void -send_hello (void *cls); - - -/** - * Task that is run when hello has been sent If tc->reason = - * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if - * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded - * - * @param cls the overlay connect context - */ -static void -occ_hello_sent_cb (void *cls) -{ - struct OverlayConnectContext *occ = cls; - struct LocalPeer2Context *lp2c; - struct Peer *peer2; - - GNUNET_assert (OCC_TYPE_LOCAL == occ->type); - GNUNET_assert (NULL != occ->timeout_task); - lp2c = &occ->p2ctx.local; - lp2c->ohh = NULL; - - GNUNET_assert (NULL == occ->send_hello_task); - GNUNET_free (occ->emsg); - - GNUNET_asprintf (&occ->emsg, - "0x%llx: Timeout while acquiring ATS of %s from cache", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->other_peer_identity)); - GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id])); - lp2c->tcc.cgh_p2_ats = - GST_connection_pool_get_handle (occ->other_peer_id, - peer2->details.local.cfg, - GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY, - &occ_cache_get_handle_ats_occ_cb, - occ, NULL, NULL, NULL); -} - - -/** - * Sends the HELLO of peer1 to peer2's controller through remote overlay connect - * request. - * - * @param occ the overlay connect context. Its type must be either - * #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL - */ -static void -send_hello_thru_rocc (struct OverlayConnectContext *occ) -{ - struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg; - char *other_peer_str; - uint16_t msize; - uint16_t hello_size; - - GNUNET_assert (OCC_TYPE_LOCAL != occ->type); - GNUNET_assert (NULL != occ->hello); - other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); - LOG_DEBUG ( - "0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->peer_identity), - ntohs (occ->hello->size), - other_peer_str); - GNUNET_free (other_peer_str); - hello_size = ntohs (occ->hello->size); - msize = sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage) - + hello_size; - msg = GNUNET_malloc (msize); - msg->header.type = - htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT); - msg->header.size = htons (msize); - msg->peer = htonl (occ->other_peer_id); - msg->operation_id = GNUNET_htonll (occ->op_id); - msg->peer_identity = occ->peer_identity; - GNUNET_memcpy (msg->hello, - occ->hello, - hello_size); - GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c, - &msg->header); -} - - -/** - * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered - * using its TRANSPORT connection; if remote the HELLO is sent remotely by using - * send_hello_thru_rocc() - * - * @param cls the OverlayConnectContext - */ -static void -send_hello (void *cls) -{ - struct OverlayConnectContext *occ = cls; - struct LocalPeer2Context *lp2c; - char *other_peer_str; - - occ->send_hello_task = NULL; - GNUNET_assert (NULL != occ->timeout_task); - GNUNET_assert (NULL != occ->hello); - if (OCC_TYPE_LOCAL != occ->type) - { - send_hello_thru_rocc (occ); - return; - } - lp2c = &occ->p2ctx.local; - other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); - LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->peer_identity), - other_peer_str); - GNUNET_free (other_peer_str); - lp2c->ohh = - GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg, - occ->hello, - &occ_hello_sent_cb, - occ); - if (NULL == lp2c->ohh) - { - GNUNET_break (0); - occ->send_hello_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, - 100 - + GNUNET_CRYPTO_random_u32 - (GNUNET_CRYPTO_QUALITY_WEAK, 500)), - &send_hello, occ); - } -} - - -/** - * Callback from cache with needed handles set - * - * @param cls the closure passed to GST_cache_get_handle_transport() - * @param ch the handle to CORE. Can be NULL if it is not requested - * @param th the handle to TRANSPORT. Can be NULL if it is not requested - * @param ac the handle to ATS. Can be NULL if it is not requested - * @param ignore_ peer identity which is ignored in this callback - * @param cfg configuration of the peer - */ -static void -p2_transport_connect_cache_callback (void *cls, - struct GNUNET_CORE_Handle *ch, - struct GNUNET_TRANSPORT_CoreHandle *th, - struct GNUNET_ATS_ConnectivityHandle *ac, - const struct GNUNET_PeerIdentity *ignore_, - const struct - GNUNET_CONFIGURATION_Handle *cfg) -{ - struct OverlayConnectContext *occ = cls; - - GNUNET_assert (OCC_TYPE_LOCAL == occ->type); - if (NULL == th) - { - GNUNET_asprintf (&occ->emsg, - "0x%llx: Cannot connect to TRANSPORT of %s", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->other_peer_identity)); - GNUNET_SCHEDULER_cancel (occ->timeout_task); - occ->timeout_task = - GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); - return; - } - occ->p2ctx.local.tcc.th_ = th; - occ->p2ctx.local.tcc.cfg = cfg; - GNUNET_asprintf (&occ->emsg, - "0x%llx: Timeout while offering HELLO to %s", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->other_peer_identity)); - occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ); -} - - -/** - * Connects to the transport of the other peer if it is a local peer and - * schedules the send hello task - * - * @param occ the overlay connect context - */ -static void -p2_transport_connect (struct OverlayConnectContext *occ) -{ - struct Peer *peer2; - - /* HUH? Why to *obtain* HELLO? Seems we use this to *SEND* the - HELLO! */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connecting to transport of peer %s to obtain HELLO\n", - GNUNET_i2s (&occ->other_peer_identity)); - GNUNET_assert (NULL == occ->emsg); - GNUNET_assert (NULL != occ->hello); - GNUNET_assert (NULL == occ->ghh); - GNUNET_assert (NULL == occ->p1th_); - GNUNET_assert (NULL == occ->cgh_p1th); - if (OCC_TYPE_LOCAL == occ->type) - { - GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id])); - occ->p2ctx.local.tcc.cgh_p2_th = - GST_connection_pool_get_handle (occ->other_peer_id, - peer2->details.local.cfg, - GST_CONNECTIONPOOL_SERVICE_TRANSPORT, - &p2_transport_connect_cache_callback, - occ, NULL, NULL, NULL); - return; - } - GNUNET_asprintf (&occ->emsg, - "0x%llx: Timeout while offering HELLO to %s", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->other_peer_identity)); - occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ); -} - - -/** - * Test for checking whether HELLO message is empty - * - * @param cls empty flag to set - * @param address the HELLO - * @param expiration expiration of the HELLO - * @return #GNUNET_OK - */ -static int -test_address (void *cls, - const struct GNUNET_HELLO_Address *address, - struct GNUNET_TIME_Absolute expiration) -{ - int *empty = cls; - - *empty = GNUNET_NO; - return GNUNET_OK; -} - - -/** - * Function called whenever there is an update to the HELLO of peers in the - * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's - * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1 - * - * @param cls closure - * @param hello our updated HELLO - */ -static void -hello_update_cb (void *cls, - const struct GNUNET_MessageHeader *hello) -{ - struct OverlayConnectContext *occ = cls; - int empty; - uint16_t msize; - - msize = ntohs (hello->size); - empty = GNUNET_YES; - (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *) - hello, GNUNET_NO, - &test_address, - &empty); - if (GNUNET_YES == empty) - { - LOG_DEBUG ("0x%llx: HELLO of %s is empty\n", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->peer_identity)); - return; - } - LOG_DEBUG ("0x%llx: Received HELLO of %s\n", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->peer_identity)); - occ->hello = GNUNET_malloc (msize); - GST_cache_add_hello (occ->peer->id, hello); - GNUNET_memcpy (occ->hello, hello, msize); - GNUNET_TRANSPORT_hello_get_cancel (occ->ghh); - occ->ghh = NULL; - GST_connection_pool_get_handle_done (occ->cgh_p1th); - occ->cgh_p1th = NULL; - occ->p1th_ = NULL; - GNUNET_free (occ->emsg); - occ->emsg = NULL; - p2_transport_connect (occ); -} - - -/** - * Callback from cache with needed handles set - * - * @param cls the closure passed to GST_cache_get_handle_transport() - * @param ch the handle to CORE. Can be NULL if it is not requested - * @param th the handle to TRANSPORT. Can be NULL if it is not requested - * @param ac the handle to ATS. Can be NULL if it is not requested - * @param ignore_ peer identity which is ignored in this callback - */ -static void -p1_transport_connect_cache_callback (void *cls, - struct GNUNET_CORE_Handle *ch, - struct GNUNET_TRANSPORT_CoreHandle *th, - struct GNUNET_ATS_ConnectivityHandle *ac, - const struct GNUNET_PeerIdentity *ignore_, - const struct - GNUNET_CONFIGURATION_Handle *cfg) -{ - struct OverlayConnectContext *occ = cls; - - GNUNET_free (occ->emsg); - occ->emsg = NULL; - if (NULL == th) - { - GNUNET_asprintf (&occ->emsg, - "0x%llx: Cannot connect to TRANSPORT of %s", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->peer_identity)); - GNUNET_SCHEDULER_cancel (occ->timeout_task); - occ->timeout_task = - GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); - return; - } - GNUNET_assert (NULL == occ->p1th_); - GNUNET_assert (NULL != occ->cgh_p1th); - occ->p1th_ = th; - GNUNET_asprintf (&occ->emsg, - "0x%llx: Timeout while acquiring HELLO of peer %s", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->peer_identity)); - occ->ghh = GNUNET_TRANSPORT_hello_get (cfg, - GNUNET_TRANSPORT_AC_ANY, - &hello_update_cb, - occ); -} - - -/** - * Callback from cache with needed CORE handle set - * - * @param cls the closure passed to GST_cache_get_handle_transport() - * @param ch the handle to CORE. Can be NULL if it is not requested - * @param th the handle to TRANSPORT. Can be NULL if it is not requested - * @param ac the handle to ATS. Can be NULL if it is not requested - * @param my_identity the identity of our peer - */ -static void -occ_cache_get_handle_core_cb (void *cls, - struct GNUNET_CORE_Handle *ch, - struct GNUNET_TRANSPORT_CoreHandle *th, - struct GNUNET_ATS_ConnectivityHandle *ac, - const struct GNUNET_PeerIdentity *my_identity, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct OverlayConnectContext *occ = cls; - const struct GNUNET_MessageHeader *hello; - - GNUNET_assert (NULL != occ->timeout_task); - GNUNET_free (occ->emsg); - if ((NULL == ch) || (NULL == my_identity)) - { - GNUNET_asprintf (&occ->emsg, - "0x%llx: Failed to connect to CORE of peer with " - "id: %u", - (unsigned long long) occ->op_id, - occ->peer->id); - GNUNET_SCHEDULER_cancel (occ->timeout_task); - occ->timeout_task = - GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); - return; - } - occ->emsg = NULL; - occ->peer_identity = *my_identity; - if (NULL != - GNUNET_CORE_get_mq (ch, - &occ->other_peer_identity)) - { - LOG_DEBUG ("0x%llx: Target peer %s already connected\n", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->other_peer_identity)); - LOG_DEBUG ("0x%llx: Target peer %s connected\n", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->peer_identity)); - GNUNET_SCHEDULER_cancel (occ->timeout_task); - occ->timeout_task = NULL; - send_overlay_connect_success_msg (occ); - occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ); - return; - } - LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->peer_identity)); - /* Lookup for HELLO in hello cache */ - if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id))) - { - LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->peer_identity)); - occ->hello = GNUNET_copy_message (hello); - p2_transport_connect (occ); - return; - } - GNUNET_asprintf (&occ->emsg, - "0x%llx: Timeout while acquiring TRANSPORT of %s from cache", - (unsigned long long) occ->op_id, - GNUNET_i2s (&occ->peer_identity)); - occ->cgh_p1th = - GST_connection_pool_get_handle (occ->peer->id, - occ->peer->details.local.cfg, - GST_CONNECTIONPOOL_SERVICE_TRANSPORT, - p1_transport_connect_cache_callback, - occ, - NULL, NULL, NULL); -} - - -/** - * Callback to be called when forwarded get peer config operation as part of - * overlay connect is successful. Connection to Peer 1's core is made and is - * checked for new connection from peer 2 - * - * @param cls ForwardedOperationContext - * @param msg the peer create success message - */ -static void -overlay_connect_get_config (void *cls, - const struct GNUNET_MessageHeader *msg) -{ - struct OverlayConnectContext *occ = cls; - struct RemotePeer2Context *rp2c; - const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg; - - GNUNET_assert (OCC_TYPE_LOCAL != occ->type); - rp2c = &occ->p2ctx.remote; - rp2c->opc = NULL; - GNUNET_assert (NULL != occ->timeout_task); - if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type)) - { - GNUNET_SCHEDULER_cancel (occ->timeout_task); - occ->timeout_task = - GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); - } - cmsg = - (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg; - occ->other_peer_identity = cmsg->peer_identity; - GNUNET_free (occ->emsg); - GNUNET_asprintf (&occ->emsg, - "0x%llx: Timeout while connecting to CORE of peer with " - "id: %u", - (unsigned long long) occ->op_id, - occ->peer->id); - occ->cgh_ch = - GST_connection_pool_get_handle (occ->peer->id, - occ->peer->details.local.cfg, - GST_CONNECTIONPOOL_SERVICE_CORE, - &occ_cache_get_handle_core_cb, - occ, - &occ->other_peer_identity, - &overlay_connect_notify, - occ); -} - - -/** - * Callback which will be called after a host registration succeeded or failed - * - * @param cls the RegisteredHostContext - * @param emsg the error message; NULL if host registration is successful - */ -static void -host_registration_comp (void *cls, const char *emsg) -{ - struct RegisteredHostContext *rhc = cls; - - rhc->state = RHC_DONE; - GST_process_next_focc (rhc); -} - - -/** - * Iterator to match a registered host context - * - * @param cls pointer 2 pointer of RegisteredHostContext - * @param key current key code - * @param value value in the hash map - * @return #GNUNET_YES if we should continue to - * iterate, - * #GNUNET_NO if not. - */ -static int -reghost_match_iterator (void *cls, - const struct GNUNET_HashCode *key, - void *value) -{ - struct RegisteredHostContext **rh = cls; - struct RegisteredHostContext *rh_val = value; - - if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host)) - { - GNUNET_free (*rh); - *rh = rh_val; - return GNUNET_NO; - } - return GNUNET_YES; -} - - -/** - * Function to generate the hashcode corresponding to a RegisteredHostContext - * - * @param reg_host the host which is being registered in RegisteredHostContext - * @param host the host of the controller which has to connect to the above rhost - * @return the hashcode - */ -static struct GNUNET_HashCode -hash_hosts (struct GNUNET_TESTBED_Host *reg_host, - struct GNUNET_TESTBED_Host *host) -{ - struct GNUNET_HashCode hash; - uint32_t host_ids[2]; - - host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host); - host_ids[1] = GNUNET_TESTBED_host_get_id_ (host); - GNUNET_CRYPTO_hash (host_ids, sizeof(host_ids), &hash); - return hash; -} - - -/** - * Checks if the given host is registered at the given slave. - * - * @param slave the slave where registration has to be checked. The check is - * actually done through a locally maintained hashmap. No - * communication with the slave is involved. - * @param host the host to register - * @return If the given host is not registered already or the registration is - * pending, it returns the registration context. Any overlay connects - * to be forwarded should be queued in the context so that they can be - * executed when the registration is completed. If the given host is - * already registered, NULL is returned. - */ -static struct RegisteredHostContext * -register_host (struct Slave *slave, - struct GNUNET_TESTBED_Host *host) -{ - struct GNUNET_HashCode hash; - struct RegisteredHostContext *rhc; - - rhc = GNUNET_new (struct RegisteredHostContext); - rhc->reg_host = host; - rhc->host = GST_host_list[slave->host_id]; - GNUNET_assert (NULL != rhc->reg_host); - GNUNET_assert (NULL != rhc->host); - rhc->state = RHC_INIT; - hash = hash_hosts (rhc->reg_host, rhc->host); - if ((GNUNET_NO == - GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map, - &hash)) || - (GNUNET_SYSERR != - GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map, - &hash, - reghost_match_iterator, - &rhc))) - { - /* create and add a new registered host context */ - /* add the focc to its queue */ - GNUNET_CONTAINER_multihashmap_put (slave->reghost_map, - &hash, - rhc, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - GST_queue_host_registration (slave, - host_registration_comp, - rhc, - rhc->reg_host); - } - else - { - /* rhc is now set to the existing one from the hash map by - * reghost_match_iterator() */ - /* if queue is empty then ignore creating focc and proceed with normal - * forwarding */ - if (RHC_DONE == rhc->state) - return NULL; - } - return rhc; -} - - -/** - * Forwards the overlay connect request to a slave controller. Before - * forwarding, any hosts which are needed to be known by the slave controller to - * execute the overlay connect request are registered at slave. - * - * @param msg the overlay connect request message to be forwarded - * @param client the client to which the status of the forwarded request has to - * be notified - */ -static void -forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg, - struct GNUNET_SERVICE_Client *client) -{ - struct ForwardedOperationContext *fopc; - struct Route *route_to_peer2_host; - struct Route *route_to_peer1_host; - struct Peer *peer; - struct RegisteredHostContext *rhc; - struct ForwardedOverlayConnectContext *focc; - uint64_t op_id; - uint32_t peer2_host_id; - uint32_t p1; - uint32_t p2; - - p1 = ntohl (msg->peer1); - p2 = ntohl (msg->peer2); - op_id = GNUNET_ntohll (msg->operation_id); - peer2_host_id = ntohl (msg->peer2_host_id); - GNUNET_assert (VALID_PEER_ID (p1)); - GNUNET_assert (VALID_HOST_ID (peer2_host_id)); - peer = GST_peer_list[p1]; - GNUNET_assert (GNUNET_YES == peer->is_remote); - LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", - (unsigned long long) op_id); - route_to_peer2_host = GST_find_dest_route (peer2_host_id); - route_to_peer1_host = GST_find_dest_route - (peer->details.remote.remote_host_id); - GNUNET_assert (NULL != route_to_peer1_host); - if ((NULL != route_to_peer2_host) && - (route_to_peer1_host->dest == route_to_peer2_host->dest)) - goto forward; - /* Peer2 is either with us OR peer1 and peer2 can be reached through - different subtrees OR peer2 is on a subtree unknown to us */ - if (NULL != (rhc = register_host (peer->details.remote.slave, - GST_host_list[peer2_host_id]))) - { - LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, - p2); - focc = GNUNET_new (struct ForwardedOverlayConnectContext); - focc->rhc = rhc; - focc->peer1 = p1; - focc->peer2 = p2; - focc->peer2_host_id = peer2_host_id; - focc->orig_msg = GNUNET_copy_message (&msg->header); - focc->operation_id = op_id; - focc->client = client; - GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head, - rhc->focc_dll_tail, - focc); - return; - } - -forward: - LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, - p2); - fopc = GNUNET_new (struct ForwardedOperationContext); - fopc->client = client; - fopc->operation_id = op_id; - fopc->type = OP_OVERLAY_CONNECT; - fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. - slave->controller, op_id, - &msg->header, - &GST_forwarded_operation_reply_relay, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, - &GST_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, - fopcq_tail, - fopc); -} - - -/** - * Callback called when a connection to the controller of peer2 has been - * established - * - * @param cls the overlay connect contexts - * @param c handle to the controller connection - */ -static void -p2_controller_connect_cb (void *cls, - struct GNUNET_TESTBED_Controller *c) -{ - struct OverlayConnectContext *occ = cls; - struct RemotePeer2Context *rp2c; - struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg; - - GNUNET_assert (OCC_TYPE_LOCAL != occ->type); - rp2c = &occ->p2ctx.remote; - rp2c->ncn = NULL; - rp2c->p2c = c; - cmsg.header.size = - htons (sizeof(struct GNUNET_TESTBED_PeerGetConfigurationMessage)); - cmsg.header.type = - htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION); - cmsg.peer_id = htonl (occ->other_peer_id); - cmsg.operation_id = GNUNET_htonll (occ->op_id); - rp2c->opc = - GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c, - occ->op_id, - &cmsg.header, - &overlay_connect_get_config, - occ); - GNUNET_free (occ->emsg); - GNUNET_asprintf (&occ->emsg, - "0x%llx: Timeout while getting peer identity of peer " - "with id: %u", - (unsigned long long) occ->op_id, - occ->other_peer_id); -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_overlay_connect (void *cls, - const struct GNUNET_TESTBED_OverlayConnectMessage *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct Peer *peer; - struct Peer *peer2; - struct OverlayConnectContext *occ; - struct Neighbour *p2n; - uint64_t operation_id; - uint32_t p1; - uint32_t p2; - uint32_t peer2_host_id; - - p1 = ntohl (msg->peer1); - p2 = ntohl (msg->peer2); - if (p1 == p2) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (client); - return; - } - if (! VALID_PEER_ID (p1)) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (client); - return; - } - peer = GST_peer_list[p1]; - operation_id = GNUNET_ntohll (msg->operation_id); - LOG_DEBUG - ("Received overlay connect for peers %u and %u with op id: 0x%llx\n", - p1, - p2, - (unsigned long long) operation_id); - peer2_host_id = ntohl (msg->peer2_host_id); - if (GNUNET_YES == peer->is_remote) - { - if (! VALID_HOST_ID (peer2_host_id)) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (client); - return; - } - forward_overlay_connect (msg, client); - GNUNET_SERVICE_client_continue (client); - return; - } - p2n = NULL; - occ = GNUNET_new (struct OverlayConnectContext); - occ->type = OCC_TYPE_LOCAL; - if (! VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */ - { - if (NULL == (p2n = GST_get_neighbour (peer2_host_id))) - { - if (! VALID_HOST_ID (peer2_host_id)) - { - GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_WARNING, - "0x%llx: Peer %u's host not in our neighbours list\n", - (unsigned long long) operation_id, p2); - GNUNET_SERVICE_client_drop (client); - GNUNET_free (occ); - return; - } - p2n = GST_create_neighbour (GST_host_list[peer2_host_id]); - } - occ->type = OCC_TYPE_REMOTE_LATERAL; - occ->p2ctx.remote.p2n = p2n; - } - else if (GNUNET_YES == GST_peer_list[p2]->is_remote) - { - occ->type = OCC_TYPE_REMOTE_SLAVE; - occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller; - } - GNUNET_CONTAINER_DLL_insert_tail (occq_head, - occq_tail, - occ); - occ->client = client; - occ->other_peer_id = p2; - GST_peer_list[p1]->reference_cnt++; - occ->peer = GST_peer_list[p1]; - occ->op_id = operation_id; - GNUNET_assert (NULL == occ->timeout_task); - occ->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, - &timeout_overlay_connect, - occ); - switch (occ->type) - { - case OCC_TYPE_REMOTE_LATERAL: - GNUNET_asprintf (&occ->emsg, - "0x%llx: Timeout while acquiring connection to peer %u's " - "host: %u\n", - (unsigned long long) occ->op_id, - occ->other_peer_id, - peer2_host_id); - occ->p2ctx.remote.ncn - = GST_neighbour_get_connection (p2n, - &p2_controller_connect_cb, - occ); - break; - case OCC_TYPE_REMOTE_SLAVE: - p2_controller_connect_cb (occ, - occ->p2ctx.remote.p2c); - break; - case OCC_TYPE_LOCAL: - peer2 = GST_peer_list[occ->other_peer_id]; - peer2->reference_cnt++; - GNUNET_TESTING_peer_get_identity (peer2->details.local.peer, - &occ->other_peer_identity); - GNUNET_asprintf (&occ->emsg, - "0x%llx: Timeout while connecting to CORE of peer with " - "id: %u", - (unsigned long long) occ->op_id, - occ->peer->id); - LOG_DEBUG ("Peer %u has PID %s\n", - occ->other_peer_id, - GNUNET_i2s (&occ->other_peer_identity)); - { - struct GNUNET_PeerIdentity lpid; - - GNUNET_TESTING_peer_get_identity (peer->details.local.peer, - &lpid); - LOG_DEBUG ("Peer %u has PID %s\n", - p1, - GNUNET_i2s (&lpid)); - } - occ->cgh_ch = - GST_connection_pool_get_handle (occ->peer->id, - occ->peer->details.local.cfg, - GST_CONNECTIONPOOL_SERVICE_CORE, - &occ_cache_get_handle_core_cb, occ, - &occ->other_peer_identity, - &overlay_connect_notify, occ); - break; - } - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Function to cleanup RemoteOverlayConnectCtx and any associated tasks - * with it - * - * @param rocc the RemoteOverlayConnectCtx - */ -static void -cleanup_rocc (struct RemoteOverlayConnectCtx *rocc) -{ - LOG_DEBUG ("0x%llx: Cleaning up rocc\n", - (unsigned long long) rocc->op_id); - if (NULL != rocc->attempt_connect_task_id) - GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id); - if (NULL != rocc->timeout_rocc_task_id) - GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id); - if (NULL != rocc->ohh) - GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh); - if (NULL != rocc->tcc.csh) - GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh); - GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th); - GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats); - GNUNET_assert (rocc->peer->reference_cnt > 0); - rocc->peer->reference_cnt--; - if ((GNUNET_YES == rocc->peer->destroy_flag) && - (0 == rocc->peer->reference_cnt)) - GST_destroy_peer (rocc->peer); - GNUNET_free (rocc->hello); - GNUNET_CONTAINER_DLL_remove (roccq_head, - roccq_tail, - rocc); - GNUNET_free (rocc); -} - - -/** - * Task to timeout rocc and cleanit up - * - * @param cls the RemoteOverlayConnectCtx - */ -static void -timeout_rocc_task (void *cls) -{ - struct RemoteOverlayConnectCtx *rocc = cls; - - GNUNET_assert (rocc->timeout_rocc_task_id != NULL); - rocc->timeout_rocc_task_id = NULL; - LOG_DEBUG ("0x%llx: rocc timed out\n", - (unsigned long long) rocc->op_id); - cleanup_rocc (rocc); -} - - -/** - * Function called to notify transport users that another - * peer connected to us. - * - * @param cls the RemoteOverlayConnectContext - * @param new_peer the peer that connected - */ -static void -cache_transport_peer_connect_notify (void *cls, - const struct GNUNET_PeerIdentity *new_peer) -{ - struct RemoteOverlayConnectCtx *rocc = cls; - - LOG_DEBUG ("0x%llx: Request Overlay connect notify\n", - (unsigned long long) rocc->op_id); - GNUNET_assert (0 == - memcmp (new_peer, &rocc->a_id, - sizeof(struct GNUNET_PeerIdentity))); - LOG_DEBUG ("0x%llx: Peer %s connected\n", - (unsigned long long) rocc->op_id, - GNUNET_i2s (&rocc->a_id)); - cleanup_rocc (rocc); -} - - -/** - * Task to offer the HELLO message to the peer and ask it to connect to the peer - * whose identity is in RemoteOverlayConnectCtx - * - * @param cls the RemoteOverlayConnectCtx - */ -static void -attempt_connect_task (void *cls); - - -/** - * Task that is run when hello has been sent If tc->reason = - * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if - * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded - * - * @param cls the overlay connect context - */ -static void -rocc_hello_sent_cb (void *cls) -{ - struct RemoteOverlayConnectCtx *rocc = cls; - - rocc->ohh = NULL; - GNUNET_assert (NULL == rocc->attempt_connect_task_id); - LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n", - (unsigned long long) rocc->op_id, - GNUNET_i2s (&rocc->a_id), - rocc->peer->id); - rocc->tcc.cgh_p2_ats = - GST_connection_pool_get_handle (rocc->peer->id, - rocc->peer->details.local.cfg, - GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY, - &occ_cache_get_handle_ats_rocc_cb, - rocc, NULL, NULL, NULL); -} - - -/** - * Task to offer the HELLO message to the peer and ask it to connect to the peer - * whose identity is in RemoteOverlayConnectCtx - * - * @param cls the RemoteOverlayConnectCtx - */ -static void -attempt_connect_task (void *cls) -{ - struct RemoteOverlayConnectCtx *rocc = cls; - - GNUNET_assert (NULL != rocc->attempt_connect_task_id); - rocc->attempt_connect_task_id = NULL; - LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n", - (unsigned long long) rocc->op_id, - GNUNET_i2s (&rocc->a_id), - rocc->peer->id); - rocc->ohh = - GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg, - rocc->hello, - &rocc_hello_sent_cb, - rocc); - if (NULL == rocc->ohh) - rocc->attempt_connect_task_id = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, - 100 - + GNUNET_CRYPTO_random_u32 - (GNUNET_CRYPTO_QUALITY_WEAK, 500)), - &attempt_connect_task, rocc); -} - - -/** - * Callback from cache with needed handles set - * - * @param cls the closure passed to GST_cache_get_handle_transport() - * @param ch the handle to CORE. Can be NULL if it is not requested - * @param th the handle to TRANSPORT. Can be NULL if it is not requested - * @param ac the handle to ATS. Can be NULL if it is not requested - * @param ignore_ peer identity which is ignored in this callback - */ -static void -rocc_cache_get_handle_transport_cb (void *cls, - struct GNUNET_CORE_Handle *ch, - struct GNUNET_TRANSPORT_CoreHandle *th, - struct GNUNET_ATS_ConnectivityHandle *ac, - const struct GNUNET_PeerIdentity *ignore_, - const struct - GNUNET_CONFIGURATION_Handle *cfg) -{ - struct RemoteOverlayConnectCtx *rocc = cls; - - if (NULL == th) - { - rocc->timeout_rocc_task_id = - GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc); - return; - } - rocc->tcc.th_ = th; - rocc->tcc.cfg = cfg; - if (NULL != - GNUNET_TRANSPORT_core_get_mq (rocc->tcc.th_, - &rocc->a_id)) - { - LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n", - (unsigned long long) rocc->op_id, - GNUNET_i2s (&rocc->a_id), - rocc->peer->id); - cleanup_rocc (rocc); - return; - } - rocc->attempt_connect_task_id = - GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc); -} - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_remote_overlay_connect (void *cls, - const struct - GNUNET_TESTBED_RemoteOverlayConnectMessage *msg) -{ - uint32_t peer_id; - uint16_t msize; - uint16_t hsize; - - msize = ntohs (msg->header.size); - if (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - hsize = ntohs (msg->hello->size); - if ((sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) != - msize) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - peer_id = ntohl (msg->peer); - if ((peer_id >= GST_peer_list_size) || - (NULL == GST_peer_list[peer_id])) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_remote_overlay_connect (void *cls, - const struct - GNUNET_TESTBED_RemoteOverlayConnectMessage *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct RemoteOverlayConnectCtx *rocc; - struct Peer *peer; - struct GNUNET_PeerIdentity pid; - static char pid_str[16]; - uint32_t peer_id; - uint16_t hsize; - - hsize = ntohs (msg->hello->size); - peer_id = ntohl (msg->peer); - peer = GST_peer_list[peer_id]; - if (GNUNET_YES == peer->is_remote) - { - struct GNUNET_MessageHeader *msg2; - - msg2 = GNUNET_copy_message (&msg->header); - GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller, - msg2); - GNUNET_SERVICE_client_continue (client); - return; - } - rocc = GNUNET_new (struct RemoteOverlayConnectCtx); - rocc->op_id = GNUNET_ntohll (msg->operation_id); - GNUNET_CONTAINER_DLL_insert_tail (roccq_head, - roccq_tail, - rocc); - rocc->a_id = msg->peer_identity; - GNUNET_TESTING_peer_get_identity (peer->details.local.peer, - &pid); - (void) GNUNET_strlcpy (pid_str, - GNUNET_i2s (&pid), - sizeof(pid_str)); - LOG_DEBUG ( - "0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n", - (unsigned long long) rocc->op_id, - pid_str, - GNUNET_i2s (&rocc->a_id), - hsize); - rocc->peer = peer; - rocc->peer->reference_cnt++; - rocc->hello = GNUNET_malloc (hsize); - GNUNET_memcpy (rocc->hello, - msg->hello, - hsize); - rocc->tcc.cgh_p2_th = - GST_connection_pool_get_handle (peer_id, - rocc->peer->details.local.cfg, - GST_CONNECTIONPOOL_SERVICE_TRANSPORT, - &rocc_cache_get_handle_transport_cb, - rocc, - &rocc->a_id, - &cache_transport_peer_connect_notify, - rocc); - rocc->timeout_rocc_task_id = - GNUNET_SCHEDULER_add_delayed (GST_timeout, - &timeout_rocc_task, - rocc); - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Clears all pending overlay connect contexts in queue - */ -void -GST_free_occq () -{ - struct OverlayConnectContext *occ; - - while (NULL != (occ = occq_head)) - cleanup_occ (occ); -} - - -/** - * Clears all pending remote overlay connect contexts in queue - */ -void -GST_free_roccq () -{ - struct RemoteOverlayConnectCtx *rocc; - - while (NULL != (rocc = roccq_head)) - cleanup_rocc (rocc); -} diff --git a/src/testbed/gnunet-service-testbed_peers.c b/src/testbed/gnunet-service-testbed_peers.c @@ -1,1552 +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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - - -/** - * @file testbed/gnunet-service-testbed_peers.c - * @brief implementation of TESTBED service that deals with peer management - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet-service-testbed.h" -#include "gnunet_arm_service.h" -#include <zlib.h> - - -/** - * A list of peers we know about - */ -struct Peer **GST_peer_list; - -/** - * The current number of peers running locally under this controller - */ -unsigned int GST_num_local_peers; - - -/** - * Context information to manage peers' services - */ -struct ManageServiceContext -{ - /** - * DLL next ptr - */ - struct ManageServiceContext *next; - - /** - * DLL prev ptr - */ - struct ManageServiceContext *prev; - - /** - * The ARM handle of the peer - */ - struct GNUNET_ARM_Handle *ah; - - /** - * peer whose service has to be managed - */ - struct Peer *peer; - - /** - * The client which requested to manage the peer's service - */ - struct GNUNET_SERVICE_Client *client; - - /** - * Name of the service. - */ - char *service; - - /** - * The operation id of the associated request - */ - uint64_t op_id; - - /** - * 1 if the service at the peer has to be started; 0 if it has to be stopped - */ - uint8_t start; - - /** - * Is this context expired? Do not work on this context if it is set to - * GNUNET_YES - */ - uint8_t expired; -}; - - -/** - * Context information for peer re-configure operations - */ -struct PeerReconfigureContext -{ - /** - * DLL next for inclusoin in peer reconfigure operations list - */ - struct PeerReconfigureContext *next; - - /** - * DLL prev - */ - struct PeerReconfigureContext *prev; - - /** - * The client which gave this operation to us - */ - struct GNUNET_SERVICE_Client *client; - - /** - * The configuration handle to use as the new template - */ - struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * The id of the operation - */ - uint64_t op_id; - - /** - * The id of the peer which has to be reconfigured - */ - uint32_t peer_id; - - /** - * The the peer stopped? Used while cleaning up this context to decide - * whether the asynchronous stop request through Testing/ARM API has to be - * cancelled - */ - uint8_t stopped; -}; - -/** - * The DLL head for the peer reconfigure list - */ -static struct PeerReconfigureContext *prc_head; - -/** - * The DLL tail for the peer reconfigure list - */ -static struct PeerReconfigureContext *prc_tail; - - -/** - * DLL head for queue of manage service requests - */ -static struct ManageServiceContext *mctx_head; - -/** - * DLL tail for queue of manage service requests - */ -static struct ManageServiceContext *mctx_tail; - - -/** - * Adds a peer to the peer array - * - * @param peer the peer to add - */ -static void -peer_list_add (struct Peer *peer) -{ - if (peer->id >= GST_peer_list_size) - GST_array_grow_large_enough (GST_peer_list, GST_peer_list_size, peer->id); - GNUNET_assert (NULL == GST_peer_list[peer->id]); - GST_peer_list[peer->id] = peer; - if (GNUNET_NO == peer->is_remote) - GST_num_local_peers++; -} - - -/** - * Removes a the give peer from the peer array - * - * @param peer the peer to be removed - */ -static void -peer_list_remove (struct Peer *peer) -{ - unsigned int orig_size; - uint32_t id; - - if (GNUNET_NO == peer->is_remote) - GST_num_local_peers--; - GST_peer_list[peer->id] = NULL; - orig_size = GST_peer_list_size; - while (GST_peer_list_size >= LIST_GROW_STEP) - { - for (id = GST_peer_list_size - 1; - (id >= GST_peer_list_size - LIST_GROW_STEP) && (id != UINT32_MAX); - id--) - if (NULL != GST_peer_list[id]) - break; - if (id != ((GST_peer_list_size - LIST_GROW_STEP) - 1)) - break; - GST_peer_list_size -= LIST_GROW_STEP; - } - if (orig_size == GST_peer_list_size) - return; - GST_peer_list = - GNUNET_realloc (GST_peer_list, - sizeof(struct Peer *) * GST_peer_list_size); -} - - -/** - * The task to be executed if the forwarded peer create operation has been - * timed out - * - * @param cls the FowardedOperationContext - */ -static void -peer_create_forward_timeout (void *cls) -{ - struct ForwardedOperationContext *fopc = cls; - - GNUNET_free (fopc->cls); - GST_forwarded_operation_timeout (fopc); -} - - -/** - * Callback to be called when forwarded peer create operation is successful. We - * have to relay the reply msg back to the client - * - * @param cls ForwardedOperationContext - * @param msg the peer create success message - */ -static void -peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) -{ - struct ForwardedOperationContext *fopc = cls; - struct Peer *remote_peer; - - if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS) - { - GNUNET_assert (NULL != fopc->cls); - remote_peer = fopc->cls; - peer_list_add (remote_peer); - } - GST_forwarded_operation_reply_relay (fopc, - msg); -} - - -/** - * Function to destroy a peer - * - * @param peer the peer structure to destroy - */ -void -GST_destroy_peer (struct Peer *peer) -{ - GNUNET_break (0 == peer->reference_cnt); - if (GNUNET_YES == peer->is_remote) - { - peer_list_remove (peer); - GNUNET_free (peer); - return; - } - if (GNUNET_YES == peer->details.local.is_running) - { - GNUNET_TESTING_peer_stop (peer->details.local.peer); - peer->details.local.is_running = GNUNET_NO; - } - GNUNET_TESTING_peer_destroy (peer->details.local.peer); - GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); - peer_list_remove (peer); - GNUNET_free (peer); -} - - -/** - * Cleanup the context information created for managing a peer's service - * - * @param mctx the ManageServiceContext - */ -static void -cleanup_mctx (struct ManageServiceContext *mctx) -{ - mctx->expired = GNUNET_YES; - GNUNET_CONTAINER_DLL_remove (mctx_head, - mctx_tail, - mctx); - GNUNET_ARM_disconnect (mctx->ah); - GNUNET_assert (0 < mctx->peer->reference_cnt); - mctx->peer->reference_cnt--; - if ((GNUNET_YES == mctx->peer->destroy_flag) && - (0 == mctx->peer->reference_cnt)) - GST_destroy_peer (mctx->peer); - GNUNET_free (mctx->service); - GNUNET_free (mctx); -} - - -/** - * Stops a peer - * - * @param peer the peer to stop - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -static int -stop_peer (struct Peer *peer) -{ - GNUNET_assert (GNUNET_NO == peer->is_remote); - if (GNUNET_OK != GNUNET_TESTING_peer_kill (peer->details.local.peer)) - return GNUNET_SYSERR; - peer->details.local.is_running = GNUNET_NO; - return GNUNET_OK; -} - - -/** - * Cleans up the given PeerReconfigureContext - * - * @param prc the PeerReconfigureContext - */ -static void -cleanup_prc (struct PeerReconfigureContext *prc) -{ - struct Peer *peer; - - if (VALID_PEER_ID (prc->peer_id)) - { - peer = GST_peer_list [prc->peer_id]; - if (1 != prc->stopped) - { - GNUNET_TESTING_peer_stop_async_cancel (peer->details.local.peer); - stop_peer (peer); /* Stop the peer synchronously */ - } - } - if (NULL != prc->cfg) - GNUNET_CONFIGURATION_destroy (prc->cfg); - GNUNET_CONTAINER_DLL_remove (prc_head, - prc_tail, - prc); - GNUNET_free (prc); -} - - -/** - * Notify peers subsystem that @a client disconnected. - * - * @param client the client that disconnected - */ -void -GST_notify_client_disconnect_peers (struct GNUNET_SERVICE_Client *client) -{ - struct ForwardedOperationContext *fopc; - struct ForwardedOperationContext *fopcn; - struct ManageServiceContext *mctx; - struct ManageServiceContext *mctxn; - struct PeerReconfigureContext *prc; - struct PeerReconfigureContext *prcn; - - for (fopc = fopcq_head; NULL != fopc; fopc = fopcn) - { - fopcn = fopc->next; - if (client == fopc->client) - { - if (OP_PEER_CREATE == fopc->type) - GNUNET_free (fopc->cls); - GNUNET_SCHEDULER_cancel (fopc->timeout_task); - GST_forwarded_operation_timeout (fopc); - } - } - for (mctx = mctx_head; NULL != mctx; mctx = mctxn) - { - mctxn = mctx->next; - if (client == mctx->client) - cleanup_mctx (mctx); - } - for (prc = prc_head; NULL != prc; prc = prcn) - { - prcn = prc->next; - if (client == prc->client) - cleanup_prc (prc); - } -} - - -/** - * Callback to be called when forwarded peer destroy operation is successful. We - * have to relay the reply msg back to the client - * - * @param cls ForwardedOperationContext - * @param msg the peer create success message - */ -static void -peer_destroy_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) -{ - struct ForwardedOperationContext *fopc = cls; - struct Peer *remote_peer; - - if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS == - ntohs (msg->type)) - { - remote_peer = fopc->cls; - GNUNET_assert (NULL != remote_peer); - remote_peer->destroy_flag = GNUNET_YES; - if (0 == remote_peer->reference_cnt) - GST_destroy_peer (remote_peer); - } - GST_forwarded_operation_reply_relay (fopc, - msg); -} - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_peer_create (void *cls, - const struct GNUNET_TESTBED_PeerCreateMessage *msg) -{ - return GNUNET_OK; /* checked later */ -} - - -void -handle_peer_create (void *cls, - const struct GNUNET_TESTBED_PeerCreateMessage *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply; - struct GNUNET_CONFIGURATION_Handle *cfg; - struct ForwardedOperationContext *fo_ctxt; - struct Route *route; - struct Peer *peer; - char *emsg; - uint32_t host_id; - uint32_t peer_id; - - host_id = ntohl (msg->host_id); - peer_id = ntohl (msg->peer_id); - if (VALID_PEER_ID (peer_id)) - { - (void) GNUNET_asprintf (&emsg, - "Peer with ID %u already exists", - peer_id); - GST_send_operation_fail_msg (client, - GNUNET_ntohll (msg->operation_id), - emsg); - GNUNET_free (emsg); - GNUNET_SERVICE_client_continue (client); - return; - } - if (UINT32_MAX == peer_id) - { - GST_send_operation_fail_msg (client, - GNUNET_ntohll (msg->operation_id), - "Cannot create peer with given ID"); - GNUNET_SERVICE_client_continue (client); - return; - } - if (host_id == GST_context->host_id) - { - /* We are responsible for this peer */ - cfg = GNUNET_TESTBED_extract_config_ (&msg->header); - if (NULL == cfg) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (client); - return; - } - GNUNET_CONFIGURATION_set_value_number (cfg, - "TESTBED", - "PEERID", - (unsigned long long) peer_id); - - GNUNET_CONFIGURATION_set_value_number (cfg, - "PATHS", - "PEERID", - (unsigned long long) peer_id); - peer = GNUNET_new (struct Peer); - peer->is_remote = GNUNET_NO; - peer->details.local.cfg = cfg; - peer->id = peer_id; - LOG_DEBUG ("Creating peer with id: %u\n", - (unsigned int) peer->id); - peer->details.local.peer = - GNUNET_TESTING_peer_configure (GST_context->system, - peer->details.local.cfg, peer->id, - NULL /* Peer id */, - &emsg); - if (NULL == peer->details.local.peer) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Configuring peer failed: %s\n", - emsg); - GNUNET_free (emsg); - GNUNET_free (peer); - GNUNET_break (0); - GNUNET_SERVICE_client_drop (client); - return; - } - peer->details.local.is_running = GNUNET_NO; - peer_list_add (peer); - env = GNUNET_MQ_msg (reply, - GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS); - reply->peer_id = msg->peer_id; - reply->operation_id = msg->operation_id; - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), - env); - GNUNET_SERVICE_client_continue (client); - return; - } - - /* Forward peer create request */ - route = GST_find_dest_route (host_id); - if (NULL == route) - { - GNUNET_break (0); - GNUNET_SERVICE_client_continue (client); // ? - return; - } - peer = GNUNET_new (struct Peer); - peer->is_remote = GNUNET_YES; - peer->id = peer_id; - peer->details.remote.slave = GST_slave_list[route->dest]; - peer->details.remote.remote_host_id = host_id; - fo_ctxt = GNUNET_new (struct ForwardedOperationContext); - fo_ctxt->client = client; - fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id); - fo_ctxt->cls = peer; - fo_ctxt->type = OP_PEER_CREATE; - fo_ctxt->opc = - GNUNET_TESTBED_forward_operation_msg_ (GST_slave_list - [route->dest]->controller, - fo_ctxt->operation_id, - &msg->header, - &peer_create_success_cb, - fo_ctxt); - fo_ctxt->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, - &peer_create_forward_timeout, - fo_ctxt); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, - fopcq_tail, - fo_ctxt); - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_peer_destroy (void *cls, - const struct GNUNET_TESTBED_PeerDestroyMessage *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct ForwardedOperationContext *fopc; - struct Peer *peer; - uint32_t peer_id; - - peer_id = ntohl (msg->peer_id); - LOG_DEBUG ("Received peer destroy on peer: %u and operation id: %llu\n", - (unsigned int) peer_id, - (unsigned long long) GNUNET_ntohll (msg->operation_id)); - if (! VALID_PEER_ID (peer_id)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Asked to destroy a non existent peer with id: %u\n", peer_id); - GST_send_operation_fail_msg (client, - GNUNET_ntohll (msg->operation_id), - "Peer doesn't exist"); - GNUNET_SERVICE_client_continue (client); - return; - } - peer = GST_peer_list[peer_id]; - if (GNUNET_YES == peer->is_remote) - { - /* Forward the destroy message to sub controller */ - fopc = GNUNET_new (struct ForwardedOperationContext); - fopc->client = client; - fopc->cls = peer; - fopc->type = OP_PEER_DESTROY; - fopc->operation_id = GNUNET_ntohll (msg->operation_id); - fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. - slave->controller, - fopc->operation_id, - &msg->header, - &peer_destroy_success_cb, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, - &GST_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, - fopcq_tail, - fopc); - GNUNET_SERVICE_client_continue (client); - return; - } - peer->destroy_flag = GNUNET_YES; - if (0 == peer->reference_cnt) - GST_destroy_peer (peer); - else - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Delaying peer destroy as peer is currently in use\n"); - GST_send_operation_success_msg (client, - GNUNET_ntohll (msg->operation_id)); - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Stats a peer - * - * @param peer the peer to start - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -static int -start_peer (struct Peer *peer) -{ - GNUNET_assert (GNUNET_NO == peer->is_remote); - if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer)) - return GNUNET_SYSERR; - peer->details.local.is_running = GNUNET_YES; - return GNUNET_OK; -} - - -void -handle_peer_start (void *cls, - const struct GNUNET_TESTBED_PeerStartMessage *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_PeerEventMessage *reply; - struct ForwardedOperationContext *fopc; - struct Peer *peer; - uint32_t peer_id; - - peer_id = ntohl (msg->peer_id); - if (! VALID_PEER_ID (peer_id)) - { - GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_ERROR, - "Asked to start a non existent peer with id: %u\n", - peer_id); - GNUNET_SERVICE_client_continue (client); - return; - } - peer = GST_peer_list[peer_id]; - if (GNUNET_YES == peer->is_remote) - { - fopc = GNUNET_new (struct ForwardedOperationContext); - fopc->client = client; - fopc->operation_id = GNUNET_ntohll (msg->operation_id); - fopc->type = OP_PEER_START; - fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. - slave->controller, - fopc->operation_id, &msg->header, - & - GST_forwarded_operation_reply_relay, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, - &GST_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, - fopcq_tail, - fopc); - GNUNET_SERVICE_client_continue (client); - return; - } - if (GNUNET_OK != start_peer (peer)) - { - GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), - "Failed to start"); - GNUNET_SERVICE_client_continue (client); - return; - } - env = GNUNET_MQ_msg (reply, - GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); - reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START); - reply->host_id = htonl (GST_context->host_id); - reply->peer_id = msg->peer_id; - reply->operation_id = msg->operation_id; - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), - env); - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_peer_stop (void *cls, - const struct GNUNET_TESTBED_PeerStopMessage *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_PeerEventMessage *reply; - struct ForwardedOperationContext *fopc; - struct Peer *peer; - uint32_t peer_id; - - peer_id = ntohl (msg->peer_id); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received PEER_STOP for peer %u\n", - (unsigned int) peer_id); - if (! VALID_PEER_ID (peer_id)) - { - GST_send_operation_fail_msg (client, - GNUNET_ntohll (msg->operation_id), - "Peer not found"); - GNUNET_SERVICE_client_continue (client); - return; - } - peer = GST_peer_list[peer_id]; - if (GNUNET_YES == peer->is_remote) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Forwarding PEER_STOP for peer %u\n", - (unsigned int) peer_id); - fopc = GNUNET_new (struct ForwardedOperationContext); - fopc->client = client; - fopc->operation_id = GNUNET_ntohll (msg->operation_id); - fopc->type = OP_PEER_STOP; - fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. - slave->controller, - fopc->operation_id, - &msg->header, - & - GST_forwarded_operation_reply_relay, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, - &GST_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, - fopcq_tail, - fopc); - GNUNET_SERVICE_client_continue (client); - return; - } - if (GNUNET_OK != stop_peer (peer)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Stopping peer %u failed\n", - (unsigned int) peer_id); - GST_send_operation_fail_msg (client, - GNUNET_ntohll (msg->operation_id), - "Peer not running"); - GNUNET_SERVICE_client_continue (client); - return; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Peer %u successfully stopped\n", - (unsigned int) peer_id); - env = GNUNET_MQ_msg (reply, - GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); - reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP); - reply->host_id = htonl (GST_context->host_id); - reply->peer_id = msg->peer_id; - reply->operation_id = msg->operation_id; - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), - env); - GNUNET_SERVICE_client_continue (client); - GNUNET_TESTING_peer_wait (peer->details.local.peer); -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_peer_get_config (void *cls, - const struct - GNUNET_TESTBED_PeerGetConfigurationMessage *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply; - struct ForwardedOperationContext *fopc; - struct Peer *peer; - char *config; - char *xconfig; - size_t c_size; - size_t xc_size; - uint32_t peer_id; - - peer_id = ntohl (msg->peer_id); - LOG_DEBUG ("Received GET_CONFIG for peer %u\n", - (unsigned int) peer_id); - if (! VALID_PEER_ID (peer_id)) - { - GST_send_operation_fail_msg (client, - GNUNET_ntohll (msg->operation_id), - "Peer not found"); - GNUNET_SERVICE_client_continue (client); - return; - } - peer = GST_peer_list[peer_id]; - if (GNUNET_YES == peer->is_remote) - { - LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n", - (unsigned int) peer_id); - fopc = GNUNET_new (struct ForwardedOperationContext); - fopc->client = client; - fopc->operation_id = GNUNET_ntohll (msg->operation_id); - fopc->type = OP_PEER_INFO; - fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. - slave->controller, - fopc->operation_id, - &msg->header, - & - GST_forwarded_operation_reply_relay, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, - &GST_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, - fopcq_tail, - fopc); - GNUNET_SERVICE_client_continue (client); - return; - } - LOG_DEBUG ("Received PEER_GET_CONFIG for peer: %u\n", - peer_id); - config = - GNUNET_CONFIGURATION_serialize (GST_peer_list[peer_id]->details.local.cfg, - &c_size); - xc_size = GNUNET_TESTBED_compress_config_ (config, - c_size, - &xconfig); - GNUNET_free (config); - env = GNUNET_MQ_msg_extra (reply, - xc_size, - GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION); - reply->peer_id = msg->peer_id; - reply->operation_id = msg->operation_id; - GNUNET_TESTING_peer_get_identity (GST_peer_list[peer_id]->details.local.peer, - &reply->peer_identity); - reply->config_size = htons ((uint16_t) c_size); - GNUNET_memcpy (&reply[1], - xconfig, - xc_size); - GNUNET_free (xconfig); - GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), - env); - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Cleans up the Peer reconfigure context list - */ -void -GST_free_prcq () -{ - while (NULL != prc_head) - cleanup_prc (prc_head); -} - - -/** - * Update peer configuration - * - * @param peer the peer to update - * @param cfg the new configuration - * @return error message (freshly allocated); NULL upon success - */ -static char * -update_peer_config (struct Peer *peer, - struct GNUNET_CONFIGURATION_Handle *cfg) -{ - char *emsg; - - GNUNET_TESTING_peer_destroy (peer->details.local.peer); - GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); - peer->details.local.cfg = cfg; - emsg = NULL; - peer->details.local.peer - = GNUNET_TESTING_peer_configure (GST_context->system, - peer->details.local.cfg, - peer->id, - NULL /* Peer id */, - &emsg); - return emsg; -} - - -/** - * Callback to inform whether the peer is running or stopped. - * - * @param cls the closure given to GNUNET_TESTING_peer_stop_async() - * @param p the respective peer whose status is being reported - * @param success #GNUNET_YES if the peer is stopped; #GNUNET_SYSERR upon any - * error - */ -static void -prc_stop_cb (void *cls, - struct GNUNET_TESTING_Peer *p, - int success) -{ - struct PeerReconfigureContext *prc = cls; - struct Peer *peer; - char *emsg; - - GNUNET_assert (VALID_PEER_ID (prc->peer_id)); - peer = GST_peer_list [prc->peer_id]; - GNUNET_assert (GNUNET_NO == peer->is_remote); - emsg = update_peer_config (peer, prc->cfg); - prc->cfg = NULL; - prc->stopped = 1; - if (NULL != emsg) - { - GST_send_operation_fail_msg (prc->client, - prc->op_id, - emsg); - goto cleanup; - } - if (GNUNET_OK != start_peer (peer)) - { - GST_send_operation_fail_msg (prc->client, - prc->op_id, - "Failed to start reconfigured peer"); - goto cleanup; - } - GST_send_operation_success_msg (prc->client, - prc->op_id); - -cleanup: - cleanup_prc (prc); - return; -} - - -/** - * Check #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. - * - * @param cls identification of the client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_peer_reconfigure (void *cls, - const struct GNUNET_TESTBED_PeerReconfigureMessage *msg) -{ - return GNUNET_OK; /* checked later */ -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. - * Should stop the peer asynchronously, destroy it and create it again with the - * new configuration. - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_peer_reconfigure (void *cls, - const struct - GNUNET_TESTBED_PeerReconfigureMessage *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct Peer *peer; - struct GNUNET_CONFIGURATION_Handle *cfg; - struct ForwardedOperationContext *fopc; - struct PeerReconfigureContext *prc; - char *emsg; - uint64_t op_id; - uint32_t peer_id; - - peer_id = ntohl (msg->peer_id); - op_id = GNUNET_ntohll (msg->operation_id); - if (! VALID_PEER_ID (peer_id)) - { - GNUNET_break (0); - GST_send_operation_fail_msg (client, - op_id, - "Peer not found"); - GNUNET_SERVICE_client_continue (client); - return; - } - peer = GST_peer_list[peer_id]; - if (GNUNET_YES == peer->is_remote) - { - LOG_DEBUG ("Forwarding PEER_RECONFIGURE for peer: %u\n", peer_id); - fopc = GNUNET_new (struct ForwardedOperationContext); - fopc->client = client; - fopc->operation_id = op_id; - fopc->type = OP_PEER_RECONFIGURE; - fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. - slave->controller, - fopc->operation_id, - &msg->header, - & - GST_forwarded_operation_reply_relay, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, - &GST_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, - fopcq_tail, - fopc); - GNUNET_SERVICE_client_continue (client); - return; - } - LOG_DEBUG ("Received PEER_RECONFIGURE for peer %u\n", - (unsigned int) peer_id); - if (0 < peer->reference_cnt) - { - GNUNET_break (0); - GST_send_operation_fail_msg (client, - op_id, - "Peer in use"); - GNUNET_SERVICE_client_continue (client); - return; - } - if (GNUNET_YES == peer->destroy_flag) - { - GNUNET_break (0); - GST_send_operation_fail_msg (client, - op_id, - "Peer is being destroyed"); - GNUNET_SERVICE_client_continue (client); - return; - } - cfg = GNUNET_TESTBED_extract_config_ (&msg->header); - if (NULL == cfg) - { - GNUNET_break (0); - GST_send_operation_fail_msg (client, - op_id, - "Compression error"); - GNUNET_SERVICE_client_continue (client); - return; - } - if (GNUNET_NO == peer->details.local.is_running) - { - emsg = update_peer_config (peer, - cfg); - if (NULL != emsg) - GST_send_operation_fail_msg (client, - op_id, - emsg); - GST_send_operation_success_msg (client, - op_id); - GNUNET_SERVICE_client_continue (client); - GNUNET_free (emsg); - return; - } - prc = GNUNET_new (struct PeerReconfigureContext); - if (GNUNET_OK != - GNUNET_TESTING_peer_stop_async (peer->details.local.peer, - &prc_stop_cb, - prc)) - { - GNUNET_assert (0 < GNUNET_asprintf (&emsg, - "Error trying to stop peer %u asynchronously\n", - peer_id)); - LOG (GNUNET_ERROR_TYPE_ERROR, - "%s\n", - emsg); - GST_send_operation_fail_msg (client, - op_id, - emsg); - GNUNET_SERVICE_client_continue (client); - GNUNET_free (prc); - GNUNET_free (emsg); - return; - } - prc->cfg = cfg; - prc->peer_id = peer_id; - prc->op_id = op_id; - prc->client = client; - GNUNET_CONTAINER_DLL_insert_tail (prc_head, - prc_tail, - prc); - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Frees the ManageServiceContext queue - */ -void -GST_free_mctxq () -{ - while (NULL != mctx_head) - cleanup_mctx (mctx_head); -} - - -/** - * Returns a string interpretation of @a rs. - * - * @param rs the request status from ARM - * @return a string interpretation of the request status - */ -static const char * -arm_req_string (enum GNUNET_ARM_RequestStatus rs) -{ - switch (rs) - { - case GNUNET_ARM_REQUEST_SENT_OK: - return _ ("Message was sent successfully"); - - case GNUNET_ARM_REQUEST_DISCONNECTED: - return _ ("We disconnected from ARM before we could send a request"); - } - return _ ("Unknown request status"); -} - - -/** - * Returns a string interpretation of the @a result. - * - * @param result the arm result - * @return a string interpretation - */ -static const char * -arm_ret_string (enum GNUNET_ARM_Result result) -{ - switch (result) - { - case GNUNET_ARM_RESULT_STOPPED: - return _ ("%s is stopped"); - - case GNUNET_ARM_RESULT_STARTING: - return _ ("%s is starting"); - - case GNUNET_ARM_RESULT_STOPPING: - return _ ("%s is stopping"); - - case GNUNET_ARM_RESULT_IS_STARTING_ALREADY: - return _ ("%s is starting already"); - - case GNUNET_ARM_RESULT_IS_STOPPING_ALREADY: - return _ ("%s is stopping already"); - - case GNUNET_ARM_RESULT_IS_STARTED_ALREADY: - return _ ("%s is started already"); - - case GNUNET_ARM_RESULT_IS_STOPPED_ALREADY: - return _ ("%s is stopped already"); - - case GNUNET_ARM_RESULT_IS_NOT_KNOWN: - return _ ("%s service is not known to ARM"); - - case GNUNET_ARM_RESULT_START_FAILED: - return _ ("%s service failed to start"); - - case GNUNET_ARM_RESULT_IN_SHUTDOWN: - return _ ("%s service can't be started because ARM is shutting down"); - } - return _ ("%.s Unknown result code."); -} - - -/** - * Function called in response to a start/stop request. - * Will be called when request was not sent successfully, - * or when a reply comes. If the request was not sent successfully, - * @a rs will indicate that, and @a result will be undefined. - * - * @param cls ManageServiceContext - * @param rs status of the request - * @param result result of the operation - */ -static void -service_manage_result_cb (void *cls, - enum GNUNET_ARM_RequestStatus rs, - enum GNUNET_ARM_Result result) -{ - struct ManageServiceContext *mctx = cls; - char *emsg; - - emsg = NULL; - if (GNUNET_YES == mctx->expired) - return; - if (GNUNET_ARM_REQUEST_SENT_OK != rs) - { - GNUNET_asprintf (&emsg, - "Error communicating with Peer %u's ARM: %s", - mctx->peer->id, - arm_req_string (rs)); - goto ret; - } - if (1 == mctx->start) - goto service_start_check; - if (! ((GNUNET_ARM_RESULT_STOPPED == result) - || (GNUNET_ARM_RESULT_STOPPING == result) - || (GNUNET_ARM_RESULT_IS_STOPPING_ALREADY == result) - || (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY == result))) - { - /* stopping a service failed */ - GNUNET_asprintf (&emsg, - arm_ret_string (result), - mctx->service); - goto ret; - } - /* service stopped successfully */ - goto ret; - -service_start_check: - if (! ((GNUNET_ARM_RESULT_STARTING == result) - || (GNUNET_ARM_RESULT_IS_STARTING_ALREADY == result) - || (GNUNET_ARM_RESULT_IS_STARTED_ALREADY == result))) - { - /* starting a service failed */ - GNUNET_asprintf (&emsg, - arm_ret_string (result), - mctx->service); - goto ret; - } - /* service started successfully */ - -ret: - if (NULL != emsg) - { - LOG_DEBUG ("%s\n", emsg); - GST_send_operation_fail_msg (mctx->client, - mctx->op_id, - emsg); - } - else - GST_send_operation_success_msg (mctx->client, - mctx->op_id); - GNUNET_free (emsg); - cleanup_mctx (mctx); -} - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE message - * - * @param cls identification of client - * @param msg the actual message - * @return #GNUNET_OK if @a msg is well-formed - */ -int -check_manage_peer_service (void *cls, - const struct - GNUNET_TESTBED_ManagePeerServiceMessage *msg) -{ - uint16_t msize; - const char*service; - - msize = ntohs (msg->header.size); - service = (const char *) &msg[1]; - if ('\0' != service[msize - sizeof - (struct GNUNET_TESTBED_ManagePeerServiceMessage) - 1]) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (1 < msg->start) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -void -handle_manage_peer_service (void *cls, - const struct - GNUNET_TESTBED_ManagePeerServiceMessage *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - const char*service; - struct Peer *peer; - char *emsg; - struct GNUNET_ARM_Handle *ah; - struct ManageServiceContext *mctx; - struct ForwardedOperationContext *fopc; - uint64_t op_id; - uint32_t peer_id; - - service = (const char *) &msg[1]; - peer_id = ntohl (msg->peer_id); - op_id = GNUNET_ntohll (msg->operation_id); - LOG_DEBUG ("Received request to manage service %s on peer %u\n", - service, (unsigned int) peer_id); - if ((GST_peer_list_size <= peer_id) - || (NULL == (peer = GST_peer_list[peer_id]))) - { - GNUNET_asprintf (&emsg, "Asked to manage service of a non existent peer " - "with id: %u", peer_id); - goto err_ret; - } - if (0 == strcasecmp ("arm", service)) - { - emsg = GNUNET_strdup ("Cannot start/stop peer's ARM service. " - "Use peer start/stop for that"); - goto err_ret; - } - if (GNUNET_YES == peer->is_remote) - { - /* Forward the destroy message to sub controller */ - fopc = GNUNET_new (struct ForwardedOperationContext); - fopc->client = client; - fopc->cls = peer; - fopc->type = OP_MANAGE_SERVICE; - fopc->operation_id = op_id; - fopc->opc = - GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. - slave->controller, - fopc->operation_id, - &msg->header, - & - GST_forwarded_operation_reply_relay, - fopc); - fopc->timeout_task = - GNUNET_SCHEDULER_add_delayed (GST_timeout, - &GST_forwarded_operation_timeout, - fopc); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, - fopcq_tail, - fopc); - GNUNET_SERVICE_client_continue (client); - return; - } - if (GNUNET_NO == peer->details.local.is_running) - { - emsg = GNUNET_strdup ("Peer not running\n"); - goto err_ret; - } - if ((0 != peer->reference_cnt) - && ((0 == strcasecmp ("core", service)) - || (0 == strcasecmp ("transport", service)))) - { - GNUNET_asprintf (&emsg, "Cannot stop %s service of peer with id: %u " - "since it is required by existing operations", - service, peer_id); - goto err_ret; - } - ah = GNUNET_ARM_connect (peer->details.local.cfg, NULL, NULL); - if (NULL == ah) - { - GNUNET_asprintf (&emsg, - "Cannot connect to ARM service of peer with id: %u", - peer_id); - goto err_ret; - } - mctx = GNUNET_new (struct ManageServiceContext); - mctx->peer = peer; - peer->reference_cnt++; - mctx->op_id = op_id; - mctx->ah = ah; - mctx->client = client; - mctx->start = msg->start; - mctx->service = GNUNET_strdup (service); - GNUNET_CONTAINER_DLL_insert_tail (mctx_head, - mctx_tail, - mctx); - if (1 == mctx->start) - GNUNET_ARM_request_service_start (mctx->ah, - service, - GNUNET_OS_INHERIT_STD_ERR, - &service_manage_result_cb, - mctx); - else - GNUNET_ARM_request_service_stop (mctx->ah, service, - &service_manage_result_cb, - mctx); - GNUNET_SERVICE_client_continue (client); - return; - -err_ret: - LOG (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg); - GST_send_operation_fail_msg (client, op_id, emsg); - GNUNET_free (emsg); - GNUNET_SERVICE_client_continue (client); -} - - -/** - * Stops and destroys all peers - */ -void -GST_destroy_peers () -{ - struct Peer *peer; - unsigned int id; - - if (NULL == GST_peer_list) - return; - for (id = 0; id < GST_peer_list_size; id++) - { - peer = GST_peer_list[id]; - if (NULL == peer) - continue; - /* If destroy flag is set it means that this peer should have been - * destroyed by a context which we destroy before */ - GNUNET_break (GNUNET_NO == peer->destroy_flag); - /* counter should be zero as we free all contexts before */ - GNUNET_break (0 == peer->reference_cnt); - if ((GNUNET_NO == peer->is_remote) && - (GNUNET_YES == peer->details.local.is_running)) - GNUNET_TESTING_peer_kill (peer->details.local.peer); - } - for (id = 0; id < GST_peer_list_size; id++) - { - peer = GST_peer_list[id]; - if (NULL == peer) - continue; - if (GNUNET_NO == peer->is_remote) - { - if (GNUNET_YES == peer->details.local.is_running) - GNUNET_TESTING_peer_wait (peer->details.local.peer); - GNUNET_TESTING_peer_destroy (peer->details.local.peer); - GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); - } - GNUNET_free (peer); - } - GNUNET_free (GST_peer_list); - GST_peer_list = NULL; - GST_peer_list_size = 0; -} - - -/** - * The reply msg handler forwarded SHUTDOWN_PEERS operation. Checks if a - * success reply is received from all clients and then sends the success message - * to the client - * - * @param cls ForwardedOperationContext - * @param msg the message to relay - */ -static void -shutdown_peers_reply_cb (void *cls, - const struct GNUNET_MessageHeader *msg) -{ - struct ForwardedOperationContext *fo_ctxt = cls; - struct HandlerContext_ShutdownPeers *hc; - - hc = fo_ctxt->cls; - GNUNET_assert (0 < hc->nslaves); - hc->nslaves--; - if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS != - ntohs (msg->type)) - hc->timeout = GNUNET_YES; - if (0 == hc->nslaves) - { - if (GNUNET_YES == hc->timeout) - GST_send_operation_fail_msg (fo_ctxt->client, - fo_ctxt->operation_id, - "Timeout at a slave controller"); - else - GST_send_operation_success_msg (fo_ctxt->client, - fo_ctxt->operation_id); - GNUNET_free (hc); - hc = NULL; - } - GNUNET_CONTAINER_DLL_remove (fopcq_head, - fopcq_tail, - fo_ctxt); - GNUNET_free (fo_ctxt); -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages - * - * @param cls identification of the client - * @param msg the actual message - */ -void -handle_shutdown_peers (void *cls, - const struct GNUNET_TESTBED_ShutdownPeersMessage *msg) -{ - struct GNUNET_SERVICE_Client *client = cls; - struct HandlerContext_ShutdownPeers *hc; - struct Slave *slave; - struct ForwardedOperationContext *fo_ctxt; - uint64_t op_id; - unsigned int cnt; - - LOG_DEBUG ("Received SHUTDOWN_PEERS\n"); - /* Stop and destroy all peers */ - GST_free_mctxq (); - GST_free_occq (); - GST_free_roccq (); - GST_clear_fopcq (); - /* Forward to all slaves which we have started */ - op_id = GNUNET_ntohll (msg->operation_id); - hc = GNUNET_new (struct HandlerContext_ShutdownPeers); - /* FIXME: have a better implementation where we track which slaves are - started by this controller */ - for (cnt = 0; cnt < GST_slave_list_size; cnt++) - { - slave = GST_slave_list[cnt]; - if (NULL == slave) - continue; - if (NULL == slave->controller_proc) /* We didn't start the slave */ - continue; - LOG_DEBUG ("Forwarding SHUTDOWN_PEERS\n"); - hc->nslaves++; - fo_ctxt = GNUNET_new (struct ForwardedOperationContext); - fo_ctxt->client = client; - fo_ctxt->operation_id = op_id; - fo_ctxt->cls = hc; - fo_ctxt->type = OP_SHUTDOWN_PEERS; - fo_ctxt->opc = - GNUNET_TESTBED_forward_operation_msg_ (slave->controller, - fo_ctxt->operation_id, - &msg->header, - shutdown_peers_reply_cb, - fo_ctxt); - GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, - fopcq_tail, - fo_ctxt); - } - LOG_DEBUG ("Shutting down peers\n"); - GST_destroy_peers (); - if (0 == hc->nslaves) - { - GST_send_operation_success_msg (client, - op_id); - GNUNET_free (hc); - } - GNUNET_SERVICE_client_continue (client); -} diff --git a/src/testbed/gnunet-testbed-profiler.c b/src/testbed/gnunet-testbed-profiler.c @@ -1,323 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/gnunet-testbed-profiler.c - * @brief Profiling driver for the testbed. - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" -#include "testbed_api_hosts.h" - -/** - * Generic loggins shorthand - */ -#define LOG(kind, ...) \ - GNUNET_log (kind, __VA_ARGS__) - - -/** - * Handle to global configuration - */ -struct GNUNET_CONFIGURATION_Handle *cfg; - -/** - * Peer linking - topology operation - */ -struct GNUNET_TESTBED_Operation *topology_op; - -/** - * Name of the file with the hosts to run the test over (configuration option). - * It will be NULL if ENABLE_LL is set - */ -static char *hosts_file; - -/** - * Abort task identifier - */ -static struct GNUNET_SCHEDULER_Task *abort_task; - -/** - * Global event mask for all testbed events - */ -uint64_t event_mask; - -/** - * Number of peers to be started by the profiler - */ -static unsigned int num_peers; - -/** - * Number of timeout failures to tolerate - */ -static unsigned int num_cont_fails; - -/** - * Continuous failures during overlay connect operations - */ -static unsigned int cont_fails; - -/** - * Links which are successfully established - */ -static unsigned int established_links; - -/** - * Links which are not successfully established - */ -static unsigned int failed_links; - -/** - * Global testing status - */ -static int result; - -/** - * Are we running non interactively - */ -static int noninteractive; - - -/** - * Shutdown nicely - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - if (NULL != abort_task) - { - GNUNET_SCHEDULER_cancel (abort_task); - abort_task = NULL; - } - if (NULL != cfg) - { - GNUNET_CONFIGURATION_destroy (cfg); - cfg = NULL; - } -} - - -/** - * abort task to run on test timed out - * - * @param cls NULL - */ -static void -do_abort (void *cls) -{ - abort_task = NULL; - LOG (GNUNET_ERROR_TYPE_WARNING, - "Aborting\n"); - result = GNUNET_SYSERR; - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Function to print summary about how many overlay links we have made and how - * many failed - */ -static void -print_overlay_links_summary () -{ - static int printed_already; - - if (GNUNET_YES == printed_already) - return; - printed_already = GNUNET_YES; - printf ("%u links succeeded\n", established_links); - printf ("%u links failed due to timeouts\n", failed_links); -} - - -/** - * Controller event callback - * - * @param cls NULL - * @param event the controller event - */ -static void -controller_event_cb (void *cls, - const struct GNUNET_TESTBED_EventInformation *event) -{ - switch (event->type) - { - case GNUNET_TESTBED_ET_OPERATION_FINISHED: - /* Control reaches here when a peer linking operation fails */ - if (NULL != event->details.operation_finished.emsg) - { - printf ("F"); - fflush (stdout); - failed_links++; - if (++cont_fails > num_cont_fails) - { - printf ("\nAborting due to very high failure rate\n"); - print_overlay_links_summary (); - GNUNET_SCHEDULER_shutdown (); - return; - } - } - break; - - case GNUNET_TESTBED_ET_CONNECT: - { - if (0 != cont_fails) - cont_fails--; - if (0 == established_links) - printf ("Establishing links. Please wait\n"); - printf ("."); - fflush (stdout); - established_links++; - } - break; - - default: - GNUNET_break (0); - } -} - - -/** - * Signature of a main function for a testcase. - * - * @param cls closure - * @param h the run handle - * @param num_peers number of peers in 'peers' - * @param peers handle to peers run in the testbed - * @param links_succeeded the number of overlay link connection attempts that - * succeeded - * @param links_failed the number of overlay link - */ -static void -test_run (void *cls, - struct GNUNET_TESTBED_RunHandle *h, - unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, - unsigned int links_succeeded, - unsigned int links_failed) -{ - result = GNUNET_OK; - fprintf (stdout, "\n"); - print_overlay_links_summary (); - GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); - if (noninteractive) - { - GNUNET_SCHEDULER_cancel (abort_task); - abort_task = NULL; - return; - } - fprintf (stdout, "Testbed running, waiting for keystroke to shut down\n"); - fflush (stdout); - (void) getc (stdin); - fprintf (stdout, "Shutting down. Please wait\n"); - fflush (stdout); - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Main function that will be run by the scheduler. - * - * @param cls closure - * @param args remaining command-line arguments - * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param config configuration - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - if (0 == num_peers) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Exiting as the number of peers is %u\n"), - num_peers); - return; - } - cfg = GNUNET_CONFIGURATION_dup (config); - event_mask = 0; - event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); - event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); - GNUNET_TESTBED_run (hosts_file, cfg, num_peers, event_mask, - &controller_event_cb, NULL, - &test_run, NULL); - abort_task = - GNUNET_SCHEDULER_add_shutdown (&do_abort, - NULL); -} - - -/** - * Main function. - * - * @return 0 on success - */ -int -main (int argc, char *const *argv) -{ - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_option_uint ('p', - "num-peers", - "COUNT", - gettext_noop ("create COUNT number of peers"), - &num_peers), - GNUNET_GETOPT_option_uint ('e', - "num-errors", - "COUNT", - gettext_noop ( - "tolerate COUNT number of continuous timeout failures"), - &num_cont_fails), - GNUNET_GETOPT_option_flag ('n', - "non-interactive", - gettext_noop ( - "run profiler in non-interactive mode where upon " - "testbed setup the profiler does not wait for a " - "keystroke but continues to run until a termination " - "signal is received"), - &noninteractive), - GNUNET_GETOPT_option_string ('H', - "hosts", - "FILENAME", - gettext_noop ( - "name of the file with the login information for the testbed"), - &hosts_file), - GNUNET_GETOPT_OPTION_END - }; - const char *binaryHelp = "gnunet-testbed-profiler [OPTIONS]"; - int ret; - - unsetenv ("XDG_DATA_HOME"); - unsetenv ("XDG_CONFIG_HOME"); - if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) - return 2; - result = GNUNET_SYSERR; - ret = - GNUNET_PROGRAM_run (argc, argv, "gnunet-testbed-profiler", binaryHelp, - options, &run, NULL); - GNUNET_free_nz ((void *) argv); - if (GNUNET_OK != ret) - return ret; - if (GNUNET_OK != result) - return 1; - return 0; -} diff --git a/src/testbed/gnunet_mpi_test.c b/src/testbed/gnunet_mpi_test.c @@ -1,108 +0,0 @@ -#include "platform.h" -#include "gnunet_util_lib.h" -#include <mpi.h> - -/** - * Generic logging shorthand - */ -#define LOG(kind, ...) \ - GNUNET_log_from (kind, "gnunet-mpi-test", __VA_ARGS__) - -int -main (int argc, char *argv[]) -{ - char *msg; - char *filename; - char **argv2; - struct GNUNET_OS_Process *proc; - unsigned long code; - pid_t pid; - enum GNUNET_OS_ProcessStatusType proc_status; - int ntasks; - int rank; - int msg_size; - int ret; - unsigned int cnt; - - ret = GNUNET_SYSERR; - if (argc < 2) - { - printf ("Need arguments: gnunet-mpi-test <cmd> <cmd_args>"); - return 1; - } - if (MPI_SUCCESS != MPI_Init (&argc, &argv)) - { - GNUNET_break (0); - return 1; - } - if (MPI_SUCCESS != MPI_Comm_size (MPI_COMM_WORLD, &ntasks)) - { - GNUNET_break (0); - goto finalize; - } - if (MPI_SUCCESS != MPI_Comm_rank (MPI_COMM_WORLD, &rank)) - { - GNUNET_break (0); - goto finalize; - } - pid = getpid (); - (void) GNUNET_asprintf (&filename, "%d-%d.mpiout", (int) pid, rank); - msg_size = GNUNET_asprintf (&msg, "My rank is: %d\n", rank); - printf ("%s", msg); - (void) GNUNET_DISK_directory_remove (filename); - if (GNUNET_OK == - GNUNET_DISK_fn_write (filename, msg, msg_size, - GNUNET_DISK_PERM_USER_READ - | GNUNET_DISK_PERM_GROUP_READ - | GNUNET_DISK_PERM_USER_WRITE - | GNUNET_DISK_PERM_GROUP_WRITE)) - ret = GNUNET_OK; - GNUNET_free (filename); - GNUNET_free (msg); - if (GNUNET_OK != ret) - { - GNUNET_break (0); - goto finalize; - } - - ret = GNUNET_SYSERR; - argv2 = GNUNET_malloc (sizeof(char *) * (argc)); - for (cnt = 1; cnt < argc; cnt++) - argv2[cnt - 1] = argv[cnt]; - proc = - GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL, - NULL, NULL, argv2[0], argv2); - if (NULL == proc) - { - printf ("Cannot exec\n"); - GNUNET_free (argv2); - goto finalize; - } - do - { - (void) sleep (1); - ret = GNUNET_OS_process_status (proc, &proc_status, &code); - } - while (GNUNET_NO == ret); - GNUNET_free (argv2); - GNUNET_assert (GNUNET_NO != ret); - if (GNUNET_OK == ret) - { - if (0 != code) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Child terminated abnormally\n"); - ret = GNUNET_SYSERR; - GNUNET_break (0); - goto finalize; - } - } - else - GNUNET_break (0); - -finalize: - (void) MPI_Finalize (); - if (GNUNET_OK == ret) - return 0; - printf ("Something went wrong\n"); - return 1; -} diff --git a/src/testbed/meson.build b/src/testbed/meson.build @@ -1,129 +0,0 @@ -libgnunettestbed_src = [ - 'testbed_api.c', - 'testbed_api_hosts.c', - 'testbed_api_operations.c', - 'testbed_api_peers.c', - 'testbed_api_services.c', - 'testbed_api_statistics.c', - 'testbed_api_testbed.c', - 'testbed_api_test.c', - 'testbed_api_topology.c', - 'testbed_api_sd.c', - 'testbed_api_barriers.c' - ] - -tdata = configuration_data() -tdata.merge_from(cdata) -tdata.set_quoted('prefix', get_option('prefix')) - -configure_file(input : 'testbed.conf.in', - output : 'testbed.conf', - configuration : tdata, - install: true, - install_dir: pkgcfgdir) - - -if get_option('monolith') - subdir_done() -endif - -libgnunettestbed = library('gnunettestbed', - libgnunettestbed_src, - soversion: '0', - version: '0.0.0', - dependencies: [libgnunetutil_dep, - m_dep, - zlib_dep, - libgnunetstatistics_dep, - libgnunethello_dep, - libgnunettesting_dep, - #libgnunettransport_dep, - libgnunetarm_dep], - include_directories: [incdir, configuration_inc], - install: true, - install_dir: get_option('libdir')) -libgnunettestbed_dep = declare_dependency(link_with : libgnunettestbed) -pkg.generate(libgnunettestbed, url: 'https://www.gnunet.org', - description : 'Provides API for testbed') - - -executable ('gnunet-helper-testbed', - ['gnunet-helper-testbed.c'], - dependencies: [libgnunetutil_dep, - libgnunetcore_dep, - libgnunethello_dep, - libgnunetpeerstore_dep, - libgnunetstatistics_dep, - libgnunettestbed_dep, - libgnunettesting_dep, - #libgnunettransport_dep, - zlib_dep], - include_directories: [incdir, configuration_inc], - install:true, - install_dir: get_option('libdir')/'gnunet'/'libexec') -executable ('gnunet-daemon-testbed-blacklist', - ['gnunet-daemon-testbed-blacklist.c'], - dependencies: [libgnunetutil_dep, - libgnunetcore_dep, - libgnunethello_dep, - libgnunetpeerstore_dep, - libgnunetstatistics_dep, - #libgnunettransport_dep - ], - include_directories: [incdir, configuration_inc], - install:true, - install_dir: get_option('libdir')/'gnunet'/'libexec') - -executable ('gnunet-daemon-testbed-underlay', - ['gnunet-daemon-testbed-underlay.c'], - dependencies: [libgnunetutil_dep, - libgnunetcore_dep, - libgnunethello_dep, - libgnunetpeerstore_dep, - libgnunetstatistics_dep, - #libgnunettransport_dep, - sqlite_dep], - include_directories: [incdir, configuration_inc], - install:true, - install_dir: get_option('libdir')/'gnunet'/'libexec') - -executable ('gnunet-testbed-profiler', - ['gnunet-testbed-profiler.c'], - dependencies: [libgnunetutil_dep, - #libgnunetats_dep, - libgnunettestbed_dep], - include_directories: [incdir, configuration_inc], - install:true, - install_dir: get_option('bindir')) -executable ('gnunet-service-testbed', - ['gnunet-service-testbed.c', - 'gnunet-service-testbed_links.c', - 'gnunet-service-testbed_peers.c', - 'gnunet-service-testbed_cache.c', - 'gnunet-service-testbed_oc.c', - 'gnunet-service-testbed_cpustatus.c', - 'gnunet-service-testbed_meminfo.c', - 'gnunet-service-testbed_barriers.c', - 'gnunet-service-testbed_connectionpool.c'], - dependencies: [libgnunetutil_dep, - libgnunetcore_dep, - # libgnunetats_dep, - libgnunetarm_dep, - libgnunethello_dep, - libgnunettestbed_dep, - libgnunettesting_dep, - #libgnunettransport_dep, - zlib_dep], - include_directories: [incdir, configuration_inc], - install:true, - install_dir: get_option('libdir')/'gnunet'/'libexec') - -# Needs ATS -#executable ('gnunet-daemon-latency-logger', -# ['gnunet-daemon-latency-logger.c'], -# dependencies: [libgnunetutil_dep, -# #libgnunetats_dep, -# sqlite_dep], -# include_directories: [incdir, configuration_inc], -# install:true, -# install_dir: get_option('libdir')/'gnunet'/'libexec') diff --git a/src/testbed/misc.supp b/src/testbed/misc.supp @@ -1,49 +0,0 @@ -{ - <get_log_call_status> - Memcheck:Leak - fun:malloc - ... - fun:re_acquire_state_context - fun:build_trtable - fun:re_search_internal - fun:regexec@@GLIBC_2.3.4 - fun:GNUNET_get_log_call_status - ... -} -{ - <log_setup> - Memcheck:Leak - ... - fun:GNUNET_log_setup - ... -} -{ - <get_log_status> - Memcheck:Leak - ... - fun:GNUNET_get_log_call_status - ... -} -{ - <linux-loader> - Memcheck:Leak - fun:malloc - obj:/lib/i386-linux-gnu/libgcrypt.so.11.7.0 - ... - obj:/lib/i386-linux-gnu/ld-2.15.so -} -{ - <glibc-networking> - Memcheck:Leak - fun:malloc - fun:make_request - fun:__check_pf -} -{ - <crypto-reachable> - Memcheck:Leak - ... - fun:GNUNET_CRYPTO_random_init - fun:call_init - ... -} diff --git a/src/testbed/overlay_topology.txt b/src/testbed/overlay_topology.txt @@ -1,5 +0,0 @@ - -1:2|3 -3:4| 0| 1 -2: 3|1|0 -0: 2 diff --git a/src/testbed/profile-testbed.patch b/src/testbed/profile-testbed.patch @@ -1,43 +0,0 @@ -Index: Makefile.am -=================================================================== ---- Makefile.am (revision 29343) -+++ Makefile.am (working copy) -@@ -59,7 +59,7 @@ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/testbed/libgnunettestbed.la \ - $(top_builddir)/src/arm/libgnunetarm.la \ -- $(LTLIBINTL) $(Z_LIBS) -+ $(LTLIBINTL) $(Z_LIBS) -lprofiler - gnunet_service_testbed_DEPENDENCIES = \ - libgnunettestbed.la - -Index: gnunet-service-testbed.c -=================================================================== ---- gnunet-service-testbed.c (revision 29341) -+++ gnunet-service-testbed.c (working copy) -@@ -26,6 +26,7 @@ - - #include "gnunet-service-testbed.h" - #include "gnunet-service-testbed_barriers.h" -+#include <gperftools/profiler.h> - - /***********/ - /* Globals */ -@@ -956,9 +957,14 @@ - main (int argc, char *const *argv) - { - //sleep (15); /* Debugging */ -- return (GNUNET_OK == -- GNUNET_SERVICE_run (argc, argv, "testbed", GNUNET_SERVICE_OPTION_NONE, -- &testbed_run, NULL)) ? 0 : 1; -+ int ret; -+ -+ ProfilerStart (NULL); -+ ret = GNUNET_SERVICE_run (argc, argv, "testbed", GNUNET_SERVICE_OPTION_NONE, -+ &testbed_run, NULL); -+ ProfilerStop (); -+ return (GNUNET_OK == ret) ? 0 : 1; -+ - } - - /* end of gnunet-service-testbed.c */ diff --git a/src/testbed/sample.job b/src/testbed/sample.job @@ -1,16 +0,0 @@ -#!/bin/bash -# This job command file is called job.cmd -#@ job_type = parallel -#@ class = general -#@ node = 1 -#@ output = job$(jobid).out -#@ error = job$(jobid).err -#@ total_tasks=16 -#@ wall_clock_limit = 0:0:1 -#@ network.MPI = sn_all,not_shared,us -##@ ... other LoadLeveler keywords (see below) -#@ notification = always -#@ notify_user = totakura@in.tum.de -#@ queue - -#@ executable = /bin/bash diff --git a/src/testbed/sample_hosts.txt b/src/testbed/sample_hosts.txt @@ -1,7 +0,0 @@ -totakura@192.168.0.1:22 -totakura@192.168.0.2:22 -totakura@opt01:22 -totakura@i19-n015:2022 -totakura@asgard.realm -rivendal -rohan:561 diff --git a/src/testbed/test-underlay.sqlite b/src/testbed/test-underlay.sqlite Binary files differ. diff --git a/src/testbed/test_gnunet_helper_testbed.c b/src/testbed/test_gnunet_helper_testbed.c @@ -1,255 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/test_gnunet_helper_testbed.c - * @brief Testcase for testing gnunet-helper-testbed.c - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" -#include <zlib.h> - -#include "testbed_api.h" -#include "testbed_helper.h" -#include "testbed_api_hosts.h" - -/** - * Generic logging shortcut - */ -#define LOG(kind, ...) \ - GNUNET_log (kind, __VA_ARGS__) - - -/** - * Handle to the helper process - */ -static struct GNUNET_HELPER_Handle *helper; - -/** - * Message to helper - */ -static struct GNUNET_TESTBED_HelperInit *msg; - -/** - * Message send handle - */ -static struct GNUNET_HELPER_SendHandle *shandle; - -/** - * Abort task identifier - */ -static struct GNUNET_SCHEDULER_Task *abort_task; - -/** - * Shutdown task identifier - */ -static struct GNUNET_SCHEDULER_Task *shutdown_task; - -/** - * Configuration handle. - */ -static struct GNUNET_CONFIGURATION_Handle *cfg; - -/** - * Global testing status - */ -static int result; - - -/** - * Shutdown nicely - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - if (NULL != abort_task) - GNUNET_SCHEDULER_cancel (abort_task); - if (NULL != helper) - GNUNET_HELPER_stop (helper, GNUNET_NO); - GNUNET_free (msg); - if (NULL != cfg) - GNUNET_CONFIGURATION_destroy (cfg); -} - - -/** - * abort task to run on test timed out - * - * @param cls NULL - */ -static void -do_abort (void *cls) -{ - abort_task = NULL; - LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); - result = GNUNET_SYSERR; - if (NULL != shandle) - GNUNET_HELPER_send_cancel (shandle); - if (NULL == shutdown_task) - shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); -} - - -/** - * Continuation function. - * - * @param cls closure - * @param result #GNUNET_OK on success, - * #GNUNET_NO if helper process died - * #GNUNET_SYSERR during GNUNET_HELPER_stop() - */ -static void -cont_cb (void *cls, - int result) -{ - shandle = NULL; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Message sent\n"); - GNUNET_assert (GNUNET_OK == result); -} - - -/** - * Functions with this signature are called whenever a - * complete message is received by the tokenizer. - * - * Do not call GNUNET_SERVER_mst_destroy in callback - * - * @param cls closure - * @param client identification of the client - * @param message the actual message - * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing - */ -static int -mst_cb (void *cls, - const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_TESTBED_HelperReply *msg; - char *config; - uLongf config_size; - uLongf xconfig_size; - - msg = (const struct GNUNET_TESTBED_HelperReply *) message; - config_size = 0; - xconfig_size = 0; - GNUNET_assert (sizeof(struct GNUNET_TESTBED_HelperReply) < - ntohs (msg->header.size)); - GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY == - ntohs (msg->header.type)); - config_size = (uLongf) ntohs (msg->config_size); - xconfig_size = - (uLongf) (ntohs (msg->header.size) - - sizeof(struct GNUNET_TESTBED_HelperReply)); - config = GNUNET_malloc (config_size); - GNUNET_assert (Z_OK == - uncompress ((Bytef *) config, &config_size, - (const Bytef *) &msg[1], xconfig_size)); - GNUNET_free (config); - if (NULL == shutdown_task) - shutdown_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 1), - &do_shutdown, NULL); - return GNUNET_OK; -} - - -/** - * Callback that will be called when the helper process dies. This is not called - * when the helper process is stopped using GNUNET_HELPER_stop() - * - * @param cls the closure from GNUNET_HELPER_start() - */ -static void -exp_cb (void *cls) -{ - helper = NULL; - result = GNUNET_SYSERR; -} - - -/** - * 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 *cfg2) -{ - static char *const binary_argv[] = { - "gnunet-helper-testbed", - NULL - }; - const char *trusted_ip = "127.0.0.1"; - - helper = - GNUNET_HELPER_start (GNUNET_YES, - "gnunet-helper-testbed", - binary_argv, - &mst_cb, - &exp_cb, - NULL); - GNUNET_assert (NULL != helper); - cfg = GNUNET_CONFIGURATION_dup (cfg2); - msg = GNUNET_TESTBED_create_helper_init_msg_ (trusted_ip, NULL, cfg); - shandle = - GNUNET_HELPER_send (helper, &msg->header, GNUNET_NO, &cont_cb, NULL); - GNUNET_assert (NULL != shandle); - abort_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MINUTES, 1), &do_abort, - NULL); -} - - -/** - * 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_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - result = GNUNET_OK; - if (GNUNET_OK != - GNUNET_PROGRAM_run (argc, argv, "test_gnunet_helper_testbed", - "Testcase for testing gnunet-helper-testbed.c", - options, &run, NULL)) - return 1; - return (GNUNET_OK == result) ? 0 : 1; -} - - -/* end of test_gnunet_helper_testbed.c */ diff --git a/src/testbed/test_testbed_api.c b/src/testbed/test_testbed_api.c @@ -1,515 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/test_testbed_api.c - * @brief testcases for the testbed api - * @author Sree Harsha Totakura - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_arm_service.h" -#include "gnunet_testing_lib.h" -#include "gnunet_testbed_service.h" - -/** - * Generic logging shortcut - */ -#define LOG(kind, ...) \ - GNUNET_log (kind, __VA_ARGS__) - -/** - * Relative time seconds shorthand - */ -#define TIME_REL_SECS(sec) \ - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) - -/** - * Our localhost - */ -static struct GNUNET_TESTBED_Host *host; - -/** - * The controller process - */ -static struct GNUNET_TESTBED_ControllerProc *cp; - -/** - * The controller handle - */ -static struct GNUNET_TESTBED_Controller *controller; - -/** - * A neighbouring host - */ -static struct GNUNET_TESTBED_Host *neighbour; - -/** - * Handle for neighbour registration - */ -static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle; - -/** - * Handle for a peer - */ -static struct GNUNET_TESTBED_Peer *peer; - -/** - * Handle to configuration - */ -static struct GNUNET_CONFIGURATION_Handle *cfg; - -/** - * Handle to operation - */ -static struct GNUNET_TESTBED_Operation *operation; - -/** - * Handle to peer's ARM service - */ -static struct GNUNET_ARM_Handle *arm_handle; - -/** - * Abort task identifier - */ -static struct GNUNET_SCHEDULER_Task *abort_task; - -/** - * The testing result - */ -static int result; - - -/** - * Enumeration of sub testcases - */ -enum Test -{ - /** - * Test cases which are not covered by the below ones - */ - OTHER, - - /** - * Test where we get a peer config from controller - */ - PEER_GETCONFIG, - - /** - * Test where we connect to a service running on the peer - */ - PEER_SERVICE_CONNECT, - - /** - * Test where we get a peer's identity from controller - */ - PEER_DESTROY -}; - -/** - * Testing status - */ -static enum Test sub_test; - -/** - * Shutdown nicely - * - * @param cls NULL - * @param tc the task context - */ -static void -do_shutdown (void *cls) -{ - LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down...\n"); - if (NULL != abort_task) - GNUNET_SCHEDULER_cancel (abort_task); - if (NULL != reg_handle) - GNUNET_TESTBED_cancel_registration (reg_handle); - if (NULL != controller) - GNUNET_TESTBED_controller_disconnect (controller); - if (NULL != cfg) - GNUNET_CONFIGURATION_destroy (cfg); - if (NULL != cp) - GNUNET_TESTBED_controller_stop (cp); - if (NULL != neighbour) - GNUNET_TESTBED_host_destroy (neighbour); - if (NULL != host) - GNUNET_TESTBED_host_destroy (host); -} - - -/** - * shortcut to exit during failure - */ -#define FAIL_TEST(cond, ret) do { \ - if (! (cond)) { \ - GNUNET_break (0); \ - if (NULL != abort_task) \ - GNUNET_SCHEDULER_cancel (abort_task); \ - abort_task = NULL; \ - GNUNET_SCHEDULER_add_now (do_shutdown, NULL); \ - ret; \ - } \ -} while (0) - - -/** - * abort task to run on test timed out - * - * @param cls NULL - * @param tc the task context - */ -static void -do_abort (void *cls) -{ - LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); - abort_task = NULL; - do_shutdown (cls); -} - - -/** - * Adapter function called to establish a connection to - * a service. - * - * @param cls closure - * @param cfg configuration of the peer to connect to; will be available until - * GNUNET_TESTBED_operation_done() is called on the operation returned - * from GNUNET_TESTBED_service_connect() - * @return service handle to return in 'op_result', NULL on error - */ -static void * -arm_connect_adapter (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - FAIL_TEST (NULL == cls, return NULL); - FAIL_TEST (OTHER == sub_test, return NULL); - sub_test = PEER_SERVICE_CONNECT; - arm_handle = GNUNET_ARM_connect (cfg, NULL, NULL); - return arm_handle; -} - - -/** - * Adapter function called to destroy a connection to - * a service. - * - * @param cls closure - * @param op_result service handle returned from the connect adapter - */ -static void -arm_disconnect_adapter (void *cls, - void *op_result) -{ - FAIL_TEST (NULL != op_result, return ); - FAIL_TEST (op_result == arm_handle, return ); - GNUNET_ARM_disconnect (arm_handle); - arm_handle = NULL; - FAIL_TEST (PEER_SERVICE_CONNECT == sub_test, return ); - FAIL_TEST (NULL != operation, return ); - operation = GNUNET_TESTBED_peer_stop (NULL, peer, NULL, NULL); - FAIL_TEST (NULL != operation, return ); -} - - -/** - * Callback to be called when a service connect operation is completed - * - * @param cls the callback closure from functions generating an operation - * @param op the operation that has been finished - * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() - * @param emsg error message in case the operation has failed; will be NULL if - * operation has executed successfully. - */ -static void -service_connect_comp_cb (void *cls, - struct GNUNET_TESTBED_Operation *op, - void *ca_result, - const char *emsg) -{ - switch (sub_test) - { - case PEER_SERVICE_CONNECT: - FAIL_TEST (operation == op, return ); - FAIL_TEST (NULL == emsg, return ); - FAIL_TEST (NULL == cls, return ); - FAIL_TEST (ca_result == arm_handle, return ); - GNUNET_TESTBED_operation_done (operation); /* This results in call to - * disconnect adapter */ - break; - - default: - FAIL_TEST (0, return ); - } -} - - -/** - * Callback to be called when the requested peer information is available - * - * @param cb_cls the closure from GNUNET_TESTBED_peer_get_information() - * @param op the operation this callback corresponds to - * @param pinfo the result; will be NULL if the operation has failed - * @param emsg error message if the operation has failed; will be NULL if the - * operation is successful - */ -static void -peerinfo_cb (void *cb_cls, - struct GNUNET_TESTBED_Operation *op, - const struct GNUNET_TESTBED_PeerInformation *pinfo, - const char *emsg) -{ - switch (sub_test) - { - case PEER_GETCONFIG: - FAIL_TEST (NULL != pinfo, return ); - FAIL_TEST (NULL == emsg, return ); - FAIL_TEST (NULL == cb_cls, return ); - FAIL_TEST (operation == op, return ); - FAIL_TEST (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit, return ); - FAIL_TEST (NULL != pinfo->result.cfg, return ); - sub_test = PEER_DESTROY; - GNUNET_TESTBED_operation_done (operation); - operation = GNUNET_TESTBED_peer_destroy (peer); - break; - - default: - FAIL_TEST (0, return ); - } -} - - -/** - * Signature of the event handler function called by the - * respective event controller. - * - * @param cls closure - * @param event information about the event - */ -static void -controller_cb (void *cls, - const struct GNUNET_TESTBED_EventInformation *event) -{ - switch (event->type) - { - case GNUNET_TESTBED_ET_OPERATION_FINISHED: - switch (sub_test) - { - case PEER_DESTROY: - FAIL_TEST (event->op == operation, return ); - FAIL_TEST (NULL == event->op_cls, return ); - FAIL_TEST (NULL == event->details.operation_finished.emsg, return ); - FAIL_TEST (NULL == event->details.operation_finished.generic, return ); - GNUNET_TESTBED_operation_done (operation); - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - break; - - case PEER_SERVICE_CONNECT: - FAIL_TEST (event->op == operation, return ); - FAIL_TEST (NULL == event->op_cls, return ); - FAIL_TEST (NULL == event->details.operation_finished.emsg, return ); - FAIL_TEST (NULL != arm_handle, return ); - FAIL_TEST (event->details.operation_finished.generic == arm_handle, - return ); - break; - - default: - FAIL_TEST (0, return ); - break; - } - break; - - case GNUNET_TESTBED_ET_PEER_START: - FAIL_TEST (event->details.peer_start.host == host, return ); - FAIL_TEST (event->details.peer_start.peer == peer, return ); - FAIL_TEST (OTHER == sub_test, return ); - GNUNET_TESTBED_operation_done (operation); - operation = - GNUNET_TESTBED_service_connect (NULL, peer, "dht", - &service_connect_comp_cb, NULL, - &arm_connect_adapter, - &arm_disconnect_adapter, NULL); - FAIL_TEST (NULL != operation, return ); - break; - - case GNUNET_TESTBED_ET_PEER_STOP: - FAIL_TEST (event->details.peer_stop.peer == peer, return ); - FAIL_TEST (PEER_SERVICE_CONNECT == sub_test, return ); - result = GNUNET_YES; - sub_test = PEER_GETCONFIG; - GNUNET_TESTBED_operation_done (operation); - operation = - GNUNET_TESTBED_peer_get_information (peer, - GNUNET_TESTBED_PIT_CONFIGURATION, - &peerinfo_cb, NULL); - break; - - default: - FAIL_TEST (0, return ); /* We should never reach this state */ - } -} - - -/** - * Functions of this signature are called when a peer has been successfully - * created - * - * @param cls the closure from GNUNET_TESTBED_peer_create() - * @param peer the handle for the created peer; NULL on any error during - * creation - * @param emsg NULL if peer is not NULL; else MAY contain the error description - */ -static void -peer_create_cb (void *cls, - struct GNUNET_TESTBED_Peer *peer, - const char *emsg) -{ - struct GNUNET_TESTBED_Peer **peer_ptr; - - peer_ptr = cls; - FAIL_TEST (NULL != peer, return ); - FAIL_TEST (NULL != peer_ptr, return ); - *peer_ptr = peer; - GNUNET_TESTBED_operation_done (operation); - operation = GNUNET_TESTBED_peer_start (NULL, - peer, - NULL, - NULL); - FAIL_TEST (NULL != operation, return ); -} - - -/** - * Callback which will be called to after a host registration succeeded or failed - * - * @param cls the host which has been registered - * @param emsg the error message; NULL if host registration is successful - */ -static void -registration_comp (void *cls, - const char *emsg) -{ - FAIL_TEST (cls == neighbour, return ); - reg_handle = NULL; - operation = - GNUNET_TESTBED_peer_create (controller, - host, - cfg, - &peer_create_cb, - &peer); - FAIL_TEST (NULL != operation, return ); -} - - -/** - * Callback to signal successful startup of the controller process - * - * @param cls the closure from GNUNET_TESTBED_controller_start() - * @param cfg the configuration with which the controller has been started; - * NULL if status is not #GNUNET_OK - * @param status #GNUNET_OK if the startup is successful; #GNUNET_SYSERR if not, - * GNUNET_TESTBED_controller_stop() shouldn't be called in this case - */ -static void -status_cb (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg_, - int status) -{ - uint64_t event_mask; - - if (GNUNET_OK != status) - { - cp = NULL; - FAIL_TEST (0, return ); - return; - } - event_mask = 0; - event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START); - event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP); - event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); - event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); - controller = - GNUNET_TESTBED_controller_connect (host, event_mask, &controller_cb, - NULL); - FAIL_TEST (NULL != controller, return ); - neighbour = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0); - FAIL_TEST (NULL != neighbour, return ); - reg_handle = - GNUNET_TESTBED_register_host (controller, neighbour, &registration_comp, - neighbour); - FAIL_TEST (NULL != reg_handle, return ); -} - - -/** - * Main run function. - * - * @param cls NULL - * @param args arguments passed to #GNUNET_PROGRAM_run() - * @param cfgfile the path to configuration file - * @param cfg the configuration file handle - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - cfg = GNUNET_CONFIGURATION_dup (config); - host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); - FAIL_TEST (NULL != host, return ); - cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, - &status_cb, - NULL); - abort_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MINUTES, 5), - &do_abort, - NULL); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - int ret; - - char *const argv2[] = { "test_testbed_api", - "-c", "test_testbed_api.conf", - NULL }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - result = GNUNET_SYSERR; - ret = - GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, - "test_testbed_api", "nohelp", options, &run, NULL); - if ((GNUNET_OK != ret) || (GNUNET_OK != result)) - return 1; - return 0; -} - - -/* end of test_testbed_api.c */ diff --git a/src/testbed/test_testbed_api.conf b/src/testbed/test_testbed_api.conf @@ -1 +0,0 @@ -@INLINE@ test_testbed_api_template.conf diff --git a/src/testbed/test_testbed_api_2peers_1controller.c b/src/testbed/test_testbed_api_2peers_1controller.c @@ -1,540 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/test_testbed_api_2peers_1controller.c - * @brief testcases for the testbed api: 2 peers are configured, started and - * connected together. The 2 peer reside on a single controller. - * @author Sree Harsha Totakura - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testing_lib.h" -#include "gnunet_testbed_service.h" - - -/** - * Generic logging shortcut - */ -#define LOG(kind, ...) \ - GNUNET_log (kind, __VA_ARGS__) - -/** - * Relative time seconds shorthand - */ -#define TIME_REL_SECS(sec) \ - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) - -/** - * Peer context - */ -struct PeerContext -{ - /** - * The peer handle - */ - struct GNUNET_TESTBED_Peer *peer; - - /** - * Operations involving this peer - */ - struct GNUNET_TESTBED_Operation *operation; - - /** - * set to GNUNET_YES when peer is started - */ - int is_running; -}; - -/** - * Our localhost - */ -static struct GNUNET_TESTBED_Host *host; - -/** - * The controller process - */ -static struct GNUNET_TESTBED_ControllerProc *cp; - -/** - * The controller handle - */ -static struct GNUNET_TESTBED_Controller *controller; - -/** - * A neighbouring host - */ -static struct GNUNET_TESTBED_Host *neighbour; - -/** - * Handle for neighbour registration - */ -static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle; - -/** - * peer 1 - */ -static struct PeerContext peer1; - -/** - * peer2 - */ -static struct PeerContext peer2; - -/** - * Handle to configuration - */ -static struct GNUNET_CONFIGURATION_Handle *cfg; - -/** - * Handle to operations involving both peers - */ -static struct GNUNET_TESTBED_Operation *common_operation; - -/** - * Abort task identifier - */ -static struct GNUNET_SCHEDULER_Task *abort_task; - -/** - * Delayed connect job identifier - */ -static struct GNUNET_SCHEDULER_Task *delayed_connect_task; - -/** - * Different stages in testing - */ -enum Stage -{ - /** - * Initial stage - */ - INIT, - - /** - * peers are created - */ - PEERS_CREATED, - - /** - * peers are started - */ - PEERS_STARTED, - - /** - * peers are connected - */ - PEERS_CONNECTED, - - /** - * Peers are connected once again (this should not fail as they are already connected) - */ - PEERS_CONNECTED_2, - - /** - * peers are stopped - */ - PEERS_STOPPED, - - /** - * Final success stage - */ - SUCCESS -}; - -/** - * The testing result - */ -static enum Stage result; - - -/** - * shortcut to exit during failure - */ -#define FAIL_TEST(cond) do { \ - if (! (cond)) { \ - GNUNET_break (0); \ - if (NULL != abort_task) \ - GNUNET_SCHEDULER_cancel (abort_task); \ - abort_task = NULL; \ - GNUNET_SCHEDULER_add_now (do_shutdown, NULL); \ - return; \ - } \ -} while (0) - - -/** - * Shutdown nicely - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - if (NULL != abort_task) - GNUNET_SCHEDULER_cancel (abort_task); - if (NULL != delayed_connect_task) - GNUNET_SCHEDULER_cancel (delayed_connect_task); - if (NULL != reg_handle) - GNUNET_TESTBED_cancel_registration (reg_handle); - GNUNET_TESTBED_controller_disconnect (controller); - GNUNET_CONFIGURATION_destroy (cfg); - if (NULL != cp) - GNUNET_TESTBED_controller_stop (cp); - GNUNET_TESTBED_host_destroy (neighbour); - GNUNET_TESTBED_host_destroy (host); -} - - -/** - * abort task to run on test timed out - * - * @param cls NULL - */ -static void -do_abort (void *cls) -{ - LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); - abort_task = NULL; - do_shutdown (cls); -} - - -/** - * Callback to be called when an operation is completed - * - * @param cls the callback closure from functions generating an operation - * @param op the operation that has been finished - * @param emsg error message in case the operation has failed; will be NULL if - * operation has executed successfully. - */ -static void -op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg); - - -/** - * task for delaying a connect - * - * @param cls NULL - */ -static void -do_delayed_connect (void *cls) -{ - delayed_connect_task = NULL; - FAIL_TEST (NULL == common_operation); - common_operation = - GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer1.peer, - peer2.peer); -} - - -/** - * Callback to be called when an operation is completed - * - * @param cls the callback closure from functions generating an operation - * @param op the operation that has been finished - * @param emsg error message in case the operation has failed; will be NULL if - * operation has executed successfully. - */ -static void -op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) -{ - FAIL_TEST (common_operation == op); - switch (result) - { - case PEERS_STARTED: - FAIL_TEST (NULL == peer1.operation); - FAIL_TEST (NULL == peer2.operation); - FAIL_TEST (NULL != common_operation); - break; - - case PEERS_CONNECTED: - FAIL_TEST (NULL == peer1.operation); - FAIL_TEST (NULL == peer2.operation); - FAIL_TEST (NULL != common_operation); - break; - - default: - FAIL_TEST (0); - } -} - - -/** - * Signature of the event handler function called by the - * respective event controller. - * - * @param cls closure - * @param event information about the event - */ -static void -controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) -{ - switch (event->type) - { - case GNUNET_TESTBED_ET_OPERATION_FINISHED: /* Will be reached when we destroy peers */ - FAIL_TEST (PEERS_STOPPED == result); - FAIL_TEST (NULL == event->op_cls); - FAIL_TEST (NULL == event->details.operation_finished.emsg); - FAIL_TEST (NULL == event->details.operation_finished.generic); - if (event->op == peer1.operation) - { - GNUNET_TESTBED_operation_done (peer1.operation); - peer1.operation = NULL; - peer1.peer = NULL; - } - else if (event->op == peer2.operation) - { - GNUNET_TESTBED_operation_done (peer2.operation); - peer2.operation = NULL; - peer2.peer = NULL; - } - else - FAIL_TEST (0); - if ((NULL == peer1.peer) && (NULL == peer2.peer)) - { - result = SUCCESS; - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - } - break; - - case GNUNET_TESTBED_ET_PEER_START: - FAIL_TEST (INIT == result); - FAIL_TEST (event->details.peer_start.host == host); - if (event->details.peer_start.peer == peer1.peer) - { - peer1.is_running = GNUNET_YES; - GNUNET_TESTBED_operation_done (peer1.operation); - peer1.operation = NULL; - } - else if (event->details.peer_start.peer == peer2.peer) - { - peer2.is_running = GNUNET_YES; - GNUNET_TESTBED_operation_done (peer2.operation); - peer2.operation = NULL; - } - else - FAIL_TEST (0); - if ((GNUNET_YES == peer1.is_running) && (GNUNET_YES == peer2.is_running)) - { - result = PEERS_STARTED; - common_operation = - GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer1.peer, - peer2.peer); - } - break; - - case GNUNET_TESTBED_ET_PEER_STOP: - FAIL_TEST (PEERS_CONNECTED_2 == result); - if (event->details.peer_stop.peer == peer1.peer) - { - peer1.is_running = GNUNET_NO; - GNUNET_TESTBED_operation_done (peer1.operation); - peer1.operation = GNUNET_TESTBED_peer_destroy (peer1.peer); - } - else if (event->details.peer_stop.peer == peer2.peer) - { - peer2.is_running = GNUNET_NO; - GNUNET_TESTBED_operation_done (peer2.operation); - peer2.operation = GNUNET_TESTBED_peer_destroy (peer2.peer); - } - else - FAIL_TEST (0); - if ((GNUNET_NO == peer1.is_running) && (GNUNET_NO == peer2.is_running)) - result = PEERS_STOPPED; - break; - - case GNUNET_TESTBED_ET_CONNECT: - switch (result) - { - case PEERS_STARTED: - FAIL_TEST (NULL == peer1.operation); - FAIL_TEST (NULL == peer2.operation); - FAIL_TEST (NULL != common_operation); - FAIL_TEST ((event->details.peer_connect.peer1 == peer1.peer) && - (event->details.peer_connect.peer2 == peer2.peer)); - GNUNET_TESTBED_operation_done (common_operation); - common_operation = NULL; - result = PEERS_CONNECTED; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected\n"); - delayed_connect_task = - GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (3), &do_delayed_connect, - NULL); - break; - - case PEERS_CONNECTED: - FAIL_TEST (NULL == peer1.operation); - FAIL_TEST (NULL == peer2.operation); - FAIL_TEST (NULL != common_operation); - GNUNET_TESTBED_operation_done (common_operation); - common_operation = NULL; - result = PEERS_CONNECTED_2; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected again\n"); - peer1.operation = GNUNET_TESTBED_peer_stop (NULL, peer1.peer, NULL, NULL); - peer2.operation = GNUNET_TESTBED_peer_stop (NULL, peer2.peer, NULL, NULL); - break; - - default: - FAIL_TEST (0); - } - break; - - default: - FAIL_TEST (0); - } - ; -} - - -/** - * Functions of this signature are called when a peer has been successfully - * created - * - * @param cls the closure from GNUNET_TESTBED_peer_create() - * @param peer the handle for the created peer; NULL on any error during - * creation - * @param emsg NULL if peer is not NULL; else MAY contain the error description - */ -static void -peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) -{ - struct PeerContext *pc = cls; - - FAIL_TEST (NULL != pc->operation); - FAIL_TEST (NULL != peer); - FAIL_TEST (NULL == pc->peer); - pc->peer = peer; - GNUNET_TESTBED_operation_done (pc->operation); - pc->operation = GNUNET_TESTBED_peer_start (NULL, pc->peer, NULL, NULL); -} - - -/** - * Callback which will be called to after a host registration succeeded or failed - * - * @param cls the host which has been registered - * @param emsg the error message; NULL if host registration is successful - */ -static void -registration_comp (void *cls, const char *emsg) -{ - FAIL_TEST (cls == neighbour); - reg_handle = NULL; - peer1.operation = - GNUNET_TESTBED_peer_create (controller, host, cfg, &peer_create_cb, - &peer1); - peer2.operation = - GNUNET_TESTBED_peer_create (controller, host, cfg, &peer_create_cb, - &peer2); - FAIL_TEST (NULL != peer1.operation); - FAIL_TEST (NULL != peer2.operation); -} - - -/** - * Callback to signal successful startup of the controller process - * - * @param cls the closure from GNUNET_TESTBED_controller_start() - * @param cfg the configuration with which the controller has been started; - * NULL if status is not GNUNET_OK - * @param status GNUNET_OK if the startup is successful; GNUNET_SYSERR if not, - * GNUNET_TESTBED_controller_stop() shouldn't be called in this case - */ -static void -status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg_, int - status) -{ - uint64_t event_mask; - - if (GNUNET_OK != status) - { - cp = NULL; - FAIL_TEST (0); - } - event_mask = 0; - event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START); - event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP); - event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); - event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); - controller = - GNUNET_TESTBED_controller_connect (host, event_mask, &controller_cb, - NULL); - FAIL_TEST (NULL != controller); - neighbour = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0); - FAIL_TEST (NULL != neighbour); - reg_handle = - GNUNET_TESTBED_register_host (controller, neighbour, &registration_comp, - neighbour); - FAIL_TEST (NULL != reg_handle); -} - - -/** - * Main run function. - * - * @param cls NULL - * @param args arguments passed to GNUNET_PROGRAM_run - * @param cfgfile the path to configuration file - * @param cfg the configuration file handle - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - cfg = GNUNET_CONFIGURATION_dup (config); - host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); - FAIL_TEST (NULL != host); - cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb, - NULL); - abort_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort, - NULL); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - int ret; - - char *const argv2[] = { "test_testbed_api_2peers_1controller", - "-c", "test_testbed_api.conf", - NULL }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - result = INIT; - ret = - GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, - "test_testbed_api_2peers_1controller", "nohelp", - options, &run, NULL); - if ((GNUNET_OK != ret) || (SUCCESS != result)) - return 1; - return 0; -} - - -/* end of test_testbed_api_2peers_1controller.c */ diff --git a/src/testbed/test_testbed_api_3peers_3controllers.c b/src/testbed/test_testbed_api_3peers_3controllers.c @@ -1,964 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/test_testbed_api_3peers_3controllers.c - * @brief testcases for the testbed api: 3 peers are configured, started and - * connected together. Each peer resides on its own controller. - * @author Sree Harsha Totakura - */ - - -/** - * The testing architecture is: - * A - * / \ - * / \ - * B === C - * A is the master controller and B, C are slave controllers. B links to C - * laterally. - * Peers are mapped to controllers in the following relations: - * Peer Controller - * 1 A - * 2 B - * 3 C - * - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testing_lib.h" -#include "gnunet_testbed_service.h" - - -/** - * Generic logging shortcut - */ -#define LOG(kind, ...) \ - GNUNET_log (kind, __VA_ARGS__) - -/** - * Relative time seconds shorthand - */ -#define TIME_REL_SECS(sec) \ - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) - - -/** - * Peer context - */ -struct PeerContext -{ - /** - * The peer handle - */ - struct GNUNET_TESTBED_Peer *peer; - - /** - * Operations involving this peer - */ - struct GNUNET_TESTBED_Operation *operation; - - /** - * set to GNUNET_YES when peer is started - */ - int is_running; -}; - -/** - * Our localhost - */ -static struct GNUNET_TESTBED_Host *host; - -/** - * The controller process of one controller - */ -static struct GNUNET_TESTBED_ControllerProc *cp1; - -/** - * A neighbouring host - */ -static struct GNUNET_TESTBED_Host *neighbour1; - -/** - * Another neighbouring host - */ -static struct GNUNET_TESTBED_Host *neighbour2; - -/** - * Handle for neighbour registration - */ -static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle; - -/** - * The controller handle of one controller - */ -static struct GNUNET_TESTBED_Controller *controller1; - -/** - * peer 1 - */ -static struct PeerContext peer1; - -/** - * peer2 - */ -static struct PeerContext peer2; - -/** - * peer3 - */ -static struct PeerContext peer3; - -/** - * Handle to starting configuration - */ -static struct GNUNET_CONFIGURATION_Handle *cfg; - -/** - * Handle to slave controller C's configuration, used to establish lateral link from - * master controller - */ -static struct GNUNET_CONFIGURATION_Handle *cfg2; - -/** - * Handle to operations involving both peers - */ -static struct GNUNET_TESTBED_Operation *common_operation; - -/** - * The handle for whether a host is habitable or not - */ -struct GNUNET_TESTBED_HostHabitableCheckHandle *hc_handle; - -/** - * Abort task identifier - */ -static struct GNUNET_SCHEDULER_Task *abort_task; - -/** - * Delayed connect job identifier - */ -static struct GNUNET_SCHEDULER_Task *delayed_connect_task; - -/** - * Different stages in testing - */ -enum Stage -{ - /** - * Initial stage - */ - INIT, - - /** - * Controller 1 has started - */ - CONTROLLER1_UP, - - /** - * peer1 is created - */ - PEER1_CREATED, - - /** - * peer1 is started - */ - PEER1_STARTED, - - /** - * Controller 2 has started - */ - CONTROLLER2_UP, - - /** - * peer2 is created - */ - PEER2_CREATED, - - /** - * peer2 is started - */ - PEER2_STARTED, - - /** - * Controller 3 has started - */ - CONTROLLER3_UP, - - /** - * Peer3 is created - */ - PEER3_CREATED, - - /** - * Peer3 started - */ - PEER3_STARTED, - - /** - * peer1 and peer2 are connected - */ - PEERS_1_2_CONNECTED, - - /** - * peer2 and peer3 are connected - */ - PEERS_2_3_CONNECTED, - - /** - * Peers are connected once again (this should not fail as they are already connected) - */ - PEERS_CONNECTED_2, - - /** - * peers are stopped - */ - PEERS_STOPPED, - - /** - * Final success stage - */ - SUCCESS, - - /** - * Optional stage for marking test to be skipped - */ - SKIP -}; - -/** - * The testing result - */ -static enum Stage result; - -/** - * Shutdown nicely - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - if (NULL != abort_task) - GNUNET_SCHEDULER_cancel (abort_task); - if (NULL != hc_handle) - GNUNET_TESTBED_is_host_habitable_cancel (hc_handle); - GNUNET_assert (NULL == delayed_connect_task); - if (NULL != common_operation) - GNUNET_TESTBED_operation_done (common_operation); - if (NULL != reg_handle) - GNUNET_TESTBED_cancel_registration (reg_handle); - if (NULL != controller1) - GNUNET_TESTBED_controller_disconnect (controller1); - GNUNET_CONFIGURATION_destroy (cfg); - if (NULL != cfg2) - GNUNET_CONFIGURATION_destroy (cfg2); - if (NULL != cp1) - GNUNET_TESTBED_controller_stop (cp1); - if (NULL != host) - GNUNET_TESTBED_host_destroy (host); - if (NULL != neighbour1) - GNUNET_TESTBED_host_destroy (neighbour1); - if (NULL != neighbour2) - GNUNET_TESTBED_host_destroy (neighbour2); -} - - -/** - * abort task to run on test timed out - * - * @param cls NULL - */ -static void -do_abort (void *cls) -{ - LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); - abort_task = NULL; - if (NULL != delayed_connect_task) - { - GNUNET_SCHEDULER_cancel (delayed_connect_task); - delayed_connect_task = NULL; - } - do_shutdown (cls); -} - - -static void -abort_test () -{ - if (NULL != abort_task) - GNUNET_SCHEDULER_cancel (abort_task); - abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); -} - - -/** - * Callback to be called when an operation is completed - * - * @param cls the callback closure from functions generating an operation - * @param op the operation that has been finished - * @param emsg error message in case the operation has failed; will be NULL if - * operation has executed successfully. - */ -static void -op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg); - - -/** - * task for delaying a connect - * - * @param cls NULL - */ -static void -do_delayed_connect (void *cls) -{ - delayed_connect_task = NULL; - if (NULL != common_operation) - { - GNUNET_break (0); - abort_test (); - return; - } - common_operation = - GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer1.peer, - peer2.peer); -} - - -/** - * Callback to be called when an operation is completed - * - * @param cls the callback closure from functions generating an operation - * @param op the operation that has been finished - * @param emsg error message in case the operation has failed; will be NULL if - * operation has executed successfully. - */ -static void -op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) -{ - if (common_operation != op) - { - GNUNET_break (0); - abort_test (); - return; - } - - switch (result) - { - case PEER3_STARTED: - case PEERS_2_3_CONNECTED: - case PEERS_1_2_CONNECTED: - break; - - default: - GNUNET_break (0); - abort_test (); - return; - } - if ((NULL != peer1.operation) || (NULL != peer2.operation) || - (NULL != peer3.operation)) - { - GNUNET_break (0); - abort_test (); - return; - } -} - - -/** - * Functions of this signature are called when a peer has been successfully - * created - * - * @param cls NULL - * @param peer the handle for the created peer; NULL on any error during - * creation - * @param emsg NULL if peer is not NULL; else MAY contain the error description - */ -static void -peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) -{ - switch (result) - { - case CONTROLLER1_UP: - if ((NULL == peer1.operation) || (NULL == peer) || (NULL != peer1.peer)) - { - GNUNET_break (0); - abort_test (); - return; - } - peer1.peer = peer; - GNUNET_TESTBED_operation_done (peer1.operation); - result = PEER1_CREATED; - peer1.operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL); - break; - - case CONTROLLER2_UP: - if ((NULL == peer2.operation) || (NULL == peer) || (NULL != peer2.peer)) - { - GNUNET_break (0); - abort_test (); - return; - } - peer2.peer = peer; - GNUNET_TESTBED_operation_done (peer2.operation); - result = PEER2_CREATED; - peer2.operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL); - break; - - case CONTROLLER3_UP: - if ((NULL == peer3.operation) || (NULL == peer) || (NULL != peer3.peer)) - { - GNUNET_break (0); - abort_test (); - return; - } - peer3.peer = peer; - GNUNET_TESTBED_operation_done (peer3.operation); - result = PEER3_CREATED; - peer3.operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL); - break; - - default: - GNUNET_break (0); - abort_test (); - return; - } -} - - -/** - * Signature of the event handler function called by the - * respective event controller. - * - * @param cls closure - * @param event information about the event - */ -static void -controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) -{ - switch (event->type) - { - case GNUNET_TESTBED_ET_OPERATION_FINISHED: - if ((NULL != event->op_cls) || - (NULL != event->details.operation_finished.emsg)) - { - GNUNET_break (0); - abort_test (); - return; - } - switch (result) - { - case PEERS_STOPPED: - if (NULL != event->details.operation_finished.generic) - { - GNUNET_break (0); - abort_test (); - return; - } - if (event->op == peer1.operation) - { - GNUNET_TESTBED_operation_done (peer1.operation); - peer1.operation = NULL; - peer1.peer = NULL; - } - else if (event->op == peer2.operation) - { - GNUNET_TESTBED_operation_done (peer2.operation); - peer2.operation = NULL; - peer2.peer = NULL; - } - else if (event->op == peer3.operation) - { - GNUNET_TESTBED_operation_done (peer3.operation); - peer3.operation = NULL; - peer3.peer = NULL; - } - else - { - GNUNET_break (0); - abort_test (); - return; - } - if ((NULL == peer1.peer) && (NULL == peer2.peer) && (NULL == peer3.peer)) - { - result = SUCCESS; - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - } - break; - - case PEER1_STARTED: - if ((NULL != event->details.operation_finished.generic) || - (NULL == common_operation)) - { - GNUNET_break (0); - abort_test (); - return; - } - GNUNET_TESTBED_operation_done (common_operation); - common_operation = NULL; - result = CONTROLLER2_UP; - peer2.operation = - GNUNET_TESTBED_peer_create (controller1, neighbour1, cfg, - &peer_create_cb, NULL); - if (NULL == peer2.operation) - { - GNUNET_break (0); - abort_test (); - return; - } - break; - - case PEER2_STARTED: - if ((NULL != event->details.operation_finished.generic) || - (NULL == common_operation)) - { - GNUNET_break (0); - abort_test (); - return; - } - GNUNET_TESTBED_operation_done (common_operation); - common_operation = NULL; - result = CONTROLLER3_UP; - peer3.operation = - GNUNET_TESTBED_peer_create (controller1, neighbour2, cfg, - &peer_create_cb, NULL); - if (NULL == peer3.operation) - { - GNUNET_break (0); - abort_test (); - return; - } - break; - - default: - GNUNET_break (0); - abort_test (); - return; - } - break; - - case GNUNET_TESTBED_ET_PEER_START: - switch (result) - { - case PEER1_CREATED: - if (event->details.peer_start.host != host) - { - GNUNET_break (0); - abort_test (); - return; - } - peer1.is_running = GNUNET_YES; - GNUNET_TESTBED_operation_done (peer1.operation); - peer1.operation = NULL; - result = PEER1_STARTED; - common_operation = - GNUNET_TESTBED_controller_link (NULL, controller1, neighbour1, NULL, - GNUNET_YES); - break; - - case PEER2_CREATED: - if (event->details.peer_start.host != neighbour1) - { - GNUNET_break (0); - abort_test (); - return; - } - peer2.is_running = GNUNET_YES; - GNUNET_TESTBED_operation_done (peer2.operation); - peer2.operation = NULL; - result = PEER2_STARTED; - if (NULL != common_operation) - { - GNUNET_break (0); - abort_test (); - return; - } - common_operation = - GNUNET_TESTBED_controller_link (NULL, controller1, neighbour2, NULL, - GNUNET_YES); - if (NULL == common_operation) - { - GNUNET_break (0); - abort_test (); - return; - } - break; - - case PEER3_CREATED: - if (event->details.peer_start.host != neighbour2) - { - GNUNET_break (0); - abort_test (); - return; - } - peer3.is_running = GNUNET_YES; - GNUNET_TESTBED_operation_done (peer3.operation); - peer3.operation = NULL; - result = PEER3_STARTED; - common_operation = - GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer2.peer, - peer1.peer); - break; - - default: - GNUNET_break (0); - abort_test (); - return; - } - break; - - case GNUNET_TESTBED_ET_PEER_STOP: - if (PEERS_CONNECTED_2 != result) - { - GNUNET_break (0); - abort_test (); - return; - } - if (event->details.peer_stop.peer == peer1.peer) - { - peer1.is_running = GNUNET_NO; - GNUNET_TESTBED_operation_done (peer1.operation); - } - else if (event->details.peer_stop.peer == peer2.peer) - { - peer2.is_running = GNUNET_NO; - GNUNET_TESTBED_operation_done (peer2.operation); - } - else if (event->details.peer_stop.peer == peer3.peer) - { - peer3.is_running = GNUNET_NO; - GNUNET_TESTBED_operation_done (peer3.operation); - } - else - { - GNUNET_break (0); - abort_test (); - return; - } - if ((GNUNET_NO == peer1.is_running) && (GNUNET_NO == peer2.is_running) && - (GNUNET_NO == peer3.is_running)) - { - result = PEERS_STOPPED; - peer1.operation = GNUNET_TESTBED_peer_destroy (peer1.peer); - peer2.operation = GNUNET_TESTBED_peer_destroy (peer2.peer); - peer3.operation = GNUNET_TESTBED_peer_destroy (peer3.peer); - } - break; - - case GNUNET_TESTBED_ET_CONNECT: - if ((NULL != peer1.operation) || (NULL != peer2.operation) || - (NULL != peer3.operation) || (NULL == common_operation)) - { - GNUNET_break (0); - abort_test (); - return; - } - switch (result) - { - case PEER3_STARTED: - if ((event->details.peer_connect.peer1 != peer2.peer) || - (event->details.peer_connect.peer2 != peer1.peer)) - { - GNUNET_break (0); - abort_test (); - return; - } - GNUNET_TESTBED_operation_done (common_operation); - common_operation = NULL; - result = PEERS_1_2_CONNECTED; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected\n"); - common_operation = - GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer2.peer, - peer3.peer); - break; - - case PEERS_1_2_CONNECTED: - if ((event->details.peer_connect.peer1 != peer2.peer) || - (event->details.peer_connect.peer2 != peer3.peer)) - { - GNUNET_break (0); - abort_test (); - return; - } - GNUNET_TESTBED_operation_done (common_operation); - common_operation = NULL; - result = PEERS_2_3_CONNECTED; - delayed_connect_task = - GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (3), &do_delayed_connect, - NULL); - break; - - case PEERS_2_3_CONNECTED: - if ((event->details.peer_connect.peer1 != peer1.peer) || - (event->details.peer_connect.peer2 != peer2.peer)) - { - GNUNET_break (0); - abort_test (); - return; - } - GNUNET_TESTBED_operation_done (common_operation); - common_operation = NULL; - result = PEERS_CONNECTED_2; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected again\n"); - peer1.operation = GNUNET_TESTBED_peer_stop (NULL, peer1.peer, NULL, NULL); - peer2.operation = GNUNET_TESTBED_peer_stop (NULL, peer2.peer, NULL, NULL); - peer3.operation = GNUNET_TESTBED_peer_stop (NULL, peer3.peer, NULL, NULL); - break; - - default: - GNUNET_break (0); - abort_test (); - return; - } - break; - - default: - GNUNET_break (0); - abort_test (); - return; - } -} - - -/** - * Callback which will be called to after a host registration succeeded or failed - * - * @param cls the host which has been registered - * @param emsg the error message; NULL if host registration is successful - */ -static void -registration_comp (void *cls, const char *emsg) -{ - reg_handle = NULL; - if (cls == neighbour1) - { - neighbour2 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, cfg, 0); - if (NULL == neighbour2) - { - GNUNET_break (0); - abort_test (); - return; - } - reg_handle = - GNUNET_TESTBED_register_host (controller1, neighbour2, - &registration_comp, neighbour2); - if (NULL == reg_handle) - { - GNUNET_break (0); - abort_test (); - return; - } - return; - } - if (cls != neighbour2) - { - GNUNET_break (0); - abort_test (); - return; - } - peer1.operation = - GNUNET_TESTBED_peer_create (controller1, host, cfg, &peer_create_cb, - &peer1); - if (NULL == peer1.operation) - { - GNUNET_break (0); - abort_test (); - return; - } -} - - -/** - * Callback to signal successful startup of the controller process - * - * @param cls the closure from GNUNET_TESTBED_controller_start() - * @param cfg the configuration with which the controller has been started; - * NULL if status is not GNUNET_OK - * @param status GNUNET_OK if the startup is successful; GNUNET_SYSERR if not, - * GNUNET_TESTBED_controller_stop() shouldn't be called in this case - */ -static void -status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, - int status) -{ - uint64_t event_mask; - - if (GNUNET_OK != status) - { - GNUNET_break (0); - cp1 = NULL; - abort_test (); - return; - } - event_mask = 0; - event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START); - event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP); - event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); - event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); - switch (result) - { - case INIT: - controller1 = - GNUNET_TESTBED_controller_connect (host, event_mask, - &controller_cb, NULL); - if (NULL == controller1) - { - GNUNET_break (0); - abort_test (); - return; - } - result = CONTROLLER1_UP; - neighbour1 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, cfg, 0); - if (NULL == neighbour1) - { - GNUNET_break (0); - abort_test (); - return; - } - reg_handle = - GNUNET_TESTBED_register_host (controller1, neighbour1, - &registration_comp, neighbour1); - if (NULL == reg_handle) - { - GNUNET_break (0); - abort_test (); - return; - } - break; - - default: - GNUNET_break (0); - abort_test (); - return; - } -} - - -/** - * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to - * inform whether the given host is habitable or not. The Handle returned by - * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called - * - * @param cls NULL - * @param host the host whose status is being reported; will be NULL if the host - * given to GNUNET_TESTBED_is_host_habitable() is NULL - * @param status #GNUNET_YES if it is habitable; #GNUNET_NO if not - */ -static void -host_habitable_cb (void *cls, - const struct GNUNET_TESTBED_Host *_host, - int status) -{ - hc_handle = NULL; - if (GNUNET_NO == status) - { - (void) printf ("%s", - "Unable to run the test as this system is not configured " - "to use password less SSH logins to localhost.\n" - "Skipping test\n"); - GNUNET_SCHEDULER_cancel (abort_task); - abort_task = NULL; - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - result = SKIP; - return; - } - cp1 = - GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb, NULL); -} - - -/** - * Main run function. - * - * @param cls NULL - * @param args arguments passed to GNUNET_PROGRAM_run - * @param cfgfile the path to configuration file - * @param cfg the configuration file handle - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - cfg = GNUNET_CONFIGURATION_dup (config); - host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); - if (NULL == host) - { - GNUNET_break (0); - abort_test (); - return; - } - if (NULL == - (hc_handle = - GNUNET_TESTBED_is_host_habitable (host, config, &host_habitable_cb, - NULL))) - { - GNUNET_TESTBED_host_destroy (host); - host = NULL; - (void) printf ("%s", - "Unable to run the test as this system is not configured " - "to use password less SSH logins to localhost.\n" - "Skipping test\n"); - result = SKIP; - return; - } - abort_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort, - NULL); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - char *const argv2[] = { "test_testbed_api_3peers_3controllers", - "-c", "test_testbed_api.conf", - NULL }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - int ret; - - result = INIT; - ret = - GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, - "test_testbed_api_3peers_3controllers", "nohelp", - options, &run, NULL); - if (GNUNET_OK != ret) - return 1; - switch (result) - { - case SUCCESS: - return 0; - - case SKIP: - return 77; /* Mark test as skipped */ - - default: - return 1; - } -} - - -/* end of test_testbed_api_3peers_3controllers.c */ diff --git a/src/testbed/test_testbed_api_barriers.c b/src/testbed/test_testbed_api_barriers.c @@ -1,234 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/test_testbed_api_barriers.c - * @brief testcase binary for testing testbed barriers API - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" -#include "test_testbed_api_barriers.h" - - -/** - * logging short hand - */ -#define LOG(type, ...) \ - GNUNET_log (type, __VA_ARGS__); - -/** - * Number of peers we start in this test case - */ -#define NUM_PEERS 3 - - -/** - * Our barrier - */ -struct GNUNET_TESTBED_Barrier *barrier; - -/** - * Identifier for the shutdown task - */ -static struct GNUNET_SCHEDULER_Task *timeout_task; - -/** - * Result of this test case - */ -static int result; - - -/** - * Handle SIGINT and SIGTERM - */ -static void -shutdown_handler (void *cls) -{ - if (NULL != timeout_task) - { - GNUNET_SCHEDULER_cancel (timeout_task); - timeout_task = NULL; - } -} - - -/** - * Shutdown this test case when it takes too long - * - * @param cls NULL - */ -static void -do_timeout (void *cls) -{ - timeout_task = NULL; - if (barrier != NULL) - GNUNET_TESTBED_barrier_cancel (barrier); - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Functions of this type are to be given as callback argument to - * GNUNET_TESTBED_barrier_init(). The callback will be called when status - * information is available for the barrier. - * - * @param cls the closure given to GNUNET_TESTBED_barrier_init() - * @param name the name of the barrier - * @param barrier the barrier handle - * @param status status of the barrier; #GNUNET_OK if the barrier is crossed; - * #GNUNET_SYSERR upon error - * @param emsg if the status were to be #GNUNET_SYSERR, this parameter has the - * error message - */ -static void -barrier_cb (void *cls, - const char *name, - struct GNUNET_TESTBED_Barrier *_barrier, - enum GNUNET_TESTBED_BarrierStatus status, - const char *emsg) -{ - static enum GNUNET_TESTBED_BarrierStatus old_status; - - GNUNET_assert (NULL == cls); - GNUNET_assert (_barrier == barrier); - switch (status) - { - case GNUNET_TESTBED_BARRIERSTATUS_INITIALISED: - LOG (GNUNET_ERROR_TYPE_INFO, - "Barrier initialised\n"); - old_status = status; - return; - - case GNUNET_TESTBED_BARRIERSTATUS_ERROR: - LOG (GNUNET_ERROR_TYPE_ERROR, - "Barrier initialisation failed: %s", - (NULL == emsg) ? "unknown reason" : emsg); - break; - - case GNUNET_TESTBED_BARRIERSTATUS_CROSSED: - LOG (GNUNET_ERROR_TYPE_INFO, - "Barrier crossed\n"); - if (old_status == GNUNET_TESTBED_BARRIERSTATUS_INITIALISED) - result = GNUNET_OK; - break; - - default: - GNUNET_assert (0); - return; - } - barrier = NULL; - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Signature of a main function for a testcase. - * - * @param cls closure - * @param h the run handle - * @param num_peers number of peers in 'peers' - * @param peers_ handle to peers run in the testbed - * @param links_succeeded the number of overlay link connection attempts that - * succeeded - * @param links_failed the number of overlay link connection attempts that - * failed - */ -static void -test_master (void *cls, - struct GNUNET_TESTBED_RunHandle *h, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers_, - unsigned int links_succeeded, - unsigned int links_failed) -{ - struct GNUNET_TESTBED_Controller *c; - - GNUNET_assert (NULL == cls); - if (NULL == peers_) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failing test due to timeout\n"); - return; - } - GNUNET_assert (NUM_PEERS == num_peers); - c = GNUNET_TESTBED_run_get_controller_handle (h); - barrier = GNUNET_TESTBED_barrier_init (c, - TEST_BARRIER_NAME, - 100, - &barrier_cb, - NULL); - timeout_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, - 10 * (NUM_PEERS + 1)), - &do_timeout, NULL); - GNUNET_SCHEDULER_add_shutdown (&shutdown_handler, NULL); -} - - -#ifndef PATH_MAX -/** - * Assumed maximum path length (for the log file name). - */ -#define PATH_MAX 4096 -#endif - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - struct GNUNET_CONFIGURATION_Handle *cfg; - char pwd[PATH_MAX]; - char *binary; - uint64_t event_mask; - - result = GNUNET_SYSERR; - event_mask = 0; - cfg = GNUNET_CONFIGURATION_create (); - GNUNET_assert (GNUNET_YES == - GNUNET_CONFIGURATION_parse (cfg, - "test_testbed_api_barriers.conf.in")); - if (NULL == getcwd (pwd, PATH_MAX)) - return 1; - GNUNET_assert (0 < GNUNET_asprintf (&binary, "%s/%s", pwd, - "gnunet-service-test-barriers")); - GNUNET_CONFIGURATION_set_value_string (cfg, "test-barriers", "BINARY", - binary); - GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_write - (cfg, "test_testbed_api_barriers.conf")); - GNUNET_CONFIGURATION_destroy (cfg); - cfg = NULL; - GNUNET_free (binary); - binary = NULL; - (void) GNUNET_TESTBED_test_run ("test_testbed_api_barriers", - "test_testbed_api_barriers.conf", NUM_PEERS, - event_mask, NULL, NULL, - &test_master, NULL); - (void) unlink ("test_testbed_api_barriers.conf"); - if (GNUNET_OK != result) - return 1; - return 0; -} diff --git a/src/testbed/test_testbed_api_barriers.conf.in b/src/testbed/test_testbed_api_barriers.conf.in @@ -1,103 +0,0 @@ -[testbed] -START_ON_DEMAND = NO -PORT = 12113 -ACCEPT_FROM = 127.0.0.1; -HOSTNAME = localhost -TOPOLOGY = RANDOM -#PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args - -[arm] -PORT = 12366 - -[test-barriers] -START_ON_DEMAND = NO -PORT = 12114 -BINARY = /will/be/overwritten/in/test_testbed_api_barriers/ -IMMEDIATE_START = YES - -[fs] -START_ON_DEMAND = NO -IMMEDIATE_START = NO - -[resolver] -HOSTNAME = localhost -START_ON_DEMAND = NO - -[cadet] -START_ON_DEMAND = NO -IMMEDIATE_START = NO - -[dht] -START_ON_DEMAND = NO -IMMEDIATE_START = NO - -[dhtcache] -QUOTA = 1 MB -DATABASE = heap - -[transport] -PLUGINS = udp -ACCEPT_FROM6 = ::1; -ACCEPT_FROM = 127.0.0.1; -NEIGHBOUR_LIMIT = 50 -PORT = 12365 -IMMEDIATE_START = YES - -[ats] -WAN_QUOTA_OUT = 3932160 -WAN_QUOTA_IN = 3932160 - -[core] -PORT = 12092 -START_ON_DEMAND = YES -IMMEDIATE_START = YES -USE_EPHEMERAL_KEYS = NO - -[transport-udp] -TIMEOUT = 300 s -PORT = 12368 - -[PATHS] -GNUNET_TEST_HOME = $GNUNET_TMP/test-testbed/ - -[dns] -START_ON_DEMAND = NO -IMMEDIATE_START = NO - -[nse] -START_ON_DEMAND = NO -IMMEDIATE_START = NO - -[vpn] -START_ON_DEMAND = NO -IMMEDIATE_START = NO - -[nat] -RETURN_LOCAL_ADDRESSES = YES -IMMEDIATE_START = NO - -[gns-helper-service-w32] -START_ON_DEMAND = NO - -[consensus] -START_ON_DEMAND = NO -IMMEDIATE_START = NO - -[gns] -START_ON_DEMAND = NO -IMMEDIATE_START = NO - -[statistics] -START_ON_DEMAND = NO -IMMEDIATE_START = NO - -[peerinfo] -NO_IO = YES - -[set] -START_ON_DEMAND = NO -IMMEDIATE_START = NO - -[revocation] -START_ON_DEMAND = NO -IMMEDIATE_START = NO diff --git a/src/testbed/test_testbed_api_barriers.h b/src/testbed/test_testbed_api_barriers.h @@ -1,4 +0,0 @@ -/** - * The name to use for the barrier in the test cases - */ -#define TEST_BARRIER_NAME "test_barrier" diff --git a/src/testbed/test_testbed_api_controllerlink.c b/src/testbed/test_testbed_api_controllerlink.c @@ -1,881 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/test_testbed_api_controllerlink.c - * @brief testcase for testing controller to subcontroller linking - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - - -/** - * The controller architecture we try to achieve in this test case: - * - * Master Controller - * // \\ - * // \\ - * Slave Controller 1---------Slave Controller 3 - * || - * || - * Slave Controller 2 - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testing_lib.h" -#include "gnunet_testbed_service.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__) - -/** - * Different stages in testing - */ -enum Stage -{ - /** - * Initial stage - */ - INIT, - - /** - * Master controller has started - */ - MASTER_STARTED, - - /** - * A peer has been created on master - */ - MASTER_PEER_CREATE_SUCCESS, - - /** - * Peer on master controller has been started successfully. - */ - MASTER_PEER_START_SUCCESS, - - /** - * The first slave has been registered at master controller - */ - SLAVE1_REGISTERED, - - /** - * The second slave has been registered at the master controller - */ - SLAVE2_REGISTERED, - - /** - * Link from master to slave 1 has been successfully created - */ - SLAVE1_LINK_SUCCESS, - - /** - * Peer create on slave 1 successful - */ - SLAVE1_PEER_CREATE_SUCCESS, - - /** - * Peer startup on slave 1 successful - */ - SLAVE1_PEER_START_SUCCESS, - - /** - * Link from slave 1 to slave 2 has been successfully created. - */ - SLAVE2_LINK_SUCCESS, - - /** - * Peer create on slave 2 successful - */ - SLAVE2_PEER_CREATE_SUCCESS, - - /** - * Peer on slave 1 successfully stopped - */ - SLAVE1_PEER_STOP_SUCCESS, - - /** - * Peer startup on slave 2 successful - */ - SLAVE2_PEER_START_SUCCESS, - - /** - * Try to connect peers on master and slave 2. - */ - MASTER_SLAVE2_PEERS_CONNECTED, - - /** - * Slave 3 has successfully registered - */ - SLAVE3_REGISTERED, - - /** - * Slave 3 has successfully started - */ - SLAVE3_STARTED, - - /** - * Peer created on slave 3 - */ - SLAVE3_PEER_CREATE_SUCCESS, - - /** - * Peer started at slave 3 - */ - SLAVE3_PEER_START_SUCCESS, - - /** - * Try to connect peers on slave2 and slave3 - */ - SLAVE2_SLAVE3_PEERS_CONNECTED, - - /** - * Peer on slave 2 successfully stopped - */ - SLAVE2_PEER_STOP_SUCCESS, - - /** - * Peer destroy on slave 1 successful - */ - SLAVE1_PEER_DESTROY_SUCCESS, - - /** - * Peer destroy on slave 2 successful - */ - SLAVE2_PEER_DESTROY_SUCCESS, - - /** - * The configuration of slave 3 is acquired - */ - SLAVE3_GET_CONFIG_SUCCESS, - - /** - * Slave 1 has linked to slave 3; - */ - SLAVE3_LINK_SUCCESS, - - /** - * Master peer destroyed. Destroy slave 3 peer - */ - MASTER_PEER_DESTROY_SUCCESS, - - /** - * Slave 3 peer destroyed. Mark test as success - */ - SUCCESS, - - /** - * Marks test as skipped - */ - SKIP -}; - -/** - * Host for running master controller - */ -static struct GNUNET_TESTBED_Host *host; - -/** - * The master controller process - */ -static struct GNUNET_TESTBED_ControllerProc *cp; - -/** - * Handle to master controller - */ -static struct GNUNET_TESTBED_Controller *mc; - -/** - * Slave host for running slave controller - */ -static struct GNUNET_TESTBED_Host *slave; - -/** - * Another slave host for running another slave controller - */ -static struct GNUNET_TESTBED_Host *slave2; - -/** - * Host for slave 3 - */ -static struct GNUNET_TESTBED_Host *slave3; - -/** - * Slave host registration handle - */ -static struct GNUNET_TESTBED_HostRegistrationHandle *rh; - -/** - * Handle to global configuration - */ -static struct GNUNET_CONFIGURATION_Handle *cfg; - -/** - * Configuration of slave 3 controller - */ -static struct GNUNET_CONFIGURATION_Handle *cfg3; - -/** - * Abort task - */ -static struct GNUNET_SCHEDULER_Task *abort_task; - -/** - * Operation handle for linking controllers - */ -static struct GNUNET_TESTBED_Operation *op; - -/** - * Handle to peer started at slave 1 - */ -static struct GNUNET_TESTBED_Peer *slave1_peer; - -/** - * Handle to peer started at slave 2 - */ -static struct GNUNET_TESTBED_Peer *slave2_peer; - -/** - * Handle to peer started at slave 2 - */ -static struct GNUNET_TESTBED_Peer *slave3_peer; - -/** - * Handle to a peer started at master controller - */ -static struct GNUNET_TESTBED_Peer *master_peer; - -/** - * The handle for whether a host is habitable or not - */ -static struct GNUNET_TESTBED_HostHabitableCheckHandle *hc_handle; - -/** - * The task handle for the delay task - */ -static struct GNUNET_SCHEDULER_Task *delay_task_id; - -/** - * Event mask - */ -static uint64_t event_mask; - -/** - * Global testing status - */ -static enum Stage result; - -/** - * shortcut to exit during failure - */ -#define FAIL_TEST(cond) \ - do \ - { \ - if (! (cond)) \ - { \ - GNUNET_break (0); \ - if (NULL != abort_task) \ - GNUNET_SCHEDULER_cancel (abort_task); \ - abort_task = NULL; \ - GNUNET_SCHEDULER_shutdown (); \ - return; \ - } \ - } while (0) - - -/** - * Shutdown nicely - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - if (NULL != abort_task) - GNUNET_SCHEDULER_cancel (abort_task); - if (NULL != delay_task_id) - { - GNUNET_SCHEDULER_cancel (delay_task_id); - delay_task_id = NULL; - } - if (NULL != hc_handle) - GNUNET_TESTBED_is_host_habitable_cancel (hc_handle); - if (NULL != op) - { - GNUNET_TESTBED_operation_done (op); - op = NULL; - } - if (NULL != mc) - GNUNET_TESTBED_controller_disconnect (mc); - if (NULL != cp) - GNUNET_TESTBED_controller_stop (cp); - if (NULL != slave3) - GNUNET_TESTBED_host_destroy (slave3); - if (NULL != slave2) - GNUNET_TESTBED_host_destroy (slave2); - if (NULL != slave) - GNUNET_TESTBED_host_destroy (slave); - if (NULL != host) - GNUNET_TESTBED_host_destroy (host); - if (NULL != cfg) - GNUNET_CONFIGURATION_destroy (cfg); - if (NULL != cfg3) - GNUNET_CONFIGURATION_destroy (cfg3); - if (NULL != rh) - GNUNET_TESTBED_cancel_registration (rh); -} - - -/** - * abort task to run on test timed out - * - * @param cls NULL - */ -static void -do_abort (void *cls) -{ - LOG (GNUNET_ERROR_TYPE_WARNING, "Aborting in stage %d\n", result); - abort_task = NULL; - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Calls abort now - * - * @param - * @return - */ -static void -do_abort_now (void *cls) -{ - if (NULL != abort_task) - GNUNET_SCHEDULER_cancel (abort_task); - abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); -} - - -/** - * Callback which will be called to after a host registration succeeded or failed - * - * @param cls the host which has been registered - * @param emsg the error message; NULL if host registration is successful - */ -static void -registration_cont (void *cls, const char *emsg); - - -/** - * Task for inserting delay between tests - * - * @param - * @return - */ -static void -delay_task (void *cls) -{ - delay_task_id = NULL; - switch (result) - { - case SLAVE2_PEER_CREATE_SUCCESS: - op = GNUNET_TESTBED_peer_stop (NULL, slave1_peer, NULL, NULL); - FAIL_TEST (NULL != op); - break; - - case MASTER_SLAVE2_PEERS_CONNECTED: - slave3 = GNUNET_TESTBED_host_create_with_id (3, "127.0.0.1", NULL, cfg, 0); - rh = GNUNET_TESTBED_register_host (mc, slave3, &registration_cont, NULL); - break; - - case SLAVE2_SLAVE3_PEERS_CONNECTED: - op = GNUNET_TESTBED_peer_stop (NULL, slave2_peer, NULL, NULL); - FAIL_TEST (NULL != op); - break; - - default: - FAIL_TEST (0); - } -} - - -/** - * Functions of this signature are called when a peer has been successfully - * created - * - * @param cls the closure from GNUNET_TESTBED_peer_create() - * @param peer the handle for the created peer; NULL on any error during - * creation - * @param emsg NULL if peer is not NULL; else MAY contain the error description - */ -static void -peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) -{ - FAIL_TEST (NULL != peer); - FAIL_TEST (NULL == emsg); - switch (result) - { - case MASTER_STARTED: - result = MASTER_PEER_CREATE_SUCCESS; - master_peer = peer; - GNUNET_TESTBED_operation_done (op); - op = GNUNET_TESTBED_peer_start (NULL, master_peer, NULL, NULL); - break; - - case SLAVE1_LINK_SUCCESS: - result = SLAVE1_PEER_CREATE_SUCCESS; - slave1_peer = peer; - GNUNET_TESTBED_operation_done (op); - op = GNUNET_TESTBED_peer_start (NULL, slave1_peer, NULL, NULL); - break; - - case SLAVE2_LINK_SUCCESS: - result = SLAVE2_PEER_CREATE_SUCCESS; - slave2_peer = peer; - GNUNET_TESTBED_operation_done (op); - op = NULL; - delay_task_id = GNUNET_SCHEDULER_add_delayed ( - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), - &delay_task, - NULL); - return; - - case SLAVE3_STARTED: - result = SLAVE3_PEER_CREATE_SUCCESS; - slave3_peer = peer; - GNUNET_TESTBED_operation_done (op); - op = GNUNET_TESTBED_peer_start (NULL, slave3_peer, NULL, NULL); - break; - - default: - FAIL_TEST (0); - } - FAIL_TEST (NULL != op); -} - - -/** - * Checks the event if it is an operation finished event and if indicates a - * successful completion of operation - * - * @param event the event information to check - */ -static void -check_operation_success (const struct GNUNET_TESTBED_EventInformation *event) -{ - FAIL_TEST (NULL != event); - FAIL_TEST (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type); - FAIL_TEST (event->op == op); - FAIL_TEST (NULL == event->op_cls); - FAIL_TEST (NULL == event->details.operation_finished.emsg); - FAIL_TEST (NULL == event->details.operation_finished.generic); -} - - -/** - * Signature of the event handler function called by the - * respective event controller. - * - * @param cls closure - * @param event information about the event - */ -static void -controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) -{ - switch (result) - { - case SLAVE2_REGISTERED: - check_operation_success (event); - GNUNET_TESTBED_operation_done (op); - op = NULL; - result = SLAVE1_LINK_SUCCESS; - FAIL_TEST (NULL != slave2); - FAIL_TEST (NULL != slave); - op = GNUNET_TESTBED_peer_create (mc, slave, cfg, peer_create_cb, NULL); - FAIL_TEST (NULL != op); - break; - - case SLAVE1_PEER_START_SUCCESS: - check_operation_success (event); - GNUNET_TESTBED_operation_done (op); - result = SLAVE2_LINK_SUCCESS; - op = GNUNET_TESTBED_peer_create (mc, slave2, cfg, peer_create_cb, NULL); - FAIL_TEST (NULL != op); - break; - - case MASTER_PEER_CREATE_SUCCESS: - FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type); - FAIL_TEST (event->details.peer_start.host == host); - FAIL_TEST (event->details.peer_start.peer == master_peer); - GNUNET_TESTBED_operation_done (op); - op = NULL; - result = MASTER_PEER_START_SUCCESS; - slave = GNUNET_TESTBED_host_create_with_id (1, "127.0.0.1", NULL, cfg, 0); - FAIL_TEST (NULL != slave); - rh = GNUNET_TESTBED_register_host (mc, slave, &registration_cont, NULL); - FAIL_TEST (NULL != rh); - break; - - case SLAVE1_PEER_CREATE_SUCCESS: - FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type); - FAIL_TEST (event->details.peer_start.host == slave); - FAIL_TEST (event->details.peer_start.peer == slave1_peer); - GNUNET_TESTBED_operation_done (op); - result = SLAVE1_PEER_START_SUCCESS; - op = GNUNET_TESTBED_controller_link (NULL, mc, slave2, slave, GNUNET_YES); - break; - - case SLAVE2_PEER_CREATE_SUCCESS: - FAIL_TEST (GNUNET_TESTBED_ET_PEER_STOP == event->type); - FAIL_TEST (event->details.peer_stop.peer == slave1_peer); - GNUNET_TESTBED_operation_done (op); - result = SLAVE1_PEER_STOP_SUCCESS; - op = GNUNET_TESTBED_peer_start (NULL, slave2_peer, NULL, NULL); - FAIL_TEST (NULL != op); - break; - - case SLAVE3_PEER_CREATE_SUCCESS: - FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type); - FAIL_TEST (event->details.peer_start.host == slave3); - FAIL_TEST (event->details.peer_start.peer == slave3_peer); - GNUNET_TESTBED_operation_done (op); - result = SLAVE3_PEER_START_SUCCESS; - sleep (1); - LOG_DEBUG ("**************************************\n"); - op = - GNUNET_TESTBED_overlay_connect (mc, NULL, NULL, slave2_peer, slave3_peer); - FAIL_TEST (NULL != op); - break; - - case SLAVE3_PEER_START_SUCCESS: - FAIL_TEST (NULL != event); - FAIL_TEST (GNUNET_TESTBED_ET_CONNECT == event->type); - FAIL_TEST (event->details.peer_connect.peer1 == slave2_peer); - FAIL_TEST (event->details.peer_connect.peer2 == slave3_peer); - result = SLAVE2_SLAVE3_PEERS_CONNECTED; - GNUNET_TESTBED_operation_done (op); - op = NULL; - delay_task_id = GNUNET_SCHEDULER_add_delayed ( - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), - &delay_task, - NULL); - break; - - case SLAVE1_PEER_STOP_SUCCESS: - FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type); - FAIL_TEST (event->details.peer_start.host == slave2); - FAIL_TEST (event->details.peer_start.peer == slave2_peer); - GNUNET_TESTBED_operation_done (op); - result = SLAVE2_PEER_START_SUCCESS; - op = - GNUNET_TESTBED_overlay_connect (mc, NULL, NULL, master_peer, slave2_peer); - break; - - case SLAVE2_PEER_START_SUCCESS: - FAIL_TEST (NULL != event); - FAIL_TEST (GNUNET_TESTBED_ET_CONNECT == event->type); - FAIL_TEST (event->details.peer_connect.peer1 == master_peer); - FAIL_TEST (event->details.peer_connect.peer2 == slave2_peer); - result = MASTER_SLAVE2_PEERS_CONNECTED; - GNUNET_TESTBED_operation_done (op); - op = NULL; - delay_task_id = GNUNET_SCHEDULER_add_delayed ( - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), - &delay_task, - NULL); - break; - - case SLAVE2_SLAVE3_PEERS_CONNECTED: - FAIL_TEST (GNUNET_TESTBED_ET_PEER_STOP == event->type); - FAIL_TEST (event->details.peer_stop.peer == slave2_peer); - GNUNET_TESTBED_operation_done (op); - result = SLAVE2_PEER_STOP_SUCCESS; - op = GNUNET_TESTBED_peer_destroy (slave1_peer); - FAIL_TEST (NULL != op); - break; - - case SLAVE2_PEER_STOP_SUCCESS: - check_operation_success (event); - GNUNET_TESTBED_operation_done (op); - result = SLAVE1_PEER_DESTROY_SUCCESS; - op = GNUNET_TESTBED_peer_destroy (slave2_peer); - FAIL_TEST (NULL != op); - break; - - case SLAVE1_PEER_DESTROY_SUCCESS: - check_operation_success (event); - GNUNET_TESTBED_operation_done (op); - op = NULL; - result = SLAVE2_PEER_DESTROY_SUCCESS; - op = GNUNET_TESTBED_get_slave_config (NULL, mc, slave3); - FAIL_TEST (NULL != op); - break; - - case SLAVE2_PEER_DESTROY_SUCCESS: - FAIL_TEST (NULL != event); - FAIL_TEST (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type); - FAIL_TEST (event->op == op); - FAIL_TEST (NULL == event->op_cls); - FAIL_TEST (NULL == event->details.operation_finished.emsg); - cfg3 = GNUNET_CONFIGURATION_dup (event->details.operation_finished.generic); - GNUNET_TESTBED_operation_done (op); - result = SLAVE3_GET_CONFIG_SUCCESS; - op = GNUNET_TESTBED_controller_link (NULL, mc, slave3, slave, GNUNET_NO); - break; - - case SLAVE3_REGISTERED: - check_operation_success (event); - GNUNET_TESTBED_operation_done (op); - result = SLAVE3_STARTED; - op = GNUNET_TESTBED_peer_create (mc, slave3, cfg, peer_create_cb, NULL); - FAIL_TEST (NULL != op); - break; - - case SLAVE3_GET_CONFIG_SUCCESS: - result = SLAVE3_LINK_SUCCESS; - GNUNET_TESTBED_operation_done (op); - op = GNUNET_TESTBED_peer_destroy (master_peer); - break; - - case SLAVE3_LINK_SUCCESS: - check_operation_success (event); - result = MASTER_PEER_DESTROY_SUCCESS; - GNUNET_TESTBED_operation_done (op); - op = GNUNET_TESTBED_peer_destroy (slave3_peer); - break; - - case MASTER_PEER_DESTROY_SUCCESS: - result = SUCCESS; - GNUNET_TESTBED_operation_done (op); - op = NULL; - GNUNET_SCHEDULER_shutdown (); - break; - - default: - FAIL_TEST (0); - } -} - - -/** - * Callback which will be called to after a host registration succeeded or failed - * - * @param cls the host which has been registered - * @param emsg the error message; NULL if host registration is successful - */ -static void -registration_cont (void *cls, const char *emsg) -{ - rh = NULL; - switch (result) - { - case MASTER_PEER_START_SUCCESS: - FAIL_TEST (NULL == emsg); - FAIL_TEST (NULL != mc); - result = SLAVE1_REGISTERED; - slave2 = GNUNET_TESTBED_host_create_with_id (2, "127.0.0.1", NULL, cfg, 0); - FAIL_TEST (NULL != slave2); - rh = GNUNET_TESTBED_register_host (mc, slave2, &registration_cont, NULL); - FAIL_TEST (NULL != rh); - break; - - case SLAVE1_REGISTERED: - FAIL_TEST (NULL == emsg); - FAIL_TEST (NULL != mc); - result = SLAVE2_REGISTERED; - FAIL_TEST (NULL != cfg); - op = GNUNET_TESTBED_controller_link (NULL, mc, slave, NULL, GNUNET_YES); - FAIL_TEST (NULL != op); - break; - - case MASTER_SLAVE2_PEERS_CONNECTED: - FAIL_TEST (NULL == emsg); - FAIL_TEST (NULL != mc); - FAIL_TEST (NULL == op); - result = SLAVE3_REGISTERED; - op = GNUNET_TESTBED_controller_link (NULL, mc, slave3, NULL, GNUNET_YES); - FAIL_TEST (NULL != op); - break; - - default: - GNUNET_break (0); - do_abort_now (NULL); - } -} - - -/** - * Callback to signal successful startup of the controller process - * - * @param cls the closure from GNUNET_TESTBED_controller_start() - * @param cfg the configuration with which the controller has been started; - * NULL if status is not GNUNET_OK - * @param status GNUNET_OK if the startup is successful; GNUNET_SYSERR if not, - * GNUNET_TESTBED_controller_stop() shouldn't be called in this case - */ -static void -status_cb (void *cls, - const struct GNUNET_CONFIGURATION_Handle *config, - int status) -{ - switch (result) - { - case INIT: - FAIL_TEST (GNUNET_OK == status); - event_mask = 0; - event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START); - event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP); - event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); - event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); - mc = GNUNET_TESTBED_controller_connect (host, - event_mask, - &controller_cb, - NULL); - FAIL_TEST (NULL != mc); - result = MASTER_STARTED; - op = GNUNET_TESTBED_peer_create (mc, host, cfg, peer_create_cb, NULL); - FAIL_TEST (NULL != op); - break; - - default: - GNUNET_break (0); - cp = NULL; - do_abort_now (NULL); - } -} - - -/** - * Callbacks of this type are called by #GNUNET_TESTBED_is_host_habitable to - * inform whether the given host is habitable or not. The Handle returned by - * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called - * - * @param cls NULL - * @param host the host whose status is being reported; will be NULL if the host - * given to GNUNET_TESTBED_is_host_habitable() is NULL - * @param status #GNUNET_YES if it is habitable; #GNUNET_NO if not - */ -static void -host_habitable_cb (void *cls, - const struct GNUNET_TESTBED_Host *_host, - int status) -{ - hc_handle = NULL; - if (GNUNET_NO == status) - { - (void) printf ("%s", - "Unable to run the test as this system is not configured " - "to use password less SSH logins to localhost.\n" - "Skipping test\n"); - GNUNET_SCHEDULER_cancel (abort_task); - abort_task = NULL; - GNUNET_SCHEDULER_shutdown (); - result = SKIP; - return; - } - cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb, NULL); -} - - -/** - * Main run function. - * - * @param cls NULL - * @param args arguments passed to #GNUNET_PROGRAM_run() - * @param cfgfile the path to configuration file - * @param cfg the configuration file handle - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - cfg = GNUNET_CONFIGURATION_dup (config); - host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); - FAIL_TEST (NULL != host); - if (NULL == (hc_handle = GNUNET_TESTBED_is_host_habitable (host, - config, - &host_habitable_cb, - NULL))) - { - GNUNET_TESTBED_host_destroy (host); - GNUNET_CONFIGURATION_destroy (cfg); - cfg = NULL; - host = NULL; - (void) printf ("%s", - "Unable to run the test as this system is not configured " - "to use password less SSH logins to localhost.\n" - "Marking test as successful\n"); - result = SKIP; - return; - } - abort_task = GNUNET_SCHEDULER_add_delayed ( - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5), - &do_abort, - NULL); - GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - char *const argv2[] = { "test_testbed_api_controllerlink", - "-c", - "test_testbed_api.conf", - NULL }; - struct GNUNET_GETOPT_CommandLineOption options[] = - { GNUNET_GETOPT_OPTION_END }; - int ret; - - result = INIT; - ret = GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, - argv2, - "test_testbed_api_controllerlink", - "nohelp", - options, - &run, - NULL); - if (GNUNET_OK != ret) - return 1; - switch (result) - { - case SUCCESS: - return 0; - - case SKIP: - return 77; /* Mark test as skipped */ - - default: - return 1; - } -} - - -/* end of test_testbed_api_controllerlink.c */ diff --git a/src/testbed/test_testbed_api_hosts.c b/src/testbed/test_testbed_api_hosts.c @@ -1,183 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/test_testbed_api_hosts.c - * @brief tests cases for testbed_api_hosts.c - * @author Sree Harsha Totakura - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" -#include "testbed_api_hosts.h" - - -#define TIME_REL_SECS(sec) \ - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) - -/** - * configuration handle to use as template configuration while creating hosts - */ -static struct GNUNET_CONFIGURATION_Handle *cfg; - -/** - * Host we are creating and using - */ -static struct GNUNET_TESTBED_Host *host; - -/** - * An array of hosts which are loaded from a file - */ -static struct GNUNET_TESTBED_Host **hosts; - -/** - * Number of hosts in the above list - */ -static unsigned int num_hosts; - -/** - * Global test status - */ -static int status; - - -/** - * The shutdown task - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - GNUNET_TESTBED_host_destroy (host); - while (0 != num_hosts) - { - GNUNET_TESTBED_host_destroy (hosts[num_hosts - 1]); - num_hosts--; - } - GNUNET_free (hosts); - if (NULL != cfg) - { - GNUNET_CONFIGURATION_destroy (cfg); - cfg = NULL; - } -} - - -/** - * Main run function. - * - * @param cls NULL - * @param args arguments passed to GNUNET_PROGRAM_run - * @param cfgfile the path to configuration file - * @param cfg the configuration file handle - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - unsigned int cnt; - - cfg = GNUNET_CONFIGURATION_dup (config); - host = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0); - GNUNET_assert (NULL != host); - GNUNET_assert (0 != GNUNET_TESTBED_host_get_id_ (host)); - GNUNET_TESTBED_host_destroy (host); - host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); - GNUNET_assert (NULL != host); - GNUNET_assert (0 == GNUNET_TESTBED_host_get_id_ (host)); - GNUNET_assert (host == GNUNET_TESTBED_host_lookup_by_id_ (0)); - hosts = NULL; - num_hosts = GNUNET_TESTBED_hosts_load_from_file ("sample_hosts.txt", cfg, - &hosts); - GNUNET_assert (7 == num_hosts); - GNUNET_assert (NULL != hosts); - for (cnt = 0; cnt < num_hosts; cnt++) - { - if (cnt < 3) - { - GNUNET_assert (0 == strcmp ("totakura", - GNUNET_TESTBED_host_get_username_ - (hosts[cnt]))); - GNUNET_assert (NULL != GNUNET_TESTBED_host_get_hostname (hosts[cnt])); - GNUNET_assert (22 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); - } - if (3 == cnt) - { - GNUNET_assert (0 == strcmp ("totakura", - GNUNET_TESTBED_host_get_username_ - (hosts[cnt]))); - GNUNET_assert (NULL != GNUNET_TESTBED_host_get_hostname (hosts[cnt])); - GNUNET_assert (2022 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); - } - if (4 == cnt) - { - GNUNET_assert (0 == strcmp ("totakura", - GNUNET_TESTBED_host_get_username_ - (hosts[cnt]))); - GNUNET_assert (0 == strcmp ("asgard.realm", - GNUNET_TESTBED_host_get_hostname - (hosts[cnt]))); - GNUNET_assert (22 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); - } - if (5 == cnt) - { - GNUNET_assert (NULL == GNUNET_TESTBED_host_get_username_ (hosts[cnt])); - GNUNET_assert (0 == strcmp ("rivendal", - GNUNET_TESTBED_host_get_hostname - (hosts[cnt]))); - GNUNET_assert (22 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); - } - if (6 == cnt) - { - GNUNET_assert (NULL == GNUNET_TESTBED_host_get_username_ (hosts[cnt])); - GNUNET_assert (0 == strcmp ("rohan", - GNUNET_TESTBED_host_get_hostname - (hosts[cnt]))); - GNUNET_assert (561 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); - } - } - status = GNUNET_YES; - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); -} - - -int -main (int argc, char **argv) -{ - char *const argv2[] = { "test_testbed_api_hosts", - "-c", "test_testbed_api.conf", - NULL }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - status = GNUNET_SYSERR; - if (GNUNET_OK != - GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, - "test_testbed_api_hosts", "nohelp", options, &run, - NULL)) - return 1; - return (GNUNET_OK == status) ? 0 : 1; -} - - -/* end of test_testbed_api_hosts.c */ diff --git a/src/testbed/test_testbed_api_operations.c b/src/testbed/test_testbed_api_operations.c @@ -1,568 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/test_testbed_api_operations.c - * @brief tests cases for testbed_api_operations.c - * @author Sree Harsha Totakura - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "testbed_api_operations.h" - -/** - * Generic logging shortcut - */ -#define LOG(kind, ...) \ - GNUNET_log (kind, __VA_ARGS__) - -/** - * Delay to start step task - */ -#define STEP_DELAY \ - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500) - -/** - * Queue A. Initially the max active is set to 2 and then reduced to 0 - this - * should block op2 even after op1 has finished. Later the max active is set to - * 2 and this should start op2 - */ -struct OperationQueue *q1; - -/** - * Queue B. Max active set to 2 is not changed throughout the test - */ -struct OperationQueue *q2; - -/** - * This operation should go into both queues and block op2 until it is done - */ -struct GNUNET_TESTBED_Operation *op1; - -/** - * This operation should go into q1 and q2 - */ -struct GNUNET_TESTBED_Operation *op2; - -/** - * This operation should go into both queues and should consume 2 units of - * resources on both queues. Since op2 needs a resource from both queues and is - * queues before this operation, it will be blocked until op2 is released even - * though q1 has enough free resources - */ -struct GNUNET_TESTBED_Operation *op3; - -/** - * Just like op3, this operation also consumes 2 units of resources on both - * queues. Since this is queued after op3 and both queues are at max active - * 2. This will be blocked until op3 is done. - */ -struct GNUNET_TESTBED_Operation *op4; - -/** - * This operation is started after op4 is released and should consume only 1 - * resource on queue q1. It should be started along with op6 and op7 - */ -struct GNUNET_TESTBED_Operation *op5; - -/** - * This operation is started after op4 is released and should consume only 1 - * resource on q2. It should be started along with op5 and op7 - */ -struct GNUNET_TESTBED_Operation *op6; - -/** - * This operation is started after op4 is released and should consume 1 resource - * on both queues q1 and q1. It should be started along with op5 and op6. It is - * then inactivated when op6 is released. op8's start should release this - * operation implicitly. - */ -struct GNUNET_TESTBED_Operation *op7; - -/** - * This operation is started after op6 is finished in step task. It consumes 2 - * resources on both queues q1 and q2. This operation should evict op7. After - * starting, it should be made inactive, active and inactive again in the step task. - */ -struct GNUNET_TESTBED_Operation *op8; - -/** - * This operation is started after activating op8. It should consume a resource - * on queues q1 and q2. It should not be started until op8 is again made - * inactive at which point it should be released. It can be released as soon as - * it begins. - */ -struct GNUNET_TESTBED_Operation *op9; - -/** - * The delay task identifier - */ -struct GNUNET_SCHEDULER_Task *step_task; - - -/** - * Enumeration of test stages - */ -enum Test -{ - /** - * Initial stage - */ - TEST_INIT, - - /** - * op1 has been started - */ - TEST_OP1_STARTED, - - /** - * op1 has been released - */ - TEST_OP1_RELEASED, - - /** - * Temporary pause where no operations should start as we set max active in q1 - * to 0 in stage TEST_OP1_STARTED - */ - TEST_PAUSE, - - /** - * op2 has started - */ - TEST_OP2_STARTED, - - /** - * op2 released - */ - TEST_OP2_RELEASED, - - /** - * op3 has started - */ - TEST_OP3_STARTED, - - /** - * op3 has finished - */ - TEST_OP3_RELEASED, - - /** - * op4 has started - */ - TEST_OP4_STARTED, - - /** - * op4 has released - */ - TEST_OP4_RELEASED, - - /** - * op5, op6, op7 started - */ - TEST_OP5_6_7_STARTED, - - /** - * op5 has released - */ - TEST_OP5_RELEASED, - - /** - * op6 has released - */ - TEST_OP6_RELEASED, - - /** - * op8 has began waiting - */ - TEST_OP8_WAITING, - - /** - * op7 has released - */ - TEST_OP7_RELEASED, - - /** - * op8 has started - */ - TEST_OP8_STARTED, - - /** - * op8 is inactive - */ - TEST_OP8_INACTIVE_1, - - /** - * op8 is active - */ - TEST_OP8_ACTIVE, - - /** - * op8 has been released - */ - TEST_OP8_RELEASED, - - /** - * op9 has started - */ - TEST_OP9_STARTED, - - /** - * op9 has been released - */ - TEST_OP9_RELEASED -}; - -/** - * The test result - */ -enum Test result; - - -/** - * Function to call to start an operation once all - * queues the operation is part of declare that the - * operation can be activated. - */ -static void -start_cb (void *cls); - - -/** - * Function to cancel an operation (release all associated resources). This can - * be because of a call to "GNUNET_TESTBED_operation_cancel" (before the - * operation generated an event) or AFTER the operation generated an event due - * to a call to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that - * a callback to the 'OperationStart' precedes the call to 'OperationRelease'. - * Implementations of this function are expected to clean up whatever state is - * in 'cls' and release all resources associated with the operation. - */ -static void -release_cb (void *cls); - - -/** - * Task to simulate artificial delay and change the test stage - * - * @param cls NULL - */ -static void -step (void *cls) -{ - GNUNET_assert (NULL != step_task); - step_task = NULL; - switch (result) - { - case TEST_OP1_STARTED: - GNUNET_TESTBED_operation_release_ (op1); - GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 0); - op3 = GNUNET_TESTBED_operation_create_ (&op3, &start_cb, &release_cb); - GNUNET_TESTBED_operation_queue_insert2_ (q1, op3, 2); - GNUNET_TESTBED_operation_queue_insert2_ (q2, op3, 2); - GNUNET_TESTBED_operation_begin_wait_ (op3); - op4 = GNUNET_TESTBED_operation_create_ (&op4, &start_cb, &release_cb); - GNUNET_TESTBED_operation_queue_insert2_ (q1, op4, 2); - GNUNET_TESTBED_operation_queue_insert2_ (q2, op4, 2); - GNUNET_TESTBED_operation_begin_wait_ (op4); - break; - - case TEST_OP1_RELEASED: - result = TEST_PAUSE; - GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 2); - break; - - case TEST_OP2_STARTED: - GNUNET_TESTBED_operation_release_ (op2); - break; - - case TEST_OP3_STARTED: - GNUNET_TESTBED_operation_release_ (op3); - break; - - case TEST_OP4_STARTED: - GNUNET_TESTBED_operation_release_ (op4); - break; - - case TEST_OP6_RELEASED: - op8 = GNUNET_TESTBED_operation_create_ (&op8, &start_cb, &release_cb); - GNUNET_TESTBED_operation_queue_insert2_ (q1, op8, 2); - GNUNET_TESTBED_operation_queue_insert2_ (q2, op8, 2); - result = TEST_OP8_WAITING; - GNUNET_TESTBED_operation_begin_wait_ (op8); - break; - - case TEST_OP8_STARTED: - GNUNET_TESTBED_operation_inactivate_ (op8); - result = TEST_OP8_INACTIVE_1; - step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); - break; - - case TEST_OP8_INACTIVE_1: - GNUNET_TESTBED_operation_activate_ (op8); - result = TEST_OP8_ACTIVE; - op9 = GNUNET_TESTBED_operation_create_ (&op9, &start_cb, &release_cb); - GNUNET_TESTBED_operation_queue_insert2_ (q1, op9, 1); - GNUNET_TESTBED_operation_queue_insert2_ (q2, op9, 1); - GNUNET_TESTBED_operation_begin_wait_ (op9); - step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); - break; - - case TEST_OP8_ACTIVE: - GNUNET_TESTBED_operation_inactivate_ (op8); - /* op8 should be released by now due to above call */ - GNUNET_assert (TEST_OP8_RELEASED == result); - break; - - case TEST_OP9_STARTED: - GNUNET_TESTBED_operation_release_ (op9); - break; - - default: - GNUNET_assert (0); - } -} - - -/** - * Function to call to start an operation once all - * queues the operation is part of declare that the - * operation can be activated. - */ -static void -start_cb (void *cls) -{ - switch (result) - { - case TEST_INIT: - GNUNET_assert (&op1 == cls); - result = TEST_OP1_STARTED; - GNUNET_assert (NULL == step_task); - step_task = - GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); - break; - - case TEST_PAUSE: - GNUNET_assert (&op2 == cls); - result = TEST_OP2_STARTED; - GNUNET_assert (NULL == step_task); - step_task = - GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); - break; - - case TEST_OP2_RELEASED: - GNUNET_assert (&op3 == cls); - result = TEST_OP3_STARTED; - GNUNET_assert (NULL == step_task); - step_task = - GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); - break; - - case TEST_OP3_RELEASED: - GNUNET_assert (&op4 == cls); - result = TEST_OP4_STARTED; - GNUNET_assert (NULL == step_task); - step_task = - GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); - break; - - case TEST_OP4_RELEASED: - { - static int nops; - - nops++; - if (nops == 3) - { - result = TEST_OP5_6_7_STARTED; - GNUNET_TESTBED_operation_release_ (op5); - op5 = NULL; - } - } - break; - - case TEST_OP7_RELEASED: - GNUNET_assert (&op8 == cls); - result = TEST_OP8_STARTED; - step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); - break; - - case TEST_OP8_RELEASED: - GNUNET_assert (&op9 == cls); - result = TEST_OP9_STARTED; - step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); - break; - - default: - GNUNET_assert (0); - } -} - - -/** - * Function to cancel an operation (release all associated resources). This can - * be because of a call to "GNUNET_TESTBED_operation_cancel" (before the - * operation generated an event) or AFTER the operation generated an event due - * to a call to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that - * a callback to the 'OperationStart' precedes the call to 'OperationRelease'. - * Implementations of this function are expected to clean up whatever state is - * in 'cls' and release all resources associated with the operation. - */ -static void -release_cb (void *cls) -{ - switch (result) - { - case TEST_OP1_STARTED: - GNUNET_assert (&op1 == cls); - result = TEST_OP1_RELEASED; - op1 = NULL; - step_task = - GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); - break; - - case TEST_OP2_STARTED: - GNUNET_assert (&op2 == cls); - result = TEST_OP2_RELEASED; - GNUNET_assert (NULL == step_task); - break; - - case TEST_OP3_STARTED: - GNUNET_assert (&op3 == cls); - result = TEST_OP3_RELEASED; - GNUNET_assert (NULL == step_task); - break; - - case TEST_OP4_STARTED: - GNUNET_assert (&op4 == cls); - result = TEST_OP4_RELEASED; - GNUNET_assert (NULL == step_task); - op5 = GNUNET_TESTBED_operation_create_ (&op5, &start_cb, &release_cb); - GNUNET_TESTBED_operation_queue_insert2_ (q1, op5, 1); - GNUNET_TESTBED_operation_begin_wait_ (op5); - op6 = GNUNET_TESTBED_operation_create_ (&op6, &start_cb, &release_cb); - GNUNET_TESTBED_operation_queue_insert2_ (q2, op6, 1); - GNUNET_TESTBED_operation_begin_wait_ (op6); - op7 = GNUNET_TESTBED_operation_create_ (&op7, &start_cb, &release_cb); - GNUNET_TESTBED_operation_queue_insert2_ (q1, op7, 1); - GNUNET_TESTBED_operation_queue_insert2_ (q2, op7, 1); - GNUNET_TESTBED_operation_begin_wait_ (op7); - break; - - case TEST_OP5_6_7_STARTED: - result = TEST_OP5_RELEASED; - op5 = NULL; - GNUNET_TESTBED_operation_release_ (op6); - break; - - case TEST_OP5_RELEASED: - op6 = NULL; - result = TEST_OP6_RELEASED; - GNUNET_TESTBED_operation_inactivate_ (op7); - step_task = GNUNET_SCHEDULER_add_now (&step, NULL); - break; - - case TEST_OP8_WAITING: - GNUNET_assert (&op7 == cls); - op7 = NULL; - result = TEST_OP7_RELEASED; - break; - - case TEST_OP8_ACTIVE: - result = TEST_OP8_RELEASED; - op8 = NULL; - break; - - case TEST_OP9_STARTED: - GNUNET_assert (&op9 == cls); - result = TEST_OP9_RELEASED; - GNUNET_TESTBED_operation_queue_destroy_ (q1); - GNUNET_TESTBED_operation_queue_destroy_ (q2); - q1 = NULL; - q2 = NULL; - break; - - default: - GNUNET_assert (0); - } -} - - -/** - * Main run function. - * - * @param cls NULL - * @param args arguments passed to GNUNET_PROGRAM_run - * @param cfgfile the path to configuration file - * @param cfg the configuration file handle - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - q1 = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, 1); - GNUNET_assert (NULL != q1); - q2 = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, 2); - GNUNET_assert (NULL != q2); - op1 = GNUNET_TESTBED_operation_create_ (&op1, start_cb, release_cb); - GNUNET_assert (NULL != op1); - op2 = GNUNET_TESTBED_operation_create_ (&op2, start_cb, release_cb); - GNUNET_TESTBED_operation_queue_insert_ (q1, op1); - GNUNET_TESTBED_operation_queue_insert_ (q2, op1); - GNUNET_TESTBED_operation_begin_wait_ (op1); - GNUNET_TESTBED_operation_queue_insert_ (q1, op2); - GNUNET_TESTBED_operation_queue_insert_ (q2, op2); - GNUNET_TESTBED_operation_begin_wait_ (op2); - result = TEST_INIT; -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - int ret; - char *const argv2[] = - { "test_testbed_api_operations", "-c", "test_testbed_api.conf", NULL }; - struct GNUNET_GETOPT_CommandLineOption options[] = - { GNUNET_GETOPT_OPTION_END }; - - ret = - GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, - "test_testbed_api_operations", "nohelp", options, - &run, NULL); - if ((GNUNET_OK != ret) || (TEST_OP9_RELEASED != result)) - return 1; - op1 = NULL; - op2 = NULL; - op3 = NULL; - op4 = NULL; - op5 = NULL; - op6 = NULL; - op7 = NULL; - op8 = NULL; - op9 = NULL; - q1 = NULL; - q2 = NULL; - return 0; -} - - -/* end of test_testbed_api_operations.c */ diff --git a/src/testbed/test_testbed_api_peer_reconfiguration.c b/src/testbed/test_testbed_api_peer_reconfiguration.c @@ -1,194 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/test_testbed_api_peer_reconfiguration.c - * @brief testcase for testing GNUNET_TESTBED_peer_manage_service() - * implementation - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" - -/** - * Number of peers we want to start - */ -#define NUM_PEERS 1 - -/** - * The array of peers; we get them from the testbed - */ -static struct GNUNET_TESTBED_Peer **peers; - -/** - * Operation handle - */ -static struct GNUNET_TESTBED_Operation *op; - -/** - * Abort task identifier - */ -static struct GNUNET_SCHEDULER_Task *abort_task; - -/** - * States in this test - */ -enum -{ - /** - * Test has just been initialized - */ - STATE_INIT, - - /** - * Peers have been started - */ - STATE_PEER_STARTED, - - /** - * Peer has been reconfigured. Test completed successfully - */ - STATE_PEER_RECONFIGURED -} state; - -/** - * Fail testcase - */ -#define FAIL_TEST(cond, ret) do { \ - if (! (cond)) { \ - GNUNET_break (0); \ - if (NULL != abort_task) \ - GNUNET_SCHEDULER_cancel (abort_task); \ - abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); \ - ret; \ - } \ -} while (0) - - -/** - * Abort task - * - * @param cls NULL - */ -static void -do_abort (void *cls) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting\n"); - abort_task = NULL; - if (NULL != op) - { - GNUNET_TESTBED_operation_done (op); - op = NULL; - } - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Signature of the event handler function called by the - * respective event controller. - * - * @param cls closure - * @param event information about the event - */ -static void -controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) -{ - if (STATE_PEER_STARTED != state) - return; - if (GNUNET_TESTBED_ET_OPERATION_FINISHED != event->type) - { - GNUNET_TESTBED_operation_done (op); - op = NULL; - FAIL_TEST (0, return ); - } - if (NULL != event->details.operation_finished.emsg) - { - fprintf (stderr, "Operation failed: %s\n", - event->details.operation_finished.emsg); - GNUNET_TESTBED_operation_done (op); - op = NULL; - FAIL_TEST (0, return ); - } - GNUNET_TESTBED_operation_done (op); - state = STATE_PEER_RECONFIGURED; - GNUNET_SCHEDULER_cancel (abort_task); - abort_task = NULL; - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Signature of a main function for a testcase. - * - * @param cls closure - * @param h the run handle - * @param num_peers number of peers in 'peers' - * @param peers_ handle to peers run in the testbed - * @param links_succeeded the number of overlay link connection attempts that - * succeeded - * @param links_failed the number of overlay link connection attempts that - * failed - */ -static void -test_master (void *cls, - struct GNUNET_TESTBED_RunHandle *h, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers_, - unsigned int links_succeeded, - unsigned int links_failed) -{ - struct GNUNET_CONFIGURATION_Handle *cfg; - - FAIL_TEST (NUM_PEERS == num_peers, return ); - state = STATE_PEER_STARTED; - peers = peers_; - cfg = GNUNET_CONFIGURATION_create (); - FAIL_TEST (GNUNET_OK == GNUNET_CONFIGURATION_load - (cfg, "test_testbed_api_testbed_run_topologyrandom.conf"), - return ); - op = GNUNET_TESTBED_peer_update_configuration (peers[0], cfg); - GNUNET_CONFIGURATION_destroy (cfg); - FAIL_TEST (NULL != op, return ); - abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 30), - &do_abort, NULL); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - state = STATE_INIT; - (void) GNUNET_TESTBED_test_run ("test_testbed_api_peer_reconfiguration", - "test_testbed_api.conf", - NUM_PEERS, - 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED, - &controller_cb, NULL, - &test_master, NULL); - if (STATE_PEER_RECONFIGURED != state) - return 1; - return 0; -} diff --git a/src/testbed/test_testbed_api_peers_manage_services.c b/src/testbed/test_testbed_api_peers_manage_services.c @@ -1,216 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/test_testbed_api_peers_manage_services.c - * @brief testcase for testing GNUNET_TESTBED_peer_manage_service() - * implementation - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" - -/** - * Number of peers we want to start - */ -#define NUM_PEERS 2 - -/** - * The array of peers; we get them from the testbed - */ -static struct GNUNET_TESTBED_Peer **peers; - -/** - * Operation handle - */ -static struct GNUNET_TESTBED_Operation *op; - -/** - * dummy pointer - */ -static void *dummy_cls = (void *) 0xDEAD0001; - -/** - * Abort task identifier - */ -static struct GNUNET_SCHEDULER_Task *abort_task; - -/** - * States in this test - */ -enum -{ - /** - * Test has just been initialized - */ - STATE_INIT, - - /** - * Peers have been started - */ - STATE_PEERS_STARTED, - - /** - * statistics service went down - */ - STATE_SERVICE_DOWN, - - /** - * statistics service went up - */ - STATE_SERVICE_UP, - - /** - * Testing completed successfully - */ - STATE_OK -} state; - -/** - * Fail testcase - */ -#define FAIL_TEST(cond, ret) do { \ - if (! (cond)) { \ - GNUNET_break (0); \ - if (NULL != abort_task) \ - GNUNET_SCHEDULER_cancel (abort_task); \ - abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); \ - ret; \ - } \ -} while (0) - - -/** - * Abort task - * - * @param cls NULL - */ -static void -do_abort (void *cls) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting\n"); - abort_task = NULL; - if (NULL != op) - { - GNUNET_TESTBED_operation_done (op); - op = NULL; - } - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Callback to be called when an operation is completed - * - * @param cls the callback closure from functions generating an operation - * @param op the operation that has been finished - * @param emsg error message in case the operation has failed; will be NULL if - * operation has executed successfully. - */ -static void -op_comp_cb (void *cls, - struct GNUNET_TESTBED_Operation *op, - const char *emsg) -{ - FAIL_TEST (cls == dummy_cls, return ); - FAIL_TEST (NULL == emsg, return ); - GNUNET_TESTBED_operation_done (op); - op = NULL; - switch (state) - { - case STATE_PEERS_STARTED: - state = STATE_SERVICE_DOWN; - op = GNUNET_TESTBED_peer_manage_service (dummy_cls, - peers[1], - "topology", - op_comp_cb, - dummy_cls, - 0); - GNUNET_assert (NULL != op); - break; - - case STATE_SERVICE_DOWN: - state = STATE_SERVICE_UP; - GNUNET_SCHEDULER_cancel (abort_task); - abort_task = NULL; - state = STATE_OK; - GNUNET_SCHEDULER_shutdown (); - break; - - default: - FAIL_TEST (0, return ); - } -} - - -/** - * Signature of a main function for a testcase. - * - * @param cls closure - * @param h the run handle - * @param num_peers number of peers in 'peers' - * @param peers_ handle to peers run in the testbed - * @param links_succeeded the number of overlay link connection attempts that - * succeeded - * @param links_failed the number of overlay link connection attempts that - * failed - */ -static void -test_master (void *cls, - struct GNUNET_TESTBED_RunHandle *h, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers_, - unsigned int links_succeeded, - unsigned int links_failed) -{ - FAIL_TEST (NUM_PEERS == num_peers, return ); - state = STATE_PEERS_STARTED; - peers = peers_; - op = GNUNET_TESTBED_peer_manage_service (dummy_cls, - peers[1], - "topology", - op_comp_cb, - dummy_cls, - 1); - FAIL_TEST (NULL != op, return ); - abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MINUTES, 1), - &do_abort, NULL); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - state = STATE_INIT; - (void) GNUNET_TESTBED_test_run ("test_testbed_api_peers_manage_services", - "test_testbed_api.conf", - NUM_PEERS, - 1LL, NULL, NULL, - &test_master, NULL); - if (STATE_OK != state) - return 1; - return 0; -} diff --git a/src/testbed/test_testbed_api_sd.c b/src/testbed/test_testbed_api_sd.c @@ -1,111 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - - -/** - * @file testbed/testbed_api_sd.c - * @brief test cases for calculating standard deviation - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "testbed_api_sd.h" - -/** - * Global return value - */ -static int ret; - -/** - * Main run function. - * - * @param cls NULL - * @param args arguments passed to GNUNET_PROGRAM_run - * @param cfgfile the path to configuration file - * @param cfg the configuration file handle - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - struct SDHandle *h = GNUNET_TESTBED_SD_init_ (20); - int sd; - - ret = 0; - GNUNET_TESTBED_SD_add_data_ (h, 40); - if (GNUNET_SYSERR != GNUNET_TESTBED_SD_deviation_factor_ (h, 10, &sd)) - { - GNUNET_break (0); - ret = 1; - goto err; - } - GNUNET_TESTBED_SD_add_data_ (h, 30); - if (GNUNET_SYSERR == GNUNET_TESTBED_SD_deviation_factor_ (h, 80, &sd)) - { - GNUNET_break (0); - ret = 1; - goto err; - } - GNUNET_TESTBED_SD_add_data_ (h, 40); - if ((GNUNET_SYSERR == GNUNET_TESTBED_SD_deviation_factor_ (h, 30, &sd)) - || (-2 != sd)) - { - GNUNET_break (0); - ret = 1; - goto err; - } - GNUNET_TESTBED_SD_add_data_ (h, 10); - GNUNET_TESTBED_SD_add_data_ (h, 30); - if ((GNUNET_SYSERR == GNUNET_TESTBED_SD_deviation_factor_ (h, 60, &sd)) - || (3 != sd)) - { - GNUNET_break (0); - ret = 1; - goto err; - } - -err: - GNUNET_TESTBED_SD_destroy_ (h); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - int result; - - result = GNUNET_SYSERR; - result = - GNUNET_PROGRAM_run (argc, argv, - "test_testbed_api_sd", "nohelp", options, &run, NULL); - if ((GNUNET_OK != result)) - return 1; - return ret; -} - - -/* end of test_testbed_api_sd.c */ diff --git a/src/testbed/test_testbed_api_statistics.c b/src/testbed/test_testbed_api_statistics.c @@ -1,205 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/test_testbed_api_statistics.c - * @brief testcase for testing GNUNET_TESTBED_get_statistics() implementation - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" - -/** - * Number of peers we want to start - */ -#define NUM_PEERS 5 - -/** - * The array of peers; we get them from the testbed - */ -static struct GNUNET_TESTBED_Peer **peers; - -/** - * Operation handle - */ -static struct GNUNET_TESTBED_Operation *op; - -/** - * dummy pointer - */ -static void *dummy_cls = (void *) 0xDEAD0001; - -/** - * Abort task identifier - */ -static struct GNUNET_SCHEDULER_Task *abort_task; - -/** - * Global testing result - */ -static int result; - -/** - * The peers we have seen in the statistics iterator - */ -static struct GNUNET_TESTBED_Peer **seen_peers; - -/** - * Number of peers in the above array - */ -static unsigned int num_seen_peers; - - -/** - * Fail testcase - */ -#define FAIL_TEST(cond, ret) do { \ - if (! (cond)) { \ - GNUNET_break (0); \ - if (NULL != abort_task) \ - GNUNET_SCHEDULER_cancel (abort_task); \ - abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); \ - ret; \ - } \ -} while (0) - - -/** - * Abort task - * - * @param cls NULL - */ -static void -do_abort (void *cls) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test timed out -- Aborting\n"); - abort_task = NULL; - if (NULL != op) - { - GNUNET_TESTBED_operation_done (op); - op = NULL; - } - result = GNUNET_SYSERR; -} - - -/** - * Callback function to process statistic values from all peers. - * - * @param cls closure - * @param peer the peer the statistic belong to - * @param subsystem name of subsystem that created the statistic - * @param name the name of the datum - * @param value the current value - * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not - * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration - */ -static int -stats_iterator (void *cls, - const struct GNUNET_TESTBED_Peer *peer, - const char *subsystem, const char *name, uint64_t value, - int is_persistent) -{ - unsigned int cnt; - - FAIL_TEST (cls == dummy_cls, return GNUNET_SYSERR); - for (cnt = 0; cnt < num_seen_peers; cnt++) - FAIL_TEST (peer != seen_peers[cnt], return GNUNET_SYSERR); - FAIL_TEST (NULL != subsystem, return GNUNET_SYSERR); - FAIL_TEST (NULL != name, return GNUNET_SYSERR); - GNUNET_array_append (seen_peers, num_seen_peers, - (struct GNUNET_TESTBED_Peer *) peer); - return GNUNET_SYSERR; -} - - -/** - * Callback to be called when an operation is completed - * - * @param cls the callback closure from functions generating an operation - * @param op the operation that has been finished - * @param emsg error message in case the operation has failed; will be NULL if - * operation has executed successfully. - */ -static void -op_comp_cb (void *cls, - struct GNUNET_TESTBED_Operation *op, - const char *emsg) -{ - FAIL_TEST (cls == dummy_cls, return ); - result = GNUNET_OK; - GNUNET_TESTBED_operation_done (op); - op = NULL; - GNUNET_SCHEDULER_cancel (abort_task); - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Signature of a main function for a testcase. - * - * @param cls closure - * @param h the run handle - * @param num_peers number of peers in 'peers' - * @param peers_ handle to peers run in the testbed - * @param links_succeeded the number of overlay link connection attempts that - * succeeded - * @param links_failed the number of overlay link connection attempts that - * failed - */ -static void -test_master (void *cls, - struct GNUNET_TESTBED_RunHandle *h, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers_, - unsigned int links_succeeded, - unsigned int links_failed) -{ - FAIL_TEST (NUM_PEERS == num_peers, return ); - peers = peers_; - op = GNUNET_TESTBED_get_statistics (num_peers, peers, - NULL, NULL, - &stats_iterator, - &op_comp_cb, - dummy_cls); - abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MINUTES, 1), - &do_abort, NULL); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - (void) GNUNET_TESTBED_test_run ("test_testbed_api_statistics", - "test_testbed_api_statistics.conf", - NUM_PEERS, - 1LL, NULL, NULL, - &test_master, NULL); - GNUNET_free (seen_peers); - if (GNUNET_OK != result) - return 1; - return 0; -} diff --git a/src/testbed/test_testbed_api_statistics.conf b/src/testbed/test_testbed_api_statistics.conf @@ -1,9 +0,0 @@ -@INLINE@ test_testbed_api_template.conf - -[testbed] -OVERLAY_TOPOLOGY = 2D_TORUS -MAX_PARALLEL_SERVICE_CONNECTIONS = 2 - -[statistics] -START_ON_DEMAND = YES -PORT = 59530 diff --git a/src/testbed/test_testbed_api_template.conf b/src/testbed/test_testbed_api_template.conf @@ -1,49 +0,0 @@ -@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf -@INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf - -[testbed] -START_ON_DEMAND = NO -PORT = 12113 -ACCEPT_FROM = 127.0.0.1; -HOSTNAME = localhost -OVERLAY_TOPOLOGY = NONE -#PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args - -[dhtcache] -QUOTA = 1 MB -DATABASE = heap - -[transport] -PLUGINS = tcp -ACCEPT_FROM6 = ::1; -ACCEPT_FROM = 127.0.0.1; -NEIGHBOUR_LIMIT = 50 -IMMEDIATE_START = YES - -# Transport requires resolver when connecting to a peer, so enable it -[resolver] -START_ON_DEMAND = YES - -[ats] -WAN_QUOTA_OUT = 3932160 -WAN_QUOTA_IN = 3932160 - -[core] -USE_EPHEMERAL_KEYS = NO -IMMEDIATE_START = YES - -[transport-tcp] -TIMEOUT = 300 s - -[PATHS] -GNUNET_TEST_HOME = $GNUNET_TMP/test-testbed/ - -[nat] -RETURN_LOCAL_ADDRESSES = YES - -[peerinfo] -NO_IO = YES - -[rps] -START_ON_DEMAND = NO -IMMEDIATE_START = NO diff --git a/src/testbed/test_testbed_api_test.c b/src/testbed/test_testbed_api_test.c @@ -1,251 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file src/testbed/test_testbed_api_test.c - * @brief testing cases for testing high level testbed api helper functions - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" - - -/** - * Generic logging shortcut - */ -#define LOG(kind, ...) \ - GNUNET_log (kind, __VA_ARGS__) - -/** - * Number of peers we want to start - */ -#define NUM_PEERS 2 - -/** - * Array of peers - */ -static struct GNUNET_TESTBED_Peer **peers; - -/** - * Operation handle - */ -static struct GNUNET_TESTBED_Operation *op; - -/** - * Abort task identifier - */ -static struct GNUNET_SCHEDULER_Task *abort_task; - -/** - * shutdown task identifier - */ -static struct GNUNET_SCHEDULER_Task *shutdown_task; - -/** - * Testing result - */ -static int result; - - -/** - * Shutdown nicely - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - shutdown_task = NULL; - if (NULL != abort_task) - GNUNET_SCHEDULER_cancel (abort_task); - if (NULL != op) - GNUNET_TESTBED_operation_done (op); - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * shortcut to exit during failure - */ -#define FAIL_TEST(cond) do { \ - if (! (cond)) { \ - GNUNET_break (0); \ - if (NULL != abort_task) \ - GNUNET_SCHEDULER_cancel (abort_task); \ - abort_task = NULL; \ - if (NULL == shutdown_task) \ - shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); \ - return; \ - } \ -} while (0) - - -/** - * abort task to run on test timed out - * - * @param cls NULL - */ -static void -do_abort (void *cls) -{ - LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); - abort_task = NULL; - if (NULL != shutdown_task) - GNUNET_SCHEDULER_cancel (shutdown_task); - do_shutdown (cls); -} - - -/** - * Callback to be called when the requested peer information is available - * - * @param cb_cls the closure from GNUNET_TESTBED_peer_get_information() - * @param op the operation this callback corresponds to - * @param pinfo the result; will be NULL if the operation has failed - * @param emsg error message if the operation has failed; will be NULL if the - * operation is successful - */ -static void -peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_, - const struct GNUNET_TESTBED_PeerInformation *pinfo, - const char *emsg) -{ - FAIL_TEST (op == op_); - FAIL_TEST (NULL == cb_cls); - FAIL_TEST (NULL == emsg); - FAIL_TEST (GNUNET_TESTBED_PIT_IDENTITY == pinfo->pit); - FAIL_TEST (NULL != pinfo->result.id); - GNUNET_TESTBED_operation_done (op); - op = NULL; - result = GNUNET_OK; - shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); -} - - -/** - * Callback to be called when an operation is completed - * - * @param cls the callback closure from functions generating an operation - * @param op the operation that has been finished - * @param emsg error message in case the operation has failed; will be NULL if - * operation has executed successfully. - */ -static void -op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op_, const char *emsg) -{ - FAIL_TEST (NULL == cls); - FAIL_TEST (op == op_); - if (NULL != emsg) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg); - FAIL_TEST (0); - } - GNUNET_TESTBED_operation_done (op); - op = GNUNET_TESTBED_peer_get_information (peers[0], - GNUNET_TESTBED_PIT_IDENTITY, - &peerinfo_cb, NULL); -} - - -/** - * Controller event callback - * - * @param cls NULL - * @param event the controller event - */ -static void -controller_event_cb (void *cls, - const struct GNUNET_TESTBED_EventInformation *event) -{ - switch (event->type) - { - case GNUNET_TESTBED_ET_CONNECT: - FAIL_TEST (event->details.peer_connect.peer1 == peers[0]); - FAIL_TEST (event->details.peer_connect.peer2 == peers[1]); - break; - - default: - FAIL_TEST (0); - } -} - - -/** - * Signature of a main function for a testcase. - * - * @param cls closure - * @param h the run handle - * @param num_peers number of peers in 'peers' - * @param peers- handle to peers run in the testbed - * @param links_succeeded the number of overlay link connection attempts that - * succeeded - * @param links_failed the number of overlay link connection attempts that - * failed - */ -static void -test_master (void *cls, - struct GNUNET_TESTBED_RunHandle *h, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers_, - unsigned int links_succeeded, - unsigned int links_failed) -{ - unsigned int peer; - - FAIL_TEST (NULL == cls); - FAIL_TEST (NUM_PEERS == num_peers); - FAIL_TEST (NULL != peers_); - for (peer = 0; peer < num_peers; peer++) - FAIL_TEST (NULL != peers_[peer]); - peers = peers_; - op = GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peers[0], - peers[1]); - abort_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort, - NULL); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - uint64_t event_mask; - - result = GNUNET_SYSERR; - event_mask = 0; - event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); - event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); - (void) GNUNET_TESTBED_test_run ("test_testbed_api_test", - "test_testbed_api.conf", NUM_PEERS, - event_mask, &controller_event_cb, NULL, - &test_master, NULL); - if (GNUNET_OK != result) - return 1; - return 0; -} - - -/* end of test_testbed_api_test.c */ diff --git a/src/testbed/test_testbed_api_test_timeout.c b/src/testbed/test_testbed_api_test_timeout.c @@ -1,126 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file src/testbed/test_testbed_api_test.c - * @brief testing cases for testing notifications via test master callback upon - * timeout while setting up testbed using functions - * GNUNET_TESTBED_test_run() - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" - - -/** - * Generic logging shortcut - */ -#define LOG(kind, ...) \ - GNUNET_log (kind, __VA_ARGS__) - -/** - * Number of peers we want to start - */ -#define NUM_PEERS 25 - -/** - * Testing result - */ -static int result; - - -/** - * shortcut to exit during failure - */ -#define FAIL_TEST(cond) do { \ - if (! (cond)) { \ - GNUNET_break (0); \ - GNUNET_SCHEDULER_shutdown (); \ - return; \ - } \ -} while (0) - - -/** - * Controller event callback - * - * @param cls NULL - * @param event the controller event - */ -static void -controller_event_cb (void *cls, - const struct GNUNET_TESTBED_EventInformation *event) -{ - FAIL_TEST (0); -} - - -/** - * Signature of a main function for a testcase. - * - * @param cls closure - * @param h the run handle - * @param num_peers number of peers in 'peers' - * @param peers- handle to peers run in the testbed - * @param links_succeeded the number of overlay link connection attempts that - * succeeded - * @param links_failed the number of overlay link connection attempts that - * failed - */ -static void -test_master (void *cls, - struct GNUNET_TESTBED_RunHandle *h, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers_, - unsigned int links_succeeded, - unsigned int links_failed) -{ - FAIL_TEST (NULL == cls); - FAIL_TEST (0 == num_peers); - FAIL_TEST (NULL == peers_); - result = GNUNET_OK; - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - uint64_t event_mask; - - result = GNUNET_SYSERR; - event_mask = 0; - (void) GNUNET_TESTBED_test_run ("test_testbed_api_test", - "test_testbed_api_test_timeout.conf", - NUM_PEERS, - event_mask, &controller_event_cb, NULL, - &test_master, NULL); - if (GNUNET_OK != result) - return 1; - return 0; -} - - -/* end of test_testbed_api_test.c */ diff --git a/src/testbed/test_testbed_api_test_timeout.conf b/src/testbed/test_testbed_api_test_timeout.conf @@ -1,5 +0,0 @@ -@INLINE@ test_testbed_api_template.conf - -[testbed] -OVERLAY_TOPOLOGY = CLIQUE -SETUP_TIMEOUT = 2 ms diff --git a/src/testbed/test_testbed_api_testbed_run.c b/src/testbed/test_testbed_api_testbed_run.c @@ -1,242 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/test_testbed_api_testbed_run.c - * @brief Test cases for testing high-level testbed management - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" - -/** - * Number of peers we want to start - */ -#define NUM_PEERS 5 - -/** - * The array of peers; we fill this as the peers are given to us by the testbed - */ -static struct GNUNET_TESTBED_Peer *peers[NUM_PEERS]; - -/** - * Operation handle - */ -static struct GNUNET_TESTBED_Operation *op; - -/** - * Abort task identifier - */ -static struct GNUNET_SCHEDULER_Task *abort_task; - -/** - * Current peer id - */ -static unsigned int peer_id; - -/** - * Testing result - */ -static int result; - -/** - * Should we wait forever after testbed is initialized? - */ -static int wait_forever; - - -/** - * Shutdown nicely - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - if (NULL != abort_task) - GNUNET_SCHEDULER_cancel (abort_task); - GNUNET_SCHEDULER_shutdown (); /* Stop scheduler to shutdown testbed run */ -} - - -/** - * abort task to run on test timed out - * - * @param cls NULL - */ -static void -do_abort (void *cls) -{ - abort_task = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Test timed out -- Aborting\n"); - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); -} - - -/** - * Signature of a main function for a testcase. - * - * @param cls closure - * @param h the run handle - * @param num_peers number of peers in 'peers' - * @param peers_ handle to peers run in the testbed - * @param links_succeeded the number of overlay link connection attempts that - * succeeded - * @param links_failed the number of overlay link connection attempts that - * failed - */ -static void -test_master (void *cls, - struct GNUNET_TESTBED_RunHandle *h, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers_, - unsigned int links_succeeded, - unsigned int links_failed) -{ - result = GNUNET_OK; - if (GNUNET_YES == wait_forever) - { - if (NULL == abort_task) - return; /* abort already scheduled */ - GNUNET_SCHEDULER_cancel (abort_task); - abort_task = NULL; - GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); - return; - } - GNUNET_assert (NULL != peers[0]); - op = GNUNET_TESTBED_peer_stop (NULL, peers[0], NULL, NULL); - GNUNET_assert (NULL != op); -} - - -/** - * Controller event callback - * - * @param cls NULL - * @param event the controller event - */ -static void -controller_event_cb (void *cls, - const struct GNUNET_TESTBED_EventInformation *event) -{ - switch (event->type) - { - case GNUNET_TESTBED_ET_PEER_START: - GNUNET_assert (NULL == peers[peer_id]); - GNUNET_assert (NULL != event->details.peer_start.peer); - peers[peer_id++] = event->details.peer_start.peer; - break; - - case GNUNET_TESTBED_ET_PEER_STOP: - GNUNET_assert (NULL != op); - GNUNET_TESTBED_operation_done (op); - GNUNET_assert (peers[0] == event->details.peer_stop.peer); - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - break; - - default: - GNUNET_assert (0); - } -} - - -/** - * Main run function. - * - * @param cls NULL - * @param args arguments passed to GNUNET_PROGRAM_run - * @param cfgfile the path to configuration file - * @param cfg the configuration file handle - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - uint64_t event_mask; - - event_mask = 0; - event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START); - event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP); - GNUNET_TESTBED_run (NULL, config, NUM_PEERS, event_mask, - &controller_event_cb, NULL, - &test_master, NULL); - abort_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 300), - &do_abort, - NULL); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - char *argv2[] = { - "test_testbed_api_testbed_run", - "-c", NULL, - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - char *testname; - char *config_filename; - int ret; - - if (NULL == (testname = strrchr (argv[0], (int) '_'))) - { - GNUNET_break (0); - return 1; - } - testname++; - testname = GNUNET_strdup (testname); - - if (0 == strcmp ("waitforever", testname)) - wait_forever = GNUNET_YES; - if ((GNUNET_YES != wait_forever) && (0 != strcmp ("run", testname))) - { - GNUNET_asprintf (&config_filename, "test_testbed_api_testbed_run_%s.conf", - testname); - } - else - config_filename = GNUNET_strdup ("test_testbed_api.conf"); - GNUNET_free (testname); - argv2[2] = config_filename; - result = GNUNET_SYSERR; - ret = - GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, - "test_testbed_api_testbed_run", "nohelp", options, - &run, NULL); - GNUNET_free (config_filename); - if ((GNUNET_OK != ret) || (GNUNET_OK != result)) - return 1; - return 0; -} - - -/* end of test_testbed_api_testbed_run.c */ diff --git a/src/testbed/test_testbed_api_testbed_run_topology2dtorus.conf b/src/testbed/test_testbed_api_testbed_run_topology2dtorus.conf @@ -1,5 +0,0 @@ -@INLINE@ test_testbed_api_template.conf - -[testbed] -OVERLAY_TOPOLOGY = 2D_TORUS - diff --git a/src/testbed/test_testbed_api_testbed_run_topologyclique.conf b/src/testbed/test_testbed_api_testbed_run_topologyclique.conf @@ -1,4 +0,0 @@ -@INLINE@ test_testbed_api_template.conf - -[testbed] -OVERLAY_TOPOLOGY = CLIQUE diff --git a/src/testbed/test_testbed_api_testbed_run_topologyfromfile.conf b/src/testbed/test_testbed_api_testbed_run_topologyfromfile.conf @@ -1,5 +0,0 @@ -@INLINE@ test_testbed_api_template.conf - -[testbed] -OVERLAY_TOPOLOGY = FROM_FILE -OVERLAY_TOPOLOGY_FILE = overlay_topology.txt diff --git a/src/testbed/test_testbed_api_testbed_run_topologyline.conf b/src/testbed/test_testbed_api_testbed_run_topologyline.conf @@ -1,4 +0,0 @@ -@INLINE@ test_testbed_api_template.conf - -[testbed] -OVERLAY_TOPOLOGY = LINE diff --git a/src/testbed/test_testbed_api_testbed_run_topologyrandom.conf b/src/testbed/test_testbed_api_testbed_run_topologyrandom.conf @@ -1,5 +0,0 @@ -@INLINE@ test_testbed_api_template.conf - -[testbed] -OVERLAY_TOPOLOGY = RANDOM -OVERLAY_RANDOM_LINKS = 5 diff --git a/src/testbed/test_testbed_api_testbed_run_topologyring.conf b/src/testbed/test_testbed_api_testbed_run_topologyring.conf @@ -1,4 +0,0 @@ -@INLINE@ test_testbed_api_template.conf - -[testbed] -OVERLAY_TOPOLOGY = RING diff --git a/src/testbed/test_testbed_api_testbed_run_topologyscalefree.conf b/src/testbed/test_testbed_api_testbed_run_topologyscalefree.conf @@ -1,6 +0,0 @@ -@INLINE@ test_testbed_api_template.conf - -[testbed] -OVERLAY_TOPOLOGY = SCALE_FREE -SCALE_FREE_TOPOLOGY_CAP = 70 -SCALE_FREE_TOPOLOGY_M = 5 diff --git a/src/testbed/test_testbed_api_testbed_run_topologysmallworld.conf b/src/testbed/test_testbed_api_testbed_run_topologysmallworld.conf @@ -1,5 +0,0 @@ -@INLINE@ test_testbed_api_template.conf - -[testbed] -OVERLAY_TOPOLOGY = SMALL_WORLD -OVERLAY_RANDOM_LINKS = 3 diff --git a/src/testbed/test_testbed_api_testbed_run_topologysmallworldring.conf b/src/testbed/test_testbed_api_testbed_run_topologysmallworldring.conf @@ -1,5 +0,0 @@ -@INLINE@ test_testbed_api_template.conf - -[testbed] -OVERLAY_TOPOLOGY = SMALL_WORLD_RING -OVERLAY_RANDOM_LINKS = 3 diff --git a/src/testbed/test_testbed_api_testbed_run_topologystar.conf b/src/testbed/test_testbed_api_testbed_run_topologystar.conf @@ -1,4 +0,0 @@ -@INLINE@ test_testbed_api_template.conf - -[testbed] -OVERLAY_TOPOLOGY = STAR diff --git a/src/testbed/test_testbed_api_topology.c b/src/testbed/test_testbed_api_topology.c @@ -1,189 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file src/testbed/test_testbed_api_topology.c - * @brief testing cases for testing high level testbed api helper functions - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" - -/** - * Number of peers we want to start - */ -#define NUM_PEERS 10 - -/** - * Array of peers - */ -static struct GNUNET_TESTBED_Peer **peers; - -/** - * Operation handle - */ -static struct GNUNET_TESTBED_Operation *op; - -/** - * Shutdown task - */ -static struct GNUNET_SCHEDULER_Task *shutdown_task; - -/** - * Testing result - */ -static int result; - -/** - * Counter for counting overlay connections - */ -static unsigned int overlay_connects; - - -/** - * Shutdown nicely - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - shutdown_task = NULL; - if (NULL != op) - { - GNUNET_TESTBED_operation_done (op); - op = NULL; - } - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Controller event callback - * - * @param cls NULL - * @param event the controller event - */ -static void -controller_event_cb (void *cls, - const struct GNUNET_TESTBED_EventInformation *event) -{ - switch (event->type) - { - case GNUNET_TESTBED_ET_CONNECT: - overlay_connects++; - if ((NUM_PEERS) == overlay_connects) - { - result = GNUNET_OK; - GNUNET_SCHEDULER_cancel (shutdown_task); - shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - } - break; - - case GNUNET_TESTBED_ET_OPERATION_FINISHED: - GNUNET_assert (NULL != event->details.operation_finished.emsg); - break; - - default: - GNUNET_break (0); - if ((GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type) && - (NULL != event->details.operation_finished.emsg)) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "An operation failed with error: %s\n", - event->details.operation_finished.emsg); - result = GNUNET_SYSERR; - GNUNET_SCHEDULER_cancel (shutdown_task); - shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - } -} - - -/** - * Signature of a main function for a testcase. - * - * @param cls closure - * @param h the run handle - * @param num_peers number of peers in 'peers' - * @param peers_ handle to peers run in the testbed - * @param links_succeeded the number of overlay link connection attempts that - * succeeded - * @param links_failed the number of overlay link connection attempts that - * failed - */ -static void -test_master (void *cls, - struct GNUNET_TESTBED_RunHandle *h, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers_, - unsigned int links_succeeded, - unsigned int links_failed) -{ - unsigned int peer; - - GNUNET_assert (NULL == cls); - if (NULL == peers_) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test due to timeout\n"); - return; - } - GNUNET_assert (NUM_PEERS == num_peers); - for (peer = 0; peer < num_peers; peer++) - GNUNET_assert (NULL != peers_[peer]); - peers = peers_; - overlay_connects = 0; - op = GNUNET_TESTBED_overlay_configure_topology (NULL, NUM_PEERS, peers, NULL, - NULL, - NULL, - GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, - NUM_PEERS, - GNUNET_TESTBED_TOPOLOGY_OPTION_END); - GNUNET_assert (NULL != op); - shutdown_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 300), - do_shutdown, NULL); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - uint64_t event_mask; - - result = GNUNET_SYSERR; - event_mask = 0; - event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); - event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); - (void) GNUNET_TESTBED_test_run ("test_testbed_api_test", - "test_testbed_api.conf", NUM_PEERS, - event_mask, &controller_event_cb, NULL, - &test_master, NULL); - if (GNUNET_OK != result) - return 1; - return 0; -} - - -/* end of test_testbed_api_topology.c */ diff --git a/src/testbed/test_testbed_api_topology_clique.c b/src/testbed/test_testbed_api_topology_clique.c @@ -1,185 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file src/testbed/test_testbed_api_topology.c - * @brief testing cases for testing high level testbed api helper functions - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" - -/** - * Number of peers we want to start - */ -#define NUM_PEERS 10 - -/** - * Array of peers - */ -static struct GNUNET_TESTBED_Peer **peers; - -/** - * Operation handle - */ -static struct GNUNET_TESTBED_Operation *op; - -/** - * Shutdown task - */ -static struct GNUNET_SCHEDULER_Task *shutdown_task; - -/** - * Testing result - */ -static int result; - -/** - * Counter for counting overlay connections - */ -static unsigned int overlay_connects; - - -/** - * Shutdown nicely - * - * @param cls NULL - */ -static void -do_shutdown (void *cls) -{ - shutdown_task = NULL; - if (NULL != op) - { - GNUNET_TESTBED_operation_done (op); - op = NULL; - } - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Controller event callback - * - * @param cls NULL - * @param event the controller event - */ -static void -controller_event_cb (void *cls, - const struct GNUNET_TESTBED_EventInformation *event) -{ - switch (event->type) - { - case GNUNET_TESTBED_ET_CONNECT: - overlay_connects++; - if ((NUM_PEERS * (NUM_PEERS - 1)) == overlay_connects) - { - result = GNUNET_OK; - GNUNET_SCHEDULER_cancel (shutdown_task); - shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - } - break; - - case GNUNET_TESTBED_ET_OPERATION_FINISHED: - GNUNET_assert (NULL != event->details.operation_finished.emsg); - break; - - default: - GNUNET_break (0); - result = GNUNET_SYSERR; - GNUNET_SCHEDULER_cancel (shutdown_task); - shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - } -} - - -/** - * Signature of a main function for a testcase. - * - * @param cls closure - * @param h the run handle - * @param num_peers number of peers in 'peers' - * @param peers_ handle to peers run in the testbed - * @param links_succeeded the number of overlay link connection attempts that - * succeeded - * @param links_failed the number of overlay link connection attempts that - * failed - */ -static void -test_master (void *cls, - struct GNUNET_TESTBED_RunHandle *h, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers_, - unsigned int links_succeeded, - unsigned int links_failed) -{ - unsigned int peer; - - GNUNET_assert (NULL == cls); - if (NULL == peers_) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test due to timeout\n"); - return; - } - GNUNET_assert (NUM_PEERS == num_peers); - for (peer = 0; peer < num_peers; peer++) - GNUNET_assert (NULL != peers_[peer]); - peers = peers_; - overlay_connects = 0; - op = GNUNET_TESTBED_overlay_configure_topology (NULL, NUM_PEERS, peers, NULL, - NULL, - NULL, - GNUNET_TESTBED_TOPOLOGY_CLIQUE, - /* GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, */ - /* NUM_PEERS, */ - GNUNET_TESTBED_TOPOLOGY_OPTION_END); - GNUNET_assert (NULL != op); - shutdown_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 300), - do_shutdown, NULL); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - uint64_t event_mask; - - result = GNUNET_SYSERR; - event_mask = 0; - event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); - event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); - (void) GNUNET_TESTBED_test_run ("test_testbed_api_test", - "test_testbed_api.conf", NUM_PEERS, - event_mask, &controller_event_cb, NULL, - &test_master, NULL); - if (GNUNET_OK != result) - return 1; - return 0; -} - - -/* end of test_testbed_api_topology.c */ diff --git a/src/testbed/test_testbed_underlay.c b/src/testbed/test_testbed_underlay.c @@ -1,174 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/test_testbed_underlay.c - * @brief testcase binary for testing testbed underlay restrictions - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" - - -/** - * Number of peers we start in this test case - */ -#define NUM_PEERS 3 - -/** - * Result of this test case - */ -static int result; - -static struct GNUNET_TESTBED_Operation *op; - - -/** - * Shutdown testcase - * - * @param cls NULL - * @param tc scheduler task context - */ -static void -do_shutdown (void *cls) -{ - if (NULL != op) - GNUNET_TESTBED_operation_done (op); - op = NULL; -} - - -/** - * Callback to be called when an operation is completed - * - * @param cls the callback closure from functions generating an operation - * @param op the operation that has been finished - * @param emsg error message in case the operation has failed; will be NULL if - * operation has executed successfully. - */ -static void -overlay_connect_status (void *cls, - struct GNUNET_TESTBED_Operation *op_, - const char *emsg) -{ - GNUNET_assert (op_ == op); - GNUNET_TESTBED_operation_done (op); - op = NULL; - if (NULL == emsg) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Peers 0 and 2 should not get connected\n"); - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Peers 0 and 2 not connected: %s. Success!\n", emsg); - result = GNUNET_OK; - } - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Signature of a main function for a testcase. - * - * @param cls closure - * @param h the run handle - * @param num_peers number of peers in 'peers' - * @param peers_ handle to peers run in the testbed - * @param links_succeeded the number of overlay link connection attempts that - * succeeded - * @param links_failed the number of overlay link connection attempts that - * failed - */ -static void -test_master (void *cls, - struct GNUNET_TESTBED_RunHandle *h, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers_, - unsigned int links_succeeded, - unsigned int links_failed) -{ - GNUNET_assert (NULL == cls); - if (NULL == peers_) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test due to timeout\n"); - GNUNET_SCHEDULER_shutdown (); - return; - } - GNUNET_assert (NUM_PEERS == num_peers); - op = GNUNET_TESTBED_overlay_connect (NULL, - &overlay_connect_status, - NULL, - peers_[0], - peers_[2]); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply ( - GNUNET_TIME_UNIT_SECONDS, - 60), - &do_shutdown, NULL); -} - - -#ifndef PATH_MAX -/** - * Assumed maximum path length (for the log file name). - */ -#define PATH_MAX 4096 -#endif - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - struct GNUNET_CONFIGURATION_Handle *cfg; - char pwd[PATH_MAX]; - char *dbfile; - uint64_t event_mask; - - result = GNUNET_SYSERR; - event_mask = 0; - cfg = GNUNET_CONFIGURATION_create (); - GNUNET_assert (GNUNET_YES == - GNUNET_CONFIGURATION_parse (cfg, - "test_testbed_underlay.conf.in")); - if (NULL == getcwd (pwd, PATH_MAX)) - return 1; - GNUNET_assert (0 < GNUNET_asprintf (&dbfile, "%s/%s", pwd, - "test-underlay.sqlite")); - GNUNET_CONFIGURATION_set_value_string (cfg, "TESTBED-UNDERLAY", "DBFILE", - dbfile); - GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_write - (cfg, "test_testbed_underlay.conf")); - GNUNET_CONFIGURATION_destroy (cfg); - cfg = NULL; - GNUNET_free (dbfile); - dbfile = NULL; - (void) GNUNET_TESTBED_test_run ("test_testbed_underlay", - "test_testbed_underlay.conf", NUM_PEERS, - event_mask, NULL, NULL, - &test_master, NULL); - (void) unlink ("test_testbed_underlay.conf"); - if (GNUNET_OK != result) - return 1; - return 0; -} diff --git a/src/testbed/test_testbed_underlay.conf.in b/src/testbed/test_testbed_underlay.conf.in @@ -1,13 +0,0 @@ -@INLINE@ test_testbed_api_template.conf - -[testbed] -OVERLAY_TOPOLOGY = LINE -OPERATION_TIMEOUT = 5 s - -[testbed-underlay] -START_ON_DEMAND = NO -DBFILE = /will/be/overwritten/by/testcase -IMMEDIATE_START = YES - -[dv] -START_ON_DEMAND = NO diff --git a/src/testbed/testbed.conf.in b/src/testbed/testbed.conf.in @@ -1,116 +0,0 @@ -[testbed] -START_ON_DEMAND = NO -@JAVAPORT@ PORT = 2101 -HOSTNAME = localhost -BINARY = gnunet-service-testbed - -# How long should operations wait? -OPERATION_TIMEOUT = 30 s - -# Set this to the path where the testbed helper is installed. By default the -# helper binary is searched in @prefix@/lib/gnunet/libexec/ -# HELPER_BINARY_PATH = @prefix@/lib/gnunet/libexec/gnunet-helper-testbed - -# Add your local network address here. For example, if you want to run -# testbed on a group of hosts connected to network 192.168.1.0/24, then set -# ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24; -# Multiple network addresses can be given. They should be separated by `;' -ACCEPT_FROM = 127.0.0.1; -ACCEPT_FROM6 = ::1; - -UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-testbed.sock -UNIX_MATCH_UID = YES -UNIX_MATCH_GID = YES - -# How many maximum number of operations can be run in parallel. This number -# should be decreased if the system is getting overloaded and to reduce the load -# exerted by the emulation. -MAX_PARALLEL_OPERATIONS = 1000 -MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 1 - -# What topology should be generated by the helper functions GNUNET_TESTBED_run() -# and GNUNET_TESTBED_test_run(). This option has no effect if testbed is -# initialized with other functions. Valid values can be found at: -# https://gnunet.org/supported-topologies -OVERLAY_TOPOLOGY = NONE - -# Number of random links to be included to the generate the above topology. -# Note that not all topologies require this option and ignore it. Topologies -# requiring this option are RANDOM, SMALL_WORLD and SMALL_WORLD ring. -# OVERLAY_RANDOM_LINKS = - -# This option is required if the OVERLAY_TOPOLOGY is set to FROM_FILE. It is -# ignored for all other topologies. This option should contain the path to -# the file containing the topology information. The format of the file is -# presented at: https://gnunet.org/topology-file-format -# OVERLAY_TOPOLOGY_FILE = /path/to/topology-file - -# The following options are required if the OVERLAY_TOPOLOGY is set to -# SCALE_FREE. They are ignored in all other cases. -# The number of maximum peers which can connect to a peer -SCALE_FREE_TOPOLOGY_CAP = 70 -# The minimum number of peers which a peer has to connect -SCALE_FREE_TOPOLOGY_M = 5 - -# How many maximum number of handles to peers' services should be kept open at -# any time. This number also keeps a check on the number of open descriptors as -# opening a service connection results in opening a file descriptor. -MAX_PARALLEL_SERVICE_CONNECTIONS = 256 - -# Size of the internal testbed cache. It is used to cache handles to peers -# while trying to connect them. -CACHE_SIZE = 30 - -# Maximum number of file descriptors a testbed controller is permitted to keep -# open. -MAX_OPEN_FDS = 512 - -# How long should we wait for testbed to setup while using helper functions -# GNUNET_TESTBED_test_run() and GNUNET_TESTBED_run() -SETUP_TIMEOUT = 5 m - -# Where should testbed write load statistics data -# STATS_DIR = /tmp/load - -# What services should be shared among peers. -# Format is "[<service:share>] [<service:share>] ...". The shared services are -# started standalone without any other peer services or a hostkey. For this -# reason, only services which doesn't depend on other services can only be -# shared. Example: To share peerinfo among every 10 peers. The following spec -# will start 5 peerinfo services when 50 peers are started: -# -# SHARED_SERVICES = peerinfo:10 -# -# To share multiple services -# -# SHARED_SERVICES = service1:n_share1 service2:n_share2 ... -# -# Default is to share no services -SHARED_SERVICES = - - -[testbed-barrier] -START_ON_DEMAND = NO -@UNIXONLY@ PORT = 2103 -HOSTNAME = localhost -UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-testbed-barrier.sock -UNIX_MATCH_UID = YES -UNIX_MATCH_GID = YES - - -# This section is related to configuring underlay restrictions to simulate -# connectivity restrictions of NAT boxes -[testbed-underlay] -START_ON_DEMAND = NO -NOARMBIND = YES -BINARY = gnunet-daemon-testbed-underlay -# The sqlite3 database file containing information about what underlay -# restrictions to apply -# DBFILE = - -[latency-logger] -START_ON_DEMAND = NO -NOARMBIND = YES -BINARY = gnunet-daemon-latency-logger -# The sqlite3 database file where the latency values are to be stored -# DBFILE = diff --git a/src/testbed/testbed.h b/src/testbed/testbed.h @@ -1,866 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed.h - * @brief IPC messages between testing API and service ("controller") - * @author Christian Grothoff - */ - -#ifndef TESTBED_H -#define TESTBED_H - -#include "gnunet_util_lib.h" - -GNUNET_NETWORK_STRUCT_BEGIN -/** - * Initial message from a client to a testing control service. - */ -struct GNUNET_TESTBED_InitMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_INIT - */ - struct GNUNET_MessageHeader header; - - /** - * Host ID that the controller is either given (if this is the - * dominating client) or assumed to have (for peer-connections - * between controllers). A controller must check that all - * connections make consistent claims... - */ - uint32_t host_id GNUNET_PACKED; - - /** - * Event mask that specifies which events this client - * is interested in. In NBO. - */ - uint64_t event_mask GNUNET_PACKED; - - /* Followed by 0-terminated hostname of the controller */ -}; - - -/** - * Notify the service about a host that we intend to use. - */ -struct GNUNET_TESTBED_AddHostMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST - */ - struct GNUNET_MessageHeader header; - - /** - * Unique ID for the host (in NBO). - */ - uint32_t host_id GNUNET_PACKED; - - /** - * SSH port to use, 0 for default (in NBO). - */ - uint16_t ssh_port GNUNET_PACKED; - - /** - * Number of bytes in the user name that follows; - * 0 to use no user name; otherwise 'strlen (username)', - * excluding 0-termination! - */ - uint16_t username_length GNUNET_PACKED; - - /** - * Number of bytes in the host name (excluding 0-termination) that follows the - * user name; cannot be 0 - */ - uint16_t hostname_length GNUNET_PACKED; - - /** - * The length of the uncompressed configuration - */ - uint16_t config_size GNUNET_PACKED; - - /* followed by non 0-terminated user name */ - - /* followed by non 0-terminated host name */ - - /* followed by gzip compressed configuration to start or connect to a - controller on this host. While starting the controller this configuration - is used as a template */ -}; - - -/** - * Confirmation from the service that adding a host - * worked (or failed). - * FIXME: Where is this required? - */ -struct GNUNET_TESTBED_HostConfirmedMessage -{ - /** - * Type is GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS - */ - struct GNUNET_MessageHeader header; - - /** - * Unique ID for the host (in NBO). - */ - uint32_t host_id GNUNET_PACKED; - - /* followed by the 0-terminated error message (on failure) - * (typical errors include host-id already in use) */ -}; - - -/** - * Client notifies controller that it should delegate - * requests for a particular client to a particular - * sub-controller. - */ -struct GNUNET_TESTBED_ControllerLinkRequest -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS - */ - struct GNUNET_MessageHeader header; - - /** - * For which host should requests be delegated? NBO. - */ - uint32_t delegated_host_id GNUNET_PACKED; - - /** - * The id of the operation which created this message - */ - uint64_t operation_id GNUNET_PACKED; - - /** - * Which host is responsible for managing the delegation? NBO - */ - uint32_t slave_host_id GNUNET_PACKED; - - /** - * Set to 1 if the receiving controller is the master controller for - * the slave host (and thus responsible for starting it?). 0 if not - */ - uint8_t is_subordinate; -}; - - -/** - * Response message for ControllerLinkRequest message - */ -struct GNUNET_TESTBED_ControllerLinkResponse -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT - */ - struct GNUNET_MessageHeader header; - - /** - * The size of the compressed configuration. Can be ZERO if the controller is - * not started (depends on the ControllerLinkRequest). NBO. - */ - uint16_t config_size GNUNET_PACKED; - - /** - * Set to #GNUNET_YES to signify SUCCESS; #GNUNET_NO to signify failure - */ - uint16_t success GNUNET_PACKED; - - /** - * The id of the operation which created this message. NBO - */ - uint64_t operation_id GNUNET_PACKED; - - /* If controller linking is successful and configuration is present, then here - * comes the serialized gzip configuration with which the controller is - * running at the delegate host */ - - /* In case of failure, here comes the error message (without \0 termination)*/ -}; - - -/** - * Message sent from client to testing service to - * create (configure, but not start) a peer. - */ -struct GNUNET_TESTBED_PeerCreateMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER - */ - struct GNUNET_MessageHeader header; - - /** - * On which host should the peer be started? - */ - uint32_t host_id GNUNET_PACKED; - - /** - * Unique operation id - */ - uint64_t operation_id GNUNET_PACKED; - - /** - * Unique ID for the peer. - */ - uint32_t peer_id GNUNET_PACKED; - - /** - * Size of the uncompressed configuration - */ - uint16_t config_size GNUNET_PACKED; - - /* followed by serialized peer configuration; - * gzip'ed configuration file in INI format */ -}; - - -/** - * Message sent from client to testing service to - * reconfigure a (stopped) a peer. - */ -struct GNUNET_TESTBED_PeerReconfigureMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER - */ - struct GNUNET_MessageHeader header; - - /** - * Unique ID for the peer. - */ - uint32_t peer_id GNUNET_PACKED; - - /** - * Operation ID that is used to identify this operation. - */ - uint64_t operation_id GNUNET_PACKED; - - /** - * The length of the serialized configuration when uncompressed - */ - uint16_t config_size GNUNET_PACKED; - - /* followed by serialized peer configuration; - * gzip'ed configuration file in INI format */ -}; - - -/** - * Message sent from client to testing service to - * start a peer. - */ -struct GNUNET_TESTBED_PeerStartMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_START_PEER - */ - struct GNUNET_MessageHeader header; - - /** - * Unique ID for the peer. - */ - uint32_t peer_id GNUNET_PACKED; - - /** - * Operation ID that is used to identify this operation. - */ - uint64_t operation_id GNUNET_PACKED; -}; - - -/** - * Message sent from client to testing service to - * stop a peer. - */ -struct GNUNET_TESTBED_PeerStopMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER - */ - struct GNUNET_MessageHeader header; - - /** - * Unique ID for the peer. - */ - uint32_t peer_id GNUNET_PACKED; - - /** - * Operation ID that is used to identify this operation. - */ - uint64_t operation_id GNUNET_PACKED; -}; - - -/** - * Message sent from client to testing service to - * destroy a (stopped) peer. - */ -struct GNUNET_TESTBED_PeerDestroyMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER - */ - struct GNUNET_MessageHeader header; - - /** - * Unique ID for the peer. - */ - uint32_t peer_id GNUNET_PACKED; - - /** - * Operation ID that is used to identify this operation. - */ - uint64_t operation_id GNUNET_PACKED; -}; - - -/** - * Message sent from client to testing service to - * (re)configure a "physical" link between two peers. - */ -struct GNUNET_TESTBED_ConfigureUnderlayLinkMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_CONFIGURE_UNDERLAY_LINK - */ - struct GNUNET_MessageHeader header; - - /** - * 'enum GNUNET_TESTBED_ConnectOption' of the option to change - */ - int32_t connect_option GNUNET_PACKED; - - /** - * Unique ID for the first peer. - */ - uint32_t peer1 GNUNET_PACKED; - - /** - * Unique ID for the second peer. - */ - uint32_t peer2 GNUNET_PACKED; - - /** - * Operation ID that is used to identify this operation. - */ - uint64_t operation_id GNUNET_PACKED; - - /* followed by option-dependent variable-size values */ -}; - - -/** - * Message sent from client to testing service to - * connect two peers. - */ -struct GNUNET_TESTBED_OverlayConnectMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT - */ - struct GNUNET_MessageHeader header; - - /** - * Unique ID for the first peer. - */ - uint32_t peer1 GNUNET_PACKED; - - /** - * Operation ID that is used to identify this operation. - */ - uint64_t operation_id GNUNET_PACKED; - - /** - * Unique ID for the second peer. - */ - uint32_t peer2 GNUNET_PACKED; - - /** - * The ID of the host which runs peer2 - */ - uint32_t peer2_host_id GNUNET_PACKED; -}; - - -/** - * Message sent from host controller of a peer(A) to the host controller of - * another peer(B) to request B to connect to A - */ -struct GNUNET_TESTBED_RemoteOverlayConnectMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT - */ - struct GNUNET_MessageHeader header; - - /** - * The Unique ID of B - */ - uint32_t peer GNUNET_PACKED; - - /** - * The Operation ID that is used to identify this operation - */ - uint64_t operation_id GNUNET_PACKED; - - /** - * Identity of A - */ - struct GNUNET_PeerIdentity peer_identity; - - /** - * To be followed by the HELLO message of A - */ - struct GNUNET_MessageHeader hello[0]; - // FIXME: we usually do not use this gcc-hack as some - // compilers / tools really get messed up by it... -}; - - -/** - * Event notification from a controller to a client. - */ -struct GNUNET_TESTBED_PeerEventMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT - */ - struct GNUNET_MessageHeader header; - - /** - * `enum GNUNET_TESTBED_EventType` (in NBO); - * either #GNUNET_TESTBED_ET_PEER_START or #GNUNET_TESTBED_ET_PEER_STOP. - */ - int32_t event_type GNUNET_PACKED; - - /** - * Host where the peer is running. - */ - uint32_t host_id GNUNET_PACKED; - - /** - * Peer that was started or stopped. - */ - uint32_t peer_id GNUNET_PACKED; - - /** - * Operation ID that is used to identify this operation. - */ - uint64_t operation_id GNUNET_PACKED; -}; - - -/** - * Event notification from a controller to a client. - */ -struct GNUNET_TESTBED_ConnectionEventMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT - */ - struct GNUNET_MessageHeader header; - - /** - * 'enum GNUNET_TESTBED_EventType' (in NBO); - * either #GNUNET_TESTBED_ET_CONNECT or #GNUNET_TESTBED_ET_DISCONNECT. - */ - int32_t event_type GNUNET_PACKED; - - /** - * First peer. - */ - uint32_t peer1 GNUNET_PACKED; - - /** - * Second peer. - */ - uint32_t peer2 GNUNET_PACKED; - - /** - * Operation ID that is used to identify this operation. - */ - uint64_t operation_id GNUNET_PACKED; -}; - - -/** - * Event notification from a controller to a client. - */ -struct GNUNET_TESTBED_OperationFailureEventMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT - */ - struct GNUNET_MessageHeader header; - - /** - * 'enum GNUNET_TESTBED_EventType' (in NBO); - * #GNUNET_TESTBED_ET_OPERATION_FINISHED. - */ - int32_t event_type GNUNET_PACKED; - - /** - * Operation ID of the operation that created this event. - */ - uint64_t operation_id GNUNET_PACKED; - - /* followed by 0-terminated error message */ -}; - - -/** - * Event notification from a controller to a client. - */ -struct GNUNET_TESTBED_PeerCreateSuccessEventMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS - */ - struct GNUNET_MessageHeader header; - - /** - * Peer identity of the peer that was created. - */ - uint32_t peer_id GNUNET_PACKED; - - /** - * Operation ID of the operation that created this event. - */ - uint64_t operation_id GNUNET_PACKED; -}; - - -/** - * Event notification from a controller to a client for - * a generic operational success where the operation does - * not return any data. - */ -struct GNUNET_TESTBED_GenericOperationSuccessEventMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS - */ - struct GNUNET_MessageHeader header; - - /** - * 'enum GNUNET_TESTBED_EventType' (in NBO); - * #GNUNET_TESTBED_ET_OPERATION_FINISHED. - */ - int32_t event_type GNUNET_PACKED; - - /** - * Operation ID of the operation that created this event. - */ - uint64_t operation_id GNUNET_PACKED; -}; - - -/** - * Message sent from client to testing service to - * obtain the configuration of a peer. - */ -struct GNUNET_TESTBED_PeerGetConfigurationMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION - */ - struct GNUNET_MessageHeader header; - - /** - * Unique ID for the peer. - */ - uint32_t peer_id GNUNET_PACKED; - - /** - * Operation ID that is used to identify this operation. - */ - uint64_t operation_id GNUNET_PACKED; -}; - - -/** - * Peer configuration and identity reply from controller to a client. - */ -struct GNUNET_TESTBED_PeerConfigurationInformationMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION - */ - struct GNUNET_MessageHeader header; - - /** - * The id of the peer relevant to this information - */ - uint32_t peer_id GNUNET_PACKED; - - /** - * Operation ID of the operation that created this event. - */ - uint64_t operation_id GNUNET_PACKED; - - /** - * Identity of the peer. - */ - struct GNUNET_PeerIdentity peer_identity; - - /** - * The size of configuration when uncompressed - */ - uint16_t config_size GNUNET_PACKED; - - /* followed by gzip-compressed configuration of the peer */ -}; - - -/** - * Message to request configuration of a slave controller - */ -struct GNUNET_TESTBED_SlaveGetConfigurationMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION - */ - struct GNUNET_MessageHeader header; - - /** - * The id of the slave host - */ - uint32_t slave_id GNUNET_PACKED; - - /** - * Operation ID - */ - uint64_t operation_id GNUNET_PACKED; -}; - - -/** - * Reply to #GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION message - */ -struct GNUNET_TESTBED_SlaveConfiguration -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION - */ - struct GNUNET_MessageHeader header; - - /** - * The id of the host where the slave is running - */ - uint32_t slave_id GNUNET_PACKED; - - /** - * Operation ID - */ - uint64_t operation_id GNUNET_PACKED; - - /** - * The size of the configuration when uncompressed - */ - uint16_t config_size GNUNET_PACKED; - - /* followed by gzip-compressed configuration of the peer */ -}; - - -/** - * Shutdown peers message - */ -struct GNUNET_TESTBED_ShutdownPeersMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS - */ - struct GNUNET_MessageHeader header; - - /** - * Operation ID - */ - uint64_t operation_id GNUNET_PACKED; -}; - - -/** - * Message to start/stop services of a peer - */ -struct GNUNET_TESTBED_ManagePeerServiceMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS - */ - struct GNUNET_MessageHeader header; - - /** - * Unique ID of the peer whose service has to be managed. - */ - uint32_t peer_id GNUNET_PACKED; - - /** - * Operation ID - */ - uint64_t operation_id GNUNET_PACKED; - - /** - * set this to 1 to start the service; 0 to stop the service - */ - uint8_t start; - - /** - * The NULL-terminated name of the service to start/stop follows here - */ -}; - - -/** - * Message to send underlay link model of a peer. This message will be - * forwarded to the controller running the peer. - */ -struct GNUNET_TESTBED_UnderlayLinkModelMsg -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_UNDERLAYLINKMODELMSG - */ - struct GNUNET_MessageHeader header; - - /** - * The number of peer entries contained in this message - */ - uint32_t nentries GNUNET_PACKED; - - /** - * The number of link properties contained in this message - */ - uint32_t nprops GNUNET_PACKED; - - /** - * Array of ids of peers to be in the blacklist/whitelist. Each id is of type - * uint32_t. Number of ids should be equal to nentries. - */ - - /** - * Array of link properties. Each link property is to be arraged in a - * sequence of four integers of type uint32_t: peer_id, latency, loss and - * bandwidth. - */ -}; - - -/**************************************/ -/* Barriers IPC messages and protocol */ -/**************************************/ - - -/** - * The environmental variable which when available refers to the configuration - * file the local testbed controller is using - */ -#define ENV_TESTBED_CONFIG "GNUNET_TESTBED_CONTROLLER_CONFIG" - - -/** - * Message to initialise a barrier - */ -struct GNUNET_TESTBED_BarrierInit -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT - */ - struct GNUNET_MessageHeader header; - - /** - * The quorum percentage needed for crossing the barrier - */ - uint8_t quorum; - - /** - * name of the barrier. Non NULL-terminated. - */ - char name[0]; -}; - - -/** - * Message to cancel a barrier - */ -struct GNUNET_TESTBED_BarrierCancel -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL - */ - struct GNUNET_MessageHeader header; - - /** - * The barrier name. Non NULL terminated - */ - char name[0]; -}; - - -/** - * Message for signalling status changes of a barrier - */ -struct GNUNET_TESTBED_BarrierStatusMsg -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS - */ - struct GNUNET_MessageHeader header; - - /** - * status. Use enumerated values of enum BarrierStatus - */ - uint16_t status GNUNET_PACKED; - - /** - * strlen of the barrier name - */ - uint16_t name_len GNUNET_PACKED; - - /** - * the barrier name (0-terminated) concatenated with an error message - * (0-terminated) if the status were to indicate an error - */ - char data[0]; -}; - - -/** - * Message sent from peers to the testbed-barrier service to indicate that they - * have reached a barrier and are waiting for it to be crossed - */ -struct GNUNET_TESTBED_BarrierWait -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT - */ - struct GNUNET_MessageHeader header; - - /** - * The name of the barrier they have reached. Non-NULL terminated. - */ - char name[0]; -}; - - -GNUNET_NETWORK_STRUCT_END -#endif -/* end of testbed.h */ diff --git a/src/testbed/testbed_api.c b/src/testbed/testbed_api.c @@ -1,2427 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api.c - * @brief API for accessing the GNUnet testing service. - * This library is supposed to make it easier to write - * testcases and script large-scale benchmarks. - * @author Christian Grothoff - * @author Sree Harsha Totakura - */ -#include "platform.h" -#include "gnunet_testbed_service.h" -#include "gnunet_core_service.h" -#include "gnunet_constants.h" -#include "gnunet_transport_service.h" -#include "gnunet_hello_lib.h" -#include <zlib.h> - -#include "testbed.h" -#include "testbed_api.h" -#include "testbed_api_hosts.h" -#include "testbed_api_peers.h" -#include "testbed_api_operations.h" -#include "testbed_api_sd.h" - -/** - * Generic logging shorthand - */ -#define LOG(kind, ...) GNUNET_log_from (kind, "testbed-api", __VA_ARGS__) - -/** - * Debug logging - */ -#define LOG_DEBUG(...) LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) - -/** - * Relative time seconds shorthand - */ -#define TIME_REL_SECS(sec) \ - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) - - -/** - * Default server message sending retry timeout - */ -#define TIMEOUT_REL TIME_REL_SECS (1) - - -/** - * Context data for forwarded Operation - */ -struct ForwardedOperationData -{ - /** - * The callback to call when reply is available - */ - GNUNET_MQ_MessageCallback cc; - - /** - * The closure for the above callback - */ - void *cc_cls; -}; - - -/** - * Context data for get slave config operations - */ -struct GetSlaveConfigData -{ - /** - * The id of the slave controller - */ - uint32_t slave_id; -}; - - -/** - * Context data for controller link operations - */ -struct ControllerLinkData -{ - /** - * The controller link message - */ - struct GNUNET_TESTBED_ControllerLinkRequest *msg; - - /** - * The id of the host which is hosting the controller to be linked - */ - uint32_t host_id; -}; - - -/** - * Date context for OP_SHUTDOWN_PEERS operations - */ -struct ShutdownPeersData -{ - /** - * The operation completion callback to call - */ - GNUNET_TESTBED_OperationCompletionCallback cb; - - /** - * The closure for the above callback - */ - void *cb_cls; -}; - - -/** - * An entry in the stack for keeping operations which are about to expire - */ -struct ExpireOperationEntry -{ - /** - * DLL head; new entries are to be inserted here - */ - struct ExpireOperationEntry *next; - - /** - * DLL tail; entries are deleted from here - */ - struct ExpireOperationEntry *prev; - - /** - * The operation. This will be a dangling pointer when the operation is freed - */ - const struct GNUNET_TESTBED_Operation *op; -}; - - -/** - * DLL head for list of operations marked for expiry - */ -static struct ExpireOperationEntry *exop_head; - -/** - * DLL tail for list of operation marked for expiry - */ -static struct ExpireOperationEntry *exop_tail; - - -/** - * Inserts an operation into the list of operations marked for expiry - * - * @param op the operation to insert - */ -static void -exop_insert (struct GNUNET_TESTBED_Operation *op) -{ - struct ExpireOperationEntry *entry; - - entry = GNUNET_new (struct ExpireOperationEntry); - entry->op = op; - GNUNET_CONTAINER_DLL_insert_tail (exop_head, exop_tail, entry); -} - - -/** - * Checks if an operation is present in the list of operations marked for - * expiry. If the operation is found, it and the tail of operations after it - * are removed from the list. - * - * @param op the operation to check - * @return GNUNET_NO if the operation is not present in the list; GNUNET_YES if - * the operation is found in the list (the operation is then removed - * from the list -- calling this function again with the same - * paramenter will return GNUNET_NO) - */ -static int -exop_check (const struct GNUNET_TESTBED_Operation *const op) -{ - struct ExpireOperationEntry *entry; - struct ExpireOperationEntry *entry2; - int found; - - found = GNUNET_NO; - entry = exop_head; - while (NULL != entry) - { - if (op == entry->op) - { - found = GNUNET_YES; - break; - } - entry = entry->next; - } - if (GNUNET_NO == found) - return GNUNET_NO; - /* Truncate the tail */ - while (NULL != entry) - { - entry2 = entry->next; - GNUNET_CONTAINER_DLL_remove (exop_head, exop_tail, entry); - GNUNET_free (entry); - entry = entry2; - } - return GNUNET_YES; -} - - -/** - * Context information to be used while searching for operation contexts - */ -struct SearchContext -{ - /** - * The result of the search - */ - struct OperationContext *opc; - - /** - * The id of the operation context we are searching for - */ - uint64_t id; -}; - - -/** - * Search iterator for searching an operation context - * - * @param cls the search context - * @param key current key code - * @param value value in the hash map - * @return #GNUNET_YES if we should continue to iterate, - * #GNUNET_NO if not. - */ -static int -opc_search_iterator (void *cls, uint32_t key, void *value) -{ - struct SearchContext *sc = cls; - struct OperationContext *opc = value; - - GNUNET_assert (NULL != opc); - GNUNET_assert (NULL == sc->opc); - if (opc->id != sc->id) - return GNUNET_YES; - sc->opc = opc; - return GNUNET_NO; -} - - -/** - * Returns the operation context with the given id if found in the Operation - * context queues of the controller - * - * @param c the controller whose operation context map is searched - * @param id the id which has to be checked - * @return the matching operation context; NULL if no match found - */ -static struct OperationContext * -find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id) -{ - struct SearchContext sc; - - sc.id = id; - sc.opc = NULL; - GNUNET_assert (NULL != c->opc_map); - if (GNUNET_SYSERR != - GNUNET_CONTAINER_multihashmap32_get_multiple (c->opc_map, - (uint32_t) id, - &opc_search_iterator, - &sc)) - return NULL; - return sc.opc; -} - - -/** - * Inserts the given operation context into the operation context map of the - * given controller. Creates the operation context map if one does not exist - * for the controller - * - * @param c the controller - * @param opc the operation context to be inserted - */ -void -GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c, - struct OperationContext *opc) -{ - if (NULL == c->opc_map) - c->opc_map = GNUNET_CONTAINER_multihashmap32_create (256); - GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put ( - c->opc_map, - (uint32_t) opc->id, - opc, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); -} - - -/** - * Removes the given operation context from the operation context map of the - * given controller - * - * @param c the controller - * @param opc the operation context to remove - */ -void -GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c, - struct OperationContext *opc) -{ - GNUNET_assert (NULL != c->opc_map); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap32_remove (c->opc_map, - (uint32_t) opc->id, - opc)); - if ((0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map)) && - (NULL != c->opcq_empty_cb)) - c->opcq_empty_cb (c->opcq_empty_cls); -} - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message is well-formed. - * - * @param cls the controller handler - * @param msg message received - * @return #GNUNET_OK if message is well-formed - */ -static int -check_add_host_confirm (void *cls, - const struct GNUNET_TESTBED_HostConfirmedMessage *msg) -{ - const char *emsg; - uint16_t msg_size; - - msg_size = ntohs (msg->header.size) - sizeof(*msg); - if (0 == msg_size) - return GNUNET_OK; - /* We have an error message */ - emsg = (const char *) &msg[1]; - if ('\0' != emsg[msg_size - 1]) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from - * controller (testbed service) - * - * @param cls the controller handler - * @param msg message received - */ -static void -handle_add_host_confirm (void *cls, - const struct GNUNET_TESTBED_HostConfirmedMessage *msg) -{ - struct GNUNET_TESTBED_Controller *c = cls; - struct GNUNET_TESTBED_HostRegistrationHandle *rh = c->rh; - const char *emsg; - uint16_t msg_size; - - if (NULL == rh) - return; - if (GNUNET_TESTBED_host_get_id_ (rh->host) != ntohl (msg->host_id)) - { - LOG_DEBUG ("Mismatch in host id's %u, %u of host confirm msg\n", - GNUNET_TESTBED_host_get_id_ (rh->host), - ntohl (msg->host_id)); - return; - } - c->rh = NULL; - msg_size = ntohs (msg->header.size) - sizeof(*msg); - if (0 == msg_size) - { - LOG_DEBUG ("Host %u successfully registered\n", ntohl (msg->host_id)); - GNUNET_TESTBED_mark_host_registered_at_ (rh->host, c); - rh->cc (rh->cc_cls, NULL); - GNUNET_free (rh); - return; - } - /* We have an error message */ - emsg = (const char *) &msg[1]; - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Adding host %u failed with error: %s\n"), - ntohl (msg->host_id), - emsg); - rh->cc (rh->cc_cls, emsg); - GNUNET_free (rh); -} - - -/** - * Handler for forwarded operations - * - * @param cls the controller handle - * @param opc the operation context - * @param msg the message - */ -static void -handle_forwarded_operation_msg (void *cls, - struct OperationContext *opc, - const struct GNUNET_MessageHeader *msg) -{ - struct GNUNET_TESTBED_Controller *c = cls; - struct ForwardedOperationData *fo_data; - - fo_data = opc->data; - if (NULL != fo_data->cc) - fo_data->cc (fo_data->cc_cls, msg); - GNUNET_TESTBED_remove_opc_ (c, opc); - GNUNET_free (fo_data); - GNUNET_free (opc); -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS message from - * controller (testbed service) - * - * @param cls the controller handler - * @param msg message received - */ -static void -handle_opsuccess ( - void *cls, - const struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg) -{ - struct GNUNET_TESTBED_Controller *c = cls; - struct OperationContext *opc; - GNUNET_TESTBED_OperationCompletionCallback op_comp_cb; - void *op_comp_cb_cls; - struct GNUNET_TESTBED_EventInformation event; - uint64_t op_id; - - op_id = GNUNET_ntohll (msg->operation_id); - LOG_DEBUG ("Operation %llu successful\n", - (unsigned long long) op_id); - if (NULL == (opc = find_opc (c, op_id))) - { - LOG_DEBUG ("Operation not found\n"); - return; - } - event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; - event.op = opc->op; - event.op_cls = opc->op_cls; - event.details.operation_finished.emsg = NULL; - event.details.operation_finished.generic = NULL; - op_comp_cb = NULL; - op_comp_cb_cls = NULL; - switch (opc->type) - { - case OP_FORWARDED: { - handle_forwarded_operation_msg (c, - opc, - (const struct - GNUNET_MessageHeader *) msg); - return; - } - break; - - case OP_PEER_DESTROY: { - struct GNUNET_TESTBED_Peer *peer; - - peer = opc->data; - GNUNET_TESTBED_peer_deregister_ (peer); - GNUNET_free (peer); - opc->data = NULL; - // PEERDESTROYDATA - } - break; - - case OP_SHUTDOWN_PEERS: { - struct ShutdownPeersData *data; - - data = opc->data; - op_comp_cb = data->cb; - op_comp_cb_cls = data->cb_cls; - GNUNET_free (data); - opc->data = NULL; - GNUNET_TESTBED_cleanup_peers_ (); - } - break; - - case OP_MANAGE_SERVICE: { - struct ManageServiceData *data; - - GNUNET_assert (NULL != (data = opc->data)); - op_comp_cb = data->cb; - op_comp_cb_cls = data->cb_cls; - GNUNET_free (data); - opc->data = NULL; - } - break; - - case OP_PEER_RECONFIGURE: - break; - - default: - GNUNET_assert (0); - } - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - opc->state = OPC_STATE_FINISHED; - exop_insert (event.op); - if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED))) - { - if (NULL != c->cc) - c->cc (c->cc_cls, &event); - if (GNUNET_NO == exop_check (event.op)) - return; - } - else - LOG_DEBUG ("Not calling callback\n"); - if (NULL != op_comp_cb) - op_comp_cb (op_comp_cb_cls, event.op, NULL); - /* You could have marked the operation as done by now */ - GNUNET_break (GNUNET_NO == exop_check (event.op)); -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS message from - * controller (testbed service) - * - * @param cls the controller handle - * @param msg message received - */ -static void -handle_peer_create_success ( - void *cls, - const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg) -{ - struct GNUNET_TESTBED_Controller *c = cls; - struct OperationContext *opc; - struct PeerCreateData *data; - struct GNUNET_TESTBED_Peer *peer; - struct GNUNET_TESTBED_Operation *op; - GNUNET_TESTBED_PeerCreateCallback cb; - void *cb_cls; - uint64_t op_id; - - GNUNET_assert (sizeof(struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) == - ntohs (msg->header.size)); - op_id = GNUNET_ntohll (msg->operation_id); - if (NULL == (opc = find_opc (c, op_id))) - { - LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n"); - return; - } - if (OP_FORWARDED == opc->type) - { - handle_forwarded_operation_msg (c, - opc, - (const struct GNUNET_MessageHeader *) msg); - return; - } - GNUNET_assert (OP_PEER_CREATE == opc->type); - GNUNET_assert (NULL != opc->data); - data = opc->data; - GNUNET_assert (NULL != data->peer); - peer = data->peer; - GNUNET_assert (peer->unique_id == ntohl (msg->peer_id)); - peer->state = TESTBED_PS_CREATED; - GNUNET_TESTBED_peer_register_ (peer); - cb = data->cb; - cb_cls = data->cls; - op = opc->op; - GNUNET_free (opc->data); - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - opc->state = OPC_STATE_FINISHED; - exop_insert (op); - if (NULL != cb) - cb (cb_cls, peer, NULL); - /* You could have marked the operation as done by now */ - GNUNET_break (GNUNET_NO == exop_check (op)); -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT message from - * controller (testbed service) - * - * @param cls the controller handler - * @param msg message received - */ -static void -handle_peer_event (void *cls, const struct GNUNET_TESTBED_PeerEventMessage *msg) -{ - struct GNUNET_TESTBED_Controller *c = cls; - struct OperationContext *opc; - struct GNUNET_TESTBED_Peer *peer; - struct PeerEventData *data; - GNUNET_TESTBED_PeerChurnCallback pcc; - void *pcc_cls; - struct GNUNET_TESTBED_EventInformation event; - uint64_t op_id; - uint64_t mask; - - GNUNET_assert (sizeof(struct GNUNET_TESTBED_PeerEventMessage) == - ntohs (msg->header.size)); - op_id = GNUNET_ntohll (msg->operation_id); - if (NULL == (opc = find_opc (c, op_id))) - { - LOG_DEBUG ("Operation not found\n"); - return; - } - if (OP_FORWARDED == opc->type) - { - handle_forwarded_operation_msg (c, - opc, - (const struct GNUNET_MessageHeader *) msg); - return; - } - GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type)); - data = opc->data; - GNUNET_assert (NULL != data); - peer = data->peer; - GNUNET_assert (NULL != peer); - event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type); - event.op = opc->op; - event.op_cls = opc->op_cls; - switch (event.type) - { - case GNUNET_TESTBED_ET_PEER_START: - peer->state = TESTBED_PS_STARTED; - event.details.peer_start.host = peer->host; - event.details.peer_start.peer = peer; - break; - - case GNUNET_TESTBED_ET_PEER_STOP: - peer->state = TESTBED_PS_STOPPED; - event.details.peer_stop.peer = peer; - break; - - default: - GNUNET_assert (0); /* We should never reach this state */ - } - pcc = data->pcc; - pcc_cls = data->pcc_cls; - GNUNET_free (data); - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - opc->state = OPC_STATE_FINISHED; - exop_insert (event.op); - mask = 1LL << GNUNET_TESTBED_ET_PEER_START; - mask |= 1LL << GNUNET_TESTBED_ET_PEER_STOP; - if (0 != (mask & c->event_mask)) - { - if (NULL != c->cc) - c->cc (c->cc_cls, &event); - if (GNUNET_NO == exop_check (event.op)) - return; - } - if (NULL != pcc) - pcc (pcc_cls, NULL); - /* You could have marked the operation as done by now */ - GNUNET_break (GNUNET_NO == exop_check (event.op)); -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT message from - * controller (testbed service) - * - * @param cls the controller handler - * @param msg message received - */ -static void -handle_peer_conevent (void *cls, - const struct GNUNET_TESTBED_ConnectionEventMessage *msg) -{ - struct GNUNET_TESTBED_Controller *c = cls; - struct OperationContext *opc; - struct OverlayConnectData *data; - GNUNET_TESTBED_OperationCompletionCallback cb; - void *cb_cls; - struct GNUNET_TESTBED_EventInformation event; - uint64_t op_id; - uint64_t mask; - - op_id = GNUNET_ntohll (msg->operation_id); - if (NULL == (opc = find_opc (c, op_id))) - { - LOG_DEBUG ("Operation not found\n"); - return; - } - if (OP_FORWARDED == opc->type) - { - handle_forwarded_operation_msg (c, - opc, - (const struct GNUNET_MessageHeader *) msg); - return; - } - GNUNET_assert (OP_OVERLAY_CONNECT == opc->type); - GNUNET_assert (NULL != (data = opc->data)); - GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) && - (ntohl (msg->peer2) == data->p2->unique_id)); - event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type); - event.op = opc->op; - event.op_cls = opc->op_cls; - switch (event.type) - { - case GNUNET_TESTBED_ET_CONNECT: - event.details.peer_connect.peer1 = data->p1; - event.details.peer_connect.peer2 = data->p2; - break; - - case GNUNET_TESTBED_ET_DISCONNECT: - GNUNET_assert (0); /* FIXME: implement */ - break; - - default: - GNUNET_assert (0); /* Should never reach here */ - break; - } - cb = data->cb; - cb_cls = data->cb_cls; - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - opc->state = OPC_STATE_FINISHED; - exop_insert (event.op); - mask = 1LL << GNUNET_TESTBED_ET_CONNECT; - mask |= 1LL << GNUNET_TESTBED_ET_DISCONNECT; - if (0 != (mask & c->event_mask)) - { - if (NULL != c->cc) - c->cc (c->cc_cls, &event); - if (GNUNET_NO == exop_check (event.op)) - return; - } - if (NULL != cb) - cb (cb_cls, opc->op, NULL); - /* You could have marked the operation as done by now */ - GNUNET_break (GNUNET_NO == exop_check (event.op)); -} - - -/** - * Validate #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION message from - * controller (testbed service) - * - * @param cls the controller handler - * @param msg message received - */ -static int -check_peer_config ( - void *cls, - const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *msg) -{ - /* anything goes? */ - return GNUNET_OK; -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION message from - * controller (testbed service) - * - * @param cls the controller handler - * @param msg message received - */ -static void -handle_peer_config ( - void *cls, - const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *msg) -{ - struct GNUNET_TESTBED_Controller *c = cls; - struct OperationContext *opc; - struct GNUNET_TESTBED_Peer *peer; - struct PeerInfoData *data; - struct GNUNET_TESTBED_PeerInformation *pinfo; - GNUNET_TESTBED_PeerInfoCallback cb; - void *cb_cls; - uint64_t op_id; - - op_id = GNUNET_ntohll (msg->operation_id); - if (NULL == (opc = find_opc (c, op_id))) - { - LOG_DEBUG ("Operation not found\n"); - return; - } - if (OP_FORWARDED == opc->type) - { - handle_forwarded_operation_msg (c, opc, &msg->header); - return; - } - data = opc->data; - GNUNET_assert (NULL != data); - peer = data->peer; - GNUNET_assert (NULL != peer); - GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id); - pinfo = GNUNET_new (struct GNUNET_TESTBED_PeerInformation); - pinfo->pit = data->pit; - cb = data->cb; - cb_cls = data->cb_cls; - GNUNET_assert (NULL != cb); - GNUNET_free (data); - opc->data = NULL; - switch (pinfo->pit) - { - case GNUNET_TESTBED_PIT_IDENTITY: - pinfo->result.id = GNUNET_new (struct GNUNET_PeerIdentity); - GNUNET_memcpy (pinfo->result.id, - &msg->peer_identity, - sizeof(struct GNUNET_PeerIdentity)); - break; - - case GNUNET_TESTBED_PIT_CONFIGURATION: - pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */ - GNUNET_TESTBED_extract_config_ (&msg->header); - break; - - case GNUNET_TESTBED_PIT_GENERIC: - GNUNET_assert (0); /* never reach here */ - break; - } - opc->data = pinfo; - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - opc->state = OPC_STATE_FINISHED; - cb (cb_cls, opc->op, pinfo, NULL); - /* We dont check whether the operation is marked as done here as the - operation contains data (cfg/identify) which will be freed at a later point - */ -} - - -/** - * Validate #GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT message from - * controller (testbed service) - * - * @param cls the controller handler - * @param msg message received - * @return #GNUNET_OK if message is well-formed - */ -static int -check_op_fail_event ( - void *cls, - const struct GNUNET_TESTBED_OperationFailureEventMessage *msg) -{ - /* we accept anything as a valid error message */ - return GNUNET_OK; -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT message from - * controller (testbed service) - * - * @param cls the controller handler - * @param msg message received - */ -static void -handle_op_fail_event ( - void *cls, - const struct GNUNET_TESTBED_OperationFailureEventMessage *msg) -{ - struct GNUNET_TESTBED_Controller *c = cls; - struct OperationContext *opc; - const char *emsg; - uint64_t op_id; - uint64_t mask; - struct GNUNET_TESTBED_EventInformation event; - - op_id = GNUNET_ntohll (msg->operation_id); - if (NULL == (opc = find_opc (c, op_id))) - { - LOG_DEBUG ("Operation not found\n"); - return; - } - if (OP_FORWARDED == opc->type) - { - handle_forwarded_operation_msg (c, - opc, - (const struct GNUNET_MessageHeader *) msg); - return; - } - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - opc->state = OPC_STATE_FINISHED; - emsg = GNUNET_TESTBED_parse_error_string_ (msg); - if (NULL == emsg) - emsg = "Unknown error"; - if (OP_PEER_INFO == opc->type) - { - struct PeerInfoData *data; - - data = opc->data; - if (NULL != data->cb) - data->cb (data->cb_cls, opc->op, NULL, emsg); - GNUNET_free (data); - return; /* We do not call controller callback for peer info */ - } - event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; - event.op = opc->op; - event.op_cls = opc->op_cls; - event.details.operation_finished.emsg = emsg; - event.details.operation_finished.generic = NULL; - mask = (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); - if ((0 != (mask & c->event_mask)) && (NULL != c->cc)) - { - exop_insert (event.op); - c->cc (c->cc_cls, &event); - if (GNUNET_NO == exop_check (event.op)) - return; - } - switch (opc->type) - { - case OP_PEER_CREATE: { - struct PeerCreateData *data; - - data = opc->data; - GNUNET_free (data->peer); - if (NULL != data->cb) - data->cb (data->cls, NULL, emsg); - GNUNET_free (data); - } - break; - - case OP_PEER_START: - case OP_PEER_STOP: { - struct PeerEventData *data; - - data = opc->data; - if (NULL != data->pcc) - data->pcc (data->pcc_cls, emsg); - GNUNET_free (data); - } - break; - - case OP_PEER_DESTROY: - break; - - case OP_PEER_INFO: - GNUNET_assert (0); - - case OP_OVERLAY_CONNECT: { - struct OverlayConnectData *data; - - data = opc->data; - GNUNET_TESTBED_operation_mark_failed (opc->op); - if (NULL != data->cb) - data->cb (data->cb_cls, opc->op, emsg); - } - break; - - case OP_FORWARDED: - GNUNET_assert (0); - - case OP_LINK_CONTROLLERS: /* No secondary callback */ - break; - - case OP_SHUTDOWN_PEERS: { - struct ShutdownPeersData *data; - - data = opc->data; - GNUNET_free (data); /* FIXME: Decide whether we call data->op_cb */ - opc->data = NULL; - } - break; - - case OP_MANAGE_SERVICE: { - struct ManageServiceData *data = opc->data; - GNUNET_TESTBED_OperationCompletionCallback cb; - void *cb_cls; - - GNUNET_assert (NULL != data); - cb = data->cb; - cb_cls = data->cb_cls; - GNUNET_free (data); - opc->data = NULL; - exop_insert (event.op); - if (NULL != cb) - cb (cb_cls, opc->op, emsg); - /* You could have marked the operation as done by now */ - GNUNET_break (GNUNET_NO == exop_check (event.op)); - } - break; - - default: - GNUNET_break (0); - } -} - - -/** - * Function to build GET_SLAVE_CONFIG message - * - * @param op_id the id this message should contain in its operation id field - * @param slave_id the id this message should contain in its slave id field - * @return newly allocated SlaveGetConfigurationMessage - */ -static struct GNUNET_TESTBED_SlaveGetConfigurationMessage * -GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id) -{ - struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg; - uint16_t msize; - - msize = sizeof(struct GNUNET_TESTBED_SlaveGetConfigurationMessage); - msg = GNUNET_malloc (msize); - msg->header.size = htons (msize); - msg->header.type = - htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION); - msg->operation_id = GNUNET_htonll (op_id); - msg->slave_id = htonl (slave_id); - return msg; -} - - -/** - * Validate #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_INFORMATION message from - * controller (testbed service) - * - * @param c the controller handler - * @param msg message received - */ -static int -check_slave_config (void *cls, - const struct GNUNET_TESTBED_SlaveConfiguration *msg) -{ - /* anything goes? */ - return GNUNET_OK; -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION message from controller - * (testbed service) - * - * @param cls the controller handler - * @param msg message received - */ -static void -handle_slave_config (void *cls, - const struct GNUNET_TESTBED_SlaveConfiguration *msg) -{ - struct GNUNET_TESTBED_Controller *c = cls; - struct OperationContext *opc; - uint64_t op_id; - uint64_t mask; - struct GNUNET_TESTBED_EventInformation event; - - op_id = GNUNET_ntohll (msg->operation_id); - if (NULL == (opc = find_opc (c, op_id))) - { - LOG_DEBUG ("Operation not found\n"); - return; - } - if (OP_GET_SLAVE_CONFIG != opc->type) - { - GNUNET_break (0); - return; - } - opc->state = OPC_STATE_FINISHED; - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED; - if ((0 != (mask & c->event_mask)) && (NULL != c->cc)) - { - opc->data = GNUNET_TESTBED_extract_config_ (&msg->header); - event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; - event.op = opc->op; - event.op_cls = opc->op_cls; - event.details.operation_finished.generic = opc->data; - event.details.operation_finished.emsg = NULL; - c->cc (c->cc_cls, &event); - } -} - - -/** - * Check #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT message from controller - * (testbed service) - * - * @param c the controller handler - * @param msg message received - * @return #GNUNET_OK if @a msg is well-formed - */ -static int -check_link_controllers_result ( - void *cls, - const struct GNUNET_TESTBED_ControllerLinkResponse *msg) -{ - /* actual check to be implemented */ - return GNUNET_OK; -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT message from controller - * (testbed service) - * - * @param cls the controller handler - * @param msg message received - */ -static void -handle_link_controllers_result ( - void *cls, - const struct GNUNET_TESTBED_ControllerLinkResponse *msg) -{ - struct GNUNET_TESTBED_Controller *c = cls; - struct OperationContext *opc; - struct ControllerLinkData *data; - struct GNUNET_CONFIGURATION_Handle *cfg; - struct GNUNET_TESTBED_Host *host; - char *emsg; - uint64_t op_id; - struct GNUNET_TESTBED_EventInformation event; - - op_id = GNUNET_ntohll (msg->operation_id); - if (NULL == (opc = find_opc (c, op_id))) - { - LOG_DEBUG ("Operation not found\n"); - return; - } - if (OP_FORWARDED == opc->type) - { - handle_forwarded_operation_msg (c, - opc, - (const struct GNUNET_MessageHeader *) msg); - return; - } - if (OP_LINK_CONTROLLERS != opc->type) - { - GNUNET_break (0); - return; - } - GNUNET_assert (NULL != (data = opc->data)); - host = GNUNET_TESTBED_host_lookup_by_id_ (data->host_id); - GNUNET_assert (NULL != host); - GNUNET_free (data); - opc->data = NULL; - opc->state = OPC_STATE_FINISHED; - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; - event.op = opc->op; - event.op_cls = opc->op_cls; - event.details.operation_finished.emsg = NULL; - event.details.operation_finished.generic = NULL; - emsg = NULL; - cfg = NULL; - if (GNUNET_NO == ntohs (msg->success)) - { - emsg = - GNUNET_malloc (ntohs (msg->header.size) - - sizeof(struct GNUNET_TESTBED_ControllerLinkResponse) - + 1); - GNUNET_memcpy (emsg, - &msg[1], - ntohs (msg->header.size) - - sizeof(struct GNUNET_TESTBED_ControllerLinkResponse)); - event.details.operation_finished.emsg = emsg; - } - else - { - if (0 != ntohs (msg->config_size)) - { - cfg = GNUNET_TESTBED_extract_config_ ( - (const struct GNUNET_MessageHeader *) msg); - GNUNET_assert (NULL != cfg); - GNUNET_TESTBED_host_replace_cfg_ (host, cfg); - } - } - if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED))) - { - if (NULL != c->cc) - c->cc (c->cc_cls, &event); - } - else - LOG_DEBUG ("Not calling callback\n"); - if (NULL != cfg) - GNUNET_CONFIGURATION_destroy (cfg); - GNUNET_free (emsg); -} - - -/** - * Validate #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS message. - * - * @param cls the controller handle to determine the connection this message - * belongs to - * @param msg the barrier status message - * @return #GNUNET_OK if the message is valid; #GNUNET_SYSERR to tear it - * down signalling an error (message malformed) - */ -static int -check_barrier_status (void *cls, - const struct GNUNET_TESTBED_BarrierStatusMsg *msg) -{ - uint16_t msize; - uint16_t name_len; - int status; - const char *name; - size_t emsg_len; - - msize = ntohs (msg->header.size); - name = msg->data; - name_len = ntohs (msg->name_len); - - if (sizeof(struct GNUNET_TESTBED_BarrierStatusMsg) + name_len + 1 > msize) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if ('\0' != name[name_len]) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - status = ntohs (msg->status); - if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status) - { - emsg_len = msize - (sizeof(struct GNUNET_TESTBED_BarrierStatusMsg) - + name_len + 1); /* +1!? */ - if (0 == emsg_len) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - } - return GNUNET_OK; -} - - -/** - * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages - * - * @param cls the controller handle to determine the connection this message - * belongs to - * @param msg the barrier status message - */ -static void -handle_barrier_status (void *cls, - const struct GNUNET_TESTBED_BarrierStatusMsg *msg) -{ - struct GNUNET_TESTBED_Controller *c = cls; - struct GNUNET_TESTBED_Barrier *barrier; - char *emsg; - const char *name; - struct GNUNET_HashCode key; - size_t emsg_len; - int status; - uint16_t msize; - uint16_t name_len; - - emsg = NULL; - barrier = NULL; - msize = ntohs (msg->header.size); - if (msize <= sizeof(struct GNUNET_TESTBED_BarrierStatusMsg)) - { - GNUNET_break_op (0); - goto cleanup; - } - name = msg->data; - name_len = ntohs (msg->name_len); - if (name_len >= // name_len is strlen(barrier_name) - (msize - ((sizeof msg->header) + sizeof(msg->status)))) - { - GNUNET_break_op (0); - goto cleanup; - } - if ('\0' != name[name_len]) - { - GNUNET_break_op (0); - goto cleanup; - } - LOG_DEBUG ("Received BARRIER_STATUS msg\n"); - status = ntohs (msg->status); - if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status) - { - status = -1; - // unlike name_len, emsg_len includes the trailing zero - emsg_len = msize - (sizeof(struct GNUNET_TESTBED_BarrierStatusMsg) - + (name_len + 1)); - if (0 == emsg_len) - { - GNUNET_break_op (0); - goto cleanup; - } - if ('\0' != (msg->data[(name_len + 1) + (emsg_len - 1)])) - { - GNUNET_break_op (0); - goto cleanup; - } - emsg = GNUNET_malloc (emsg_len); - GNUNET_memcpy (emsg, msg->data + name_len + 1, emsg_len); - } - if (NULL == c->barrier_map) - { - GNUNET_break_op (0); - goto cleanup; - } - GNUNET_CRYPTO_hash (name, name_len, &key); - barrier = GNUNET_CONTAINER_multihashmap_get (c->barrier_map, &key); - if (NULL == barrier) - { - GNUNET_break_op (0); - goto cleanup; - } - GNUNET_assert (NULL != barrier->cb); - if ((GNUNET_YES == barrier->echo) && - (GNUNET_TESTBED_BARRIERSTATUS_CROSSED == status)) - GNUNET_TESTBED_queue_message_ (c, GNUNET_copy_message (&msg->header)); - barrier->cb (barrier->cls, name, barrier, status, emsg); - if (GNUNET_TESTBED_BARRIERSTATUS_INITIALISED == status) - return; /* just initialised; skip cleanup */ - -cleanup: - GNUNET_free (emsg); - /** - * Do not remove the barrier if we did not echo the status back; this is - * required at the chained testbed controller setup to ensure the only the - * test-driver echos the status and the controller hierarchy properly - * propagates the status. - */if ((NULL != barrier) && (GNUNET_YES == barrier->echo)) - GNUNET_TESTBED_barrier_remove_ (barrier); -} - - -/** - * Queues a message in send queue for sending to the service - * - * @param controller the handle to the controller - * @param msg the message to queue - */ -void -GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller, - struct GNUNET_MessageHeader *msg) -{ - struct GNUNET_MQ_Envelope *env; - struct GNUNET_MessageHeader *m2; - uint16_t type; - uint16_t size; - - type = ntohs (msg->type); - size = ntohs (msg->size); - GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) && - (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type)); - env = GNUNET_MQ_msg_extra (m2, size - sizeof(*m2), type); - GNUNET_memcpy (m2, msg, size); - GNUNET_free (msg); - GNUNET_MQ_send (controller->mq, env); -} - - -/** - * Sends the given message as an operation. The given callback is called when a - * reply for the operation is available. Call - * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned - * operation context if the cc hasn't been called - * - * @param controller the controller to which the message has to be sent - * @param operation_id the operation id of the message - * @param msg the message to send - * @param cc the callback to call when reply is available - * @param cc_cls the closure for the above callback - * @return the operation context which can be used to cancel the forwarded - * operation - */ -struct OperationContext * -GNUNET_TESTBED_forward_operation_msg_ ( - struct GNUNET_TESTBED_Controller *controller, - uint64_t operation_id, - const struct GNUNET_MessageHeader *msg, - GNUNET_MQ_MessageCallback cc, - void *cc_cls) -{ - struct OperationContext *opc; - struct ForwardedOperationData *data; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_MessageHeader *m2; - uint16_t type = ntohs (msg->type); - uint16_t size = ntohs (msg->size); - - env = GNUNET_MQ_msg_extra (m2, size - sizeof(*m2), type); - GNUNET_memcpy (m2, msg, size); - GNUNET_MQ_send (controller->mq, env); - data = GNUNET_new (struct ForwardedOperationData); - data->cc = cc; - data->cc_cls = cc_cls; - opc = GNUNET_new (struct OperationContext); - opc->c = controller; - opc->type = OP_FORWARDED; - opc->data = data; - opc->id = operation_id; - GNUNET_TESTBED_insert_opc_ (controller, opc); - return opc; -} - - -/** - * Function to cancel an operation created by simply forwarding an operation - * message. - * - * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_() - */ -void -GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc) -{ - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - GNUNET_free (opc->data); - GNUNET_free (opc); -} - - -/** - * Function to call to start a link-controllers type operation once all queues - * the operation is part of declare that the operation can be activated. - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -opstart_link_controllers (void *cls) -{ - struct OperationContext *opc = cls; - struct ControllerLinkData *data; - struct GNUNET_TESTBED_ControllerLinkRequest *msg; - - GNUNET_assert (NULL != opc->data); - data = opc->data; - msg = data->msg; - data->msg = NULL; - opc->state = OPC_STATE_STARTED; - GNUNET_TESTBED_insert_opc_ (opc->c, opc); - GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); -} - - -/** - * Callback which will be called when link-controllers type operation is released - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -oprelease_link_controllers (void *cls) -{ - struct OperationContext *opc = cls; - struct ControllerLinkData *data; - - data = opc->data; - switch (opc->state) - { - case OPC_STATE_INIT: - GNUNET_free (data->msg); - break; - - case OPC_STATE_STARTED: - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - break; - - case OPC_STATE_FINISHED: - break; - } - GNUNET_free (data); - GNUNET_free (opc); -} - - -/** - * Function to be called when get slave config operation is ready - * - * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG - */ -static void -opstart_get_slave_config (void *cls) -{ - struct OperationContext *opc = cls; - struct GetSlaveConfigData *data = opc->data; - struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg; - - GNUNET_assert (NULL != data); - msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id); - GNUNET_free (opc->data); - data = NULL; - opc->data = NULL; - GNUNET_TESTBED_insert_opc_ (opc->c, opc); - GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); - opc->state = OPC_STATE_STARTED; -} - - -/** - * Function to be called when get slave config operation is cancelled or finished - * - * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG - */ -static void -oprelease_get_slave_config (void *cls) -{ - struct OperationContext *opc = cls; - - switch (opc->state) - { - case OPC_STATE_INIT: - GNUNET_free (opc->data); - break; - - case OPC_STATE_STARTED: - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - break; - - case OPC_STATE_FINISHED: - if (NULL != opc->data) - GNUNET_CONFIGURATION_destroy (opc->data); - break; - } - GNUNET_free (opc); -} - - -/** - * Generic error handler, called with the appropriate error code and - * the same closure specified at the creation of the message queue. - * Not every message queue implementation supports an error handler. - * - * @param cls closure, a `struct GNUNET_TESTBED_Controller *` - * @param error error code - */ -static void -mq_error_handler (void *cls, enum GNUNET_MQ_Error error) -{ - /* struct GNUNET_TESTBED_Controller *c = cls; */ - - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Encountered MQ error: %d\n", error); - /* now what? */ - GNUNET_SCHEDULER_shutdown (); /* seems most reasonable */ -} - - -/** - * Start a controller process using the given configuration at the - * given host. - * - * @param host host to run the controller on; This should be the same host if - * the controller was previously started with - * GNUNET_TESTBED_controller_start() - * @param event_mask bit mask with set of events to call 'cc' for; - * or-ed values of "1LL" shifted by the - * respective 'enum GNUNET_TESTBED_EventType' - * (e.g. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...") - * @param cc controller callback to invoke on events - * @param cc_cls closure for cc - * @return handle to the controller - */ -struct GNUNET_TESTBED_Controller * -GNUNET_TESTBED_controller_connect (struct GNUNET_TESTBED_Host *host, - uint64_t event_mask, - GNUNET_TESTBED_ControllerCallback cc, - void *cc_cls) -{ - struct GNUNET_TESTBED_Controller *controller = - GNUNET_new (struct GNUNET_TESTBED_Controller); - struct GNUNET_MQ_MessageHandler handlers[] = - { GNUNET_MQ_hd_var_size (add_host_confirm, - GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS, - struct GNUNET_TESTBED_HostConfirmedMessage, - controller), - GNUNET_MQ_hd_fixed_size (peer_conevent, - GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT, - struct GNUNET_TESTBED_ConnectionEventMessage, - controller), - GNUNET_MQ_hd_fixed_size (opsuccess, - GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS, - struct - GNUNET_TESTBED_GenericOperationSuccessEventMessage, - controller), - GNUNET_MQ_hd_var_size (op_fail_event, - GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT, - struct GNUNET_TESTBED_OperationFailureEventMessage, - controller), - GNUNET_MQ_hd_fixed_size (peer_create_success, - GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS, - struct - GNUNET_TESTBED_PeerCreateSuccessEventMessage, - controller), - GNUNET_MQ_hd_fixed_size (peer_event, - GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT, - struct GNUNET_TESTBED_PeerEventMessage, - controller), - GNUNET_MQ_hd_var_size (peer_config, - GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION, - struct - GNUNET_TESTBED_PeerConfigurationInformationMessage, - controller), - GNUNET_MQ_hd_var_size (slave_config, - GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION, - struct GNUNET_TESTBED_SlaveConfiguration, - controller), - GNUNET_MQ_hd_var_size (link_controllers_result, - GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT, - struct GNUNET_TESTBED_ControllerLinkResponse, - controller), - GNUNET_MQ_hd_var_size (barrier_status, - GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, - struct GNUNET_TESTBED_BarrierStatusMsg, - controller), - GNUNET_MQ_handler_end () }; - struct GNUNET_TESTBED_InitMessage *msg; - struct GNUNET_MQ_Envelope *env; - const struct GNUNET_CONFIGURATION_Handle *cfg; - const char *controller_hostname; - unsigned long long max_parallel_operations; - unsigned long long max_parallel_service_connections; - unsigned long long max_parallel_topology_config_operations; - size_t slen; - - GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host))); - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, - "testbed", - "MAX_PARALLEL_OPERATIONS", - &max_parallel_operations)) - { - GNUNET_break (0); - GNUNET_free (controller); - return NULL; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, - "testbed", - "MAX_PARALLEL_SERVICE_CONNECTIONS", - &max_parallel_service_connections)) - { - GNUNET_break (0); - GNUNET_free (controller); - return NULL; - } - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number ( - cfg, - "testbed", - "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS", - &max_parallel_topology_config_operations)) - { - GNUNET_break (0); - GNUNET_free (controller); - return NULL; - } - controller->cc = cc; - controller->cc_cls = cc_cls; - controller->event_mask = event_mask; - controller->cfg = GNUNET_CONFIGURATION_dup (cfg); - controller->mq = GNUNET_CLIENT_connect (controller->cfg, - "testbed", - handlers, - &mq_error_handler, - controller); - if (NULL == controller->mq) - { - GNUNET_break (0); - GNUNET_TESTBED_controller_disconnect (controller); - return NULL; - } - GNUNET_TESTBED_mark_host_registered_at_ (host, controller); - controller->host = host; - controller->opq_parallel_operations = - GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, - (unsigned int) - max_parallel_operations); - controller->opq_parallel_service_connections = - GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, - (unsigned int) - max_parallel_service_connections); - controller->opq_parallel_topology_config_operations = - GNUNET_TESTBED_operation_queue_create_ ( - OPERATION_QUEUE_TYPE_FIXED, - (unsigned int) max_parallel_topology_config_operations); - controller_hostname = GNUNET_TESTBED_host_get_hostname (host); - if (NULL == controller_hostname) - controller_hostname = "127.0.0.1"; - slen = strlen (controller_hostname) + 1; - env = GNUNET_MQ_msg_extra (msg, slen, GNUNET_MESSAGE_TYPE_TESTBED_INIT); - msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host)); - msg->event_mask = GNUNET_htonll (controller->event_mask); - GNUNET_memcpy (&msg[1], controller_hostname, slen); - GNUNET_MQ_send (controller->mq, env); - return controller; -} - - -/** - * Iterator to free opc map entries - * - * @param cls closure - * @param key current key code - * @param value value in the hash map - * @return #GNUNET_YES if we should continue to iterate, - * #GNUNET_NO if not. - */ -static int -opc_free_iterator (void *cls, uint32_t key, void *value) -{ - struct GNUNET_CONTAINER_MultiHashMap32 *map = cls; - struct OperationContext *opc = value; - - GNUNET_assert (NULL != opc); - GNUNET_break (0); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap32_remove (map, key, value)); - GNUNET_free (opc); - return GNUNET_YES; -} - - -/** - * Stop the given controller (also will terminate all peers and - * controllers dependent on this controller). This function - * blocks until the testbed has been fully terminated (!). - * - * @param c handle to controller to stop - */ -void -GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller *c) -{ - if (NULL != c->mq) - { - GNUNET_MQ_destroy (c->mq); - c->mq = NULL; - } - if (NULL != c->host) - GNUNET_TESTBED_deregister_host_at_ (c->host, c); - GNUNET_CONFIGURATION_destroy (c->cfg); - GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_operations); - GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_service_connections); - GNUNET_TESTBED_operation_queue_destroy_ ( - c->opq_parallel_topology_config_operations); - if (NULL != c->opc_map) - { - GNUNET_assert (GNUNET_SYSERR != - GNUNET_CONTAINER_multihashmap32_iterate (c->opc_map, - &opc_free_iterator, - c->opc_map)); - GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map)); - GNUNET_CONTAINER_multihashmap32_destroy (c->opc_map); - } - GNUNET_free (c); -} - - -/** - * Compresses given configuration using zlib compress - * - * @param config the serialized configuration - * @param size the size of config - * @param xconfig will be set to the compressed configuration (memory is fresly - * allocated) - * @return the size of the xconfig - */ -size_t -GNUNET_TESTBED_compress_config_ (const char *config, - size_t size, - char **xconfig) -{ - size_t xsize; - - xsize = compressBound ((uLong) size); - *xconfig = GNUNET_malloc (xsize); - GNUNET_assert (Z_OK == compress2 ((Bytef *) *xconfig, - (uLongf *) &xsize, - (const Bytef *) config, - (uLongf) size, - Z_BEST_SPEED)); - return xsize; -} - - -/** - * Function to serialize and compress using zlib a configuration through a - * configuration handle - * - * @param cfg the configuration - * @param size the size of configuration when serialize. Will be set on success. - * @param xsize the sizeo of the compressed configuration. Will be set on success. - * @return the serialized and compressed configuration - */ -char * -GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg, - size_t *size, - size_t *xsize) -{ - char *config; - char *xconfig; - size_t size_; - size_t xsize_; - - config = GNUNET_CONFIGURATION_serialize (cfg, &size_); - xsize_ = GNUNET_TESTBED_compress_config_ (config, size_, &xconfig); - GNUNET_free (config); - *size = size_; - *xsize = xsize_; - return xconfig; -} - - -/** - * Create a link from slave controller to delegated controller. Whenever the - * master controller is asked to start a peer at the delegated controller the - * request will be routed towards slave controller (if a route exists). The - * slave controller will then route it to the delegated controller. The - * configuration of the delegated controller is given and is used to either - * create the delegated controller or to connect to an existing controller. Note - * that while starting the delegated controller the configuration will be - * modified to accommodate available free ports. the 'is_subordinate' specifies - * if the given delegated controller should be started and managed by the slave - * controller, or if the delegated controller already has a master and the slave - * controller connects to it as a non master controller. The success or failure - * of this operation will be signalled through the - * GNUNET_TESTBED_ControllerCallback() with an event of type - * GNUNET_TESTBED_ET_OPERATION_FINISHED - * - * @param op_cls the operation closure for the event which is generated to - * signal success or failure of this operation - * @param master handle to the master controller who creates the association - * @param delegated_host requests to which host should be delegated; cannot be NULL - * @param slave_host which host is used to run the slave controller; use NULL to - * make the master controller connect to the delegated host - * @param is_subordinate GNUNET_YES if the controller at delegated_host should - * be started by the slave controller; GNUNET_NO if the slave - * controller has to connect to the already started delegated - * controller via TCP/IP - * @return the operation handle - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_controller_link (void *op_cls, - struct GNUNET_TESTBED_Controller *master, - struct GNUNET_TESTBED_Host *delegated_host, - struct GNUNET_TESTBED_Host *slave_host, - int is_subordinate) -{ - struct OperationContext *opc; - struct GNUNET_TESTBED_ControllerLinkRequest *msg; - struct ControllerLinkData *data; - uint32_t slave_host_id; - uint32_t delegated_host_id; - uint16_t msg_size; - - GNUNET_assert (GNUNET_YES == - GNUNET_TESTBED_is_host_registered_ (delegated_host, master)); - slave_host_id = GNUNET_TESTBED_host_get_id_ ( - (NULL != slave_host) ? slave_host : master->host); - delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host); - if ((NULL != slave_host) && (0 != slave_host_id)) - GNUNET_assert (GNUNET_YES == - GNUNET_TESTBED_is_host_registered_ (slave_host, master)); - msg_size = sizeof(struct GNUNET_TESTBED_ControllerLinkRequest); - msg = GNUNET_malloc (msg_size); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS); - msg->header.size = htons (msg_size); - msg->delegated_host_id = htonl (delegated_host_id); - msg->slave_host_id = htonl (slave_host_id); - msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0; - data = GNUNET_new (struct ControllerLinkData); - data->msg = msg; - data->host_id = delegated_host_id; - opc = GNUNET_new (struct OperationContext); - opc->c = master; - opc->data = data; - opc->type = OP_LINK_CONTROLLERS; - opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); - opc->state = OPC_STATE_INIT; - opc->op_cls = op_cls; - msg->operation_id = GNUNET_htonll (opc->id); - opc->op = GNUNET_TESTBED_operation_create_ (opc, - &opstart_link_controllers, - &oprelease_link_controllers); - GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations, - opc->op); - GNUNET_TESTBED_operation_begin_wait_ (opc->op); - return opc->op; -} - - -/** - * Like GNUNET_TESTBED_get_slave_config(), however without the host registration - * check. Another difference is that this function takes the id of the slave - * host. - * - * @param op_cls the closure for the operation - * @param master the handle to master controller - * @param slave_host_id id of the host where the slave controller is running to - * the slave_host should remain valid until this operation is cancelled - * or marked as finished - * @return the operation handle; - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_get_slave_config_ (void *op_cls, - struct GNUNET_TESTBED_Controller *master, - uint32_t slave_host_id) -{ - struct OperationContext *opc; - struct GetSlaveConfigData *data; - - data = GNUNET_new (struct GetSlaveConfigData); - data->slave_id = slave_host_id; - opc = GNUNET_new (struct OperationContext); - opc->state = OPC_STATE_INIT; - opc->c = master; - opc->id = GNUNET_TESTBED_get_next_op_id (master); - opc->type = OP_GET_SLAVE_CONFIG; - opc->data = data; - opc->op_cls = op_cls; - opc->op = GNUNET_TESTBED_operation_create_ (opc, - &opstart_get_slave_config, - &oprelease_get_slave_config); - GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations, - opc->op); - GNUNET_TESTBED_operation_begin_wait_ (opc->op); - return opc->op; -} - - -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_get_slave_config (void *op_cls, - struct GNUNET_TESTBED_Controller *master, - struct GNUNET_TESTBED_Host *slave_host) -{ - if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master)) - return NULL; - return GNUNET_TESTBED_get_slave_config_ (op_cls, - master, - GNUNET_TESTBED_host_get_id_ ( - slave_host)); -} - - -void -GNUNET_TESTBED_overlay_write_topology_to_file ( - struct GNUNET_TESTBED_Controller *controller, - const char *filename) -{ - GNUNET_break (0); -} - - -/** - * Creates a helper initialization message. This function is here because we - * want to use this in testing - * - * @param trusted_ip the ip address of the controller which will be set as TRUSTED - * HOST(all connections from this ip are permitted by the testbed) when - * starting testbed controller at host. This can either be a single ip - * address or a network address in CIDR notation. - * @param hostname the hostname of the destination this message is intended for - * @param cfg the configuration that has to used to start the testbed service - * thru helper - * @return the initialization message - */ -struct GNUNET_TESTBED_HelperInit * -GNUNET_TESTBED_create_helper_init_msg_ ( - const char *trusted_ip, - const char *hostname, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_TESTBED_HelperInit *msg; - char *config; - char *xconfig; - size_t config_size; - size_t xconfig_size; - uint16_t trusted_ip_len; - uint16_t hostname_len; - uint16_t msg_size; - - config = GNUNET_CONFIGURATION_serialize (cfg, &config_size); - GNUNET_assert (NULL != config); - xconfig_size = - GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig); - GNUNET_free (config); - trusted_ip_len = strlen (trusted_ip); - hostname_len = (NULL == hostname) ? 0 : strlen (hostname); - msg_size = xconfig_size + trusted_ip_len + 1 - + sizeof(struct GNUNET_TESTBED_HelperInit); - msg_size += hostname_len; - msg = GNUNET_realloc (xconfig, msg_size); - (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, - msg, - xconfig_size); - msg->header.size = htons (msg_size); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT); - msg->trusted_ip_size = htons (trusted_ip_len); - msg->hostname_size = htons (hostname_len); - msg->config_size = htons (config_size); - (void) strcpy ((char *) &msg[1], trusted_ip); - if (0 != hostname_len) - GNUNET_memcpy ((char *) &msg[1] + trusted_ip_len + 1, - hostname, - hostname_len); - return msg; -} - - -/** - * This function is used to signal that the event information (struct - * GNUNET_TESTBED_EventInformation) from an operation has been fully processed - * i.e. if the event callback is ever called for this operation. If the event - * callback for this operation has not yet been called, calling this function - * cancels the operation, frees its resources and ensures the no event is - * generated with respect to this operation. Note that however cancelling an - * operation does NOT guarantee that the operation will be fully undone (or that - * nothing ever happened). - * - * This function MUST be called for every operation to fully remove the - * operation from the operation queue. After calling this function, if - * operation is completed and its event information is of type - * GNUNET_TESTBED_ET_OPERATION_FINISHED, the 'op_result' becomes invalid (!). - - * If the operation is generated from GNUNET_TESTBED_service_connect() then - * calling this function on such as operation calls the disconnect adapter if - * the connect adapter was ever called. - * - * @param operation operation to signal completion or cancellation - */ -void -GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation) -{ - (void) exop_check (operation); - GNUNET_TESTBED_operation_release_ (operation); -} - - -/** - * Generates configuration by uncompressing configuration in given message. The - * given message should be of the following types: - * #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION, - * #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION, - * #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, - * #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, - * #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT, - * - * FIXME: This API is incredibly ugly. - * - * @param msg the message containing compressed configuration - * @return handle to the parsed configuration; NULL upon error while parsing the message - */ -struct GNUNET_CONFIGURATION_Handle * -GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg) -{ - struct GNUNET_CONFIGURATION_Handle *cfg; - Bytef *data; - const Bytef *xdata; - uLong data_len; - uLong xdata_len; - int ret; - - switch (ntohs (msg->type)) - { - case GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION: { - const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg; - - imsg = - (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg; - data_len = (uLong) ntohs (imsg->config_size); - xdata_len = - ntohs (imsg->header.size) - - sizeof(struct GNUNET_TESTBED_PeerConfigurationInformationMessage); - xdata = (const Bytef *) &imsg[1]; - } - break; - - case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION: { - const struct GNUNET_TESTBED_SlaveConfiguration *imsg; - - imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg; - data_len = (uLong) ntohs (imsg->config_size); - xdata_len = ntohs (imsg->header.size) - - sizeof(struct GNUNET_TESTBED_SlaveConfiguration); - xdata = (const Bytef *) &imsg[1]; - } - break; - - case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST: { - const struct GNUNET_TESTBED_AddHostMessage *imsg; - uint16_t osize; - - imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg; - data_len = (uLong) ntohs (imsg->config_size); - osize = sizeof(struct GNUNET_TESTBED_AddHostMessage) - + ntohs (imsg->username_length) + ntohs (imsg->hostname_length); - xdata_len = ntohs (imsg->header.size) - osize; - xdata = (const Bytef *) ((const void *) imsg + osize); - } - break; - - case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT: { - const struct GNUNET_TESTBED_ControllerLinkResponse *imsg; - - imsg = (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg; - data_len = ntohs (imsg->config_size); - xdata_len = ntohs (imsg->header.size) - - sizeof(const struct GNUNET_TESTBED_ControllerLinkResponse); - xdata = (const Bytef *) &imsg[1]; - } - break; - - case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER: { - const struct GNUNET_TESTBED_PeerCreateMessage *imsg; - - imsg = (const struct GNUNET_TESTBED_PeerCreateMessage *) msg; - data_len = ntohs (imsg->config_size); - xdata_len = ntohs (imsg->header.size) - - sizeof(struct GNUNET_TESTBED_PeerCreateMessage); - xdata = (const Bytef *) &imsg[1]; - } - break; - - case GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER: { - const struct GNUNET_TESTBED_PeerReconfigureMessage *imsg; - - imsg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) msg; - data_len = ntohs (imsg->config_size); - xdata_len = ntohs (imsg->header.size) - - sizeof(struct GNUNET_TESTBED_PeerReconfigureMessage); - xdata = (const Bytef *) &imsg[1]; - } - break; - - default: - GNUNET_assert (0); - } - data = GNUNET_malloc (data_len); - if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len))) - { - GNUNET_free (data); - GNUNET_break_op (0); /* Un-compression failure */ - return NULL; - } - cfg = GNUNET_CONFIGURATION_create (); - if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, - (const char *) data, - (size_t) data_len, - NULL)) - { - GNUNET_free (data); - GNUNET_break_op (0); /* De-serialization failure */ - return NULL; - } - GNUNET_free (data); - return cfg; -} - - -const char * -GNUNET_TESTBED_parse_error_string_ ( - const struct GNUNET_TESTBED_OperationFailureEventMessage *msg) -{ - uint16_t msize; - const char *emsg; - - msize = ntohs (msg->header.size); - if (sizeof(struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize) - return NULL; - msize -= sizeof(struct GNUNET_TESTBED_OperationFailureEventMessage); - emsg = (const char *) &msg[1]; - if ('\0' != emsg[msize - 1]) - { - GNUNET_break (0); - return NULL; - } - return emsg; -} - - -/** - * Function to return the operation id for a controller. The operation id is - * created from the controllers host id and its internal operation counter. - * - * @param controller the handle to the controller whose operation id has to be incremented - * @return the incremented operation id. - */ -uint64_t -GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller *controller) -{ - uint64_t op_id; - - op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host); - op_id = op_id << 32; - op_id |= (uint64_t) controller->operation_counter++; - return op_id; -} - - -/** - * Function called when a shutdown peers operation is ready - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -opstart_shutdown_peers (void *cls) -{ - struct OperationContext *opc = cls; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_ShutdownPeersMessage *msg; - - opc->state = OPC_STATE_STARTED; - env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS); - msg->operation_id = GNUNET_htonll (opc->id); - GNUNET_TESTBED_insert_opc_ (opc->c, opc); - GNUNET_MQ_send (opc->c->mq, env); -} - - -/** - * Callback which will be called when shutdown peers operation is released - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -oprelease_shutdown_peers (void *cls) -{ - struct OperationContext *opc = cls; - - switch (opc->state) - { - case OPC_STATE_STARTED: - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - - /* no break; continue */ - case OPC_STATE_INIT: - GNUNET_free (opc->data); - break; - - case OPC_STATE_FINISHED: - break; - } - GNUNET_free (opc); -} - - -/** - * Stops and destroys all peers. Is equivalent of calling - * GNUNET_TESTBED_peer_stop() and GNUNET_TESTBED_peer_destroy() on all peers, - * except that the peer stop event and operation finished event corresponding to - * the respective functions are not generated. This function should be called - * when there are no other pending operations. If there are pending operations, - * it will return NULL - * - * @param c the controller to send this message to - * @param op_cls closure for the operation - * @param cb the callback to call when all peers are stopped and destroyed - * @param cb_cls the closure for the callback - * @return operation handle on success; NULL if any pending operations are - * present - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *c, - void *op_cls, - GNUNET_TESTBED_OperationCompletionCallback cb, - void *cb_cls) -{ - struct OperationContext *opc; - struct ShutdownPeersData *data; - - if (0 != GNUNET_CONTAINER_multihashmap32_size (c->opc_map)) - return NULL; - data = GNUNET_new (struct ShutdownPeersData); - data->cb = cb; - data->cb_cls = cb_cls; - opc = GNUNET_new (struct OperationContext); - opc->c = c; - opc->op_cls = op_cls; - opc->data = data; - opc->id = GNUNET_TESTBED_get_next_op_id (c); - opc->type = OP_SHUTDOWN_PEERS; - opc->state = OPC_STATE_INIT; - opc->op = GNUNET_TESTBED_operation_create_ (opc, - &opstart_shutdown_peers, - &oprelease_shutdown_peers); - GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, - opc->op); - GNUNET_TESTBED_operation_begin_wait_ (opc->op); - return opc->op; -} - - -/** - * Return the index of the peer inside of the total peer array, - * aka. the peer's "unique ID". - * - * @param peer Peer handle. - * - * @return The peer's unique ID. - */ -uint32_t -GNUNET_TESTBED_get_index (const struct GNUNET_TESTBED_Peer *peer) -{ - return peer->unique_id; -} - - -/** - * Remove a barrier and it was the last one in the barrier hash map, destroy the - * hash map - * - * @param barrier the barrier to remove - */ -void -GNUNET_TESTBED_barrier_remove_ (struct GNUNET_TESTBED_Barrier *barrier) -{ - struct GNUNET_TESTBED_Controller *c = barrier->c; - - GNUNET_assert (NULL != c->barrier_map); /* No barriers present */ - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_remove (c->barrier_map, - &barrier->key, - barrier)); - GNUNET_free (barrier->name); - GNUNET_free (barrier); - if (0 == GNUNET_CONTAINER_multihashmap_size (c->barrier_map)) - { - GNUNET_CONTAINER_multihashmap_destroy (c->barrier_map); - c->barrier_map = NULL; - } -} - - -struct GNUNET_TESTBED_Barrier * -GNUNET_TESTBED_barrier_init_ (struct GNUNET_TESTBED_Controller *controller, - const char *name, - unsigned int quorum, - GNUNET_TESTBED_barrier_status_cb cb, - void *cls, - int echo) -{ - struct GNUNET_TESTBED_BarrierInit *msg; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_Barrier *barrier; - struct GNUNET_HashCode key; - size_t name_len; - - GNUNET_assert (quorum <= 100); - GNUNET_assert (NULL != cb); - name_len = strlen (name); - GNUNET_assert (0 < name_len); - GNUNET_CRYPTO_hash (name, name_len, &key); - if (NULL == controller->barrier_map) - controller->barrier_map = - GNUNET_CONTAINER_multihashmap_create (3, GNUNET_YES); - if (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (controller->barrier_map, &key)) - { - GNUNET_break (0); - return NULL; - } - LOG_DEBUG ("Initialising barrier `%s'\n", name); - barrier = GNUNET_new (struct GNUNET_TESTBED_Barrier); - barrier->c = controller; - barrier->name = GNUNET_strdup (name); - barrier->cb = cb; - barrier->cls = cls; - barrier->echo = echo; - GNUNET_memcpy (&barrier->key, &key, sizeof(struct GNUNET_HashCode)); - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put ( - controller->barrier_map, - &barrier->key, - barrier, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); - - env = GNUNET_MQ_msg_extra (msg, - name_len, - GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT); - msg->quorum = (uint8_t) quorum; - GNUNET_memcpy (msg->name, barrier->name, name_len); - GNUNET_MQ_send (barrier->c->mq, env); - return barrier; -} - - -/** - * Initialise a barrier and call the given callback when the required percentage - * of peers (quorum) reach the barrier OR upon error. - * - * @param controller the handle to the controller - * @param name identification name of the barrier - * @param quorum the percentage of peers that is required to reach the barrier. - * Peers signal reaching a barrier by calling - * GNUNET_TESTBED_barrier_reached(). - * @param cb the callback to call when the barrier is reached or upon error. - * Cannot be NULL. - * @param cb_cls closure for the above callback - * @return barrier handle; NULL upon error - */ -struct GNUNET_TESTBED_Barrier * -GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller, - const char *name, - unsigned int quorum, - GNUNET_TESTBED_barrier_status_cb cb, - void *cb_cls) -{ - return GNUNET_TESTBED_barrier_init_ (controller, - name, - quorum, - cb, - cb_cls, - GNUNET_YES); -} - - -/** - * Cancel a barrier. - * - * @param barrier the barrier handle - */ -void -GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier) -{ - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_BarrierCancel *msg; - size_t slen; - - slen = strlen (barrier->name); - env = - GNUNET_MQ_msg_extra (msg, slen, GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL); - GNUNET_memcpy (msg->name, barrier->name, slen); - GNUNET_MQ_send (barrier->c->mq, env); - GNUNET_TESTBED_barrier_remove_ (barrier); -} - - -/* end of testbed_api.c */ diff --git a/src/testbed/testbed_api.h b/src/testbed/testbed_api.h @@ -1,521 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api.h - * @brief Interface for functions internally exported from testbed_api.c - * @author Sree Harsha Totakura - */ - -#ifndef TESTBED_API_H -#define TESTBED_API_H - -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" -#include "testbed.h" -#include "testbed_helper.h" - -/** - * Testbed Helper binary name - */ -#define HELPER_TESTBED_BINARY "gnunet-helper-testbed" - - -/** - * Enumeration of operations - */ -enum OperationType -{ - /** - * Peer create operation - */ - OP_PEER_CREATE, - - /** - * Peer start operation - */ - OP_PEER_START, - - /** - * Peer stop operation - */ - OP_PEER_STOP, - - /** - * Peer destroy operation - */ - OP_PEER_DESTROY, - - /** - * Get peer information operation - */ - OP_PEER_INFO, - - /** - * Reconfigure a peer - */ - OP_PEER_RECONFIGURE, - - /** - * Overlay connection operation - */ - OP_OVERLAY_CONNECT, - - /** - * Forwarded operation - */ - OP_FORWARDED, - - /** - * Link controllers operation - */ - OP_LINK_CONTROLLERS, - - /** - * Get slave config operation - */ - OP_GET_SLAVE_CONFIG, - - /** - * Stop and destroy all peers - */ - OP_SHUTDOWN_PEERS, - - /** - * Start/stop service at a peer - */ - OP_MANAGE_SERVICE -}; - - -/** - * Enumeration of states of OperationContext - */ -enum OperationContextState -{ - /** - * The initial state where the associated operation has just been created - * and is waiting in the operation queues to be started - */ - OPC_STATE_INIT = 0, - - /** - * The operation has been started. It may occupy some resources which are to - * be freed if cancelled. - */ - OPC_STATE_STARTED, - - /** - * The operation has finished. The end results of this operation may occupy - * some resources which are to be freed by operation_done - */ - OPC_STATE_FINISHED -}; - - -/** - * Context information for GNUNET_TESTBED_Operation - */ -struct OperationContext -{ - /** - * The controller to which this operation context belongs to - */ - struct GNUNET_TESTBED_Controller *c; - - /** - * The operation - */ - struct GNUNET_TESTBED_Operation *op; - - /** - * The operation closure - */ - void *op_cls; - - /** - * Data relevant to the operation - */ - void *data; - - /** - * The id of the operation - */ - uint64_t id; - - /** - * The type of operation - */ - enum OperationType type; - - /** - * The state of the operation - */ - enum OperationContextState state; -}; - - -/** - * Operation empty callback - * - * @param cls closure - */ -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 - * controller is created; this master handle interacts with the - * controller process, destroying it destroys the controller (by - * closing stdin of the controller process). Additionally, - * controllers can interact with each other (in a P2P fashion); those - * links are established via TCP/IP on the controller's service port. - */ -struct GNUNET_TESTBED_Controller -{ - /** - * The host where the controller is running - */ - struct GNUNET_TESTBED_Host *host; - - /** - * The controller callback - */ - GNUNET_TESTBED_ControllerCallback cc; - - /** - * The closure for controller callback - */ - void *cc_cls; - - /** - * The configuration to use while connecting to controller - */ - struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * The message queue to the controller service - */ - struct GNUNET_MQ_Handle *mq; - - /** - * The host registration handle; NULL if no current registration requests are - * present - */ - struct GNUNET_TESTBED_HostRegistrationHandle *rh; - - /** - * The map of active operation contexts - */ - struct GNUNET_CONTAINER_MultiHashMap32 *opc_map; - - /** - * If this callback is not NULL, schedule it as a task when opc_map gets empty - */ - TESTBED_opcq_empty_cb opcq_empty_cb; - - /** - * Closure for the above task - */ - void *opcq_empty_cls; - - /** - * Operation queue for simultaneous operations - */ - struct OperationQueue *opq_parallel_operations; - - /** - * Operation queue for simultaneous service connections - */ - struct OperationQueue *opq_parallel_service_connections; - - /** - * Operation queue for simultaneous topology configuration operations - */ - struct OperationQueue *opq_parallel_topology_config_operations; - - /** - * handle for hashtable of barrier handles, values are - * of type `struct GNUNET_TESTBED_Barrier`. - */ - struct GNUNET_CONTAINER_MultiHashMap *barrier_map; - - /** - * The controller event mask - */ - uint64_t event_mask; - - /** - * The operation id counter. use current value and increment - */ - uint32_t operation_counter; -}; - - -/** - * Handle for barrier - */ -struct GNUNET_TESTBED_Barrier -{ - /** - * hashcode identifying this barrier in the hashmap - */ - struct GNUNET_HashCode key; - - /** - * The controller handle given while initialising this barrier - */ - struct GNUNET_TESTBED_Controller *c; - - /** - * The name of the barrier - */ - char *name; - - /** - * The continuation callback to call when we have a status update on this - */ - GNUNET_TESTBED_barrier_status_cb cb; - - /** - * the closure for the above callback - */ - void *cls; - - /** - * Should the barrier crossed status message be echoed back to the controller? - */ - int echo; -}; - - -/** - * Queues a message in send queue for sending to the service - * - * @param controller the handle to the controller - * @param msg the message to queue - * @deprecated - */ -void -GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller, - struct GNUNET_MessageHeader *msg); - - -/** - * Inserts the given operation context into the operation context map of the - * given controller. Creates the operation context map if one does not exist - * for the controller - * - * @param c the controller - * @param opc the operation context to be inserted - */ -void -GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c, - struct OperationContext *opc); - - -/** - * Removes the given operation context from the operation context map of the - * given controller - * - * @param c the controller - * @param opc the operation context to remove - */ -void -GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c, - struct OperationContext *opc); - - -/** - * Compresses given configuration using zlib compress - * - * @param config the serialized configuration - * @param size the size of config - * @param xconfig will be set to the compressed configuration (memory is fresly - * allocated) - * @return the size of the xconfig - */ -size_t -GNUNET_TESTBED_compress_config_ (const char *config, - size_t size, - char **xconfig); - - -/** - * Function to serialize and compress using zlib a configuration through a - * configuration handle - * - * @param cfg the configuration - * @param size the size of configuration when serialize. Will be set on success. - * @param xsize the sizeo of the compressed configuration. Will be set on success. - * @return the serialized and compressed configuration - */ -char * -GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg, - size_t *size, - size_t *xsize); - - -/** - * Creates a helper initialization message. This function is here because we - * want to use this in testing - * - * @param trusted_ip the ip address of the controller which will be set as TRUSTED - * HOST(all connections form this ip are permitted by the testbed) when - * starting testbed controller at host. This can either be a single ip - * address or a network address in CIDR notation. - * @param hostname the hostname of the destination this message is intended for - * @param cfg the configuration that has to used to start the testbed service - * thru helper - * @return the initialization message - */ -struct GNUNET_TESTBED_HelperInit * -GNUNET_TESTBED_create_helper_init_msg_ (const char *cname, - const char *hostname, - const struct - GNUNET_CONFIGURATION_Handle *cfg); - - -/** - * Sends the given message as an operation. The given callback is called when a - * reply for the operation is available. Call - * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned - * operation context if the cc hasn't been called - * - * @param controller the controller to which the message has to be sent - * @param operation_id the operation id of the message - * @param msg the message to send - * @param cc the callback to call when reply is available - * @param cc_cls the closure for the above callback - * @return the operation context which can be used to cancel the forwarded - * operation - */ -struct OperationContext * -GNUNET_TESTBED_forward_operation_msg_ (struct - GNUNET_TESTBED_Controller *controller, - uint64_t operation_id, - const struct GNUNET_MessageHeader *msg, - GNUNET_MQ_MessageCallback cc, - void *cc_cls); - -/** - * Function to cancel an operation created by simply forwarding an operation - * message. - * - * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_() - */ -void -GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc); - - -/** - * Generates configuration by uncompressing configuration in given message. The - * given message should be of the following types: - * #GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG, - * #GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG - * - * @param msg the message containing compressed configuration - * @return handle to the parsed configuration - */ -struct GNUNET_CONFIGURATION_Handle * -GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg); - - -/** - * Checks the integrity of the OpeationFailureEventMessage and if good returns - * the error message it contains. - * - * @param msg the OperationFailureEventMessage - * @return the error message - */ -const char * -GNUNET_TESTBED_parse_error_string_ (const struct - GNUNET_TESTBED_OperationFailureEventMessage - *msg); - - -/** - * Function to return the operation id for a controller. The operation id is - * created from the controllers host id and its internal operation counter. - * - * @param controller the handle to the controller whose operation id has to be incremented - * @return the incremented operation id. - */ -uint64_t -GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller *controller); - - -/** - * Like GNUNET_TESTBED_get_slave_config(), however without the host registration - * check. Another difference is that this function takes the id of the slave - * host. - * - * @param op_cls the closure for the operation - * @param master the handle to master controller - * @param slave_host_id id of the host where the slave controller is running to - * the slave_host should remain valid until this operation is cancelled - * or marked as finished - * @return the operation handle; - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_get_slave_config_ (void *op_cls, - struct GNUNET_TESTBED_Controller *master, - uint32_t slave_host_id); - - -/** - * Initialise a barrier and call the given callback when the required percentage - * of peers (quorum) reach the barrier OR upon error. - * - * @param controller the handle to the controller - * @param name identification name of the barrier - * @param quorum the percentage of peers that is required to reach the barrier. - * Peers signal reaching a barrier by calling - * GNUNET_TESTBED_barrier_reached(). - * @param cb the callback to call when the barrier is reached or upon error. - * Cannot be NULL. - * @param cls closure for the above callback - * @param echo #GNUNET_YES to echo the barrier crossed status message back to the - * controller - * @return barrier handle; NULL upon error - */ -struct GNUNET_TESTBED_Barrier * -GNUNET_TESTBED_barrier_init_ (struct GNUNET_TESTBED_Controller *controller, - const char *name, - unsigned int quorum, - GNUNET_TESTBED_barrier_status_cb cb, - void *cls, - int echo); - - -/** - * Remove a barrier and it was the last one in the barrier hash map, destroy the - * hash map - * - * @param barrier the barrier to remove - */ -void -GNUNET_TESTBED_barrier_remove_ (struct GNUNET_TESTBED_Barrier *barrier); - - -#endif -/* end of testbed_api.h */ diff --git a/src/testbed/testbed_api_barriers.c b/src/testbed/testbed_api_barriers.c @@ -1,253 +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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_barriers.c - * @brief API implementation for testbed barriers - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ -#include "platform.h" -#include "gnunet_testbed_service.h" -#include "testbed_api.h" - -/** - * Logging shorthand - */ -#define LOG(type, ...) \ - GNUNET_log_from (type, "testbed-api-barriers", __VA_ARGS__); - -/** - * Debug logging shorthand - */ -#define LOG_DEBUG(...) \ - LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__); - - -/** - * Barrier wait handle - */ -struct GNUNET_TESTBED_BarrierWaitHandle -{ - /** - * The name of the barrier - */ - char *name; - - /** - * Then configuration used for the client connection - */ - struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * The testbed-barrier service message queue. - */ - struct GNUNET_MQ_Handle *mq; - - /** - * The barrier wait callback - */ - GNUNET_TESTBED_barrier_wait_cb cb; - - /** - * The closure for @e cb. - */ - void *cb_cls; -}; - - -/** - * Check if barrier status message is well-formed. - * - * @param cls closure - * @param msg received message - * @return #GNUNET_OK if the message is well-formed. - */ -static int -check_status (void *cls, - const struct GNUNET_TESTBED_BarrierStatusMsg *msg) -{ - /* FIXME: this fails to actually check that the message - follows the protocol spec (0-terminations!). However, - not critical as #handle_status() doesn't interpret the - variable-size part anyway right now. */ - return GNUNET_OK; -} - - -/** - * Type of a function to call when we receive a message - * from the service. - * - * @param cls closure - * @param msg received message - */ -static void -handle_status (void *cls, - const struct GNUNET_TESTBED_BarrierStatusMsg *msg) -{ - struct GNUNET_TESTBED_BarrierWaitHandle *h = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Got barrier status %d\n", - (int) ntohs (msg->status)); - switch (ntohs (msg->status)) - { - case GNUNET_TESTBED_BARRIERSTATUS_ERROR: - h->cb (h->cb_cls, - h->name, - GNUNET_SYSERR); - break; - - case GNUNET_TESTBED_BARRIERSTATUS_INITIALISED: - h->cb (h->cb_cls, - h->name, - GNUNET_SYSERR); - GNUNET_break (0); - break; - - case GNUNET_TESTBED_BARRIERSTATUS_CROSSED: - h->cb (h->cb_cls, - h->name, - GNUNET_OK); - break; - - default: - GNUNET_break_op (0); - h->cb (h->cb_cls, - h->name, - GNUNET_SYSERR); - break; - } - GNUNET_TESTBED_barrier_wait_cancel (h); -} - - -/** - * Generic error handler, called with the appropriate error code and - * the same closure specified at the creation of the message queue. - * Not every message queue implementation supports an error handler. - * - * @param cls closure with the `struct GNUNET_TESTBED_BarrierWaitHandle *` - * @param error error code - */ -static void -mq_error_handler (void *cls, - enum GNUNET_MQ_Error error) -{ - struct GNUNET_TESTBED_BarrierWaitHandle *h = cls; - - h->cb (h->cb_cls, - h->name, - GNUNET_SYSERR); - GNUNET_TESTBED_barrier_wait_cancel (h); -} - - -struct GNUNET_TESTBED_BarrierWaitHandle * -GNUNET_TESTBED_barrier_wait (const char *name, - GNUNET_TESTBED_barrier_wait_cb cb, - void *cb_cls) -{ - struct GNUNET_TESTBED_BarrierWaitHandle *h - = GNUNET_new (struct GNUNET_TESTBED_BarrierWaitHandle); - struct GNUNET_MQ_MessageHandler handlers[] = { - GNUNET_MQ_hd_var_size (status, - GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, - struct GNUNET_TESTBED_BarrierStatusMsg, - h), - GNUNET_MQ_handler_end () - }; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_BarrierWait *msg; - const char *cfg_filename; - size_t name_len; - - GNUNET_assert (NULL != cb); - cfg_filename = getenv (ENV_TESTBED_CONFIG); - if (NULL == cfg_filename) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Are you running under testbed?\n"); - GNUNET_free (h); - return NULL; - } - h->cfg = GNUNET_CONFIGURATION_create (); - if (GNUNET_OK != - GNUNET_CONFIGURATION_load (h->cfg, - cfg_filename)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Unable to load configuration from file `%s'\n", - cfg_filename); - GNUNET_CONFIGURATION_destroy (h->cfg); - GNUNET_free (h); - return NULL; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Waiting on barrier `%s'\n", - name); - h->name = GNUNET_strdup (name); - h->cb = cb; - h->cb_cls = cb_cls; - h->mq = GNUNET_CLIENT_connect (h->cfg, - "testbed-barrier", - handlers, - &mq_error_handler, - h); - if (NULL == h->mq) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Unable to connect to local testbed-barrier service\n"); - GNUNET_TESTBED_barrier_wait_cancel (h); - return NULL; - } - name_len = strlen (name); /* NOTE: unusual to not have 0-termination, change? */ - env = GNUNET_MQ_msg_extra (msg, - name_len, - GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT); - GNUNET_memcpy (msg->name, - name, - name_len); - GNUNET_MQ_send (h->mq, - env); - return h; -} - - -/** - * Cancel a barrier wait handle - * - * @param h the barrier wait handle - */ -void -GNUNET_TESTBED_barrier_wait_cancel (struct GNUNET_TESTBED_BarrierWaitHandle *h) -{ - if (NULL != h->mq) - { - GNUNET_MQ_destroy (h->mq); - h->mq = NULL; - } - GNUNET_free (h->name); - GNUNET_CONFIGURATION_destroy (h->cfg); - GNUNET_free (h); -} - - -/* end of testbed_api_barriers.c */ diff --git a/src/testbed/testbed_api_hosts.c b/src/testbed/testbed_api_hosts.c @@ -1,1521 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_hosts.c - * @brief API for manipulating 'hosts' controlled by the GNUnet testing service; - * allows parsing hosts files, starting, stopping and communicating (via - * SSH/stdin/stdout) with the remote (or local) processes - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" -#include "gnunet_core_service.h" -#include "gnunet_transport_service.h" - -#include "testbed_api.h" -#include "testbed_api_hosts.h" -#include "testbed_helper.h" -#include "testbed_api_operations.h" - -#include <zlib.h> -#include <regex.h> - -/** - * Generic logging shorthand - */ -#define LOG(kind, ...) GNUNET_log_from (kind, "testbed-api-hosts", __VA_ARGS__); - -/** - * Debug logging shorthand - */ -#define LOG_DEBUG(...) LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__); - -/** - * Prints API violation message - */ -#define API_VIOLATION(cond, errstr) \ - do \ - { \ - if (cond) \ - break; \ - LOG (GNUNET_ERROR_TYPE_ERROR, "API violation detected: %s\n", errstr); \ - GNUNET_assert (0); \ - } while (0) - -/** - * Log an error message at log-level 'level' that indicates a failure of the - * command 'cmd' with the message given by gai_strerror(rc). - */ -#define LOG_GAI(level, cmd, rc) \ - do \ - { \ - LOG (level, \ - _ ("`%s' failed at %s:%d with error: %s\n"), \ - cmd, \ - __FILE__, \ - __LINE__, \ - gai_strerror (rc)); \ - } while (0) - -/** - * Number of extra elements we create space for when we grow host list - */ -#define HOST_LIST_GROW_STEP 10 - - -/** - * A list entry for registered controllers list - */ -struct RegisteredController -{ - /** - * The controller at which this host is registered - */ - const struct GNUNET_TESTBED_Controller *controller; - - /** - * The next ptr for DLL - */ - struct RegisteredController *next; - - /** - * The prev ptr for DLL - */ - struct RegisteredController *prev; -}; - - -/** - * Opaque handle to a host running experiments managed by the testing framework. - * The master process must be able to SSH to this host without password (via - * ssh-agent). - */ -struct GNUNET_TESTBED_Host -{ - /** - * The hostname of the host; NULL for localhost - */ - const char *hostname; - - /** - * The username to be used for SSH login - */ - const char *username; - - /** - * the configuration to use as a template while starting a controller on this - * host. Operation queue size specific to a host are also read from this - * configuration handle. After starting the controller, it points to the actual - * configuration with which the controller is running - */ - struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * The head for the list of controllers where this host is registered - */ - struct RegisteredController *rc_head; - - /** - * The tail for the list of controllers where this host is registered - */ - struct RegisteredController *rc_tail; - - /** - * Operation queue for simultaneous overlay connect operations target at this - * host - */ - struct OperationQueue *opq_parallel_overlay_connect_operations; - - /** - * Is a controller started on this host? FIXME: Is this needed? - */ - int controller_started; - - /** - * Is this host locked by GNUNET_TESTBED_controller_start()? - */ - int locked; - - /** - * Global ID we use to refer to a host on the network - */ - uint32_t id; - - /** - * The port which is to be used for SSH - */ - uint16_t port; -}; - - -/** - * Array of available hosts - */ -static struct GNUNET_TESTBED_Host **host_list; - -/** - * The size of the available hosts list - */ -static unsigned int host_list_size; - - -/** - * Lookup a host by ID. - * - * @param id global host ID assigned to the host; 0 is - * reserved to always mean 'localhost' - * @return handle to the host, NULL if host not found - */ -struct GNUNET_TESTBED_Host * -GNUNET_TESTBED_host_lookup_by_id_ (uint32_t id) -{ - if (host_list_size <= id) - return NULL; - return host_list[id]; -} - - -/** - * Create a host by ID; given this host handle, we could not - * run peers at the host, but we can talk about the host - * internally. - * - * @param id global host ID assigned to the host; 0 is - * reserved to always mean 'localhost' - * @param cfg the configuration to use as a template while starting a controller - * on this host. Operation queue sizes specific to a host are also - * read from this configuration handle - * @return handle to the host, NULL on error - */ -struct GNUNET_TESTBED_Host * -GNUNET_TESTBED_host_create_by_id_ ( - uint32_t id, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - return GNUNET_TESTBED_host_create_with_id (id, NULL, NULL, cfg, 0); -} - - -uint32_t -GNUNET_TESTBED_host_get_id_ (const struct GNUNET_TESTBED_Host *host) -{ - return host->id; -} - - -/** - * Obtain the host's hostname. - * - * @param host handle to the host, NULL means 'localhost' - * @return hostname of the host - */ -const char * -GNUNET_TESTBED_host_get_hostname (const struct GNUNET_TESTBED_Host *host) -{ - return host->hostname; -} - - -/** - * Obtain the host's username - * - * @param host handle to the host, NULL means 'localhost' - * @return username to login to the host - */ -const char * -GNUNET_TESTBED_host_get_username_ (const struct GNUNET_TESTBED_Host *host) -{ - return host->username; -} - - -/** - * Obtain the host's ssh port - * - * @param host handle to the host, NULL means 'localhost' - * @return username to login to the host - */ -uint16_t -GNUNET_TESTBED_host_get_ssh_port_ (const struct GNUNET_TESTBED_Host *host) -{ - return host->port; -} - - -/** - * Check whether a controller is already started on the given host - * - * @param host the handle to the host - * @return GNUNET_YES if the controller is already started; GNUNET_NO if not - */ -int -GNUNET_TESTBED_host_controller_started (const struct GNUNET_TESTBED_Host *host) -{ - return host->controller_started; -} - - -/** - * Obtain the host's configuration template - * - * @param host handle to the host - * @return the host's configuration template - */ -const struct GNUNET_CONFIGURATION_Handle * -GNUNET_TESTBED_host_get_cfg_ (const struct GNUNET_TESTBED_Host *host) -{ - return host->cfg; -} - - -/** - * Function to replace host's configuration - * - * @param host the host handle - * @param new_cfg the new configuration to replace the old one - */ -void -GNUNET_TESTBED_host_replace_cfg_ ( - struct GNUNET_TESTBED_Host *host, - const struct GNUNET_CONFIGURATION_Handle *new_cfg) -{ - GNUNET_CONFIGURATION_destroy (host->cfg); - host->cfg = GNUNET_CONFIGURATION_dup (new_cfg); -} - - -/** - * Create a host to run peers and controllers on. - * - * @param id global host ID assigned to the host; 0 is - * reserved to always mean 'localhost' - * @param hostname name of the host, use "NULL" for localhost - * @param username username to use for the login; may be NULL - * @param cfg the configuration to use as a template while starting a controller - * on this host. Operation queue sizes specific to a host are also - * read from this configuration handle - * @param port port number to use for ssh; use 0 to let ssh decide - * @return handle to the host, NULL on error - */ -struct GNUNET_TESTBED_Host * -GNUNET_TESTBED_host_create_with_id ( - uint32_t id, - const char *hostname, - const char *username, - const struct GNUNET_CONFIGURATION_Handle *cfg, - uint16_t port) -{ - struct GNUNET_TESTBED_Host *host; - unsigned int new_size; - - if ((id < host_list_size) && (NULL != host_list[id])) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Host with id: %u already created\n", id); - return NULL; - } - host = GNUNET_new (struct GNUNET_TESTBED_Host); - host->hostname = (NULL != hostname) ? GNUNET_strdup (hostname) : NULL; - host->username = (NULL != username) ? GNUNET_strdup (username) : NULL; - host->id = id; - host->port = (0 == port) ? 22 : port; - host->cfg = GNUNET_CONFIGURATION_dup (cfg); - host->opq_parallel_overlay_connect_operations = - GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_ADAPTIVE, - UINT_MAX); - new_size = host_list_size; - while (id >= new_size) - new_size += HOST_LIST_GROW_STEP; - if (new_size != host_list_size) - GNUNET_array_grow (host_list, host_list_size, new_size); - GNUNET_assert (id < host_list_size); - LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding host with id: %u\n", host->id); - host_list[id] = host; - return host; -} - - -/** - * Create a host to run peers and controllers on. - * - * @param hostname name of the host, use "NULL" for localhost - * @param username username to use for the login; may be NULL - * @param cfg the configuration to use as a template while starting a controller - * on this host. Operation queue sizes specific to a host are also - * read from this configuration handle - * @param port port number to use for ssh; use 0 to let ssh decide - * @return handle to the host, NULL on error - */ -struct GNUNET_TESTBED_Host * -GNUNET_TESTBED_host_create (const char *hostname, - const char *username, - const struct GNUNET_CONFIGURATION_Handle *cfg, - uint16_t port) -{ - static uint32_t uid_generator; - - if (NULL == hostname) - return GNUNET_TESTBED_host_create_with_id (0, - hostname, - username, - cfg, - port); - return GNUNET_TESTBED_host_create_with_id (++uid_generator, - hostname, - username, - cfg, - port); -} - - -unsigned int -GNUNET_TESTBED_hosts_load_from_file ( - const char *filename, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTBED_Host ***hosts) -{ - struct GNUNET_TESTBED_Host *starting_host; - char *data; - char *buf; - char *username; - char *hostname; - regex_t rex; - regmatch_t pmatch[6]; - uint64_t fs; - short int port; - unsigned int offset; - unsigned int count; - - - GNUNET_assert (NULL != filename); - if (GNUNET_YES != GNUNET_DISK_file_test (filename)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, _ ("Hosts file %s not found\n"), filename); - return 0; - } - if (GNUNET_OK != - GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES)) - fs = 0; - if (0 == fs) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - _ ("Hosts file %s has no data\n"), - filename); - return 0; - } - data = GNUNET_malloc (fs); - if (fs != GNUNET_DISK_fn_read (filename, data, fs)) - { - GNUNET_free (data); - LOG (GNUNET_ERROR_TYPE_WARNING, - _ ("Hosts file %s cannot be read\n"), - filename); - return 0; - } - buf = data; - offset = 0; - starting_host = NULL; - count = 0; - /* refer RFC 952 and RFC 1123 for valid hostnames */ - GNUNET_assert (0 == regcomp (&rex, - "^(([[:alnum:]]+)@)?" /* username */ - "([[:alnum:]]+[-[:alnum:]_\\.]+)" /* hostname */ - "(:([[:digit:]]{1,5}))?", /* port */ - REG_EXTENDED | REG_ICASE)); - while (offset < (fs - 1)) - { - offset++; - if (((data[offset] == '\n')) && (buf != &data[offset])) - { - unsigned int size; - - data[offset] = '\0'; - username = NULL; - hostname = NULL; - port = 0; - if ((REG_NOMATCH == regexec (&rex, buf, 6, pmatch, 0)) || - (-1 == pmatch[3].rm_so)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Error reading line `%s' in hostfile\n", - buf); - buf = &data[offset + 1]; - continue; - } - if (-1 != pmatch[2].rm_so) - { - size = pmatch[2].rm_eo - pmatch[2].rm_so; - username = GNUNET_malloc (size + 1); - GNUNET_assert ( - 0 != GNUNET_strlcpy (username, buf + pmatch[2].rm_so, size + 1)); - } - if (-1 != pmatch[5].rm_so) - { - (void) sscanf (buf + pmatch[5].rm_so, "%5hd", &port); - } - size = pmatch[3].rm_eo - pmatch[3].rm_so; - hostname = GNUNET_malloc (size + 1); - GNUNET_assert ( - 0 != GNUNET_strlcpy (hostname, buf + pmatch[3].rm_so, size + 1)); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Successfully read host %s, port %d and user %s from file\n", - (NULL == hostname) ? "NULL" : hostname, - port, - (NULL == username) ? "NULL" : username); - /* We store hosts in a static list; hence we only require the starting - * host pointer in that list to access the newly created list of hosts */ - if (NULL == starting_host) - starting_host = - GNUNET_TESTBED_host_create (hostname, username, cfg, port); - else - (void) GNUNET_TESTBED_host_create (hostname, username, cfg, port); - count++; - GNUNET_free (username); - GNUNET_free (hostname); - buf = &data[offset + 1]; - } - else if ((data[offset] == '\n') || (data[offset] == '\0')) - buf = &data[offset + 1]; - } - regfree (&rex); - GNUNET_free (data); - if (NULL == starting_host) - return 0; - *hosts = GNUNET_malloc (sizeof(struct GNUNET_TESTBED_Host *) * count); - GNUNET_memcpy (*hosts, - &host_list[GNUNET_TESTBED_host_get_id_ (starting_host)], - sizeof(struct GNUNET_TESTBED_Host *) * count); - return count; -} - - -/** - * Resolves a hostname using getaddrinfo - * - * @param host the hostname - * @return the string representing the IPv4 address of the given host; NULL upon error - */ -const char * -simple_resolve (const char *host) -{ - struct addrinfo *res; - const struct sockaddr_in *in_addr; - char *hostip; - struct addrinfo hint; - unsigned int rc; - - hint.ai_family = AF_INET; /* IPv4 */ - hint.ai_socktype = 0; - hint.ai_protocol = 0; - hint.ai_addrlen = 0; - hint.ai_addr = NULL; - hint.ai_canonname = NULL; - hint.ai_next = NULL; - hint.ai_flags = AI_NUMERICSERV; - res = NULL; - LOG_DEBUG ("Resolving [%s]\n", host); - if (0 != (rc = getaddrinfo (host, "22", &hint, &res))) - { - LOG_GAI (GNUNET_ERROR_TYPE_ERROR, "getaddrinfo", rc); - return NULL; - } - GNUNET_assert (NULL != res); - GNUNET_assert (NULL != res->ai_addr); - GNUNET_assert (sizeof(struct sockaddr_in) == res->ai_addrlen); - in_addr = (const struct sockaddr_in *) res->ai_addr; - hostip = inet_ntoa (in_addr->sin_addr); - GNUNET_assert (NULL != hostip); - freeaddrinfo (res); - LOG_DEBUG ("Resolved [%s] to [%s]\n", host, hostip); - return hostip; -} - - -/** - * Destroy a host handle. Must only be called once everything - * running on that host has been stopped. - * - * @param host handle to destroy - */ -void -GNUNET_TESTBED_host_destroy (struct GNUNET_TESTBED_Host *host) -{ - GNUNET_assert (host->id < host_list_size); - GNUNET_assert (host_list[host->id] == host); - host_list[host->id] = NULL; - /* clear registered controllers list */ - for (struct RegisteredController *rc = host->rc_head; - NULL != rc; - rc = host->rc_head) - { - GNUNET_CONTAINER_DLL_remove (host->rc_head, host->rc_tail, rc); - GNUNET_free (rc); - } - GNUNET_free_nz ((char *) host->username); - GNUNET_free_nz ((char *) host->hostname); - GNUNET_TESTBED_operation_queue_destroy_ ( - host->opq_parallel_overlay_connect_operations); - GNUNET_CONFIGURATION_destroy (host->cfg); - GNUNET_free (host); - while (host_list_size >= HOST_LIST_GROW_STEP) - { - uint32_t id; - - for (id = host_list_size - 1; id > host_list_size - HOST_LIST_GROW_STEP; - id--) - if (NULL != host_list[id]) - break; - if (id != host_list_size - HOST_LIST_GROW_STEP) - break; - if (NULL != host_list[id]) - break; - host_list_size -= HOST_LIST_GROW_STEP; - } - host_list = - GNUNET_realloc (host_list, - sizeof(struct GNUNET_TESTBED_Host *) * host_list_size); -} - - -/** - * Marks a host as registered with a controller - * - * @param host the host to mark - * @param controller the controller at which this host is registered - */ -void -GNUNET_TESTBED_mark_host_registered_at_ ( - struct GNUNET_TESTBED_Host *host, - const struct GNUNET_TESTBED_Controller *const controller) -{ - struct RegisteredController *rc; - - for (rc = host->rc_head; NULL != rc; rc = rc->next) - { - if (controller == rc->controller) /* already registered at controller */ - { - GNUNET_break (0); - return; - } - } - rc = GNUNET_new (struct RegisteredController); - rc->controller = controller; - GNUNET_CONTAINER_DLL_insert_tail (host->rc_head, host->rc_tail, rc); -} - - -/** - * Unmarks a host registered at a controller - * - * @param host the host to unmark - * @param controller the controller at which this host has to be unmarked - */ -void -GNUNET_TESTBED_deregister_host_at_ ( - struct GNUNET_TESTBED_Host *host, - const struct GNUNET_TESTBED_Controller *const controller) -{ - struct RegisteredController *rc; - - for (rc = host->rc_head; NULL != rc; rc = rc->next) - if (controller == rc->controller) - break; - if (NULL == rc) - { - GNUNET_break (0); - return; - } - GNUNET_CONTAINER_DLL_remove (host->rc_head, host->rc_tail, rc); - GNUNET_free (rc); -} - - -/** - * Checks whether a host has been registered - * - * @param host the host to check - * @param controller the controller at which host's registration is checked - * @return GNUNET_YES if registered; GNUNET_NO if not - */ -int -GNUNET_TESTBED_is_host_registered_ ( - const struct GNUNET_TESTBED_Host *host, - const struct GNUNET_TESTBED_Controller *const controller) -{ - struct RegisteredController *rc; - - for (rc = host->rc_head; NULL != rc; rc = rc->next) - { - if (controller == rc->controller) /* already registered at controller */ - { - return GNUNET_YES; - } - } - return GNUNET_NO; -} - - -/** - * Handle for controller process - */ -struct GNUNET_TESTBED_ControllerProc -{ - /** - * The process handle - */ - struct GNUNET_HELPER_Handle *helper; - - /** - * The arguments used to start the helper - */ - char **helper_argv; - - /** - * The host where the helper is run - */ - struct GNUNET_TESTBED_Host *host; - - /** - * The controller error callback - */ - GNUNET_TESTBED_ControllerStatusCallback cb; - - /** - * The closure for the above callback - */ - void *cls; - - /** - * The send handle for the helper - */ - struct GNUNET_HELPER_SendHandle *shandle; - - /** - * The message corresponding to send handle - */ - struct GNUNET_MessageHeader *msg; -}; - - -/** - * Function to copy NULL terminated list of arguments - * - * @param argv the NULL terminated list of arguments. Cannot be NULL. - * @return the copied NULL terminated arguments - */ -static char ** -copy_argv (const char *const *argv) -{ - char **argv_dup; - unsigned int argp; - - GNUNET_assert (NULL != argv); - for (argp = 0; NULL != argv[argp]; argp++) - ; - argv_dup = GNUNET_malloc (sizeof(char *) * (argp + 1)); - for (argp = 0; NULL != argv[argp]; argp++) - argv_dup[argp] = GNUNET_strdup (argv[argp]); - return argv_dup; -} - - -/** - * Function to join NULL terminated list of arguments - * - * @param argv1 the NULL terminated list of arguments. Cannot be NULL. - * @param argv2 the NULL terminated list of arguments. Cannot be NULL. - * @return the joined NULL terminated arguments - */ -static char ** -join_argv (const char *const *argv1, const char *const *argv2) -{ - char **argvj; - char *argv; - unsigned int carg; - unsigned int cnt; - - carg = 0; - argvj = NULL; - for (cnt = 0; NULL != argv1[cnt]; cnt++) - { - argv = GNUNET_strdup (argv1[cnt]); - GNUNET_array_append (argvj, carg, argv); - } - for (cnt = 0; NULL != argv2[cnt]; cnt++) - { - argv = GNUNET_strdup (argv2[cnt]); - GNUNET_array_append (argvj, carg, argv); - } - GNUNET_array_append (argvj, carg, NULL); - return argvj; -} - - -/** - * Frees the given NULL terminated arguments - * - * @param argv the NULL terminated list of arguments - */ -static void -free_argv (char **argv) -{ - unsigned int argp; - - for (argp = 0; NULL != argv[argp]; argp++) - GNUNET_free (argv[argp]); - GNUNET_free (argv); -} - - -/** - * Generates arguments for opening a remote shell. Builds up the arguments - * from the environment variable GNUNET_TESTBED_RSH_CMD. The variable - * should not mention `-p' (port) option and destination address as these will - * be set locally in the function from its parameteres. If the environmental - * variable is not found then it defaults to `ssh -o BatchMode=yes -o - * NoHostAuthenticationForLocalhost=yes -o StrictHostkeyChecking=no -o - * PasswordAuthentication=no' - * - * @param port the destination port number - * @param hostname the hostname of the target host - * @param username the username to use while connecting to target host - * @return NULL terminated list of arguments - */ -static char ** -gen_rsh_args (const char *port, const char *hostname, const char *username) -{ - static const char *default_ssh_args[] = - { "ssh", - "-o", - "BatchMode=yes", - "-o", - "NoHostAuthenticationForLocalhost=yes", - "-o", - "StrictHostKeyChecking=no", - "-o", - "PasswordAuthentication=no", - "%h", - NULL }; - char **ssh_args; - char *ssh_cmd; - char *ssh_cmd_cp; - char *arg; - const char *new_arg; - unsigned int size; - unsigned int cnt; - - ssh_args = NULL; - if (NULL != (ssh_cmd = getenv ("GNUNET_TESTBED_RSH_CMD"))) - { - ssh_cmd = GNUNET_strdup (ssh_cmd); - ssh_cmd_cp = ssh_cmd; - for (size = 0; NULL != (arg = strtok (ssh_cmd, " ")); ssh_cmd = NULL) - GNUNET_array_append (ssh_args, size, GNUNET_strdup (arg)); - GNUNET_free (ssh_cmd_cp); - } - else - { - ssh_args = copy_argv (default_ssh_args); - size = (sizeof(default_ssh_args)) / (sizeof(const char *)); - GNUNET_array_grow (ssh_args, size, size - 1); - } - for (cnt = 0; cnt < size; cnt++) - { - arg = ssh_args[cnt]; - if ('%' != arg[0]) - continue; - switch (arg[1]) - { - case 'p': - new_arg = port; - break; - - case 'u': - new_arg = username; - break; - - case 'h': - new_arg = hostname; - break; - - default: - continue; - } - if (NULL == new_arg) - continue; - GNUNET_free (arg); - ssh_args[cnt] = GNUNET_strdup (new_arg); - } - GNUNET_array_append (ssh_args, size, NULL); - return ssh_args; -} - - -/** - * Generates the arguments needed for executing the given binary in a remote - * shell. Builds the arguments from the environmental variable - * GNUNET_TESTBED_RSH_CMD_SUFFIX. If the environmental variable is not found, - * only the given binary name will be present in the returned arguments - * - * @param append_args the arguments to append after generating the suffix - * arguments. Can be NULL; if not must be NULL terminated 'char *' array - * @return NULL-terminated args - */ -static char ** -gen_rsh_suffix_args (const char *const *append_args) -{ - char **rshell_args; - char *rshell_cmd; - char *rshell_cmd_cp; - char *arg; - unsigned int cnt; - unsigned int append_cnt; - - rshell_args = NULL; - cnt = 0; - if (NULL != (rshell_cmd = getenv ("GNUNET_TESTBED_RSH_CMD_SUFFIX"))) - { - rshell_cmd = GNUNET_strdup (rshell_cmd); - rshell_cmd_cp = rshell_cmd; - for (; NULL != (arg = strtok (rshell_cmd, " ")); rshell_cmd = NULL) - GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (arg)); - GNUNET_free (rshell_cmd_cp); - } - if (NULL != append_args) - { - for (append_cnt = 0; NULL != append_args[append_cnt]; append_cnt++) - GNUNET_array_append (rshell_args, - cnt, - GNUNET_strdup (append_args[append_cnt])); - } - GNUNET_array_append (rshell_args, cnt, NULL); - return rshell_args; -} - - -/** - * Functions with this signature are called whenever a - * complete message is received by the tokenizer. - * - * Do not call GNUNET_SERVER_mst_destroy in callback - * - * @param cls closure - * @param message the actual message - * - * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing - */ -static int -helper_mst (void *cls, const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_TESTBED_ControllerProc *cp = cls; - const struct GNUNET_TESTBED_HelperReply *msg; - const char *hostname; - char *config; - uLongf config_size; - uLongf xconfig_size; - - msg = (const struct GNUNET_TESTBED_HelperReply *) message; - GNUNET_assert (sizeof(struct GNUNET_TESTBED_HelperReply) < - ntohs (msg->header.size)); - GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY == - ntohs (msg->header.type)); - config_size = (uLongf) ntohs (msg->config_size); - xconfig_size = (uLongf) (ntohs (msg->header.size) - - sizeof(struct GNUNET_TESTBED_HelperReply)); - config = GNUNET_malloc (config_size); - GNUNET_assert (Z_OK == uncompress ((Bytef *) config, - &config_size, - (const Bytef *) &msg[1], - xconfig_size)); - /* Replace the configuration template present in the host with the - controller's running configuration */ - GNUNET_CONFIGURATION_destroy (cp->host->cfg); - cp->host->cfg = GNUNET_CONFIGURATION_create (); - GNUNET_assert (GNUNET_CONFIGURATION_deserialize (cp->host->cfg, - config, - config_size, - NULL)); - GNUNET_free (config); - if (NULL == (hostname = GNUNET_TESTBED_host_get_hostname (cp->host))) - hostname = "localhost"; - /* Change the hostname so that we can connect to it */ - GNUNET_CONFIGURATION_set_value_string (cp->host->cfg, - "testbed", - "hostname", - hostname); - cp->host->locked = GNUNET_NO; - cp->host->controller_started = GNUNET_YES; - cp->cb (cp->cls, cp->host->cfg, GNUNET_OK); - return GNUNET_OK; -} - - -/** - * Continuation function from GNUNET_HELPER_send() - * - * @param cls closure - * @param result GNUNET_OK on success, - * GNUNET_NO if helper process died - * GNUNET_SYSERR during GNUNET_HELPER_stop - */ -static void -clear_msg (void *cls, int result) -{ - struct GNUNET_TESTBED_ControllerProc *cp = cls; - - GNUNET_assert (NULL != cp->shandle); - cp->shandle = NULL; - GNUNET_free (cp->msg); - cp->msg = NULL; -} - - -/** - * Callback that will be called when the helper process dies. This is not called - * when the helper process is stopped using GNUNET_HELPER_stop() - * - * @param cls the closure from GNUNET_HELPER_start() - */ -static void -helper_exp_cb (void *cls) -{ - struct GNUNET_TESTBED_ControllerProc *cp = cls; - GNUNET_TESTBED_ControllerStatusCallback cb; - void *cb_cls; - - cb = cp->cb; - cb_cls = cp->cls; - cp->helper = NULL; - GNUNET_TESTBED_controller_stop (cp); - if (NULL != cb) - cb (cb_cls, NULL, GNUNET_SYSERR); -} - - -/** - * Starts a controller process at the given host. The given host's configuration - * is used as a Template configuration to use for the remote controller; the - * remote controller will be started with a slightly modified configuration - * (port numbers, unix domain sockets and service home values are changed as per - * TESTING library on the remote host). The modified configuration replaces the - * host's existing configuration before signalling success through the - * GNUNET_TESTBED_ControllerStatusCallback() - * - * @param trusted_ip the ip address of the controller which will be set as TRUSTED - * HOST(all connections form this ip are permitted by the testbed) when - * starting testbed controller at host. This can either be a single ip - * address or a network address in CIDR notation. - * @param host the host where the controller has to be started. CANNOT be NULL. - * @param cb function called when the controller is successfully started or - * dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be - * called if cb is called with GNUNET_SYSERR as status. Will never be - * called in the same task as 'GNUNET_TESTBED_controller_start' - * (synchronous errors will be signalled by returning NULL). This - * parameter cannot be NULL. - * @param cls closure for above callbacks - * @return the controller process handle, NULL on errors - */ -struct GNUNET_TESTBED_ControllerProc * -GNUNET_TESTBED_controller_start (const char *trusted_ip, - struct GNUNET_TESTBED_Host *host, - GNUNET_TESTBED_ControllerStatusCallback cb, - void *cls) -{ - struct GNUNET_TESTBED_ControllerProc *cp; - struct GNUNET_TESTBED_HelperInit *msg; - const struct GNUNET_CONFIGURATION_Handle *cfg; - const char *hostname; - static char *const binary_argv[] = { HELPER_TESTBED_BINARY, NULL }; - - GNUNET_assert (NULL != host); - GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host))); - hostname = NULL; - API_VIOLATION ( - GNUNET_NO == host->locked, - "Host is already locked by a previous call to GNUNET_TESTBED_controller_start()"); - host->locked = GNUNET_YES; - API_VIOLATION ( - GNUNET_NO == host->controller_started, - "Attempting to start a controller on a host on which a controller is already started"); - cp = GNUNET_new (struct GNUNET_TESTBED_ControllerProc); - if (0 == GNUNET_TESTBED_host_get_id_ (host)) - { - cp->helper = GNUNET_HELPER_start (GNUNET_YES, - HELPER_TESTBED_BINARY, - binary_argv, - &helper_mst, - &helper_exp_cb, - cp); - } - else - { - char *helper_binary_path_args[2]; - char **rsh_args; - char **rsh_suffix_args; - const char *username; - char *port; - char *argstr; - char *aux; - unsigned int cnt; - - username = host->username; - hostname = host->hostname; - GNUNET_asprintf (&port, "%u", host->port); - LOG_DEBUG ("Starting remote connection to destination %s\n", hostname); - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, - "testbed", - "HELPER_BINARY_PATH", - &helper_binary_path_args[0])) - helper_binary_path_args[0] = - GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY); - helper_binary_path_args[1] = NULL; - rsh_args = gen_rsh_args (port, hostname, username); - rsh_suffix_args = - gen_rsh_suffix_args ((const char **) helper_binary_path_args); - cp->helper_argv = - join_argv ((const char **) rsh_args, (const char **) rsh_suffix_args); - free_argv (rsh_args); - free_argv (rsh_suffix_args); - GNUNET_free (port); - argstr = GNUNET_strdup (""); - for (cnt = 0; NULL != cp->helper_argv[cnt]; cnt++) - { - aux = argstr; - GNUNET_assert ( - 0 < GNUNET_asprintf (&argstr, "%s %s", aux, cp->helper_argv[cnt])); - GNUNET_free (aux); - } - LOG_DEBUG ("Helper cmd str: %s\n", argstr); - GNUNET_free (argstr); - cp->helper = GNUNET_HELPER_start (GNUNET_NO, - cp->helper_argv[0], - cp->helper_argv, - &helper_mst, - &helper_exp_cb, - cp); - GNUNET_free (helper_binary_path_args[0]); - } - if (NULL == cp->helper) - { - if (NULL != cp->helper_argv) - free_argv (cp->helper_argv); - GNUNET_free (cp); - return NULL; - } - cp->host = host; - cp->cb = cb; - cp->cls = cls; - msg = GNUNET_TESTBED_create_helper_init_msg_ (trusted_ip, hostname, cfg); - cp->msg = &msg->header; - cp->shandle = - GNUNET_HELPER_send (cp->helper, &msg->header, GNUNET_NO, &clear_msg, cp); - if (NULL == cp->shandle) - { - GNUNET_free (msg); - GNUNET_TESTBED_controller_stop (cp); - return NULL; - } - return cp; -} - - -/** - * Sends termination signal to the controller's helper process - * - * @param cproc the handle to the controller's helper process - */ -void -GNUNET_TESTBED_controller_kill_ (struct GNUNET_TESTBED_ControllerProc *cproc) -{ - if (NULL != cproc->shandle) - GNUNET_HELPER_send_cancel (cproc->shandle); - if (NULL != cproc->helper) - GNUNET_HELPER_kill (cproc->helper, GNUNET_YES); -} - - -/** - * Cleans-up the controller's helper process handle - * - * @param cproc the handle to the controller's helper process - */ -void -GNUNET_TESTBED_controller_destroy_ (struct GNUNET_TESTBED_ControllerProc *cproc) -{ - if (NULL != cproc->helper) - { - GNUNET_break (GNUNET_OK == GNUNET_HELPER_wait (cproc->helper)); - GNUNET_HELPER_destroy (cproc->helper); - } - if (NULL != cproc->helper_argv) - free_argv (cproc->helper_argv); - cproc->host->controller_started = GNUNET_NO; - cproc->host->locked = GNUNET_NO; - GNUNET_free (cproc->msg); - GNUNET_free (cproc); -} - - -/** - * Stop the controller process (also will terminate all peers and controllers - * dependent on this controller). This function blocks until the testbed has - * been fully terminated (!). The controller status cb from - * GNUNET_TESTBED_controller_start() will not be called. - * - * @param cproc the controller process handle - */ -void -GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc) -{ - GNUNET_TESTBED_controller_kill_ (cproc); - GNUNET_TESTBED_controller_destroy_ (cproc); -} - - -/** - * The handle for whether a host is habitable or not - */ -struct GNUNET_TESTBED_HostHabitableCheckHandle -{ - /** - * The host to check - */ - const struct GNUNET_TESTBED_Host *host; - - /** - * The callback to call once we have the status - */ - GNUNET_TESTBED_HostHabitableCallback cb; - - /** - * The callback closure - */ - void *cb_cls; - - /** - * The process handle for the SSH process - */ - struct GNUNET_OS_Process *auxp; - - /** - * The arguments used to start the helper - */ - char **helper_argv; - - /** - * Task id for the habitability check task - */ - struct GNUNET_SCHEDULER_Task *habitability_check_task; - - /** - * How long we wait before checking the process status. Should grow - * exponentially - */ - struct GNUNET_TIME_Relative wait_time; -}; - - -/** - * Task for checking whether a host is habitable or not - * - * @param cls GNUNET_TESTBED_HostHabitableCheckHandle - */ -static void -habitability_check (void *cls) -{ - struct GNUNET_TESTBED_HostHabitableCheckHandle *h = cls; - void *cb_cls; - GNUNET_TESTBED_HostHabitableCallback cb; - const struct GNUNET_TESTBED_Host *host; - unsigned long code; - enum GNUNET_OS_ProcessStatusType type; - int ret; - - h->habitability_check_task = NULL; - ret = GNUNET_OS_process_status (h->auxp, &type, &code); - if (GNUNET_SYSERR == ret) - { - GNUNET_break (0); - ret = GNUNET_NO; - goto call_cb; - } - if (GNUNET_NO == ret) - { - h->wait_time = GNUNET_TIME_STD_BACKOFF (h->wait_time); - h->habitability_check_task = - GNUNET_SCHEDULER_add_delayed (h->wait_time, &habitability_check, h); - return; - } - GNUNET_OS_process_destroy (h->auxp); - h->auxp = NULL; - ret = (0 != code) ? GNUNET_NO : GNUNET_YES; - - call_cb: - if (NULL != h->auxp) - GNUNET_OS_process_destroy (h->auxp); - cb = h->cb; - cb_cls = h->cb_cls; - host = h->host; - free_argv (h->helper_argv); - GNUNET_free (h); - if (NULL != cb) - cb (cb_cls, host, ret); -} - - -/** - * Checks whether a host can be used to start testbed service - * - * @param host the host to check - * @param config the configuration handle to lookup the path of the testbed - * helper - * @param cb the callback to call to inform about habitability of the given host - * @param cb_cls the closure for the callback - * @return NULL upon any error or a handle which can be passed to - * GNUNET_TESTBED_is_host_habitable_cancel() - */ -struct GNUNET_TESTBED_HostHabitableCheckHandle * -GNUNET_TESTBED_is_host_habitable ( - const struct GNUNET_TESTBED_Host *host, - const struct GNUNET_CONFIGURATION_Handle *config, - GNUNET_TESTBED_HostHabitableCallback cb, - void *cb_cls) -{ - struct GNUNET_TESTBED_HostHabitableCheckHandle *h; - char **rsh_args; - char **rsh_suffix_args; - char *stat_args[3]; - const char *hostname; - char *port; - - h = GNUNET_new (struct GNUNET_TESTBED_HostHabitableCheckHandle); - h->cb = cb; - h->cb_cls = cb_cls; - h->host = host; - hostname = (NULL == host->hostname) ? "127.0.0.1" : host->hostname; - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (config, - "testbed", - "HELPER_BINARY_PATH", - &stat_args[1])) - stat_args[1] = GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY); - GNUNET_asprintf (&port, "%u", host->port); - rsh_args = gen_rsh_args (port, hostname, host->username); - GNUNET_free (port); - port = NULL; - stat_args[0] = "stat"; - stat_args[2] = NULL; - rsh_suffix_args = gen_rsh_suffix_args ((const char **) stat_args); - GNUNET_free (stat_args[1]); - h->helper_argv = - join_argv ((const char **) rsh_args, (const char **) rsh_suffix_args); - free_argv (rsh_suffix_args); - free_argv (rsh_args); - h->auxp = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR, - NULL, - NULL, - NULL, - h->helper_argv[0], - h->helper_argv); - if (NULL == h->auxp) - { - GNUNET_break (0); /* Cannot exec SSH? */ - free_argv (h->helper_argv); - GNUNET_free (h); - return NULL; - } - h->wait_time = GNUNET_TIME_STD_BACKOFF (h->wait_time); - h->habitability_check_task = - GNUNET_SCHEDULER_add_delayed (h->wait_time, &habitability_check, h); - return h; -} - - -/** - * Function to cancel a request started using GNUNET_TESTBED_is_host_habitable() - * - * @param handle the habitability check handle - */ -void -GNUNET_TESTBED_is_host_habitable_cancel ( - struct GNUNET_TESTBED_HostHabitableCheckHandle *handle) -{ - GNUNET_SCHEDULER_cancel (handle->habitability_check_task); - (void) GNUNET_OS_process_kill (handle->auxp, GNUNET_TERM_SIG); - (void) GNUNET_OS_process_wait (handle->auxp); - GNUNET_OS_process_destroy (handle->auxp); - free_argv (handle->helper_argv); - GNUNET_free (handle); -} - - -/** - * Register a host with the controller - * - * @param controller the controller handle - * @param host the host to register - * @param cc the completion callback to call to inform the status of - * registration. After calling this callback the registration handle - * will be invalid. Cannot be NULL. - * @param cc_cls the closure for the cc - * @return handle to the host registration which can be used to cancel the - * registration - */ -struct GNUNET_TESTBED_HostRegistrationHandle * -GNUNET_TESTBED_register_host (struct GNUNET_TESTBED_Controller *controller, - struct GNUNET_TESTBED_Host *host, - GNUNET_TESTBED_HostRegistrationCompletion cc, - void *cc_cls) -{ - struct GNUNET_TESTBED_HostRegistrationHandle *rh; - struct GNUNET_TESTBED_AddHostMessage *msg; - const char *username; - const char *hostname; - char *config; - char *cconfig; - void *ptr; - size_t cc_size; - size_t config_size; - uint16_t msg_size; - uint16_t username_length; - uint16_t hostname_length; - - if (NULL != controller->rh) - return NULL; - hostname = GNUNET_TESTBED_host_get_hostname (host); - if (GNUNET_YES == GNUNET_TESTBED_is_host_registered_ (host, controller)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Host hostname: %s already registered\n", - (NULL == hostname) ? "localhost" : hostname); - return NULL; - } - rh = GNUNET_new (struct GNUNET_TESTBED_HostRegistrationHandle); - rh->host = host; - rh->c = controller; - GNUNET_assert (NULL != cc); - rh->cc = cc; - rh->cc_cls = cc_cls; - controller->rh = rh; - username = GNUNET_TESTBED_host_get_username_ (host); - username_length = 0; - if (NULL != username) - username_length = strlen (username); - GNUNET_assert (NULL != hostname); /* Hostname must be present */ - hostname_length = strlen (hostname); - GNUNET_assert (NULL != host->cfg); - config = GNUNET_CONFIGURATION_serialize (host->cfg, &config_size); - cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig); - GNUNET_free (config); - msg_size = (sizeof(struct GNUNET_TESTBED_AddHostMessage)); - msg_size += username_length; - msg_size += hostname_length; - msg_size += cc_size; - msg = GNUNET_malloc (msg_size); - msg->header.size = htons (msg_size); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST); - msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host)); - msg->ssh_port = htons (GNUNET_TESTBED_host_get_ssh_port_ (host)); - ptr = &msg[1]; - if (NULL != username) - { - msg->username_length = htons (username_length); - GNUNET_memcpy (ptr, username, username_length); - ptr += username_length; - } - msg->hostname_length = htons (hostname_length); - GNUNET_memcpy (ptr, hostname, hostname_length); - ptr += hostname_length; - msg->config_size = htons (config_size); - GNUNET_memcpy (ptr, cconfig, cc_size); - ptr += cc_size; - GNUNET_assert ((ptr - (void *) msg) == msg_size); - GNUNET_free (cconfig); - GNUNET_TESTBED_queue_message_ (controller, - (struct GNUNET_MessageHeader *) msg); - return rh; -} - - -/** - * Cancel the pending registration. Note that if the registration message is - * already sent to the service the cancellation has only the effect that the - * registration completion callback for the registration is never called. - * - * @param handle the registration handle to cancel - */ -void -GNUNET_TESTBED_cancel_registration ( - struct GNUNET_TESTBED_HostRegistrationHandle *handle) -{ - if (handle != handle->c->rh) - { - GNUNET_break (0); - return; - } - handle->c->rh = NULL; - GNUNET_free (handle); -} - - -/** - * Queues the given operation in the queue for parallel overlay connects of the - * given host - * - * @param h the host handle - * @param op the operation to queue in the given host's parally overlay connect - * queue - */ -void -GNUNET_TESTBED_host_queue_oc_ (struct GNUNET_TESTBED_Host *h, - struct GNUNET_TESTBED_Operation *op) -{ - GNUNET_TESTBED_operation_queue_insert_ ( - h->opq_parallel_overlay_connect_operations, - op); -} - - -/** - * Resolves the hostname of the host to an ip address - * - * @param host the host whose hostname is to be resolved - */ -void -GNUNET_TESTBED_host_resolve_ (struct GNUNET_TESTBED_Host *host) -{ - char *hostname; - - hostname = (char *) host->hostname; - host->hostname = simple_resolve (hostname); - if (NULL == host->hostname) - { - GNUNET_break (0); - host->hostname = hostname; - return; - } - GNUNET_free (hostname); - host->hostname = GNUNET_strdup (host->hostname); -} - - -/* end of testbed_api_hosts.c */ diff --git a/src/testbed/testbed_api_hosts.h b/src/testbed/testbed_api_hosts.h @@ -1,227 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_hosts.h - * @brief internal API to access the 'hosts' subsystem - * @author Christian Grothoff - */ - -#ifndef TESTBED_API_HOSTS_H -#define TESTBED_API_HOSTS_H - -// #include "gnunet_testbed_service.h" -// #include "testbed_helper.h" -#include "testbed.h" - - -/** - * handle for host registration - */ -struct GNUNET_TESTBED_HostRegistrationHandle -{ - /** - * The host being registered - */ - struct GNUNET_TESTBED_Host *host; - - /** - * The controller at which this host is being registered - */ - struct GNUNET_TESTBED_Controller *c; - - /** - * The Registration completion callback - */ - GNUNET_TESTBED_HostRegistrationCompletion cc; - - /** - * The closure for above callback - */ - void *cc_cls; -}; - - -/** - * Lookup a host by ID. - * - * @param id global host ID assigned to the host; 0 is - * reserved to always mean 'localhost' - * @return handle to the host, NULL on error - */ -struct GNUNET_TESTBED_Host * -GNUNET_TESTBED_host_lookup_by_id_ (uint32_t id); - - -/** - * Create a host by ID; given this host handle, we could not - * run peers at the host, but we can talk about the host - * internally. - * - * @param id global host ID assigned to the host; 0 is - * reserved to always mean 'localhost' - * @param cfg the configuration to use as a template while starting a controller - * on this host. Operation queue sizes specific to a host are also - * read from this configuration handle - * @return handle to the host, NULL on error - */ -struct GNUNET_TESTBED_Host * -GNUNET_TESTBED_host_create_by_id_ (uint32_t id, - const struct GNUNET_CONFIGURATION_Handle - *cfg); - - -/** - * Obtain a host's unique global ID. - * - * @param host handle to the host, NULL means 'localhost' - * @return id global host ID assigned to the host (0 is - * 'localhost', but then obviously not globally unique) - */ -uint32_t -GNUNET_TESTBED_host_get_id_ (const struct GNUNET_TESTBED_Host *host); - - -/** - * Obtain the host's username - * - * @param host handle to the host, NULL means 'localhost' - * @return username to login to the host - */ -const char * -GNUNET_TESTBED_host_get_username_ (const struct GNUNET_TESTBED_Host *host); - - -/** - * Obtain the host's ssh port - * - * @param host handle to the host, NULL means 'localhost' - * @return username to login to the host - */ -uint16_t -GNUNET_TESTBED_host_get_ssh_port_ (const struct GNUNET_TESTBED_Host *host); - - -/** - * Obtain the host's configuration template - * - * @param host handle to the host - * @return the host's configuration template - */ -const struct GNUNET_CONFIGURATION_Handle * -GNUNET_TESTBED_host_get_cfg_ (const struct GNUNET_TESTBED_Host *host); - - -/** - * Function to replace host's configuration - * - * @param host the host handle - * @param new_cfg the new configuration to replace the old one - */ -void -GNUNET_TESTBED_host_replace_cfg_ (struct GNUNET_TESTBED_Host *host, - const struct - GNUNET_CONFIGURATION_Handle *new_cfg); - - -/** - * Marks a host as registered with a controller - * - * @param host the host to mark - * @param controller the controller at which this host is registered - */ -void -GNUNET_TESTBED_mark_host_registered_at_ (struct GNUNET_TESTBED_Host *host, - const struct GNUNET_TESTBED_Controller - *controller); - - -/** - * Unmarks a host registered at a controller - * - * @param host the host to unmark - * @param controller the controller at which this host has to be unmarked - */ -void -GNUNET_TESTBED_deregister_host_at_ (struct GNUNET_TESTBED_Host *host, - const struct GNUNET_TESTBED_Controller - *const controller); - - -/** - * Checks whether a host has been registered with the given controller - * - * @param host the host to check - * @param controller the controller at which host's registration is checked - * @return GNUNET_YES if registered; GNUNET_NO if not - */ -int -GNUNET_TESTBED_is_host_registered_ (const struct GNUNET_TESTBED_Host *host, - const struct GNUNET_TESTBED_Controller - *controller); - - -/** - * Queues the given operation in the queue for parallel overlay connects of the - * given host - * - * @param h the host handle - * @param op the operation to queue in the given host's parally overlay connect - * queue - */ -void -GNUNET_TESTBED_host_queue_oc_ (struct GNUNET_TESTBED_Host *h, - struct GNUNET_TESTBED_Operation *op); - - -/** - * Sends termination signal to the controller's helper process - * - * @param cproc the handle to the controller's helper process - */ -void -GNUNET_TESTBED_controller_kill_ (struct GNUNET_TESTBED_ControllerProc *cproc); - - -/** - * Cleans-up the controller's helper process handle - * - * @param cproc the handle to the controller's helper process - */ -void -GNUNET_TESTBED_controller_destroy_ (struct GNUNET_TESTBED_ControllerProc - *cproc); - - -/** - * Resolves the hostname of the host to an ip address - * - * @param host the host whose hostname is to be resolved - */ -void -GNUNET_TESTBED_host_resolve_ (struct GNUNET_TESTBED_Host *host); - -void -GNUNET_TESTBED_extract_cfg (struct GNUNET_TESTBED_Host *host, const struct - GNUNET_MessageHeader *message); - - -#endif -/* end of testbed_api_hosts.h */ diff --git a/src/testbed/testbed_api_operations.c b/src/testbed/testbed_api_operations.c @@ -1,1379 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_operations.c - * @brief functions to manage operation queues - * @author Christian Grothoff - * @author Sree Harsha Totakura - */ - -#include "platform.h" -#include "testbed_api_operations.h" -#include "testbed_api_sd.h" - -/** - * The number of readings containing past operation's timing information that we - * keep track of for adaptive queues - */ -#define ADAPTIVE_QUEUE_DEFAULT_HISTORY 40 - -/** - * The number of parallel operations we start with by default for adaptive - * queues - */ -#define ADAPTIVE_QUEUE_DEFAULT_MAX_ACTIVE 4 - -/** - * An entry in the operation queue - */ -struct QueueEntry -{ - /** - * The next DLL pointer - */ - struct QueueEntry *next; - - /** - * The prev DLL pointer - */ - struct QueueEntry *prev; - - /** - * The operation this entry holds - */ - struct GNUNET_TESTBED_Operation *op; - - /** - * How many units of resources does the operation need - */ - unsigned int nres; -}; - - -/** - * Queue of operations where we can only support a certain - * number of concurrent operations of a particular type. - */ -struct OperationQueue; - - -/** - * A slot to record time taken by an operation - */ -struct TimeSlot -{ - /** - * DLL next pointer - */ - struct TimeSlot *next; - - /** - * DLL prev pointer - */ - struct TimeSlot *prev; - - /** - * This operation queue to which this time slot belongs to - */ - struct OperationQueue *queue; - - /** - * The operation to which this timeslot is currently allocated to - */ - struct GNUNET_TESTBED_Operation *op; - - /** - * Accumulated time - */ - struct GNUNET_TIME_Relative tsum; - - /** - * Number of timing values accumulated - */ - unsigned int nvals; -}; - - -/** - * Context for operation queues of type OPERATION_QUEUE_TYPE_ADAPTIVE - */ -struct FeedbackCtx -{ - /** - * Handle for calculating standard deviation - */ - struct SDHandle *sd; - - /** - * Head for DLL of time slots which are free to be allocated to operations - */ - struct TimeSlot *alloc_head; - - /** - * Tail for DLL of time slots which are free to be allocated to operations - */ - struct TimeSlot *alloc_tail; - - /** - * Pointer to the chunk of time slots. Free all time slots at a time using - * this pointer. - */ - struct TimeSlot *tslots_freeptr; - - /** - * Number of time slots filled so far - */ - unsigned int tslots_filled; - - /** - * Bound on the maximum number of operations which can be active - */ - unsigned int max_active_bound; - - /** - * Number of operations that have failed - */ - unsigned int nfailed; -}; - - -/** - * Queue of operations where we can only support a certain - * number of concurrent operations of a particular type. - */ -struct OperationQueue -{ - /** - * DLL head for the wait queue. Operations which are waiting for this - * operation queue are put here - */ - struct QueueEntry *wq_head; - - /** - * DLL tail for the wait queue. - */ - struct QueueEntry *wq_tail; - - /** - * DLL head for the ready queue. Operations which are in this operation queue - * and are in ready state are put here - */ - struct QueueEntry *rq_head; - - /** - * DLL tail for the ready queue - */ - struct QueueEntry *rq_tail; - - /** - * DLL head for the active queue. Operations which are in this operation - * queue and are currently active are put here - */ - struct QueueEntry *aq_head; - - /** - * DLL tail for the active queue. - */ - struct QueueEntry *aq_tail; - - /** - * DLL head for the inactive queue. Operations which are inactive and can be - * evicted if the queues it holds are maxed out and another operation begins - * to wait on them. - */ - struct QueueEntry *nq_head; - - /** - * DLL tail for the inactive queue. - */ - struct QueueEntry *nq_tail; - - /** - * Feedback context; only relevant for adaptive operation queues. NULL for - * fixed operation queues - */ - struct FeedbackCtx *fctx; - - /** - * The type of this operation queue - */ - enum OperationQueueType type; - - /** - * Number of operations that are currently active in this queue. - */ - unsigned int active; - - /** - * Max number of operations which can be active at any time in this queue. - * This value can be changed either by calling - * GNUNET_TESTBED_operation_queue_reset_max_active_() or by the adaptive - * algorithm if this operation queue is of type #OPERATION_QUEUE_TYPE_ADAPTIVE - */ - unsigned int max_active; - - /** - * The number of resources occupied by failed operations in the current shot. - * This is only relevant if the operation queue is of type - * #OPERATION_QUEUE_TYPE_ADAPTIVE - */ - unsigned int overload; - - /** - * Is this queue marked for expiry? - */ - unsigned int expired; -}; - - -/** - * Operation state - */ -enum OperationState -{ - /** - * The operation is just created and is in initial state - */ - OP_STATE_INIT, - - /** - * The operation is currently waiting for resources - */ - OP_STATE_WAITING, - - /** - * The operation is ready to be started - */ - OP_STATE_READY, - - /** - * The operation has started and is active - */ - OP_STATE_ACTIVE, - - /** - * The operation is inactive. It still holds resources on the operation - * queues. However, this operation will be evicted when another operation - * requires resources from the maxed out queues this operation is holding - * resources from. - */ - OP_STATE_INACTIVE -}; - - -/** - * An entry in the ready queue (implemented as DLL) - */ -struct ReadyQueueEntry -{ - /** - * next ptr for DLL - */ - struct ReadyQueueEntry *next; - - /** - * prev ptr for DLL - */ - struct ReadyQueueEntry *prev; - - /** - * The operation associated with this entry - */ - struct GNUNET_TESTBED_Operation *op; -}; - - -/** - * Opaque handle to an abstract operation to be executed by the testing framework. - */ -struct GNUNET_TESTBED_Operation -{ - /** - * Function to call when we have the resources to begin the operation. - */ - OperationStart start; - - /** - * Function to call to clean up after the operation (which may or may - * not have been started yet). - */ - OperationRelease release; - - /** - * Closure for callbacks. - */ - void *cb_cls; - - /** - * Array of operation queues this Operation belongs to. - */ - struct OperationQueue **queues; - - /** - * Array of operation queue entries corresponding to this operation in - * operation queues for this operation - */ - struct QueueEntry **qentries; - - /** - * Array of number of resources an operation need from each queue. The numbers - * in this array should correspond to the queues array - */ - unsigned int *nres; - - /** - * Entry corresponding to this operation in ready queue. Will be NULL if the - * operation is not marked as READY - */ - struct ReadyQueueEntry *rq_entry; - - /** - * Head pointer for DLL of tslots allocated to this operation - */ - struct TimeSlot *tslots_head; - - /** - * Tail pointer for DLL of tslots allocated to this operation - */ - struct TimeSlot *tslots_tail; - - /** - * The time at which the operation is started - */ - struct GNUNET_TIME_Absolute tstart; - - /** - * Number of queues in the operation queues array - */ - unsigned int nqueues; - - /** - * The state of the operation - */ - enum OperationState state; - - /** - * Is this a failed operation? - */ - int failed; -}; - -/** - * DLL head for the ready queue - */ -static struct ReadyQueueEntry *rq_head; - -/** - * DLL tail for the ready queue - */ -static struct ReadyQueueEntry *rq_tail; - -/** - * Array of operation queues which are to be destroyed - */ -static struct OperationQueue **expired_opqs; - -/** - * Number of expired operation queues in the above array - */ -static unsigned int n_expired_opqs; - -/** - * The id of the task to process the ready queue - */ -struct GNUNET_SCHEDULER_Task *process_rq_task_id; - - -/** - * Assigns the given operation a time slot from the given operation queue - * - * @param op the operation - * @param queue the operation queue - * @return the timeslot - */ -static void -assign_timeslot (struct GNUNET_TESTBED_Operation *op, - struct OperationQueue *queue) -{ - struct FeedbackCtx *fctx = queue->fctx; - struct TimeSlot *tslot; - - GNUNET_assert (OPERATION_QUEUE_TYPE_ADAPTIVE == queue->type); - tslot = fctx->alloc_head; - GNUNET_assert (NULL != tslot); - GNUNET_CONTAINER_DLL_remove (fctx->alloc_head, fctx->alloc_tail, tslot); - GNUNET_CONTAINER_DLL_insert_tail (op->tslots_head, op->tslots_tail, tslot); - tslot->op = op; -} - - -/** - * Removes a queue entry of an operation from one of the operation queues' lists - * depending on the state of the operation - * - * @param op the operation whose entry has to be removed - * @param index the index of the entry in the operation's array of queue entries - */ -static void -remove_queue_entry (struct GNUNET_TESTBED_Operation *op, unsigned int index) -{ - struct OperationQueue *opq; - struct QueueEntry *entry; - - opq = op->queues[index]; - entry = op->qentries[index]; - switch (op->state) - { - case OP_STATE_INIT: - GNUNET_assert (0); - break; - - case OP_STATE_WAITING: - GNUNET_CONTAINER_DLL_remove (opq->wq_head, opq->wq_tail, entry); - break; - - case OP_STATE_READY: - GNUNET_CONTAINER_DLL_remove (opq->rq_head, opq->rq_tail, entry); - break; - - case OP_STATE_ACTIVE: - GNUNET_CONTAINER_DLL_remove (opq->aq_head, opq->aq_tail, entry); - break; - - case OP_STATE_INACTIVE: - GNUNET_CONTAINER_DLL_remove (opq->nq_head, opq->nq_tail, entry); - break; - } -} - - -/** - * Changes the state of the operation while moving its associated queue entries - * in the operation's operation queues - * - * @param op the operation whose state has to be changed - * @param state the state the operation should have. It cannot be OP_STATE_INIT - */ -static void -change_state (struct GNUNET_TESTBED_Operation *op, enum OperationState state) -{ - struct QueueEntry *entry; - struct OperationQueue *opq; - unsigned int cnt; - unsigned int s; - - GNUNET_assert (OP_STATE_INIT != state); - GNUNET_assert (NULL != op->queues); - GNUNET_assert (NULL != op->nres); - GNUNET_assert ((OP_STATE_INIT == op->state) || (NULL != op->qentries)); - GNUNET_assert (op->state != state); - for (cnt = 0; cnt < op->nqueues; cnt++) - { - if (OP_STATE_INIT == op->state) - { - entry = GNUNET_new (struct QueueEntry); - entry->op = op; - entry->nres = op->nres[cnt]; - s = cnt; - GNUNET_array_append (op->qentries, s, entry); - } - else - { - entry = op->qentries[cnt]; - remove_queue_entry (op, cnt); - } - opq = op->queues[cnt]; - switch (state) - { - case OP_STATE_INIT: - GNUNET_assert (0); - break; - - case OP_STATE_WAITING: - GNUNET_CONTAINER_DLL_insert_tail (opq->wq_head, opq->wq_tail, entry); - break; - - case OP_STATE_READY: - GNUNET_CONTAINER_DLL_insert_tail (opq->rq_head, opq->rq_tail, entry); - break; - - case OP_STATE_ACTIVE: - GNUNET_CONTAINER_DLL_insert_tail (opq->aq_head, opq->aq_tail, entry); - break; - - case OP_STATE_INACTIVE: - GNUNET_CONTAINER_DLL_insert_tail (opq->nq_head, opq->nq_tail, entry); - break; - } - } - op->state = state; -} - - -/** - * Removes an operation from the ready queue. Also stops the 'process_rq_task' - * if the given operation is the last one in the queue. - * - * @param op the operation to be removed - */ -static void -rq_remove (struct GNUNET_TESTBED_Operation *op) -{ - GNUNET_assert (NULL != op->rq_entry); - GNUNET_CONTAINER_DLL_remove (rq_head, rq_tail, op->rq_entry); - GNUNET_free (op->rq_entry); - op->rq_entry = NULL; - if ((NULL == rq_head) && (NULL != process_rq_task_id)) - { - GNUNET_SCHEDULER_cancel (process_rq_task_id); - process_rq_task_id = NULL; - } -} - - -/** - * Processes the ready queue by calling the operation start callback of the - * operation at the head. The operation is then removed from the queue. The - * task is scheduled to run again immediately until no more operations are in - * the ready queue. - * - * @param cls NULL - */ -static void -process_rq_task (void *cls) -{ - struct GNUNET_TESTBED_Operation *op; - struct OperationQueue *queue; - unsigned int cnt; - - process_rq_task_id = NULL; - GNUNET_assert (NULL != rq_head); - GNUNET_assert (NULL != (op = rq_head->op)); - rq_remove (op); - if (NULL != rq_head) - process_rq_task_id = GNUNET_SCHEDULER_add_now (&process_rq_task, NULL); - change_state (op, OP_STATE_ACTIVE); - for (cnt = 0; cnt < op->nqueues; cnt++) - { - queue = op->queues[cnt]; - if (OPERATION_QUEUE_TYPE_ADAPTIVE == queue->type) - assign_timeslot (op, queue); - } - op->tstart = GNUNET_TIME_absolute_get (); - if (NULL != op->start) - op->start (op->cb_cls); -} - - -/** - * Adds the operation to the ready queue and starts the 'process_rq_task' - * - * @param op the operation to be queued - */ -static void -rq_add (struct GNUNET_TESTBED_Operation *op) -{ - struct ReadyQueueEntry *rq_entry; - - GNUNET_assert (NULL == op->rq_entry); - rq_entry = GNUNET_new (struct ReadyQueueEntry); - rq_entry->op = op; - GNUNET_CONTAINER_DLL_insert_tail (rq_head, rq_tail, rq_entry); - op->rq_entry = rq_entry; - if (NULL == process_rq_task_id) - process_rq_task_id = GNUNET_SCHEDULER_add_now (&process_rq_task, NULL); -} - - -/** - * Checks if the given operation queue is empty or not - * - * @param opq the operation queue - * @return GNUNET_YES if the given operation queue has no operations; GNUNET_NO - * otherwise - */ -static int -is_queue_empty (struct OperationQueue *opq) -{ - if ((NULL != opq->wq_head) - || (NULL != opq->rq_head) - || (NULL != opq->aq_head) - || (NULL != opq->nq_head)) - return GNUNET_NO; - return GNUNET_YES; -} - - -/** - * Checks if the given operation queue has enough resources to provide for the - * operation of the given queue entry. It also checks if any inactive - * operations are to be released in order to accommodate the needed resources - * and returns them as an array. - * - * @param opq the operation queue to check for resource accommodation - * @param entry the operation queue entry whose operation's resources are to be - * accommodated - * @param ops_ pointer to return the array of operations which are to be released - * in order to accommodate the new operation. Can be NULL - * @param n_ops_ the number of operations in ops_ - * @return GNUNET_YES if the given entry's operation can be accommodated in this - * queue. GNUNET_NO if it cannot be accommodated; ops_ and n_ops_ will - * be set to NULL and 0 respectively. - */ -static int -decide_capacity (struct OperationQueue *opq, - struct QueueEntry *entry, - struct GNUNET_TESTBED_Operation ***ops_, - unsigned int *n_ops_) -{ - struct QueueEntry **evict_entries; - struct GNUNET_TESTBED_Operation **ops; - struct GNUNET_TESTBED_Operation *op; - unsigned int n_ops; - unsigned int n_evict_entries; - unsigned int need; - unsigned int max; - int deficit; - int rval; - - GNUNET_assert (NULL != (op = entry->op)); - GNUNET_assert (0 < (need = entry->nres)); - ops = NULL; - n_ops = 0; - evict_entries = NULL; - n_evict_entries = 0; - rval = GNUNET_YES; - if (OPERATION_QUEUE_TYPE_ADAPTIVE == opq->type) - { - GNUNET_assert (NULL != opq->fctx); - GNUNET_assert (opq->max_active >= opq->overload); - max = opq->max_active - opq->overload; - } - else - max = opq->max_active; - if (opq->active > max) - { - rval = GNUNET_NO; - goto ret; - } - if ((opq->active + need) <= max) - goto ret; - deficit = need - (max - opq->active); - for (entry = opq->nq_head; - (0 < deficit) && (NULL != entry); - entry = entry->next) - { - GNUNET_array_append (evict_entries, n_evict_entries, entry); - deficit -= entry->nres; - } - if (0 < deficit) - { - rval = GNUNET_NO; - goto ret; - } - for (n_ops = 0; n_ops < n_evict_entries;) - { - op = evict_entries[n_ops]->op; - GNUNET_array_append (ops, n_ops, op); /* increments n-ops */ - } - -ret: - GNUNET_free (evict_entries); - if (NULL != ops_) - *ops_ = ops; - else - GNUNET_free (ops); - if (NULL != n_ops_) - *n_ops_ = n_ops; - return rval; -} - - -/** - * Merges an array of operations into another, eliminating duplicates. No - * ordering is guaranteed. - * - * @param old the array into which the merging is done. - * @param n_old the number of operations in old array - * @param new the array from which operations are to be merged - * @param n_new the number of operations in new array - */ -static void -merge_ops (struct GNUNET_TESTBED_Operation ***old, - unsigned int *n_old, - struct GNUNET_TESTBED_Operation **new, - unsigned int n_new) -{ - struct GNUNET_TESTBED_Operation **cur; - unsigned int i; - unsigned int j; - unsigned int n_cur; - - GNUNET_assert (NULL != old); - n_cur = *n_old; - cur = *old; - for (i = 0; i < n_new; i++) - { - for (j = 0; j < *n_old; j++) - { - if (new[i] == cur[j]) - break; - } - if (j < *n_old) - continue; - GNUNET_array_append (cur, n_cur, new[j]); - } - *old = cur; - *n_old = n_cur; -} - - -/** - * Checks for the readiness of an operation and schedules a operation start task - * - * @param op the operation - */ -static int -check_readiness (struct GNUNET_TESTBED_Operation *op) -{ - struct GNUNET_TESTBED_Operation **evict_ops; - struct GNUNET_TESTBED_Operation **ops; - unsigned int n_ops; - unsigned int n_evict_ops; - unsigned int i; - - GNUNET_assert (NULL == op->rq_entry); - GNUNET_assert (OP_STATE_WAITING == op->state); - evict_ops = NULL; - n_evict_ops = 0; - for (i = 0; i < op->nqueues; i++) - { - ops = NULL; - n_ops = 0; - if (GNUNET_NO == decide_capacity (op->queues[i], op->qentries[i], - &ops, &n_ops)) - { - GNUNET_free (evict_ops); - return GNUNET_NO; - } - if (NULL == ops) - continue; - merge_ops (&evict_ops, &n_evict_ops, ops, n_ops); - GNUNET_free (ops); - } - if (NULL != evict_ops) - { - for (i = 0; i < n_evict_ops; i++) - GNUNET_TESTBED_operation_release_ (evict_ops[i]); - GNUNET_free (evict_ops); - evict_ops = NULL; - /* Evicting the operations should schedule this operation */ - GNUNET_assert (OP_STATE_READY == op->state); - return GNUNET_YES; - } - for (i = 0; i < op->nqueues; i++) - op->queues[i]->active += op->nres[i]; - change_state (op, OP_STATE_READY); - rq_add (op); - return GNUNET_YES; -} - - -/** - * Defers a ready to be executed operation back to waiting - * - * @param op the operation to defer - */ -static void -defer (struct GNUNET_TESTBED_Operation *op) -{ - unsigned int i; - - GNUNET_assert (OP_STATE_READY == op->state); - rq_remove (op); - for (i = 0; i < op->nqueues; i++) - { - GNUNET_assert (op->queues[i]->active >= op->nres[i]); - op->queues[i]->active -= op->nres[i]; - } - change_state (op, OP_STATE_WAITING); -} - - -/** - * Cleanups the array of timeslots of an operation queue. For each time slot in - * the array, if it is allocated to an operation, it will be deallocated from - * the operation - * - * @param queue the operation queue - */ -static void -cleanup_tslots (struct OperationQueue *queue) -{ - struct FeedbackCtx *fctx = queue->fctx; - struct TimeSlot *tslot; - struct GNUNET_TESTBED_Operation *op; - unsigned int cnt; - - GNUNET_assert (NULL != fctx); - for (cnt = 0; cnt < queue->max_active; cnt++) - { - tslot = &fctx->tslots_freeptr[cnt]; - op = tslot->op; - if (NULL == op) - continue; - GNUNET_CONTAINER_DLL_remove (op->tslots_head, op->tslots_tail, tslot); - } - GNUNET_free (fctx->tslots_freeptr); - fctx->tslots_freeptr = NULL; - fctx->alloc_head = NULL; - fctx->alloc_tail = NULL; - fctx->tslots_filled = 0; -} - - -/** - * Cleansup the existing timing slots and sets new timing slots in the given - * queue to accommodate given number of max active operations. - * - * @param queue the queue - * @param n the number of maximum active operations. If n is greater than the - * maximum limit set while creating the queue, then the minimum of these two - * will be selected as n - */ -static void -adaptive_queue_set_max_active (struct OperationQueue *queue, unsigned int n) -{ - struct FeedbackCtx *fctx = queue->fctx; - struct TimeSlot *tslot; - unsigned int cnt; - - cleanup_tslots (queue); - n = GNUNET_MIN (n, fctx->max_active_bound); - fctx->tslots_freeptr = GNUNET_malloc (n * sizeof(struct TimeSlot)); - fctx->nfailed = 0; - for (cnt = 0; cnt < n; cnt++) - { - tslot = &fctx->tslots_freeptr[cnt]; - tslot->queue = queue; - GNUNET_CONTAINER_DLL_insert_tail (fctx->alloc_head, fctx->alloc_tail, - tslot); - } - GNUNET_TESTBED_operation_queue_reset_max_active_ (queue, n); -} - - -/** - * Adapts parallelism in an adaptive queue by using the statistical data from - * the feedback context. - * - * @param queue the queue - */ -static void -adapt_parallelism (struct OperationQueue *queue) -{ - struct GNUNET_TIME_Relative avg; - struct FeedbackCtx *fctx; - struct TimeSlot *tslot; - int sd; - unsigned int nvals; - unsigned int cnt; - unsigned int parallelism; - - avg = GNUNET_TIME_UNIT_ZERO; - nvals = 0; - fctx = queue->fctx; - for (cnt = 0; cnt < queue->max_active; cnt++) - { - tslot = &fctx->tslots_freeptr[cnt]; - avg = GNUNET_TIME_relative_add (avg, tslot->tsum); - nvals += tslot->nvals; - } - GNUNET_assert (nvals >= queue->max_active); - GNUNET_assert (fctx->nfailed <= nvals); - nvals -= fctx->nfailed; - if (0 == nvals) - { - if (1 == queue->max_active) - adaptive_queue_set_max_active (queue, 1); - else - adaptive_queue_set_max_active (queue, queue->max_active / 2); - return; - } - avg = GNUNET_TIME_relative_divide (avg, nvals); - GNUNET_TESTBED_SD_add_data_ (fctx->sd, (unsigned int) avg.rel_value_us); - if (GNUNET_SYSERR == - GNUNET_TESTBED_SD_deviation_factor_ (fctx->sd, - (unsigned int) avg.rel_value_us, - &sd)) - { - adaptive_queue_set_max_active (queue, queue->max_active); /* no change */ - return; - } - - parallelism = 0; - if (-1 == sd) - parallelism = queue->max_active + 1; - if (sd <= -2) - parallelism = queue->max_active * 2; - if (1 == sd) - parallelism = queue->max_active - 1; - if (2 <= sd) - parallelism = queue->max_active / 2; - parallelism = GNUNET_MAX (parallelism, ADAPTIVE_QUEUE_DEFAULT_MAX_ACTIVE); - adaptive_queue_set_max_active (queue, parallelism); - -#if 0 - /* old algorithm */ - if (sd < 0) - sd = 0; - GNUNET_assert (0 <= sd); - // GNUNET_TESTBED_SD_add_data_ (fctx->sd, (unsigned int) avg.rel_value_us); - if (0 == sd) - { - adaptive_queue_set_max_active (queue, queue->max_active * 2); - return; - } - if (1 == sd) - { - adaptive_queue_set_max_active (queue, queue->max_active + 1); - return; - } - if (1 == queue->max_active) - { - adaptive_queue_set_max_active (queue, 1); - return; - } - if (2 == sd) - { - adaptive_queue_set_max_active (queue, queue->max_active - 1); - return; - } - adaptive_queue_set_max_active (queue, queue->max_active / 2); -#endif -} - - -/** - * update tslots with the operation's completion time. Additionally, if - * updating a timeslot makes all timeslots filled in an adaptive operation - * queue, call adapt_parallelism() for that queue. - * - * @param op the operation - */ -static void -update_tslots (struct GNUNET_TESTBED_Operation *op) -{ - struct OperationQueue *queue; - struct GNUNET_TIME_Relative t; - struct TimeSlot *tslot; - struct FeedbackCtx *fctx; - unsigned int i; - - t = GNUNET_TIME_absolute_get_duration (op->tstart); - while (NULL != (tslot = op->tslots_head)) /* update time slots */ - { - queue = tslot->queue; - fctx = queue->fctx; - GNUNET_CONTAINER_DLL_remove (op->tslots_head, op->tslots_tail, tslot); - tslot->op = NULL; - GNUNET_CONTAINER_DLL_insert_tail (fctx->alloc_head, fctx->alloc_tail, - tslot); - if (op->failed) - { - fctx->nfailed++; - for (i = 0; i < op->nqueues; i++) - if (queue == op->queues[i]) - break; - GNUNET_assert (i != op->nqueues); - op->queues[i]->overload += op->nres[i]; - } - tslot->tsum = GNUNET_TIME_relative_add (tslot->tsum, t); - if (0 != tslot->nvals++) - continue; - fctx->tslots_filled++; - if (queue->max_active == fctx->tslots_filled) - adapt_parallelism (queue); - } -} - - -/** - * Create an 'operation' to be performed. - * - * @param cls closure for the callbacks - * @param start function to call to start the operation - * @param release function to call to close down the operation - * @return handle to the operation - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_operation_create_ (void *cls, OperationStart start, - OperationRelease release) -{ - struct GNUNET_TESTBED_Operation *op; - - op = GNUNET_new (struct GNUNET_TESTBED_Operation); - op->start = start; - op->state = OP_STATE_INIT; - op->release = release; - op->cb_cls = cls; - return op; -} - - -struct OperationQueue * -GNUNET_TESTBED_operation_queue_create_ (enum OperationQueueType type, - unsigned int max_active) -{ - struct OperationQueue *queue; - struct FeedbackCtx *fctx; - - queue = GNUNET_new (struct OperationQueue); - queue->type = type; - if (OPERATION_QUEUE_TYPE_FIXED == type) - { - queue->max_active = max_active; - } - else - { - fctx = GNUNET_new (struct FeedbackCtx); - fctx->max_active_bound = max_active; - fctx->sd = GNUNET_TESTBED_SD_init_ (ADAPTIVE_QUEUE_DEFAULT_HISTORY); - queue->fctx = fctx; - adaptive_queue_set_max_active (queue, ADAPTIVE_QUEUE_DEFAULT_MAX_ACTIVE); - } - return queue; -} - - -/** - * Cleanup the given operation queue. - * - * @param queue the operation queue to destroy - */ -static void -queue_destroy (struct OperationQueue *queue) -{ - struct FeedbackCtx *fctx; - - if (OPERATION_QUEUE_TYPE_ADAPTIVE == queue->type) - { - cleanup_tslots (queue); - fctx = queue->fctx; - GNUNET_TESTBED_SD_destroy_ (fctx->sd); - GNUNET_free (fctx); - } - GNUNET_free (queue); -} - - -/** - * Destroys an operation queue. If the queue is still in use by operations it - * is marked as expired and its resources are released in the destructor - * GNUNET_TESTBED_operations_fini(). - * - * @param queue queue to destroy - */ -void -GNUNET_TESTBED_operation_queue_destroy_ (struct OperationQueue *queue) -{ - if (GNUNET_YES != is_queue_empty (queue)) - { - GNUNET_assert (0 == queue->expired); /* Are you calling twice on same queue? */ - queue->expired = 1; - GNUNET_array_append (expired_opqs, n_expired_opqs, queue); - return; - } - queue_destroy (queue); -} - - -/** - * Destroys the operation queue if it is empty. If not empty return GNUNET_NO. - * - * @param queue the queue to destroy if empty - * @return GNUNET_YES if the queue is destroyed. GNUNET_NO if not (because it - * is not empty) - */ -int -GNUNET_TESTBED_operation_queue_destroy_empty_ (struct OperationQueue *queue) -{ - if (GNUNET_NO == is_queue_empty (queue)) - return GNUNET_NO; - GNUNET_TESTBED_operation_queue_destroy_ (queue); - return GNUNET_YES; -} - - -/** - * Rechecks if any of the operations in the given operation queue's waiting list - * can be made active - * - * @param opq the operation queue - */ -static void -recheck_waiting (struct OperationQueue *opq) -{ - struct QueueEntry *entry; - struct QueueEntry *entry2; - - entry = opq->wq_head; - while (NULL != entry) - { - entry2 = entry->next; - if (GNUNET_NO == check_readiness (entry->op)) - break; - entry = entry2; - } -} - - -/** - * Function to reset the maximum number of operations in the given queue. If - * max_active is lesser than the number of currently active operations, the - * active operations are not stopped immediately. - * - * @param queue the operation queue which has to be modified - * @param max_active the new maximum number of active operations - */ -void -GNUNET_TESTBED_operation_queue_reset_max_active_ (struct OperationQueue *queue, - unsigned int max_active) -{ - struct QueueEntry *entry; - - queue->max_active = max_active; - queue->overload = 0; - while ((queue->active > queue->max_active) - && (NULL != (entry = queue->rq_head))) - defer (entry->op); - recheck_waiting (queue); -} - - -/** - * Add an operation to a queue. An operation can be in multiple queues at - * once. Once the operation is inserted into all the queues - * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start - * waiting for the operation to become active. - * - * @param queue queue to add the operation to - * @param op operation to add to the queue - * @param nres the number of units of the resources of queue needed by the - * operation. Should be greater than 0. - */ -void -GNUNET_TESTBED_operation_queue_insert2_ (struct OperationQueue *queue, - struct GNUNET_TESTBED_Operation *op, - unsigned int nres) -{ - unsigned int qsize; - - GNUNET_assert (0 < nres); - qsize = op->nqueues; - GNUNET_array_append (op->queues, op->nqueues, queue); - GNUNET_array_append (op->nres, qsize, nres); - GNUNET_assert (qsize == op->nqueues); -} - - -/** - * Add an operation to a queue. An operation can be in multiple queues at - * once. Once the operation is inserted into all the queues - * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start - * waiting for the operation to become active. The operation is assumed to take - * 1 queue resource. Use GNUNET_TESTBED_operation_queue_insert2_() if it - * requires more than 1 - * - * @param queue queue to add the operation to - * @param op operation to add to the queue - */ -void -GNUNET_TESTBED_operation_queue_insert_ (struct OperationQueue *queue, - struct GNUNET_TESTBED_Operation *op) -{ - return GNUNET_TESTBED_operation_queue_insert2_ (queue, op, 1); -} - - -/** - * Marks the given operation as waiting on the queues. Once all queues permit - * the operation to become active, the operation will be activated. The actual - * activation will occur in a separate task (thus allowing multiple queue - * insertions to be made without having the first one instantly trigger the - * operation if the first queue has sufficient resources). - * - * @param op the operation to marks as waiting - */ -void -GNUNET_TESTBED_operation_begin_wait_ (struct GNUNET_TESTBED_Operation *op) -{ - GNUNET_assert (NULL == op->rq_entry); - change_state (op, OP_STATE_WAITING); - (void) check_readiness (op); -} - - -/** - * Marks an active operation as inactive - the operation will be kept in a - * ready-to-be-released state and continues to hold resources until another - * operation contents for them. - * - * @param op the operation to be marked as inactive. The operation start - * callback should have been called before for this operation to mark - * it as inactive. - */ -void -GNUNET_TESTBED_operation_inactivate_ (struct GNUNET_TESTBED_Operation *op) -{ - struct OperationQueue **queues; - size_t ms; - unsigned int nqueues; - unsigned int i; - - GNUNET_assert (OP_STATE_ACTIVE == op->state); - change_state (op, OP_STATE_INACTIVE); - nqueues = op->nqueues; - ms = sizeof(struct OperationQueue *) * nqueues; - queues = GNUNET_malloc (ms); - /* Cloning is needed as the operation be released by waiting operations and - hence its nqueues memory ptr will be freed */ - GNUNET_memcpy (queues, op->queues, ms); - for (i = 0; i < nqueues; i++) - recheck_waiting (queues[i]); - GNUNET_free (queues); -} - - -/** - * Marks and inactive operation as active. This function should be called to - * ensure that the oprelease callback will not be called until it is either - * marked as inactive or released. - * - * @param op the operation to be marked as active - */ -void -GNUNET_TESTBED_operation_activate_ (struct GNUNET_TESTBED_Operation *op) -{ - GNUNET_assert (OP_STATE_INACTIVE == op->state); - change_state (op, OP_STATE_ACTIVE); -} - - -/** - * An operation is 'done' (was cancelled or finished); remove - * it from the queues and release associated resources. - * - * @param op operation that finished - */ -void -GNUNET_TESTBED_operation_release_ (struct GNUNET_TESTBED_Operation *op) -{ - struct QueueEntry *entry; - struct OperationQueue *opq; - unsigned int i; - - if (OP_STATE_INIT == op->state) - { - GNUNET_free (op); - return; - } - if (OP_STATE_READY == op->state) - rq_remove (op); - if (OP_STATE_INACTIVE == op->state) /* Activate the operation if inactive */ - GNUNET_TESTBED_operation_activate_ (op); - if (OP_STATE_ACTIVE == op->state) - update_tslots (op); - GNUNET_assert (NULL != op->queues); - GNUNET_assert (NULL != op->qentries); - for (i = 0; i < op->nqueues; i++) - { - entry = op->qentries[i]; - remove_queue_entry (op, i); - opq = op->queues[i]; - switch (op->state) - { - case OP_STATE_INIT: - case OP_STATE_INACTIVE: - GNUNET_assert (0); - break; - - case OP_STATE_WAITING: - break; - - case OP_STATE_ACTIVE: - case OP_STATE_READY: - GNUNET_assert (0 != opq->active); - GNUNET_assert (opq->active >= entry->nres); - opq->active -= entry->nres; - recheck_waiting (opq); - break; - } - GNUNET_free (entry); - } - GNUNET_free (op->qentries); - GNUNET_free (op->queues); - GNUNET_free (op->nres); - if (NULL != op->release) - op->release (op->cb_cls); - GNUNET_free (op); -} - - -/** - * Marks an operation as failed - * - * @param op the operation to be marked as failed - */ -void -GNUNET_TESTBED_operation_mark_failed (struct GNUNET_TESTBED_Operation *op) -{ - op->failed = GNUNET_YES; -} - - -/** - * Cleanup expired operation queues. While doing so, also check for any - * operations which are not completed and warn about them. - */ -void __attribute__ ((destructor)) -GNUNET_TESTBED_operations_fini () -{ - struct OperationQueue *queue; - unsigned int i; - int warn = 0; - - for (i = 0; i < n_expired_opqs; i++) - { - queue = expired_opqs[i]; - if (GNUNET_NO == is_queue_empty (queue)) - warn = 1; - queue_destroy (queue); - } - GNUNET_free (expired_opqs); - n_expired_opqs = 0; - if (warn) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Be disciplined. Some operations were not marked as done.\n"); -} - - -/* end of testbed_api_operations.c */ diff --git a/src/testbed/testbed_api_operations.h b/src/testbed/testbed_api_operations.h @@ -1,233 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_operations.h - * @brief internal API to access the 'operations' subsystem - * @author Christian Grothoff - */ -#ifndef NEW_TESTING_API_OPERATIONS_H -#define NEW_TESTING_API_OPERATIONS_H - -#include "gnunet_testbed_service.h" -#include "gnunet_util_lib.h" - - -/** - * Queue of operations where we can only support a certain - * number of concurrent operations of a particular type. - */ -struct OperationQueue; - - -/** - * The type of operation queue - */ -enum OperationQueueType -{ - /** - * Operation queue which permits a fixed maximum number of operations to be - * active at any time - */ - OPERATION_QUEUE_TYPE_FIXED, - - /** - * Operation queue which adapts the number of operations to be active based on - * the operation completion times of previously executed operation in it - */ - OPERATION_QUEUE_TYPE_ADAPTIVE -}; - - -/** - * Create an operation queue. - * - * @param type the type of operation queue - * @param max_active maximum number of operations in this - * queue that can be active in parallel at the same time. - * @return handle to the queue - */ -struct OperationQueue * -GNUNET_TESTBED_operation_queue_create_ (enum OperationQueueType type, - unsigned int max_active); - - -/** - * Destroy an operation queue. The queue MUST be empty - * at this time. - * - * @param queue queue to destroy - */ -void -GNUNET_TESTBED_operation_queue_destroy_ (struct OperationQueue *queue); - - -/** - * Destroys the operation queue if it is empty. If not empty return GNUNET_NO. - * - * @param queue the queue to destroy if empty - * @return GNUNET_YES if the queue is destroyed. GNUNET_NO if not (because it - * is not empty) - */ -int -GNUNET_TESTBED_operation_queue_destroy_empty_ (struct OperationQueue *queue); - - -/** - * Function to reset the maximum number of operations in the given queue. If - * max_active is lesser than the number of currently active operations, the - * active operations are not stopped immediately. - * - * @param queue the operation queue which has to be modified - * @param max_active the new maximum number of active operations - */ -void -GNUNET_TESTBED_operation_queue_reset_max_active_ (struct OperationQueue *queue, - unsigned int max_active); - - -/** - * Add an operation to a queue. An operation can be in multiple queues at - * once. Once the operation is inserted into all the queues - * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start - * waiting for the operation to become active. - * - * @param queue queue to add the operation to - * @param op operation to add to the queue - * @param nres the number of units of the resources of queue needed by the - * operation. Should be greater than 0. - */ -void -GNUNET_TESTBED_operation_queue_insert2_ (struct OperationQueue *queue, - struct GNUNET_TESTBED_Operation *op, - unsigned int nres); - - -/** - * Add an operation to a queue. An operation can be in multiple queues at - * once. Once the operation is inserted into all the queues - * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start - * waiting for the operation to become active. - * - * @param queue queue to add the operation to - * @param op operation to add to the queue - */ -void -GNUNET_TESTBED_operation_queue_insert_ (struct OperationQueue *queue, - struct GNUNET_TESTBED_Operation *op); - - -/** - * Marks the given operation as waiting on the queues. Once all queues permit - * the operation to become active, the operation will be activated. The actual - * activation will occur in a separate task (thus allowing multiple queue - * insertions to be made without having the first one instantly trigger the - * operation if the first queue has sufficient resources). - * - * @param op the operation to marks as waiting - */ -void -GNUNET_TESTBED_operation_begin_wait_ (struct GNUNET_TESTBED_Operation *op); - - -/** - * Function to call to start an operation once all - * queues the operation is part of declare that the - * operation can be activated. - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -typedef void (*OperationStart) (void *cls); - - -/** - * Function to call to cancel an operation (release all associated - * resources). This can be because of a call to - * "GNUNET_TESTBED_operation_cancel" (before the operation generated - * an event) or AFTER the operation generated an event due to a call - * to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that - * a callback to the 'OperationStart' precedes the call to - * 'OperationRelease'. Implementations of this function are expected - * to clean up whatever state is in 'cls' and release all resources - * associated with the operation. - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -typedef void (*OperationRelease) (void *cls); - - -/** - * Create an 'operation' to be performed. - * - * @param cls closure for the callbacks - * @param start function to call to start the operation - * @param release function to call to close down the operation - * @return handle to the operation - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_operation_create_ (void *cls, OperationStart start, - OperationRelease release); - - -/** - * An operation is 'done' (was cancelled or finished); remove - * it from the queues and release associated resources. - * - * @param op operation that finished - */ -void -GNUNET_TESTBED_operation_release_ (struct GNUNET_TESTBED_Operation *op); - - -/** - * Marks an active operation as inactive - the operation will be kept in a - * ready-to-be-released state and continues to hold resources until another - * operation contents for them. - * - * @param op the operation to be marked as inactive. The operation start - * callback should have been called before for this operation to mark - * it as inactive. - */ -void -GNUNET_TESTBED_operation_inactivate_ (struct GNUNET_TESTBED_Operation *op); - - -/** - * Marks and inactive operation as active. This function should be called to - * ensure that the oprelease callback will not be called until it is either - * marked as inactive or released. - * - * @param op the operation to be marked as active - */ -void -GNUNET_TESTBED_operation_activate_ (struct GNUNET_TESTBED_Operation *op); - - -/** - * Marks an operation as failed - * - * @param op the operation to be marked as failed - */ -void -GNUNET_TESTBED_operation_mark_failed (struct GNUNET_TESTBED_Operation *op); - - -#endif -/* end of testbed_api_operations.h */ diff --git a/src/testbed/testbed_api_peers.c b/src/testbed/testbed_api_peers.c @@ -1,961 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_peers.c - * @brief management of the knowledge about peers in this library - * (we know the peer ID, its host, pending operations, etc.) - * @author Christian Grothoff - * @author Sree Harsha Totakura - */ - -#include "platform.h" -#include "testbed_api_peers.h" -#include "testbed_api.h" -#include "testbed.h" -#include "testbed_api_hosts.h" -#include "testbed_api_operations.h" - - -/** - * Peer list DLL head - */ -static struct GNUNET_TESTBED_Peer *peer_list_head; - -/** - * Peer list DLL tail - */ -static struct GNUNET_TESTBED_Peer *peer_list_tail; - - -/** - * Adds a peer to the peer list - * - * @param peer the peer to add to the peer list - */ -void -GNUNET_TESTBED_peer_register_ (struct GNUNET_TESTBED_Peer *peer) -{ - GNUNET_CONTAINER_DLL_insert_tail (peer_list_head, peer_list_tail, peer); -} - - -/** - * Removes a peer from the peer list - * - * @param peer the peer to remove - */ -void -GNUNET_TESTBED_peer_deregister_ (struct GNUNET_TESTBED_Peer *peer) -{ - GNUNET_CONTAINER_DLL_remove (peer_list_head, peer_list_tail, peer); -} - - -/** - * Frees all peers - */ -void -GNUNET_TESTBED_cleanup_peers_ (void) -{ - struct GNUNET_TESTBED_Peer *peer; - - while (NULL != (peer = peer_list_head)) - { - GNUNET_TESTBED_peer_deregister_ (peer); - GNUNET_free (peer); - } -} - - -/** - * Function to call to start a peer_create type operation once all - * queues the operation is part of declare that the - * operation can be activated. - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -opstart_peer_create (void *cls) -{ - struct OperationContext *opc = cls; - struct PeerCreateData *data = opc->data; - struct GNUNET_TESTBED_PeerCreateMessage *msg; - struct GNUNET_MQ_Envelope *env; - char *config; - char *xconfig; - size_t c_size; - size_t xc_size; - - GNUNET_assert (OP_PEER_CREATE == opc->type); - GNUNET_assert (NULL != data); - GNUNET_assert (NULL != data->peer); - opc->state = OPC_STATE_STARTED; - config = GNUNET_CONFIGURATION_serialize (data->cfg, - &c_size); - xc_size = GNUNET_TESTBED_compress_config_ (config, - c_size, - &xconfig); - GNUNET_free (config); - env = GNUNET_MQ_msg_extra (msg, - xc_size, - GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER); - msg->operation_id = GNUNET_htonll (opc->id); - msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->peer->host)); - msg->peer_id = htonl (data->peer->unique_id); - msg->config_size = htons ((uint16_t) c_size); - GNUNET_memcpy (&msg[1], - xconfig, - xc_size); - GNUNET_MQ_send (opc->c->mq, - env); - GNUNET_free (xconfig); - GNUNET_TESTBED_insert_opc_ (opc->c, opc); -} - - -/** - * Callback which will be called when peer_create type operation is released - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -oprelease_peer_create (void *cls) -{ - struct OperationContext *opc = cls; - - switch (opc->state) - { - case OPC_STATE_STARTED: - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - - /* No break we continue flow */ - case OPC_STATE_INIT: - GNUNET_free (((struct PeerCreateData *) opc->data)->peer); - GNUNET_free (opc->data); - break; - - case OPC_STATE_FINISHED: - break; - } - GNUNET_free (opc); -} - - -/** - * Function called when a peer destroy operation is ready - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -opstart_peer_destroy (void *cls) -{ - struct OperationContext *opc = cls; - struct GNUNET_TESTBED_Peer *peer = opc->data; - struct GNUNET_TESTBED_PeerDestroyMessage *msg; - struct GNUNET_MQ_Envelope *env; - - GNUNET_assert (OP_PEER_DESTROY == opc->type); - GNUNET_assert (NULL != peer); - opc->state = OPC_STATE_STARTED; - env = GNUNET_MQ_msg (msg, - GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER); - msg->peer_id = htonl (peer->unique_id); - msg->operation_id = GNUNET_htonll (opc->id); - GNUNET_TESTBED_insert_opc_ (opc->c, opc); - GNUNET_MQ_send (peer->controller->mq, - env); -} - - -/** - * Callback which will be called when peer_create type operation is released - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -oprelease_peer_destroy (void *cls) -{ - struct OperationContext *opc = cls; - - switch (opc->state) - { - case OPC_STATE_STARTED: - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - - /* no break; continue */ - case OPC_STATE_INIT: - break; - - case OPC_STATE_FINISHED: - break; - } - GNUNET_free (opc); -} - - -/** - * Function called when a peer start operation is ready - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -opstart_peer_start (void *cls) -{ - struct OperationContext *opc = cls; - struct GNUNET_TESTBED_PeerStartMessage *msg; - struct GNUNET_MQ_Envelope *env; - struct PeerEventData *data; - struct GNUNET_TESTBED_Peer *peer; - - GNUNET_assert (OP_PEER_START == opc->type); - GNUNET_assert (NULL != (data = opc->data)); - GNUNET_assert (NULL != (peer = data->peer)); - GNUNET_assert ((TESTBED_PS_CREATED == peer->state) || (TESTBED_PS_STOPPED == - peer->state)); - opc->state = OPC_STATE_STARTED; - env = GNUNET_MQ_msg (msg, - GNUNET_MESSAGE_TYPE_TESTBED_START_PEER); - msg->peer_id = htonl (peer->unique_id); - msg->operation_id = GNUNET_htonll (opc->id); - GNUNET_TESTBED_insert_opc_ (opc->c, opc); - GNUNET_MQ_send (peer->controller->mq, - env); -} - - -/** - * Callback which will be called when peer start type operation is released - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -oprelease_peer_start (void *cls) -{ - struct OperationContext *opc = cls; - - switch (opc->state) - { - case OPC_STATE_STARTED: - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - - /* no break; continue */ - case OPC_STATE_INIT: - GNUNET_free (opc->data); - break; - - case OPC_STATE_FINISHED: - break; - } - GNUNET_free (opc); -} - - -/** - * Function called when a peer stop operation is ready - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -opstart_peer_stop (void *cls) -{ - struct OperationContext *opc = cls; - struct GNUNET_TESTBED_PeerStopMessage *msg; - struct PeerEventData *data; - struct GNUNET_TESTBED_Peer *peer; - struct GNUNET_MQ_Envelope *env; - - GNUNET_assert (NULL != (data = opc->data)); - GNUNET_assert (NULL != (peer = data->peer)); - GNUNET_assert (TESTBED_PS_STARTED == peer->state); - opc->state = OPC_STATE_STARTED; - env = GNUNET_MQ_msg (msg, - GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER); - msg->peer_id = htonl (peer->unique_id); - msg->operation_id = GNUNET_htonll (opc->id); - GNUNET_TESTBED_insert_opc_ (opc->c, opc); - GNUNET_MQ_send (peer->controller->mq, - env); -} - - -/** - * Callback which will be called when peer stop type operation is released - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -oprelease_peer_stop (void *cls) -{ - struct OperationContext *opc = cls; - - switch (opc->state) - { - case OPC_STATE_STARTED: - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - - /* no break; continue */ - case OPC_STATE_INIT: - GNUNET_free (opc->data); - break; - - case OPC_STATE_FINISHED: - break; - } - GNUNET_free (opc); -} - - -/** - * Generate PeerGetConfigurationMessage - * - * @param peer_id the id of the peer whose information we have to get - * @param operation_id the ip of the operation that should be represented in the - * message - * @return the PeerGetConfigurationMessage - */ -struct GNUNET_TESTBED_PeerGetConfigurationMessage * -GNUNET_TESTBED_generate_peergetconfig_msg_ (uint32_t peer_id, - uint64_t operation_id) -{ - struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; - - msg = - GNUNET_malloc (sizeof - (struct GNUNET_TESTBED_PeerGetConfigurationMessage)); - msg->header.size = - htons (sizeof(struct GNUNET_TESTBED_PeerGetConfigurationMessage)); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION); - msg->peer_id = htonl (peer_id); - msg->operation_id = GNUNET_htonll (operation_id); - return msg; -} - - -/** - * Function called when a peer get information operation is ready - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -opstart_peer_getinfo (void *cls) -{ - struct OperationContext *opc = cls; - struct PeerInfoData *data = opc->data; - struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; - - GNUNET_assert (NULL != data); - opc->state = OPC_STATE_STARTED; - msg = - GNUNET_TESTBED_generate_peergetconfig_msg_ (data->peer->unique_id, - opc->id); - GNUNET_TESTBED_insert_opc_ (opc->c, opc); - GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); -} - - -/** - * Callback which will be called when peer stop type operation is released - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -oprelease_peer_getinfo (void *cls) -{ - struct OperationContext *opc = cls; - struct GNUNET_TESTBED_PeerInformation *data; - - switch (opc->state) - { - case OPC_STATE_STARTED: - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - - /* no break; continue */ - case OPC_STATE_INIT: - GNUNET_free (opc->data); - break; - - case OPC_STATE_FINISHED: - data = opc->data; - GNUNET_assert (NULL != data); - switch (data->pit) - { - case GNUNET_TESTBED_PIT_CONFIGURATION: - if (NULL != data->result.cfg) - GNUNET_CONFIGURATION_destroy (data->result.cfg); - break; - - case GNUNET_TESTBED_PIT_IDENTITY: - GNUNET_free (data->result.id); - break; - - default: - GNUNET_assert (0); /* We should never reach here */ - } - GNUNET_free (data); - break; - } - GNUNET_free (opc); -} - - -/** - * Function called when a overlay connect operation is ready - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -opstart_overlay_connect (void *cls) -{ - struct OperationContext *opc = cls; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_OverlayConnectMessage *msg; - struct OverlayConnectData *data; - - opc->state = OPC_STATE_STARTED; - data = opc->data; - GNUNET_assert (NULL != data); - env = GNUNET_MQ_msg (msg, - GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT); - msg->peer1 = htonl (data->p1->unique_id); - msg->peer2 = htonl (data->p2->unique_id); - msg->operation_id = GNUNET_htonll (opc->id); - msg->peer2_host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->p2->host)); - GNUNET_TESTBED_insert_opc_ (opc->c, - opc); - GNUNET_MQ_send (opc->c->mq, - env); -} - - -/** - * Callback which will be called when overlay connect operation is released - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -oprelease_overlay_connect (void *cls) -{ - struct OperationContext *opc = cls; - struct OverlayConnectData *data; - - data = opc->data; - switch (opc->state) - { - case OPC_STATE_INIT: - break; - - case OPC_STATE_STARTED: - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - break; - - case OPC_STATE_FINISHED: - break; - } - GNUNET_free (data); - GNUNET_free (opc); -} - - -/** - * Function called when a peer reconfigure operation is ready - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -opstart_peer_reconfigure (void *cls) -{ - struct OperationContext *opc = cls; - struct PeerReconfigureData *data = opc->data; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_PeerReconfigureMessage *msg; - char *xconfig; - size_t xc_size; - - opc->state = OPC_STATE_STARTED; - GNUNET_assert (NULL != data); - xc_size = GNUNET_TESTBED_compress_config_ (data->config, - data->cfg_size, - &xconfig); - GNUNET_free (data->config); - data->config = NULL; - GNUNET_assert (xc_size < UINT16_MAX - sizeof(*msg)); - env = GNUNET_MQ_msg_extra (msg, - xc_size, - GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER); - msg->peer_id = htonl (data->peer->unique_id); - msg->operation_id = GNUNET_htonll (opc->id); - msg->config_size = htons (data->cfg_size); - GNUNET_memcpy (&msg[1], - xconfig, - xc_size); - GNUNET_free (xconfig); - GNUNET_free (data); - opc->data = NULL; - GNUNET_TESTBED_insert_opc_ (opc->c, opc); - GNUNET_MQ_send (opc->c->mq, - env); -} - - -/** - * Callback which will be called when a peer reconfigure operation is released - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -oprelease_peer_reconfigure (void *cls) -{ - struct OperationContext *opc = cls; - struct PeerReconfigureData *data = opc->data; - - switch (opc->state) - { - case OPC_STATE_INIT: - GNUNET_free (data->config); - GNUNET_free (data); - break; - - case OPC_STATE_STARTED: - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - break; - - case OPC_STATE_FINISHED: - break; - } - GNUNET_free (opc); -} - - -/** - * Lookup a peer by ID. - * - * @param id global peer ID assigned to the peer - * @return handle to the host, NULL on error - */ -struct GNUNET_TESTBED_Peer * -GNUNET_TESTBED_peer_lookup_by_id_ (uint32_t id) -{ - GNUNET_break (0); - return NULL; -} - - -/** - * Create the given peer at the specified host using the given - * controller. If the given controller is not running on the target - * host, it should find or create a controller at the target host and - * delegate creating the peer. Explicit delegation paths can be setup - * using 'GNUNET_TESTBED_controller_link'. If no explicit delegation - * path exists, a direct link with a subordinate controller is setup - * for the first delegated peer to a particular host; the subordinate - * controller is then destroyed once the last peer that was delegated - * to the remote host is stopped. - * - * Creating the peer only creates the handle to manipulate and further - * configure the peer; use "GNUNET_TESTBED_peer_start" and - * "GNUNET_TESTBED_peer_stop" to actually start/stop the peer's - * processes. - * - * Note that the given configuration will be adjusted by the - * controller to avoid port/path conflicts with other peers. - * The "final" configuration can be obtained using - * 'GNUNET_TESTBED_peer_get_information'. - * - * @param controller controller process to use - * @param host host to run the peer on; cannot be NULL - * @param cfg Template configuration to use for the peer. Should exist until - * operation is cancelled or GNUNET_TESTBED_operation_done() is called - * @param cb the callback to call when the peer has been created - * @param cls the closure to the above callback - * @return the operation handle - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_peer_create (struct GNUNET_TESTBED_Controller *controller, - struct GNUNET_TESTBED_Host *host, - const struct GNUNET_CONFIGURATION_Handle *cfg, - GNUNET_TESTBED_PeerCreateCallback cb, void *cls) -{ - struct GNUNET_TESTBED_Peer *peer; - struct PeerCreateData *data; - struct OperationContext *opc; - static uint32_t id_gen; - - peer = GNUNET_new (struct GNUNET_TESTBED_Peer); - peer->controller = controller; - peer->host = host; - peer->unique_id = id_gen++; - peer->state = TESTBED_PS_INVALID; - data = GNUNET_new (struct PeerCreateData); - data->host = host; - data->cfg = cfg; - data->cb = cb; - data->cls = cls; - data->peer = peer; - opc = GNUNET_new (struct OperationContext); - opc->c = controller; - opc->data = data; - opc->id = GNUNET_TESTBED_get_next_op_id (controller); - opc->type = OP_PEER_CREATE; - opc->op = - GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_create, - &oprelease_peer_create); - GNUNET_TESTBED_operation_queue_insert_ (controller->opq_parallel_operations, - opc->op); - GNUNET_TESTBED_operation_begin_wait_ (opc->op); - return opc->op; -} - - -/** - * Start the given peer. - * - * @param op_cls the closure for this operation; will be set in - * event->details.operation_finished.op_cls when this operation fails. - * @param peer peer to start - * @param pcc function to call upon completion - * @param pcc_cls closure for 'pcc' - * @return handle to the operation - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_peer_start (void *op_cls, struct GNUNET_TESTBED_Peer *peer, - GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls) -{ - struct OperationContext *opc; - struct PeerEventData *data; - - data = GNUNET_new (struct PeerEventData); - data->peer = peer; - data->pcc = pcc; - data->pcc_cls = pcc_cls; - opc = GNUNET_new (struct OperationContext); - opc->c = peer->controller; - opc->data = data; - opc->op_cls = op_cls; - opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); - opc->type = OP_PEER_START; - opc->op = - GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_start, - &oprelease_peer_start); - GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, - opc->op); - GNUNET_TESTBED_operation_begin_wait_ (opc->op); - return opc->op; -} - - -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_peer_stop (void *op_cls, - struct GNUNET_TESTBED_Peer *peer, - GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls) -{ - struct OperationContext *opc; - struct PeerEventData *data; - - data = GNUNET_new (struct PeerEventData); - data->peer = peer; - data->pcc = pcc; - data->pcc_cls = pcc_cls; - opc = GNUNET_new (struct OperationContext); - opc->c = peer->controller; - opc->data = data; - opc->op_cls = op_cls; - opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); - opc->type = OP_PEER_STOP; - opc->op = - GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_stop, - &oprelease_peer_stop); - GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, - opc->op); - GNUNET_TESTBED_operation_begin_wait_ (opc->op); - return opc->op; -} - - -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_peer_get_information (struct GNUNET_TESTBED_Peer *peer, - enum GNUNET_TESTBED_PeerInformationType - pit, GNUNET_TESTBED_PeerInfoCallback cb, - void *cb_cls) -{ - struct OperationContext *opc; - struct PeerInfoData *data; - - GNUNET_assert (GNUNET_TESTBED_PIT_GENERIC != pit); - GNUNET_assert (NULL != cb); - data = GNUNET_new (struct PeerInfoData); - data->peer = peer; - data->pit = pit; - data->cb = cb; - data->cb_cls = cb_cls; - opc = GNUNET_new (struct OperationContext); - opc->c = peer->controller; - opc->data = data; - opc->type = OP_PEER_INFO; - opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); - opc->op = - GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_getinfo, - &oprelease_peer_getinfo); - GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, - opc->op); - GNUNET_TESTBED_operation_begin_wait_ (opc->op); - return opc->op; -} - - -/** - * Change peer configuration. Must only be called while the - * peer is stopped. Ports and paths cannot be changed this - * way. - * - * @param peer peer to change configuration for - * @param cfg new configuration (differences to existing - * configuration only) - * @return handle to the operation - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_peer_update_configuration (struct GNUNET_TESTBED_Peer *peer, - const struct - GNUNET_CONFIGURATION_Handle *cfg) -{ - struct OperationContext *opc; - struct PeerReconfigureData *data; - size_t csize; - - data = GNUNET_new (struct PeerReconfigureData); - data->peer = peer; - data->config = GNUNET_CONFIGURATION_serialize (cfg, &csize); - if (NULL == data->config) - { - GNUNET_free (data); - return NULL; - } - if (csize > UINT16_MAX) - { - GNUNET_break (0); - GNUNET_free (data->config); - GNUNET_free (data); - return NULL; - } - data->cfg_size = (uint16_t) csize; - opc = GNUNET_new (struct OperationContext); - opc->c = peer->controller; - opc->data = data; - opc->type = OP_PEER_RECONFIGURE; - opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); - opc->op = - GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_reconfigure, - &oprelease_peer_reconfigure); - GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, - opc->op); - GNUNET_TESTBED_operation_begin_wait_ (opc->op); - return opc->op; -} - - -/** - * Destroy the given peer; the peer should have been - * stopped first (if it was started). - * - * @param peer peer to stop - * @return handle to the operation - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_peer_destroy (struct GNUNET_TESTBED_Peer *peer) -{ - struct OperationContext *opc; - - opc = GNUNET_new (struct OperationContext); - opc->data = peer; - opc->c = peer->controller; - opc->id = GNUNET_TESTBED_get_next_op_id (peer->controller); - opc->type = OP_PEER_DESTROY; - opc->op = - GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_destroy, - &oprelease_peer_destroy); - GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, - opc->op); - GNUNET_TESTBED_operation_begin_wait_ (opc->op); - return opc->op; -} - - -/** - * Manipulate the P2P underlay topology by configuring a link - * between two peers. - * - * @param op_cls closure argument to give with the operation event - * @param p1 first peer - * @param p2 second peer - * @param co option to change - * @param ... option-specific values - * @return handle to the operation, NULL if configuring the link at this - * time is not allowed - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_underlay_configure_link (void *op_cls, - struct GNUNET_TESTBED_Peer *p1, - struct GNUNET_TESTBED_Peer *p2, - enum GNUNET_TESTBED_ConnectOption co, - ...) -{ - GNUNET_break (0); - return NULL; -} - - -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_overlay_connect (void *op_cls, - GNUNET_TESTBED_OperationCompletionCallback cb, - void *cb_cls, struct GNUNET_TESTBED_Peer *p1, - struct GNUNET_TESTBED_Peer *p2) -{ - struct OperationContext *opc; - struct OverlayConnectData *data; - - GNUNET_assert ((TESTBED_PS_STARTED == p1->state) && (TESTBED_PS_STARTED == - p2->state)); - data = GNUNET_new (struct OverlayConnectData); - data->p1 = p1; - data->p2 = p2; - data->cb = cb; - data->cb_cls = cb_cls; - opc = GNUNET_new (struct OperationContext); - opc->data = data; - opc->c = p1->controller; - opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); - opc->type = OP_OVERLAY_CONNECT; - opc->op_cls = op_cls; - opc->op = - GNUNET_TESTBED_operation_create_ (opc, &opstart_overlay_connect, - &oprelease_overlay_connect); - GNUNET_TESTBED_host_queue_oc_ (p1->host, opc->op); - GNUNET_TESTBED_operation_begin_wait_ (opc->op); - return opc->op; -} - - -/** - * Function called when a peer manage service operation is ready - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -opstart_manage_service (void *cls) -{ - struct OperationContext *opc = cls; - struct ManageServiceData *data = opc->data; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_TESTBED_ManagePeerServiceMessage *msg; - size_t xlen; - - GNUNET_assert (NULL != data); - xlen = data->msize - sizeof(struct GNUNET_TESTBED_ManagePeerServiceMessage); - env = GNUNET_MQ_msg_extra (msg, - xlen, - GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE); - msg->peer_id = htonl (data->peer->unique_id); - msg->operation_id = GNUNET_htonll (opc->id); - msg->start = (uint8_t) data->start; - GNUNET_memcpy (&msg[1], - data->service_name, - xlen); - GNUNET_free (data->service_name); - data->service_name = NULL; - opc->state = OPC_STATE_STARTED; - GNUNET_TESTBED_insert_opc_ (opc->c, opc); - GNUNET_MQ_send (opc->c->mq, - env); -} - - -/** - * Callback which will be called when peer manage server operation is released - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -oprelease_manage_service (void *cls) -{ - struct OperationContext *opc = cls; - struct ManageServiceData *data; - - data = opc->data; - switch (opc->state) - { - case OPC_STATE_STARTED: - GNUNET_TESTBED_remove_opc_ (opc->c, opc); - break; - - case OPC_STATE_INIT: - GNUNET_assert (NULL != data); - GNUNET_free (data->service_name); - break; - - case OPC_STATE_FINISHED: - break; - } - GNUNET_free (data); - GNUNET_free (opc); -} - - -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_peer_manage_service (void *op_cls, - struct GNUNET_TESTBED_Peer *peer, - const char *service_name, - GNUNET_TESTBED_OperationCompletionCallback - cb, - void *cb_cls, - unsigned int start) -{ - struct ManageServiceData *data; - struct OperationContext *opc; - size_t msize; - - GNUNET_assert (TESTBED_PS_STARTED == peer->state); /* peer is not running? */ - msize = strlen (service_name) + 1; - msize += sizeof(struct GNUNET_TESTBED_ManagePeerServiceMessage); - if (GNUNET_MAX_MESSAGE_SIZE < msize) - return NULL; - data = GNUNET_new (struct ManageServiceData); - data->cb = cb; - data->cb_cls = cb_cls; - data->peer = peer; - data->service_name = GNUNET_strdup (service_name); - data->start = start; - data->msize = (uint16_t) msize; - opc = GNUNET_new (struct OperationContext); - opc->data = data; - opc->c = peer->controller; - opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); - opc->type = OP_MANAGE_SERVICE; - opc->op_cls = op_cls; - opc->op = - GNUNET_TESTBED_operation_create_ (opc, &opstart_manage_service, - &oprelease_manage_service); - GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, - opc->op); - GNUNET_TESTBED_operation_begin_wait_ (opc->op); - return opc->op; -} - - -/* end of testbed_api_peers.c */ diff --git a/src/testbed/testbed_api_peers.h b/src/testbed/testbed_api_peers.h @@ -1,311 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_peers.h - * @brief internal API to access the 'peers' subsystem - * @author Christian Grothoff - * @author Sree Harsha Totakura - */ - -#ifndef NEW_TESTING_API_PEERS_H -#define NEW_TESTING_API_PEERS_H - -#include "gnunet_testbed_service.h" -#include "gnunet_util_lib.h" - - -/** - * Enumeration of possible states a peer could be in - */ -enum PeerState -{ - /** - * State to signify that this peer is invalid - */ - TESTBED_PS_INVALID, - - /** - * The peer has been created - */ - TESTBED_PS_CREATED, - - /** - * The peer is running - */ - TESTBED_PS_STARTED, - - /** - * The peer is stopped - */ - TESTBED_PS_STOPPED, -}; - - -/** - * A peer controlled by the testing framework. A peer runs - * at a particular host. - */ -struct GNUNET_TESTBED_Peer -{ - /** - * peer list DLL - */ - struct GNUNET_TESTBED_Peer *next; - - /** - * peer list DLL - */ - struct GNUNET_TESTBED_Peer *prev; - - /** - * Our controller context (not necessarily the controller - * that is responsible for starting/running the peer!). - */ - struct GNUNET_TESTBED_Controller *controller; - - /** - * Which host does this peer run on? - */ - struct GNUNET_TESTBED_Host *host; - - /** - * Globally unique ID of the peer. - */ - uint32_t unique_id; - - /** - * Peer's state - */ - enum PeerState state; - - /** - * Has an underlay model already set for this peer? - */ - uint8_t underlay_model_exists; -}; - - -/** - * Data for the OperationType OP_PEER_CREATE - */ -struct PeerCreateData -{ - /** - * The host where the peer has to be created - */ - struct GNUNET_TESTBED_Host *host; - - /** - * The template configuration of the peer - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * The call back to call when we receive peer create success message - */ - GNUNET_TESTBED_PeerCreateCallback cb; - - /** - * The closure for the above callback - */ - void *cls; - - /** - * The peer structure to return when we get success message - */ - struct GNUNET_TESTBED_Peer *peer; -}; - - -/** - * Data for OperationType OP_PEER_START and OP_PEER_STOP - */ -struct PeerEventData -{ - /** - * The handle of the peer to start - */ - struct GNUNET_TESTBED_Peer *peer; - - /** - * The Peer churn callback to call when this operation is completed - */ - GNUNET_TESTBED_PeerChurnCallback pcc; - - /** - * Closure for the above callback - */ - void *pcc_cls; -}; - - -/** - * Data for the OperationType OP_PEER_DESTROY; - */ -struct PeerDestroyData -{ - /** - * The peer structure - */ - struct GNUNET_TESTBED_Peer *peer; - - // PEERDESTROYDATA -}; - - -/** - * Data for the OperationType OP_PEER_INFO - */ -struct PeerInfoData -{ - /** - * The peer whose information has been requested - */ - struct GNUNET_TESTBED_Peer *peer; - - /** - * The Peer info callback to call when this operation has completed - */ - GNUNET_TESTBED_PeerInfoCallback cb; - - /** - * The closure for peer info callback - */ - void *cb_cls; - - /** - * The type of peer information requested - */ - enum GNUNET_TESTBED_PeerInformationType pit; -}; - - -/** - * Data for the operations of type OP_PEER_RECONFIGURE - */ -struct PeerReconfigureData -{ - /** - * The peer whose information has been requested - */ - struct GNUNET_TESTBED_Peer *peer; - - /** - * The serialized new configuration template - */ - char *config; - - /** - * the size of the serialized configuration - */ - uint16_t cfg_size; -}; - - -/** - * Data structure for OperationType OP_OVERLAY_CONNECT - */ -struct OverlayConnectData -{ - /** - * Peer A to connect to peer B - */ - struct GNUNET_TESTBED_Peer *p1; - - /** - * Peer B - */ - struct GNUNET_TESTBED_Peer *p2; - - /** - * The operation completion callback to call once this operation is done - */ - GNUNET_TESTBED_OperationCompletionCallback cb; - - /** - * The closure for the above callback - */ - void *cb_cls; - - /** - * OperationContext for forwarded operations generated when peer1's controller doesn't have the - * configuration of peer2's controller for linking laterally to attempt an - * overlay connection between peer 1 and peer 2. - */ - struct OperationContext *sub_opc; -}; - - -struct ManageServiceData -{ - GNUNET_TESTBED_OperationCompletionCallback cb; - - void *cb_cls; - - struct GNUNET_TESTBED_Peer *peer; - - char *service_name; - - unsigned int start; - - uint16_t msize; -}; - - -/** - * Generate PeerGetConfigurationMessage - * - * @param peer_id the id of the peer whose information we have to get - * @param operation_id the ip of the operation that should be represented in - * the message - * @return the PeerGetConfigurationMessage - */ -struct GNUNET_TESTBED_PeerGetConfigurationMessage * -GNUNET_TESTBED_generate_peergetconfig_msg_ (uint32_t peer_id, - uint64_t operation_id); - - -/** - * Adds a peer to the peer list - * - * @param peer the peer to add to the peer list - */ -void -GNUNET_TESTBED_peer_register_ (struct GNUNET_TESTBED_Peer *peer); - - -/** - * Removes a peer from the peer list - * - * @param peer the peer to remove - */ -void -GNUNET_TESTBED_peer_deregister_ (struct GNUNET_TESTBED_Peer *peer); - - -/** - * Frees all peers - */ -void -GNUNET_TESTBED_cleanup_peers_ (void); - -#endif -/* end of testbed_api_peers.h */ diff --git a/src/testbed/testbed_api_sd.c b/src/testbed/testbed_api_sd.c @@ -1,213 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_sd.c - * @brief functions to calculate standard deviation - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "testbed_api_sd.h" - -/** - * An entry to hold data which will be used to calculate SD - */ -struct SDEntry -{ - /** - * DLL next pointer - */ - struct SDEntry *next; - - /** - * DLL prev pointer - */ - struct SDEntry *prev; - - /** - * The value to store - */ - unsigned int amount; -}; - - -/** - * Opaque handle for calculating SD - */ -struct SDHandle -{ - /** - * DLL head for storing entries - */ - struct SDEntry *head; - - /** - * DLL tail for storing entries - */ - struct SDEntry *tail; - - /** - * Squared sum of data values - */ - unsigned long long sqsum; - - /** - * Sum of the data values - */ - unsigned long sum; - - /** - * The average of data amounts - */ - float avg; - - /** - * The variance - */ - double vr; - - /** - * Number of data values; also the length of DLL containing SDEntries - */ - unsigned int cnt; - - /** - * max number of entries we can have in the DLL - */ - unsigned int max_cnt; -}; - - -/** - * Initialize standard deviation calculation handle - * - * @param max_cnt the maximum number of readings to keep - * @return the initialized handle - */ -struct SDHandle * -GNUNET_TESTBED_SD_init_ (unsigned int max_cnt) -{ - struct SDHandle *h; - - GNUNET_assert (1 < max_cnt); - h = GNUNET_new (struct SDHandle); - h->max_cnt = max_cnt; - return h; -} - - -/** - * Frees the memory allocated to the SD handle - * - * @param h the SD handle - */ -void -GNUNET_TESTBED_SD_destroy_ (struct SDHandle *h) -{ - struct SDEntry *entry; - - while (NULL != (entry = h->head)) - { - GNUNET_CONTAINER_DLL_remove (h->head, h->tail, entry); - GNUNET_free (entry); - } - GNUNET_free (h); -} - - -/** - * Add a reading to SD - * - * @param h the SD handle - * @param amount the reading value - */ -void -GNUNET_TESTBED_SD_add_data_ (struct SDHandle *h, unsigned int amount) -{ - struct SDEntry *entry; - double sqavg; - double sqsum_avg; - - entry = NULL; - if (h->cnt == h->max_cnt) - { - entry = h->head; - GNUNET_CONTAINER_DLL_remove (h->head, h->tail, entry); - h->sum -= entry->amount; - h->sqsum -= - ((unsigned long) entry->amount) * ((unsigned long) entry->amount); - h->cnt--; - } - GNUNET_assert (h->cnt < h->max_cnt); - if (NULL == entry) - entry = GNUNET_new (struct SDEntry); - entry->amount = amount; - GNUNET_CONTAINER_DLL_insert_tail (h->head, h->tail, entry); - h->sum += amount; - h->cnt++; - h->avg = ((float) h->sum) / ((float) h->cnt); - h->sqsum += ((unsigned long) amount) * ((unsigned long) amount); - sqsum_avg = ((double) h->sqsum) / ((double) h->cnt); - sqavg = ((double) h->avg) * ((double) h->avg); - h->vr = sqsum_avg - sqavg; -} - - -/** - * Calculates the factor by which the given amount differs - * - * @param h the SDhandle - * @param amount the value for which the deviation is returned - * @param factor the factor by which the given amont differs - * @return GNUNET_SYSERR if the deviation cannot - * be calculated; GNUNET_OK if the deviation is returned through factor - */ -int -GNUNET_TESTBED_SD_deviation_factor_ (struct SDHandle *h, unsigned int amount, - int *factor) -{ - double diff; - int f; - int n; - - if (h->cnt < 2) - return GNUNET_SYSERR; - if (((float) amount) > h->avg) - { - diff = ((float) amount) - h->avg; - f = 1; - } - else - { - diff = h->avg - ((float) amount); - f = -1; - } - diff *= diff; - for (n = 1; n < 4; n++) - if (diff < (((double) (n * n)) * h->vr)) - break; - *factor = f * n; - return GNUNET_OK; -} - - -/* end of testbed_api_sd.c */ diff --git a/src/testbed/testbed_api_sd.h b/src/testbed/testbed_api_sd.h @@ -1,81 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_sd.h - * @brief functions to calculate standard deviation - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#ifndef TESTBED_API_SD_H -#define TESTBED_API_SD_H - - -/** - * Opaque handle for calculating SD - */ -struct SDHandle; - - -/** - * Initialize standard deviation calculation handle - * - * @param max_cnt the maximum number of readings to keep - * @return the initialized handle - */ -struct SDHandle * -GNUNET_TESTBED_SD_init_ (unsigned int max_cnt); - - -/** - * Frees the memory allocated to the SD handle - * - * @param h the SD handle - */ -void -GNUNET_TESTBED_SD_destroy_ (struct SDHandle *h); - - -/** - * Add a reading to SD - * - * @param h the SD handle - * @param amount the reading value - */ -void -GNUNET_TESTBED_SD_add_data_ (struct SDHandle *h, unsigned int amount); - - -/** - * Returns the factor by which the given amount differs from the standard deviation - * - * @param h the SDhandle - * @param amount the value for which the deviation is returned - * @param factor the factor by which the given amont differs - * @return the deviation from the average; GNUNET_SYSERR if the deviation cannot - * be calculated OR 0 if the deviation is less than the average; a - * maximum of 4 is returned for deviations equal to or larger than 4 - */ -int -GNUNET_TESTBED_SD_deviation_factor_ (struct SDHandle *h, unsigned int amount, - int *factor); - -#endif -/* end of testbed_api.h */ diff --git a/src/testbed/testbed_api_services.c b/src/testbed/testbed_api_services.c @@ -1,291 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_services.c - * @brief convenience functions for accessing services - * @author Christian Grothoff - */ -#include "platform.h" -#include "testbed_api.h" -#include "testbed_api_peers.h" -#include "testbed_api_operations.h" - - -/** - * States for Service connect operations - */ -enum State -{ - /** - * Initial state - */ - INIT, - - /** - * The configuration request has been sent - */ - CFG_REQUEST_QUEUED, - - /** - * connected to service - */ - SERVICE_CONNECTED -}; - - -/** - * Data accessed during service connections - */ -struct ServiceConnectData -{ - /** - * helper function callback to establish the connection - */ - GNUNET_TESTBED_ConnectAdapter ca; - - /** - * helper function callback to close the connection - */ - GNUNET_TESTBED_DisconnectAdapter da; - - /** - * Closure to the above callbacks - */ - void *cada_cls; - - /** - * Service name - */ - char *service_name; - - /** - * Closure for operation event - */ - void *op_cls; - - /** - * The operation which created this structure - */ - struct GNUNET_TESTBED_Operation *operation; - - /** - * The operation context from GNUNET_TESTBED_forward_operation_msg_() - */ - struct OperationContext *opc; - - /** - * The peer handle - */ - struct GNUNET_TESTBED_Peer *peer; - - /** - * The acquired configuration of the peer - */ - struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * The op_result pointer from ConnectAdapter - */ - void *op_result; - - /** - * The operation completion callback - */ - GNUNET_TESTBED_ServiceConnectCompletionCallback cb; - - /** - * The closure for operation completion callback - */ - void *cb_cls; - - /** - * State information - */ - enum State state; -}; - - -/** - * Type of a function to call when we receive a message - * from the service. - * - * @param cls ServiceConnectData - * @param msg message received, NULL on timeout or fatal error - */ -static void -configuration_receiver (void *cls, const struct GNUNET_MessageHeader *msg) -{ - struct ServiceConnectData *data = cls; - struct GNUNET_TESTBED_Controller *c; - const char *emsg; - struct GNUNET_TESTBED_EventInformation info; - uint16_t mtype; - - c = data->peer->controller; - mtype = ntohs (msg->type); - emsg = NULL; - info.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; - info.op = data->operation; - info.op_cls = data->op_cls; - if (GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT == mtype) - { - emsg = - GNUNET_TESTBED_parse_error_string_ ((const struct - GNUNET_TESTBED_OperationFailureEventMessage - *) msg); - if (NULL == emsg) - emsg = "Unknown error"; - info.details.operation_finished.emsg = emsg; - info.details.operation_finished.generic = NULL; - goto call_cb; - } - data->cfg = GNUNET_TESTBED_extract_config_ (msg); - GNUNET_assert (NULL == data->op_result); - data->op_result = data->ca (data->cada_cls, data->cfg); - info.details.operation_finished.emsg = NULL; - info.details.operation_finished.generic = data->op_result; - data->state = SERVICE_CONNECTED; - -call_cb: - if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) && - (NULL != c->cc)) - c->cc (c->cc_cls, &info); - if (NULL != data->cb) - data->cb (data->cb_cls, data->operation, data->op_result, emsg); -} - - -/** - * Function called when a service connect operation is ready - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -opstart_service_connect (void *cls) -{ - struct ServiceConnectData *data = cls; - struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; - struct GNUNET_TESTBED_Controller *c; - uint64_t op_id; - - GNUNET_assert (NULL != data); - GNUNET_assert (NULL != data->peer); - c = data->peer->controller; - op_id = GNUNET_TESTBED_get_next_op_id (c); - msg = - GNUNET_TESTBED_generate_peergetconfig_msg_ (data->peer->unique_id, op_id); - data->opc = - GNUNET_TESTBED_forward_operation_msg_ (c, op_id, &msg->header, - &configuration_receiver, data); - GNUNET_free (msg); - data->state = CFG_REQUEST_QUEUED; -} - - -/** - * Callback which will be called when service connect type operation is - * released - * - * @param cls the closure from GNUNET_TESTBED_operation_create_() - */ -static void -oprelease_service_connect (void *cls) -{ - struct ServiceConnectData *data = cls; - - switch (data->state) - { - case INIT: - break; - - case CFG_REQUEST_QUEUED: - GNUNET_assert (NULL != data->opc); - GNUNET_TESTBED_forward_operation_msg_cancel_ (data->opc); - break; - - case SERVICE_CONNECTED: - GNUNET_assert (NULL != data->cfg); - GNUNET_CONFIGURATION_destroy (data->cfg); - if (NULL != data->da) - data->da (data->cada_cls, data->op_result); - break; - } - GNUNET_free (data); -} - - -/** - * Connect to a service offered by the given peer. Will ensure that - * the request is queued to not overwhelm our ability to create and - * maintain connections with other systems. The actual service - * handle is then returned via the 'op_result' member in the event - * callback. The 'ca' callback is used to create the connection - * when the time is right; the 'da' callback will be used to - * destroy the connection (upon 'GNUNET_TESTBED_operation_done'). - * 'GNUNET_TESTBED_operation_done' can be used to abort this - * operation until the event callback has been called. - * - * @param op_cls closure to pass in operation event - * @param peer peer that runs the service - * @param service_name name of the service to connect to - * @param cb the callback to call when this operation finishes - * @param cb_cls closure for the above callback - * @param ca helper function to establish the connection - * @param da helper function to close the connection - * @param cada_cls closure for ca and da - * @return handle for the operation - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_service_connect (void *op_cls, struct GNUNET_TESTBED_Peer *peer, - const char *service_name, - GNUNET_TESTBED_ServiceConnectCompletionCallback - cb, void *cb_cls, - GNUNET_TESTBED_ConnectAdapter ca, - GNUNET_TESTBED_DisconnectAdapter da, - void *cada_cls) -{ - struct ServiceConnectData *data; - - data = GNUNET_new (struct ServiceConnectData); - data->ca = ca; - data->da = da; - data->cada_cls = cada_cls; - data->op_cls = op_cls; - data->peer = peer; - data->state = INIT; - data->cb = cb; - data->cb_cls = cb_cls; - data->operation = - GNUNET_TESTBED_operation_create_ (data, &opstart_service_connect, - &oprelease_service_connect); - GNUNET_TESTBED_operation_queue_insert_ (peer-> - controller-> - opq_parallel_service_connections, - data->operation); - GNUNET_TESTBED_operation_queue_insert_ (peer-> - controller->opq_parallel_operations, - data->operation); - GNUNET_TESTBED_operation_begin_wait_ (data->operation); - return data->operation; -} - - -/* end of testbed_api_services.c */ diff --git a/src/testbed/testbed_api_statistics.c b/src/testbed/testbed_api_statistics.c @@ -1,435 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_statistics.c - * @brief high-level statistics function - * @author Christian Grothoff - * @author Sree Harsha Totakura - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" - -#include "testbed_api_operations.h" - - -/** - * Generic logging shorthand - */ -#define LOG(kind, ...) \ - GNUNET_log_from (kind, "testbed-api-statistics", __VA_ARGS__) - -/** - * Debug logging shorthand - */ -#define LOG_DEBUG(...) \ - LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) - - -/** - * Context information for use in GNUNET_TESTBED_get_statistics() - */ -struct GetStatsContext -{ - /** - * The main operation we generate while creating this context - */ - struct GNUNET_TESTBED_Operation *main_op; - - /** - * The service connect operations we create to open connection to the - * statistics service of each given peer - */ - struct GNUNET_TESTBED_Operation **ops; - - /** - * The array of peers whose statistics services are to be accessed - */ - struct GNUNET_TESTBED_Peer **peers; - - /** - * The subsystem of peers for which statistics are requested - */ - char *subsystem; - - /** - * The particular statistics value of interest - */ - char *name; - - /** - * The iterator to call with statistics information - */ - GNUNET_TESTBED_StatisticsIterator proc; - - /** - * The callback to call when we are done iterating through all peers' - * statistics services - */ - GNUNET_TESTBED_OperationCompletionCallback cont; - - /** - * The closure for the above callbacks - */ - void *cb_cls; - - /** - * The task for calling the continuation callback - */ - struct GNUNET_SCHEDULER_Task *call_completion_task_id; - - /** - * The number of peers present in the peers array. This number also - * represents the number of service connect operations in the ops array - */ - unsigned int num_peers; - - /** - * How many peers' statistics have we iterated through - */ - unsigned int num_completed; -}; - - -/** - * Context information with respect to a particular peer - */ -struct PeerGetStatsContext -{ - /** - * The GetStatsContext which is associated with this context - */ - struct GetStatsContext *sc; - - /** - * The handle from GNUNET_STATISTICS_get() - */ - struct GNUNET_STATISTICS_GetHandle *get_handle; - - /** - * Task to mark the statistics service connect operation as done - */ - struct GNUNET_SCHEDULER_Task *op_done_task_id; - - /** - * The index of this peer in the peers array of GetStatsContext - */ - unsigned int peer_index; -}; - - -/** - * A no-wait operation queue - */ -static struct OperationQueue *no_wait_queue; - - -/** - * Call statistics operation completion. We call it in a separate task because - * the iteration_completion_cb() cannot destroy statistics handle which will be - * the case if the user calls GNUNET_TESTBED_operation_done() on the - * get_statistics operation. - * - * @param cls the GetStatsContext - */ -static void -call_completion_task (void *cls) -{ - struct GetStatsContext *sc = cls; - - GNUNET_assert (sc->call_completion_task_id != NULL); - sc->call_completion_task_id = NULL; - LOG_DEBUG ("Calling get_statistics() continuation callback\n"); - sc->cont (sc->cb_cls, sc->main_op, NULL); -} - - -/** - * Task to mark statistics service connect operation as done. We call it here - * as we cannot destroy the statistics handle in iteration_completion_cb() - * - * @param cls the PeerGetStatsContext - */ -static void -op_done_task (void *cls) -{ - struct PeerGetStatsContext *peer_sc = cls; - struct GetStatsContext *sc; - struct GNUNET_TESTBED_Operation **op; - - sc = peer_sc->sc; - peer_sc->op_done_task_id = NULL; - op = &sc->ops[peer_sc->peer_index]; - GNUNET_assert (NULL != *op); - GNUNET_TESTBED_operation_done (*op); - *op = NULL; -} - - -/** - * Continuation called by the "get_all" and "get" functions. - * - * @param cls the PeerGetStatsContext - * @param success GNUNET_OK if statistics were - * successfully obtained, GNUNET_SYSERR if not. - */ -static void -iteration_completion_cb (void *cls, int success) -{ - struct PeerGetStatsContext *peer_sc = cls; - struct GetStatsContext *sc; - - GNUNET_break (GNUNET_OK == success); - sc = peer_sc->sc; - peer_sc->get_handle = NULL; - sc->num_completed++; - peer_sc->op_done_task_id = GNUNET_SCHEDULER_add_now (&op_done_task, peer_sc); - if (sc->num_completed == sc->num_peers) - { - LOG_DEBUG ("Scheduling to call iteration completion callback\n"); - sc->call_completion_task_id = - GNUNET_SCHEDULER_add_now (&call_completion_task, sc); - } -} - - -/** - * Callback function to process statistic values. - * - * @param cls the PeerGetStatsContext - * @param subsystem name of subsystem that created the statistic - * @param name the name of the datum - * @param value the current value - * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not - * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration - */ -static int -iterator_cb (void *cls, const char *subsystem, - const char *name, uint64_t value, - int is_persistent) -{ - struct PeerGetStatsContext *peer_sc = cls; - struct GetStatsContext *sc; - struct GNUNET_TESTBED_Peer *peer; - int ret; - - sc = peer_sc->sc; - peer = sc->peers[peer_sc->peer_index]; - LOG_DEBUG ("Peer %u: [%s,%s] -> %lu\n", peer_sc->peer_index, - subsystem, name, (unsigned long) value); - ret = sc->proc (sc->cb_cls, peer, - subsystem, name, value, is_persistent); - if (GNUNET_SYSERR == ret) - LOG_DEBUG ("Aborting iteration for peer %u\n", peer_sc->peer_index); - return ret; -} - - -/** - * Called after opening a connection to the statistics service of a peer - * - * @param cls the PeerGetStatsContext - * @param op the operation that has been finished - * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() - * @param emsg error message in case the operation has failed; will be NULL if - * operation has executed successfully. - */ -static void -service_connect_comp (void *cls, - struct GNUNET_TESTBED_Operation *op, - void *ca_result, - const char *emsg) -{ - struct PeerGetStatsContext *peer_sc = cls; - struct GNUNET_STATISTICS_Handle *h = ca_result; - - LOG_DEBUG ("Retrieving statistics of peer %u\n", - peer_sc->peer_index); - peer_sc->get_handle = - GNUNET_STATISTICS_get (h, peer_sc->sc->subsystem, - peer_sc->sc->name, - &iteration_completion_cb, - iterator_cb, peer_sc); -} - - -/** - * Adapter function called to establish a connection to the statistics service - * of a peer. - * - * @param cls the PeerGetStatsContext - * @param cfg configuration of the peer to connect to; will be available until - * GNUNET_TESTBED_operation_done() is called on the operation returned - * from GNUNET_TESTBED_service_connect() - * @return service handle to return in 'op_result', NULL on error - */ -static void * -statistics_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct PeerGetStatsContext *peer_sc = cls; - - LOG_DEBUG ("Connecting to statistics service of peer %u\n", - peer_sc->peer_index); - return GNUNET_STATISTICS_create ("<testbed-api>", cfg); -} - - -/** - * Adapter function called to destroy statistics connection - * - * @param cls the PeerGetStatsContext - * @param op_result service handle returned from the connect adapter - */ -static void -statistics_da (void *cls, void *op_result) -{ - struct PeerGetStatsContext *peer_sc = cls; - struct GNUNET_STATISTICS_Handle *sh = op_result; - - if (NULL != peer_sc->get_handle) - { - GNUNET_STATISTICS_get_cancel (peer_sc->get_handle); - peer_sc->get_handle = NULL; - } - GNUNET_STATISTICS_destroy (sh, GNUNET_NO); - if (NULL != peer_sc->op_done_task_id) - GNUNET_SCHEDULER_cancel (peer_sc->op_done_task_id); - GNUNET_free (peer_sc); -} - - -/** - * Function called when get_statistics operation is ready - * - * @param cls the GetStatsContext - */ -static void -opstart_get_stats (void *cls) -{ - struct GetStatsContext *sc = cls; - struct PeerGetStatsContext *peer_sc; - unsigned int peer; - - LOG_DEBUG ("Starting get_statistics operation\n"); - sc->ops = GNUNET_malloc (sc->num_peers - * sizeof(struct GNUNET_TESTBED_Operation *)); - for (peer = 0; peer < sc->num_peers; peer++) - { - if (NULL == sc->peers[peer]) - { - GNUNET_break (0); - continue; - } - peer_sc = GNUNET_new (struct PeerGetStatsContext); - peer_sc->sc = sc; - peer_sc->peer_index = peer; - sc->ops[peer] = - GNUNET_TESTBED_service_connect (sc, sc->peers[peer], "statistics", - &service_connect_comp, - peer_sc, - &statistics_ca, - &statistics_da, - peer_sc); - } -} - - -/** - * Function called when get_statistics operation is cancelled or marked as done - * - * @param cls the GetStatsContext - */ -static void -oprelease_get_stats (void *cls) -{ - struct GetStatsContext *sc = cls; - unsigned int peer; - - LOG_DEBUG ("Cleaning up get_statistics operation\n"); - if (NULL != sc->call_completion_task_id) - GNUNET_SCHEDULER_cancel (sc->call_completion_task_id); - if (NULL != sc->ops) - { - for (peer = 0; peer < sc->num_peers; peer++) - { - if (NULL != sc->ops[peer]) - { - GNUNET_TESTBED_operation_done (sc->ops[peer]); - sc->ops[peer] = NULL; - } - } - GNUNET_free (sc->ops); - } - GNUNET_free (sc->subsystem); - GNUNET_free (sc->name); - GNUNET_free (sc); - if (GNUNET_YES == - GNUNET_TESTBED_operation_queue_destroy_empty_ (no_wait_queue)) - no_wait_queue = NULL; -} - - -/** - * Convenience method that iterates over all (running) peers - * and retrieves all statistics from each peer. - * - * @param num_peers number of peers to iterate over - * @param peers array of peers to iterate over - * @param subsystem limit to the specified subsystem, NULL for all subsystems - * @param name name of the statistic value, NULL for all values - * @param proc processing function for each statistic retrieved - * @param cont continuation to call once call is completed(?) - * @param cls closure to pass to proc and cont - * @return operation handle to cancel the operation - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_get_statistics (unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers, - const char *subsystem, const char *name, - GNUNET_TESTBED_StatisticsIterator proc, - GNUNET_TESTBED_OperationCompletionCallback cont, - void *cls) -{ - struct GetStatsContext *sc; - - GNUNET_assert (NULL != proc); - GNUNET_assert (NULL != cont); - if (NULL == no_wait_queue) - no_wait_queue = GNUNET_TESTBED_operation_queue_create_ - (OPERATION_QUEUE_TYPE_FIXED, UINT_MAX); - sc = GNUNET_new (struct GetStatsContext); - sc->peers = peers; - sc->subsystem = (NULL == subsystem) ? NULL : GNUNET_strdup (subsystem); - sc->name = (NULL == name) ? NULL : GNUNET_strdup (name); - sc->proc = proc; - sc->cont = cont; - sc->cb_cls = cls; - sc->num_peers = num_peers; - sc->main_op = - GNUNET_TESTBED_operation_create_ (sc, &opstart_get_stats, - &oprelease_get_stats); - GNUNET_TESTBED_operation_queue_insert_ (no_wait_queue, sc->main_op); - GNUNET_TESTBED_operation_begin_wait_ (sc->main_op); - return sc->main_op; -} - - -/* end of testbed_api_statistics.c */ diff --git a/src/testbed/testbed_api_test.c b/src/testbed/testbed_api_test.c @@ -1,175 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_test.c - * @brief high-level test function - * @author Christian Grothoff - * @author Sree Harsha Totakura - * @author Tobias Frisch - */ -#include "platform.h" -#include "gnunet_testbed_service.h" -#include "testbed.h" - - -/** - * Context information for test run - */ -struct TestRunContext -{ - /** - * Test master callback - */ - GNUNET_TESTBED_TestMaster test_master; - - /** - * Closure for test master - */ - void *test_master_cls; - - /** - * The controller event callback - */ - GNUNET_TESTBED_ControllerCallback cc; - - /** - * Closure for the above callback - */ - void *cc_cls; - - /** - * event mask for the controller callback - */ - uint64_t event_mask; - - /** - * Number of peers to start - */ - unsigned int num_peers; -}; - - -/** - * Main run function. - * - * @param cls NULL - * @param args arguments passed to GNUNET_PROGRAM_run - * @param cfgfile the path to configuration file - * @param config the configuration file handle - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) -{ - struct TestRunContext *rc = cls; - - GNUNET_TESTBED_run (NULL, config, rc->num_peers, rc->event_mask, rc->cc, - rc->cc_cls, rc->test_master, rc->test_master_cls); -} - - -/** - * Convenience method for running a "simple" test on the local system - * with a single call from 'main'. Underlay and overlay topology are - * configured using the "UNDERLAY" and "OVERLAY" options in the - * "[testbed]" section of the configuration (with possible options - * given in "UNDERLAY_XXX" and/or "OVERLAY_XXX"). - * - * The test is to be terminated using a call to - * "GNUNET_SCHEDULER_shutdown". If starting the test fails, - * the program is stopped without 'master' ever being run. - * - * NOTE: this function should be called from 'main', NOT from - * within a GNUNET_SCHEDULER-loop. This function will initialize - * the scheduler loop, the testbed and then pass control to - * 'master'. - * - * @param testname name of the testcase (to configure logging, etc.) - * @param cfg_filename configuration filename to use - * (for testbed, controller and peers) - * @param num_peers number of peers to start - * @param event_mask bit mask with set of events to call 'cc' for; - * or-ed values of "1LL" shifted by the - * respective 'enum GNUNET_TESTBED_EventType' - * (e.g. "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...") - * @param cc controller callback to invoke on events; This callback is called - * for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't - * set in the event_mask as this is the only way get access to the - * handle of each peer - * @param cc_cls closure for cc - * @param test_master task to run once the test is ready - * @param test_master_cls closure for @a test_master - * @return #GNUNET_SYSERR on error, #GNUNET_OK on success - */ -int -GNUNET_TESTBED_test_run (const char *testname, - const char *cfg_filename, - unsigned int num_peers, - uint64_t event_mask, - GNUNET_TESTBED_ControllerCallback cc, - void *cc_cls, - GNUNET_TESTBED_TestMaster test_master, - void *test_master_cls) -{ - char *argv2[] = { - NULL, - "-c", - NULL, - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - struct TestRunContext *rc; - int ret; - - argv2[0] = GNUNET_strdup (testname); - argv2[2] = GNUNET_strdup (cfg_filename); - GNUNET_assert (NULL != test_master); - GNUNET_assert (num_peers > 0); - - char* envcfg = getenv(ENV_TESTBED_CONFIG); - setenv(ENV_TESTBED_CONFIG, cfg_filename, 1); - - rc = GNUNET_malloc (sizeof(struct TestRunContext) - + (num_peers * sizeof(struct GNUNET_TESTBED_Peer *))); - rc->test_master = test_master; - rc->test_master_cls = test_master_cls; - rc->num_peers = num_peers; - rc->event_mask = event_mask; - rc->cc = cc; - rc->cc_cls = cc_cls; - ret = GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, - testname, "nohelp", options, &run, rc); - - if (envcfg) - setenv(ENV_TESTBED_CONFIG, envcfg, 1); - else - unsetenv(ENV_TESTBED_CONFIG); - - GNUNET_free (rc); - GNUNET_free (argv2[0]); - GNUNET_free (argv2[2]); - return ret; -} - - -/* end of testbed_api_test.c */ diff --git a/src/testbed/testbed_api_testbed.c b/src/testbed/testbed_api_testbed.c @@ -1,1467 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_testbed.c - * @brief high-level testbed management - * @author Christian Grothoff - * @author Sree Harsha Totakura - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testbed_service.h" -#include "testbed_api.h" -#include "testbed_api_peers.h" -#include "testbed_api_hosts.h" -#include "testbed_api_topology.h" - -/** - * Generic loggins shorthand - */ -#define LOG(kind, ...) \ - GNUNET_log_from (kind, "testbed-api-testbed", __VA_ARGS__) - -/** - * Debug logging shortcut - */ -#define DEBUG(...) \ - LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) - -/** - * The default setup timeout in seconds - */ -#define DEFAULT_SETUP_TIMEOUT 300 - - -/** - * Configuration section for testbed - */ -#define TESTBED_CONFIG_SECTION "testbed" - -/** - * Option string for the maximum number of edges a peer is permitted to have - * while generating scale free topology - */ -#define SCALE_FREE_CAP "SCALE_FREE_TOPOLOGY_CAP" - -/** - * Option string for the number of edges to be established when adding a new - * node to the scale free network - */ -#define SCALE_FREE_M "SCALE_FREE_TOPOLOGY_M" - -/** - * Context information for the operation we start - */ -struct RunContextOperation -{ - /** - * The testbed operation handle - */ - struct GNUNET_TESTBED_Operation *op; - - /** - * Context information for GNUNET_TESTBED_run() - */ - struct GNUNET_TESTBED_RunHandle *rc; - - /** - * Closure - */ - void *cls; -}; - - -/** - * States of RunContext - */ -enum State -{ - /** - * Initial state - */ - RC_INIT = 0, - - /** - * Controllers on given hosts started and linked - */ - RC_LINKED, - - /** - * Peers are created - */ - RC_PEERS_CREATED, - - /** - * The testbed run is ready and the master callback can be called now. At this - * time the peers are all started and if a topology is provided in the - * configuration the topology would have been attempted - */ - RC_READY, - - /* /\** */ - /* * Peers are stopped */ - /* *\/ */ - /* RC_PEERS_STOPPED, */ - - /* /\** */ - /* * Peers are destroyed */ - /* *\/ */ - /* RC_PEERS_DESTROYED */ - - /** - * All peers shutdown (stopped and destroyed) - */ - RC_PEERS_SHUTDOWN -}; - - -/** - * Context for host compatibility checks - */ -struct CompatibilityCheckContext -{ - /** - * The run context - */ - struct GNUNET_TESTBED_RunHandle *rc; - - /** - * Handle for the compatibility check - */ - struct GNUNET_TESTBED_HostHabitableCheckHandle *h; - - /** - * Index of the host in the run context's hosts array - */ - unsigned int index; -}; - - -/** - * Testbed Run Handle - */ -struct GNUNET_TESTBED_RunHandle -{ - /** - * The controller handle - */ - struct GNUNET_TESTBED_Controller *c; - - /** - * The configuration of the controller. This is based on the cfg given to the - * function GNUNET_TESTBED_run(). We also use this config as a template while - * for peers - */ - struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Handle to the host on which the controller runs - */ - struct GNUNET_TESTBED_Host *h; - - /** - * The handle to the controller process - */ - struct GNUNET_TESTBED_ControllerProc *cproc; - - /** - * The callback to use as controller callback - */ - GNUNET_TESTBED_ControllerCallback cc; - - /** - * The pointer to the controller callback - */ - void *cc_cls; - - /** - * The trusted IP string - */ - char *trusted_ip; - - /** - * TestMaster callback to call when testbed initialization is done - */ - GNUNET_TESTBED_TestMaster test_master; - - /** - * The closure for the TestMaster callback - */ - void *test_master_cls; - - /** - * A hashmap for operations started by us - */ - struct GNUNET_CONTAINER_MultiHashMap32 *rcop_map; - - /** - * An array of hosts loaded from the hostkeys file - */ - struct GNUNET_TESTBED_Host **hosts; - - /** - * Array of compatibility check contexts - */ - struct CompatibilityCheckContext *hclist; - - /** - * Array of peers which we create - */ - struct GNUNET_TESTBED_Peer **peers; - - /** - * The topology generation operation. Will be null if no topology is set in - * the configuration - */ - struct GNUNET_TESTBED_Operation *topology_operation; - - /** - * The file containing topology data. Only used if the topology is set to 'FROM_FILE' - */ - char *topo_file; - - /** - * Host registration handle - */ - struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle; - - /** - * Profiling start time - */ - struct GNUNET_TIME_Absolute pstart_time; - - /** - * Host registration task - */ - struct GNUNET_SCHEDULER_Task *register_hosts_task; - - /** - * Task to be run of a timeout - */ - struct GNUNET_SCHEDULER_Task *timeout_task; - - /** - * Task run upon shutdown interrupts - */ - struct GNUNET_SCHEDULER_Task *interrupt_task; - - /** - * The event mask for the controller - */ - uint64_t event_mask; - - /** - * State of this context - */ - enum State state; - - /** - * The topology which has to be achieved with the peers started in this context - */ - enum GNUNET_TESTBED_TopologyOption topology; - - /** - * Have we already shutdown - */ - int shutdown; - - /** - * Number of hosts in the given host file - */ - unsigned int num_hosts; - - /** - * Number of registered hosts. Also used as a counter while checking - * habitabillity of hosts - */ - unsigned int reg_hosts; - - /** - * Current peer count for an operation; Set this to 0 and increment for each - * successful operation on a peer - */ - unsigned int peer_count; - - /** - * number of peers to start - */ - unsigned int num_peers; - - /** - * Expected overlay connects. Should be zero if no topology is relevant - */ - unsigned int num_oc; - - /** - * Number of random links to established - */ - unsigned int random_links; - - /** - * the number of overlay link connection attempts that succeeded - */ - unsigned int links_succeeded; - - /** - * the number of overlay link connection attempts that failed - */ - unsigned int links_failed; -}; - - -/** - * Return a 32-bit key from a pointer - * - * @param rcop the pointer - * @return 32-bit key - */ -static uint32_t -rcop_key (void *rcop) -{ - return *((uint32_t *) &rcop); -} - - -/** - * Context information used for finding a pointer in the rcop_map - */ -struct SearchContext -{ - /** - * The operation pointer to look for - */ - struct GNUNET_TESTBED_Operation *query; - - /** - * The Run context operation which has the operation being queried - */ - struct RunContextOperation *result; -}; - - -/** - * Iterator for searching over the elements matching a given query - * - * @param cls the SearchContext - * @param key the 32-bit key - * @param value the RunContextOperation element - * @return GNUNET_YES to continue iteration; GNUNET_NO to cancel it - */ -static int -search_iterator (void *cls, uint32_t key, void *value) -{ - struct RunContextOperation *rcop = value; - struct SearchContext *sc = cls; - - GNUNET_assert (NULL != rcop); - if (sc->query == rcop->op) - { - GNUNET_assert (NULL == sc->result); - sc->result = rcop; - return GNUNET_NO; - } - return GNUNET_YES; -} - - -/** - * Initiate a search for the given operation in the rcop_map - * - * @param rc the RunContext whose rcop_map will be searched for the given - * operation - * @param op the given operation to search for - * @return the matching RunContextOperation if found; NULL if not - */ -static struct RunContextOperation * -search_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct - GNUNET_TESTBED_Operation *op) -{ - struct SearchContext sc; - - sc.query = op; - sc.result = NULL; - if (GNUNET_SYSERR == - GNUNET_CONTAINER_multihashmap32_get_multiple (rc->rcop_map, - rcop_key (op), - &search_iterator, - &sc)) - { - GNUNET_assert (NULL != sc.result); - return sc.result; - } - return NULL; -} - - -/** - * Insert an RunContextOperation into the rcop_map of the given RunContext - * - * @param rc the RunContext into whose map is to be used for insertion - * @param rcop the RunContextOperation to insert - */ -static void -insert_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct - RunContextOperation *rcop) -{ - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap32_put (rc->rcop_map, - rcop_key (rcop->op), rcop, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); -} - - -/** - * Remove a RunContextOperation from the rcop_map of the given RunContext - * - * @param rc the RunContext from whose map the given RunContextOperaton has to - * be removed - * @param rcop the RunContextOperation - */ -static void -remove_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct - RunContextOperation *rcop) -{ - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap32_remove (rc->rcop_map, - rcop_key (rcop->op), - rcop)); -} - - -/** - * Assuming all peers have been destroyed cleanup run handle - * - * @param rc the run context - */ -static void -cleanup (struct GNUNET_TESTBED_RunHandle *rc) -{ - unsigned int hid; - - GNUNET_assert (NULL == rc->register_hosts_task); - GNUNET_assert (NULL == rc->reg_handle); - GNUNET_assert (NULL == rc->peers); - GNUNET_assert (NULL == rc->hclist); - GNUNET_assert (RC_PEERS_SHUTDOWN == rc->state); - GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (rc->rcop_map)); - GNUNET_CONTAINER_multihashmap32_destroy (rc->rcop_map); - if (NULL != rc->c) - GNUNET_TESTBED_controller_disconnect (rc->c); - if (NULL != rc->cproc) - GNUNET_TESTBED_controller_stop (rc->cproc); - if (NULL != rc->h) - GNUNET_TESTBED_host_destroy (rc->h); - for (hid = 0; hid < rc->num_hosts; hid++) - GNUNET_TESTBED_host_destroy (rc->hosts[hid]); - GNUNET_free (rc->hosts); - if (NULL != rc->cfg) - GNUNET_CONFIGURATION_destroy (rc->cfg); - GNUNET_free (rc->topo_file); - GNUNET_free (rc->trusted_ip); - GNUNET_free (rc); -} - - -/** - * Iterator for cleaning up elements from rcop_map - * - * @param cls the RunContext - * @param key the 32-bit key - * @param value the RunContextOperation element - * @return always GNUNET_YES - */ -static int -rcop_cleanup_iterator (void *cls, uint32_t key, void *value) -{ - struct GNUNET_TESTBED_RunHandle *rc = cls; - struct RunContextOperation *rcop = value; - - GNUNET_assert (rc == rcop->rc); - remove_rcop (rc, rcop); - GNUNET_TESTBED_operation_done (rcop->op); - GNUNET_free (rcop); - return GNUNET_YES; -} - - -/** - * Cancels operations and tasks which are assigned to the given run context - * - * @param rc the RunContext - */ -static void -rc_cleanup_operations (struct GNUNET_TESTBED_RunHandle *rc) -{ - struct CompatibilityCheckContext *hc; - unsigned int nhost; - - if (NULL != rc->hclist) - { - for (nhost = 0; nhost < rc->num_hosts; nhost++) - { - hc = &rc->hclist[nhost]; - if (NULL != hc->h) - GNUNET_TESTBED_is_host_habitable_cancel (hc->h); - } - GNUNET_free (rc->hclist); - rc->hclist = NULL; - } - /* Stop register hosts task if it is running */ - if (NULL != rc->register_hosts_task) - { - GNUNET_SCHEDULER_cancel (rc->register_hosts_task); - rc->register_hosts_task = NULL; - } - if (NULL != rc->timeout_task) - { - GNUNET_SCHEDULER_cancel (rc->timeout_task); - rc->timeout_task = NULL; - } - if (NULL != rc->reg_handle) - { - GNUNET_TESTBED_cancel_registration (rc->reg_handle); - rc->reg_handle = NULL; - } - if (NULL != rc->topology_operation) - { - GNUNET_TESTBED_operation_done (rc->topology_operation); - rc->topology_operation = NULL; - } - /* cancel any exiting operations */ - GNUNET_assert (GNUNET_SYSERR != - GNUNET_CONTAINER_multihashmap32_iterate (rc->rcop_map, - &rcop_cleanup_iterator, - rc)); -} - - -/** - * Cancels the scheduled interrupt task - * - * @param rc the run context - */ -static void -cancel_interrupt_task (struct GNUNET_TESTBED_RunHandle *rc) -{ - GNUNET_SCHEDULER_cancel (rc->interrupt_task); - rc->interrupt_task = NULL; -} - - -/** - * This callback will be called when all the operations are completed - * (done/cancelled) - * - * @param cls run context - */ -static void -wait_op_completion (void *cls) -{ - struct GNUNET_TESTBED_RunHandle *rc = cls; - struct RunContextOperation *rcop; - - if ((NULL == rc->cproc) - || (NULL == rc->c) - || (GNUNET_YES == rc->shutdown)) - { - if (NULL != rc->peers) - { - GNUNET_free (rc->peers); - rc->peers = NULL; - } - goto cleanup_; - } - if (NULL == rc->peers) - goto cleanup_; - rc->shutdown = GNUNET_YES; - rcop = GNUNET_new (struct RunContextOperation); - rcop->rc = rc; - rcop->op = GNUNET_TESTBED_shutdown_peers (rc->c, rcop, NULL, NULL); - GNUNET_assert (NULL != rcop->op); - DEBUG ("Shutting down peers\n"); - rc->pstart_time = GNUNET_TIME_absolute_get (); - insert_rcop (rc, rcop); - return; - -cleanup_: - rc->state = RC_PEERS_SHUTDOWN; - cancel_interrupt_task (rc); - cleanup (rc); -} - - -/** - * Task run upon interrupts (SIGINT, SIGTERM) and upon scheduler shutdown. - * - * @param cls the RunContext which has to be acted upon - */ -static void -interrupt (void *cls) -{ - struct GNUNET_TESTBED_RunHandle *rc = cls; - struct GNUNET_TESTBED_Controller *c = rc->c; - unsigned int size; - - /* reschedule */ - rc->interrupt_task = GNUNET_SCHEDULER_add_shutdown (&interrupt, rc); - rc_cleanup_operations (rc); - if ((GNUNET_NO == rc->shutdown) && - (NULL != c) && - (NULL != c->opc_map) && - (0 != (size = GNUNET_CONTAINER_multihashmap32_size (c->opc_map)))) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Shutdown postponed as there are %u operations currently active\n", - size); - c->opcq_empty_cb = &wait_op_completion; - c->opcq_empty_cls = rc; - return; - } - wait_op_completion (rc); -} - - -/** - * Function to return the string representation of the duration between current - * time and `pstart_time' in `RunContext' - * - * @param rc the RunContext - * @return the representation string; this is NOT reentrant - */ -static const char * -prof_time (struct GNUNET_TESTBED_RunHandle *rc) -{ - struct GNUNET_TIME_Relative ptime; - - ptime = GNUNET_TIME_absolute_get_duration (rc->pstart_time); - return GNUNET_STRINGS_relative_time_to_string (ptime, GNUNET_YES); -} - - -/** - * Task for starting peers - * - * @param cls the RunHandle - */ -static void -start_peers_task (void *cls) -{ - struct GNUNET_TESTBED_RunHandle *rc = cls; - struct RunContextOperation *rcop; - unsigned int peer; - - DEBUG ("Starting Peers\n"); - rc->pstart_time = GNUNET_TIME_absolute_get (); - for (peer = 0; peer < rc->num_peers; peer++) - { - rcop = GNUNET_new (struct RunContextOperation); - rcop->rc = rc; - rcop->op = GNUNET_TESTBED_peer_start (NULL, rc->peers[peer], NULL, NULL); - GNUNET_assert (NULL != rcop->op); - rcop->cls = rc->peers[peer]; - insert_rcop (rc, rcop); - } - rc->peer_count = 0; -} - - -/** - * Functions of this signature are called when a peer has been successfully - * created - * - * @param cls the closure from GNUNET_TESTBED_peer_create() - * @param peer the handle for the created peer; NULL on any error during - * creation - * @param emsg NULL if peer is not NULL; else MAY contain the error description - */ -static void -peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) -{ - struct RunContextOperation *rcop = cls; - struct GNUNET_TESTBED_RunHandle *rc; - - GNUNET_assert (NULL != rcop); - GNUNET_assert (NULL != (rc = rcop->rc)); - remove_rcop (rc, rcop); - GNUNET_TESTBED_operation_done (rcop->op); - GNUNET_free (rcop); - if (NULL == peer) - { - if (NULL != emsg) - LOG (GNUNET_ERROR_TYPE_ERROR, "Error while creating a peer: %s\n", - emsg); - GNUNET_SCHEDULER_shutdown (); - return; - } - rc->peers[rc->peer_count] = peer; - rc->peer_count++; - if (rc->peer_count < rc->num_peers) - return; - DEBUG ("%u peers created in %s\n", rc->num_peers, prof_time (rc)); - rc->state = RC_PEERS_CREATED; - GNUNET_SCHEDULER_add_now (&start_peers_task, rc); -} - - -/** - * call test master callback - * - * @param rc the RunContext - */ -static void -call_master (struct GNUNET_TESTBED_RunHandle *rc) -{ - GNUNET_SCHEDULER_cancel (rc->timeout_task); - rc->timeout_task = NULL; - if (NULL != rc->test_master) - rc->test_master (rc->test_master_cls, rc, rc->num_peers, rc->peers, - rc->links_succeeded, rc->links_failed); -} - - -/** - * Callbacks of this type are called when topology configuration is completed - * - * @param cls the operation closure given to - * GNUNET_TESTBED_overlay_configure_topology_va() and - * GNUNET_TESTBED_overlay_configure() calls - * @param nsuccess the number of successful overlay connects - * @param nfailures the number of overlay connects which failed - */ -static void -topology_completion_callback (void *cls, unsigned int nsuccess, - unsigned int nfailures) -{ - struct GNUNET_TESTBED_RunHandle *rc = cls; - - DEBUG ("Overlay topology generated in %s\n", prof_time (rc)); - GNUNET_TESTBED_operation_done (rc->topology_operation); - rc->topology_operation = NULL; - rc->links_succeeded = nsuccess; - rc->links_failed = nfailures; - rc->state = RC_READY; - call_master (rc); -} - - -/** - * Function to create peers - * - * @param rc the RunContext - */ -static void -create_peers (struct GNUNET_TESTBED_RunHandle *rc) -{ - struct RunContextOperation *rcop; - unsigned int peer; - - DEBUG ("Creating peers\n"); - rc->pstart_time = GNUNET_TIME_absolute_get (); - rc->peers = - GNUNET_malloc (sizeof(struct GNUNET_TESTBED_Peer *) * rc->num_peers); - GNUNET_assert (NULL != rc->c); - rc->peer_count = 0; - for (peer = 0; peer < rc->num_peers; peer++) - { - rcop = GNUNET_new (struct RunContextOperation); - rcop->rc = rc; - rcop->op = - GNUNET_TESTBED_peer_create (rc->c, - (0 == - rc->num_hosts) ? rc->h : rc->hosts[peer - % rc-> - num_hosts], - rc->cfg, &peer_create_cb, rcop); - GNUNET_assert (NULL != rcop->op); - insert_rcop (rc, rcop); - } -} - - -/** - * Signature of the event handler function called by the - * respective event controller. - * - * @param cls closure - * @param event information about the event - */ -static void -event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) -{ - struct GNUNET_TESTBED_RunHandle *rc = cls; - struct RunContextOperation *rcop; - - if (RC_INIT == rc->state) - { - switch (event->type) - { - case GNUNET_TESTBED_ET_OPERATION_FINISHED: - rcop = event->op_cls; - if (NULL != event->details.operation_finished.emsg) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ( - "Linking controllers failed. Exiting")); - GNUNET_SCHEDULER_shutdown (); - } - else - rc->reg_hosts++; - GNUNET_assert (event->op == rcop->op); - remove_rcop (rc, rcop); - GNUNET_TESTBED_operation_done (rcop->op); - GNUNET_free (rcop); - if (rc->reg_hosts == rc->num_hosts) - { - rc->state = RC_LINKED; - create_peers (rc); - } - return; - - default: - GNUNET_break (0); - GNUNET_SCHEDULER_shutdown (); - return; - } - } - if (GNUNET_TESTBED_ET_OPERATION_FINISHED != event->type) - goto call_cc; - if (NULL == (rcop = search_rcop (rc, event->op))) - goto call_cc; - remove_rcop (rc, rcop); - GNUNET_TESTBED_operation_done (rcop->op); - GNUNET_free (rcop); - if ((GNUNET_NO == rc->shutdown) - && (NULL != event->details.operation_finished.emsg)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, "A operation has failed with error: %s\n", - event->details.operation_finished.emsg); - GNUNET_SCHEDULER_shutdown (); - return; - } - GNUNET_assert (GNUNET_YES == rc->shutdown); - switch (rc->state) - { - case RC_LINKED: - case RC_PEERS_CREATED: - case RC_READY: - rc->state = RC_PEERS_SHUTDOWN; - GNUNET_free (rc->peers); - rc->peers = NULL; - DEBUG ("Peers shut down in %s\n", prof_time (rc)); - GNUNET_SCHEDULER_shutdown (); - break; - - default: - GNUNET_assert (0); - } - return; - -call_cc: - if ((0 != (rc->event_mask & (1LL << event->type))) && (NULL != rc->cc)) - rc->cc (rc->cc_cls, event); - if (GNUNET_TESTBED_ET_PEER_START != event->type) - return; - if (NULL == (rcop = search_rcop (rc, event->op))) /* Not our operation */ - return; - remove_rcop (rc, rcop); - GNUNET_TESTBED_operation_done (rcop->op); - GNUNET_free (rcop); - rc->peer_count++; - if (rc->peer_count < rc->num_peers) - return; - DEBUG ("%u peers started in %s\n", rc->num_peers, prof_time (rc)); - if (GNUNET_TESTBED_TOPOLOGY_NONE != rc->topology) - { - switch (rc->topology) - { - case GNUNET_TESTBED_TOPOLOGY_NONE: - GNUNET_assert (0); - - case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: - case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: - case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: - rc->topology_operation = - GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, - rc->peers, &rc->num_oc, - &topology_completion_callback, - rc, - rc->topology, - rc->random_links, - GNUNET_TESTBED_TOPOLOGY_OPTION_END); - break; - - case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: - GNUNET_assert (NULL != rc->topo_file); - rc->topology_operation = - GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, - rc->peers, &rc->num_oc, - &topology_completion_callback, - rc, - rc->topology, - rc->topo_file, - GNUNET_TESTBED_TOPOLOGY_OPTION_END); - break; - - case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: - { - unsigned long long number; - unsigned int cap; - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number (rc->cfg, - TESTBED_CONFIG_SECTION, - SCALE_FREE_CAP, - &number)); - cap = (unsigned int) number; - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number (rc->cfg, - TESTBED_CONFIG_SECTION, - SCALE_FREE_M, - &number)); - rc->topology_operation = - GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, - rc->peers, &rc->num_oc, - & - topology_completion_callback, - rc, - rc->topology, - cap, /* uint16_t */ - (unsigned int) number, /* uint8_t */ - GNUNET_TESTBED_TOPOLOGY_OPTION_END); - } - break; - - default: - rc->topology_operation = - GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, - rc->peers, &rc->num_oc, - &topology_completion_callback, - rc, - rc->topology, - GNUNET_TESTBED_TOPOLOGY_OPTION_END); - } - if (NULL == rc->topology_operation) - LOG (GNUNET_ERROR_TYPE_WARNING, - "Not generating a topology. Check number of peers\n"); - else - { - DEBUG ("Creating overlay topology\n"); - rc->pstart_time = GNUNET_TIME_absolute_get (); - return; - } - } - rc->state = RC_READY; - call_master (rc); -} - - -/** - * Task to register all hosts available in the global host list - * - * @param cls the RunContext - */ -static void -register_hosts (void *cls); - - -/** - * Callback which will be called to after a host registration succeeded or failed - * - * @param cls the closure - * @param emsg the error message; NULL if host registration is successful - */ -static void -host_registration_completion (void *cls, const char *emsg) -{ - struct GNUNET_TESTBED_RunHandle *rc = cls; - - rc->reg_handle = NULL; - if (NULL != emsg) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - _ ("Host registration failed for a host. Error: %s\n"), emsg); - GNUNET_SCHEDULER_shutdown (); - return; - } - rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, - rc); -} - - -static void -register_hosts (void *cls) -{ - struct GNUNET_TESTBED_RunHandle *rc = cls; - struct RunContextOperation *rcop; - unsigned int slave; - - rc->register_hosts_task = NULL; - if (rc->reg_hosts == rc->num_hosts) - { - DEBUG ("All hosts successfully registered\n"); - /* Start slaves */ - for (slave = 0; slave < rc->num_hosts; slave++) - { - rcop = GNUNET_new (struct RunContextOperation); - rcop->rc = rc; - rcop->op = - GNUNET_TESTBED_controller_link (rcop, rc->c, rc->hosts[slave], - rc->h, GNUNET_YES); - GNUNET_assert (NULL != rcop->op); - insert_rcop (rc, rcop); - } - rc->reg_hosts = 0; - return; - } - rc->reg_handle = - GNUNET_TESTBED_register_host (rc->c, rc->hosts[rc->reg_hosts], - host_registration_completion, rc); - rc->reg_hosts++; -} - - -/** - * Callback to signal successful startup of the controller process - * - * @param cls the closure from GNUNET_TESTBED_controller_start() - * @param cfg the configuration with which the controller has been started; - * NULL if status is not GNUNET_OK - * @param status GNUNET_OK if the startup is successful; GNUNET_SYSERR if not, - * GNUNET_TESTBED_controller_stop() shouldn't be called in this case - */ -static void -controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, - int status) -{ - struct GNUNET_TESTBED_RunHandle *rc = cls; - uint64_t event_mask; - - if (status != GNUNET_OK) - { - rc->cproc = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ ("Controller crash detected. Shutting down.\n")); - GNUNET_SCHEDULER_shutdown (); - return; - } - GNUNET_CONFIGURATION_destroy (rc->cfg); - rc->cfg = GNUNET_CONFIGURATION_dup (cfg); - event_mask = rc->event_mask; - event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); - event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START); - if (rc->topology < GNUNET_TESTBED_TOPOLOGY_NONE) - event_mask |= GNUNET_TESTBED_ET_CONNECT; - rc->c = - GNUNET_TESTBED_controller_connect (rc->h, event_mask, &event_cb, rc); - if (0 < rc->num_hosts) - { - rc->reg_hosts = 0; - rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, rc); - return; - } - rc->state = RC_LINKED; - create_peers (rc); -} - - -/** - * Callback function invoked for each interface found. - * - * @param cls closure - * @param name name of the interface (can be NULL for unknown) - * @param isDefault is this presumably the default interface - * @param addr address of this interface (can be NULL for unknown or unassigned) - * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned) - * @param netmask the network mask (can be NULL for unknown or unassigned)) - * @param addrlen length of the address - * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort - */ -static int -netint_proc (void *cls, const char *name, int isDefault, - const struct sockaddr *addr, const struct sockaddr *broadcast_addr, - const struct sockaddr *netmask, socklen_t addrlen) -{ - struct GNUNET_TESTBED_RunHandle *rc = cls; - char hostip[NI_MAXHOST]; - char *buf; - - if (sizeof(struct sockaddr_in) != addrlen) - return GNUNET_OK; /* Only consider IPv4 for now */ - if (0 != - getnameinfo (addr, addrlen, hostip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST)) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "getnameinfo"); - if (NULL == rc->trusted_ip) - { - rc->trusted_ip = GNUNET_strdup (hostip); - return GNUNET_YES; - } - (void) GNUNET_asprintf (&buf, "%s; %s", rc->trusted_ip, hostip); - GNUNET_free (rc->trusted_ip); - rc->trusted_ip = buf; - return GNUNET_YES; -} - - -/** - * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to - * inform whether the given host is habitable or not. The Handle returned by - * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called - * - * @param cls NULL - * @param host the host whose status is being reported; will be NULL if the host - * given to GNUNET_TESTBED_is_host_habitable() is NULL - * @param status GNUNET_YES if it is habitable; GNUNET_NO if not - */ -static void -host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host, - int status) -{ - struct CompatibilityCheckContext *hc = cls; - struct GNUNET_TESTBED_RunHandle *rc; - struct GNUNET_TESTBED_Host **old_hosts; - unsigned int nhost; - - GNUNET_assert (NULL != (rc = hc->rc)); - nhost = hc->index; - GNUNET_assert (nhost <= rc->num_hosts); - GNUNET_assert (host == rc->hosts[nhost]); - hc->h = NULL; - if (GNUNET_NO == status) - { - if ((NULL != host) && (NULL != GNUNET_TESTBED_host_get_hostname (host))) - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Host %s cannot start testbed\n"), - GNUNET_TESTBED_host_get_hostname (host)); - else - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Testbed cannot be started on localhost\n")); - GNUNET_SCHEDULER_shutdown (); - return; - } - rc->reg_hosts++; - if (rc->reg_hosts < rc->num_hosts) - return; - GNUNET_free (rc->hclist); - rc->hclist = NULL; - rc->h = rc->hosts[0]; - rc->num_hosts--; - if (0 < rc->num_hosts) - { - old_hosts = rc->hosts; - rc->hosts = - GNUNET_malloc (sizeof(struct GNUNET_TESTBED_Host *) * rc->num_hosts); - GNUNET_memcpy (rc->hosts, &old_hosts[1], - (sizeof(struct GNUNET_TESTBED_Host *) * rc->num_hosts)); - GNUNET_free (old_hosts); - } - else - { - GNUNET_free (rc->hosts); - rc->hosts = NULL; - } - GNUNET_TESTBED_host_resolve_ (rc->h); - for (nhost = 0; nhost < rc->num_hosts; nhost++) - GNUNET_TESTBED_host_resolve_ (rc->hosts[nhost]); - GNUNET_OS_network_interfaces_list (netint_proc, rc); - if (NULL == rc->trusted_ip) - rc->trusted_ip = GNUNET_strdup ("127.0.0.1"); - rc->cproc = - GNUNET_TESTBED_controller_start (rc->trusted_ip, rc->h, - &controller_status_cb, rc); - GNUNET_free (rc->trusted_ip); - rc->trusted_ip = NULL; - if (NULL == rc->cproc) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Cannot start the master controller")); - GNUNET_SCHEDULER_shutdown (); - } -} - - -/** - * Task run upon timeout while setting up the testbed - * - * @param cls the RunContext - */ -static void -timeout_task (void *cls) -{ - struct GNUNET_TESTBED_RunHandle *rc = cls; - - rc->timeout_task = NULL; - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Shutting down testbed due to timeout while setup.\n")); - GNUNET_SCHEDULER_shutdown (); - if (NULL != rc->test_master) - rc->test_master (rc->test_master_cls, rc, 0, NULL, 0, 0); - rc->test_master = NULL; -} - - -/** - * Convenience method for running a testbed with - * a single call. Underlay and overlay topology - * are configured using the "UNDERLAY" and "OVERLAY" - * options in the "[testbed]" section of the configuration\ - * (with possible options given in "UNDERLAY_XXX" and/or - * "OVERLAY_XXX"). - * - * The testbed is to be terminated using a call to - * "GNUNET_SCHEDULER_shutdown". - * - * @param host_filename name of the file with the 'hosts', NULL - * to run everything on 'localhost' - * @param cfg configuration to use (for testbed, controller and peers) - * @param num_peers number of peers to start; FIXME: maybe put that ALSO into cfg? - * @param event_mask bit mask with set of events to call 'cc' for; - * or-ed values of "1LL" shifted by the - * respective 'enum GNUNET_TESTBED_EventType' - * (e.g. "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...") - * @param cc controller callback to invoke on events; This callback is called - * for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't - * set in the event_mask as this is the only way get access to the - * handle of each peer - * @param cc_cls closure for cc - * @param test_master this callback will be called once the test is ready - * @param test_master_cls closure for 'test_master'. - */ -void -GNUNET_TESTBED_run (const char *host_filename, - const struct GNUNET_CONFIGURATION_Handle *cfg, - unsigned int num_peers, uint64_t event_mask, - GNUNET_TESTBED_ControllerCallback cc, void *cc_cls, - GNUNET_TESTBED_TestMaster test_master, - void *test_master_cls) -{ - struct GNUNET_TESTBED_RunHandle *rc; - char *topology; - struct CompatibilityCheckContext *hc; - struct GNUNET_TIME_Relative timeout; - unsigned long long number; - unsigned int hid; - unsigned int nhost; - - GNUNET_assert (num_peers > 0); - rc = GNUNET_new (struct GNUNET_TESTBED_RunHandle); - rc->cfg = GNUNET_CONFIGURATION_dup (cfg); - if (NULL != host_filename) - { - rc->num_hosts = - GNUNET_TESTBED_hosts_load_from_file (host_filename, rc->cfg, - &rc->hosts); - if (0 == rc->num_hosts) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - _ ("No hosts loaded. Need at least one host\n")); - goto error_cleanup; - } - } - else - rc->h = GNUNET_TESTBED_host_create (NULL, NULL, rc->cfg, 0); - rc->num_peers = num_peers; - rc->event_mask = event_mask; - rc->cc = cc; - rc->cc_cls = cc_cls; - rc->test_master = test_master; - rc->test_master_cls = test_master_cls; - rc->state = RC_INIT; - rc->topology = GNUNET_TESTBED_TOPOLOGY_NONE; - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (rc->cfg, TESTBED_CONFIG_SECTION, - "OVERLAY_TOPOLOGY", &topology)) - { - if (GNUNET_NO == GNUNET_TESTBED_topology_get_ (&rc->topology, topology)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - TESTBED_CONFIG_SECTION, - "OVERLAY_TOPLOGY", - _ - ( - "Specified topology must be supported by testbed")); - } - GNUNET_free (topology); - } - switch (rc->topology) - { - case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: - case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: - case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, - "OVERLAY_RANDOM_LINKS", - &number)) - { - /* OVERLAY option RANDOM & SMALL_WORLD_RING requires OVERLAY_RANDOM_LINKS - * option to be set to the number of random links to be established */ - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - TESTBED_CONFIG_SECTION, - "OVERLAY_RANDOM_LINKS"); - goto error_cleanup; - } - if (number > UINT32_MAX) - { - GNUNET_break (0); /* Too big number */ - goto error_cleanup; - } - rc->random_links = (unsigned int) number; - break; - - case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (rc->cfg, - TESTBED_CONFIG_SECTION, - "OVERLAY_TOPOLOGY_FILE", - &rc->topo_file)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - TESTBED_CONFIG_SECTION, - "OVERLAY_TOPOLOGY_FILE"); - goto error_cleanup; - } - goto warn_ignore; - - case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, - SCALE_FREE_CAP, &number)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - TESTBED_CONFIG_SECTION, - SCALE_FREE_CAP); - goto error_cleanup; - } - if (UINT16_MAX < number) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Maximum number of edges a peer can have in a scale free topology" - " cannot be more than %u. Given `%s = %llu'"), UINT16_MAX, - SCALE_FREE_CAP, number); - goto error_cleanup; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, - SCALE_FREE_M, &number)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - TESTBED_CONFIG_SECTION, - SCALE_FREE_M); - goto error_cleanup; - } - if (UINT8_MAX < number) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("The number of edges that can established when adding a new node" - " to scale free topology cannot be more than %u. Given `%s = %llu'"), - UINT8_MAX, SCALE_FREE_M, number); - goto error_cleanup; - } - goto warn_ignore; - - case GNUNET_TESTBED_TOPOLOGY_OPTION_END: - /* not allowed! */ - GNUNET_assert (0); - - default: -warn_ignore: - /* Warn if OVERLAY_RANDOM_LINKS is present that it will be ignored */ - if (GNUNET_YES == - GNUNET_CONFIGURATION_have_value (rc->cfg, TESTBED_CONFIG_SECTION, - "OVERLAY_RANDOM_LINKS")) - LOG (GNUNET_ERROR_TYPE_WARNING, - "Ignoring value of `OVERLAY_RANDOM_LINKS' in given configuration\n"); - break; - } - if (0 != rc->num_hosts) - { - rc->hclist = GNUNET_malloc (sizeof(struct CompatibilityCheckContext) - * rc->num_hosts); - for (nhost = 0; nhost < rc->num_hosts; nhost++) - { - hc = &rc->hclist[nhost]; - hc->index = nhost; - hc->rc = rc; - hc->h = GNUNET_TESTBED_is_host_habitable (rc->hosts[nhost], rc->cfg, - &host_habitable_cb, hc); - if (NULL == hc->h) - { - GNUNET_break (0); - for (nhost = 0; nhost < rc->num_hosts; nhost++) - { - hc = &rc->hclist[nhost]; - if (NULL != hc->h) - GNUNET_TESTBED_is_host_habitable_cancel (hc->h); - } - GNUNET_free (rc->hclist); - rc->hclist = NULL; - goto error_cleanup; - } - } - } - else - rc->cproc = - GNUNET_TESTBED_controller_start ("127.0.0.1", rc->h, - &controller_status_cb, rc); - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, - TESTBED_CONFIG_SECTION, - "SETUP_TIMEOUT", - &timeout)) - { - timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, - DEFAULT_SETUP_TIMEOUT); - } - rc->rcop_map = GNUNET_CONTAINER_multihashmap32_create (256); - rc->timeout_task = - GNUNET_SCHEDULER_add_delayed (timeout, &timeout_task, rc); - GNUNET_assert (NULL == rc->interrupt_task); - rc->interrupt_task = - GNUNET_SCHEDULER_add_shutdown (&interrupt, - rc); - return; - -error_cleanup: - if (NULL != rc->h) - GNUNET_TESTBED_host_destroy (rc->h); - if (NULL != rc->hosts) - { - for (hid = 0; hid < rc->num_hosts; hid++) - if (NULL != rc->hosts[hid]) - GNUNET_TESTBED_host_destroy (rc->hosts[hid]); - GNUNET_free (rc->hosts); - } - if (NULL != rc->cfg) - GNUNET_CONFIGURATION_destroy (rc->cfg); - GNUNET_free (rc); -} - - -/** - * Obtain handle to the master controller from a testbed run. The handle - * returned should not be disconnected. - * - * @param h the testbed run handle - * @return handle to the master controller - */ -struct GNUNET_TESTBED_Controller * -GNUNET_TESTBED_run_get_controller_handle (struct GNUNET_TESTBED_RunHandle *h) -{ - return h->c; -} - - -/* end of testbed_api_testbed.c */ diff --git a/src/testbed/testbed_api_topology.c b/src/testbed/testbed_api_topology.c @@ -1,1598 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_topology.c - * @brief topology-generation functions - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_testbed_service.h" -#include "testbed_api.h" -#include "testbed_api_peers.h" -#include "testbed_api_operations.h" -#include "testbed_api_topology.h" - -/** - * Generic loggins shorthand - */ -#define LOG(kind, ...) \ - GNUNET_log_from (kind, "testbed-api-topology", __VA_ARGS__) - - -/** - * Default number of retires - */ -#define DEFAULT_RETRY_CNT 3 - - -/** - * Context information for topology operations - */ -struct TopologyContext; - - -/** - * Representation of an overlay link - */ -struct OverlayLink -{ - /** - * An operation corresponding to this link - */ - struct GNUNET_TESTBED_Operation *op; - - /** - * The topology context this link is a part of - */ - struct TopologyContext *tc; - - /** - * position of peer A's handle in peers array - */ - uint32_t A; - - /** - * position of peer B's handle in peers array - */ - uint32_t B; -}; - - -/** - * Representation of an underlay link - */ -struct UnderlayLink -{ - /** - * position of peer A's handle in peers array - */ - uint32_t A; - - /** - * position of peer B's handle in peers array - */ - uint32_t B; - - /** - * Bandwidth of the link in bytes per second - */ - uint32_t bandwidth; - - /** - * Latency of the link in milliseconds - */ - uint32_t latency; - - /** - * Loss in the link in percentage of message dropped - */ - uint32_t loss; -}; - - -struct RetryListEntry -{ - /** - * the next pointer for the DLL - */ - struct RetryListEntry *next; - - /** - * the prev pointer for the DLL - */ - struct RetryListEntry *prev; - - /** - * The link to be retired - */ - struct OverlayLink *link; -}; - - -/** - * Context information for overlay topologies - */ -struct TopologyContextOverlay -{ - /** - * The array of peers - */ - struct GNUNET_TESTBED_Peer **peers; - - /** - * An array of links; this array is of size link_array_size - */ - struct OverlayLink *link_array; - - /** - * The operation closure - */ - void *op_cls; - - /** - * topology generation completion callback - */ - GNUNET_TESTBED_TopologyCompletionCallback comp_cb; - - /** - * The closure for the above callback - */ - void *comp_cb_cls; - - /** - * DLL head for retry list - */ - struct RetryListEntry *rl_head; - - /** - * DLL tail for retry list - */ - struct RetryListEntry *rl_tail; - - /** - * How many retries to do before we give up - */ - unsigned int retry_cnt; - - /** - * Number of links to try - */ - unsigned int nlinks; - - /** - * How many links have been completed - */ - unsigned int ncompleted; - - /** - * Total successfully established overlay connections - */ - unsigned int nsuccess; - - /** - * Total failed overlay connections - */ - unsigned int nfailures; -}; - - -/** - * Topology context information for underlay topologies - */ -struct TopologyContextUnderlay -{ - /** - * The link array - */ - struct UnderlayLink *link_array; -}; - - -/** - * Context information for topology operations - */ -struct TopologyContext -{ - /** - * The type of this context - */ - enum - { - /** - * Type for underlay topology - */ - TOPOLOGYCONTEXT_TYPE_UNDERLAY = 0, - - /** - * Type for overlay topology - */ - TOPOLOGYCONTEXT_TYPE_OVERLAY - } type; - - union - { - /** - * Topology context information for overlay topology - */ - struct TopologyContextOverlay overlay; - - /** - * Topology context information for underlay topology - */ - struct TopologyContextUnderlay underlay; - } u; - - /** - * The number of peers - */ - unsigned int num_peers; - - /** - * The size of the link array - */ - unsigned int link_array_size; -}; - - -/** - * A array of names representing topologies. Should be in sync with enum - * GNUNET_TESTBED_TopologyOption - */ -static const char *topology_strings[] = { - /** - * A clique (everyone connected to everyone else). No options. If there are N - * peers this topology results in (N * (N -1)) connections. - */ - "CLIQUE", - - /* - * Small-world network (2d torus plus random links). Followed - * by the number of random links to add (unsigned int). - */ - "SMALL_WORLD", - - /** - * Small-world network (ring plus random links). Followed - * by the number of random links to add (unsigned int). - */ - "SMALL_WORLD_RING", - - /** - * Ring topology. No options. - */ - "RING", - - /** - * Star topology. No options. - */ - "STAR", - - /** - * 2-d torus. No options. - */ - "2D_TORUS", - - /** - * Random graph. Followed by the number of random links to be established - * (unsigned int) - */ - "RANDOM", // GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI - - /** - * Certain percentage of peers are unable to communicate directly - * replicating NAT conditions. Followed by the fraction of - * NAT'ed peers (float). - */ - "INTERNAT", - - /** - * Scale free topology. Followed by the maximum number of links a node can - * have (unsigned int); and the number of links a new node should have when - * it is added to the network (unsigned int) - */ - "SCALE_FREE", - - /** - * Straight line topology. No options. - */ - "LINE", - - /** - * Read a topology from a given file. Followed by the name of the file (const char *). - */ - "FROM_FILE", - - /** - * All peers are disconnected. No options. - */ - "NONE", - - /** - * End of strings - */ - NULL -}; - - -/** - * Callback to be called when an overlay_link operation complete - * - * @param cls element of the link_op array which points to the corresponding operation - * @param op the operation that has been finished - * @param emsg error message in case the operation has failed; will be NULL if - * operation has executed successfully. - */ -static void -overlay_link_completed (void *cls, - struct GNUNET_TESTBED_Operation *op, - const char *emsg) -{ - struct OverlayLink *link = cls; - struct TopologyContext *tc; - struct TopologyContextOverlay *overlay; - struct RetryListEntry *retry_entry; - - GNUNET_assert (op == link->op); - GNUNET_TESTBED_operation_done (op); - link->op = NULL; - tc = link->tc; - GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type); - overlay = &tc->u.overlay; - if (NULL != emsg) - { - overlay->nfailures++; - if (0 != overlay->retry_cnt) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Error while establishing a link: %s -- Retrying\n", - emsg); - retry_entry = GNUNET_new (struct RetryListEntry); - retry_entry->link = link; - GNUNET_CONTAINER_DLL_insert_tail (overlay->rl_head, - overlay->rl_tail, - retry_entry); - } - } - else - overlay->nsuccess++; - overlay->ncompleted++; - if (overlay->ncompleted < overlay->nlinks) - return; - if ((0 != overlay->retry_cnt) && (NULL != overlay->rl_head)) - { - overlay->retry_cnt--; - overlay->ncompleted = 0; - overlay->nlinks = 0; - while (NULL != (retry_entry = overlay->rl_head)) - { - link = retry_entry->link; - link->op = - GNUNET_TESTBED_overlay_connect (overlay->op_cls, - &overlay_link_completed, - link, - overlay->peers[link->A], - overlay->peers[link->B]); - overlay->nlinks++; - GNUNET_CONTAINER_DLL_remove (overlay->rl_head, - overlay->rl_tail, - retry_entry); - GNUNET_free (retry_entry); - } - return; - } - if (NULL != overlay->comp_cb) - { - overlay->comp_cb (overlay->comp_cb_cls, - overlay->nsuccess, - overlay->nfailures); - } -} - - -/** - * Function called when a overlay connect operation is ready - * - * @param cls the Topology context - */ -static void -opstart_overlay_configure_topology (void *cls) -{ - struct TopologyContext *tc = cls; - struct TopologyContextOverlay *overlay; - unsigned int p; - - GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type); - overlay = &tc->u.overlay; - overlay->nlinks = tc->link_array_size; - for (p = 0; p < tc->link_array_size; p++) - { - overlay->link_array[p].op = - GNUNET_TESTBED_overlay_connect (overlay->op_cls, - &overlay_link_completed, - &overlay->link_array[p], - overlay->peers[overlay->link_array[p].A], - overlay->peers[overlay->link_array[p].B]); - } -} - - -/** - * Callback which will be called when overlay connect operation is released - * - * @param cls the Topology context - */ -static void -oprelease_overlay_configure_topology (void *cls) -{ - struct TopologyContext *tc = cls; - struct TopologyContextOverlay *overlay; - struct RetryListEntry *retry_entry; - unsigned int p; - - GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type); - overlay = &tc->u.overlay; - while (NULL != (retry_entry = overlay->rl_head)) - { - GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail, - retry_entry); - GNUNET_free (retry_entry); - } - if (NULL != overlay->link_array) - { - for (p = 0; p < tc->link_array_size; p++) - if (NULL != overlay->link_array[p].op) - GNUNET_TESTBED_operation_done (overlay->link_array[p].op); - GNUNET_free (overlay->link_array); - } - GNUNET_free (tc); -} - - -/** - * Populates the OverlayLink structure. - * - * @param offset the offset of the link array to use - * @param A the peer A. Should be different from B - * @param B the peer B. Should be different from A - * @param tc the TopologyContext - * @return - */ -static void -make_link (unsigned int offset, - uint32_t A, - uint32_t B, - struct TopologyContext *tc) -{ - GNUNET_assert (A != B); - switch (tc->type) - { - case TOPOLOGYCONTEXT_TYPE_OVERLAY: - { - struct TopologyContextOverlay *overlay; - struct OverlayLink *olink; - - overlay = &tc->u.overlay; - GNUNET_assert (offset < tc->link_array_size); - olink = &overlay->link_array[offset]; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A); - olink->A = A; - olink->B = B; - olink->op = NULL; - olink->tc = tc; - } - break; - - case TOPOLOGYCONTEXT_TYPE_UNDERLAY: - { - struct TopologyContextUnderlay *underlay; - struct UnderlayLink *ulink; - - underlay = &tc->u.underlay; - GNUNET_assert (offset < tc->link_array_size); - ulink = &underlay->link_array[offset]; - ulink->A = A; - ulink->B = B; - } - break; - } -} - - -/** - * Generates line topology - * - * @param tc the topology context - */ -static void -gen_topo_line (struct TopologyContext *tc) -{ - unsigned int cnt; - - tc->link_array_size = tc->num_peers - 1; - switch (tc->type) - { - case TOPOLOGYCONTEXT_TYPE_OVERLAY: - { - struct TopologyContextOverlay *overlay; - - overlay = &tc->u.overlay; - overlay->link_array = - GNUNET_new_array (tc->link_array_size, - struct OverlayLink); - } - break; - - case TOPOLOGYCONTEXT_TYPE_UNDERLAY: - { - struct TopologyContextUnderlay *underlay; - - underlay = &tc->u.underlay; - underlay->link_array = - GNUNET_new_array (tc->link_array_size, - struct UnderlayLink); - } - break; - } - for (cnt = 0; cnt < (tc->link_array_size); cnt++) - make_link (cnt, cnt, cnt + 1, tc); -} - - -/** - * Generates star topology - * - * @param tc the topology context - */ -static void -gen_topo_star (struct TopologyContext *tc) -{ - unsigned int cnt; - - tc->link_array_size = tc->num_peers - 1; - switch (tc->type) - { - case TOPOLOGYCONTEXT_TYPE_OVERLAY: - { - struct TopologyContextOverlay *overlay; - - overlay = &tc->u.overlay; - overlay->link_array = - GNUNET_new_array (tc->link_array_size, - struct OverlayLink); - } - break; - - case TOPOLOGYCONTEXT_TYPE_UNDERLAY: - { - struct TopologyContextUnderlay *underlay; - - underlay = &tc->u.underlay; - underlay->link_array = - GNUNET_new_array (tc->link_array_size, - struct UnderlayLink); - } - break; - } - for (cnt = tc->link_array_size; cnt; cnt--) - make_link (cnt - 1, - 0, - cnt, - tc); -} - - -/** - * Generates ring topology - * - * @param tc the topology context - */ -static void -gen_topo_ring (struct TopologyContext *tc) -{ - gen_topo_line (tc); - tc->link_array_size++; - switch (tc->type) - { - case TOPOLOGYCONTEXT_TYPE_OVERLAY: - { - struct TopologyContextOverlay *overlay; - - overlay = &tc->u.overlay; - overlay->link_array = - GNUNET_realloc (overlay->link_array, sizeof(struct OverlayLink) - * tc->link_array_size); - } - break; - - case TOPOLOGYCONTEXT_TYPE_UNDERLAY: - { - struct TopologyContextUnderlay *underlay; - - underlay = &tc->u.underlay; - underlay->link_array = - GNUNET_realloc (underlay->link_array, sizeof(struct UnderlayLink) - * tc->link_array_size); - } - break; - } - make_link (tc->link_array_size - 1, tc->num_peers - 1, 0, tc); -} - - -unsigned int -GNUNET_TESTBED_2dtorus_calc_links (unsigned int num_peers, unsigned int *rows, - unsigned int **rows_len) -{ - double sq; - unsigned int sq_floor; - unsigned int _rows; - unsigned int *_rows_len; - unsigned int x; - unsigned int y; - unsigned int _num_peers; - unsigned int cnt; - - sq = sqrt (num_peers); - sq = floor (sq); - sq_floor = (unsigned int) sq; - _rows = (sq_floor + 1); - _rows_len = GNUNET_malloc (sizeof(unsigned int) * _rows); - for (y = 0; y < _rows - 1; y++) - _rows_len[y] = sq_floor; - _num_peers = sq_floor * sq_floor; - cnt = (_num_peers < 2) ? _num_peers : 2 * _num_peers; - x = 0; - y = 0; - while (_num_peers < num_peers) - { - if (x < y) - _rows_len[_rows - 1] = ++x; - else - _rows_len[y++]++; - _num_peers++; - } - cnt += (x < 2) ? x : 2 * x; - cnt += (y < 2) ? y : 2 * y; - if (0 == _rows_len[_rows - 1]) - _rows--; - if (NULL != rows) - *rows = _rows; - if (NULL != rows_len) - *rows_len = _rows_len; - else - GNUNET_free (_rows_len); - return cnt; -} - - -/** - * Generates ring topology - * - * @param tc the topology context - */ -static void -gen_topo_2dtorus (struct TopologyContext *tc) -{ - unsigned int rows; - unsigned int *rows_len; - unsigned int x; - unsigned int y; - unsigned int cnt; - unsigned int offset; - - tc->link_array_size = - GNUNET_TESTBED_2dtorus_calc_links (tc->num_peers, &rows, &rows_len); - switch (tc->type) - { - case TOPOLOGYCONTEXT_TYPE_OVERLAY: - { - struct TopologyContextOverlay *overlay; - - overlay = &tc->u.overlay; - overlay->link_array = - GNUNET_malloc (sizeof(struct OverlayLink) * tc->link_array_size); - } - break; - - case TOPOLOGYCONTEXT_TYPE_UNDERLAY: - { - struct TopologyContextUnderlay *underlay; - - underlay = &tc->u.underlay; - underlay->link_array = - GNUNET_malloc (sizeof(struct UnderlayLink) * tc->link_array_size); - break; - } - } - cnt = 0; - offset = 0; - for (y = 0; y < rows; y++) - { - for (x = 0; x < rows_len[y] - 1; x++) - { - make_link (cnt, offset + x, offset + x + 1, tc); - cnt++; - } - if (0 == x) - break; - make_link (cnt, offset + x, offset, tc); - cnt++; - offset += rows_len[y]; - } - for (x = 0; x < rows_len[0]; x++) - { - offset = 0; - for (y = 0; y < rows - 1; y++) - { - if (x >= rows_len[y + 1]) - break; - GNUNET_assert (x < rows_len[y + 1]); - make_link (cnt, offset + x, offset + rows_len[y] + x, tc); - offset += rows_len[y]; - cnt++; - } - if (0 == offset) - break; - make_link (cnt, offset + x, x, tc); - cnt++; - } - GNUNET_assert (cnt == tc->link_array_size); - GNUNET_free (rows_len); -} - - -/** - * Generates ring topology - * - * @param tc the topology context - * @param links the number of random links to establish - * @param append #GNUNET_YES to add links to existing link array; #GNUNET_NO to - * create a new link array - */ -static void -gen_topo_random (struct TopologyContext *tc, - unsigned int links, - int append) -{ - unsigned int cnt; - unsigned int index; - uint32_t A_rand; - uint32_t B_rand; - - if (1 == tc->num_peers) - return; - if (GNUNET_YES == append) - { - index = tc->link_array_size; - tc->link_array_size += links; - } - else - { - index = 0; - tc->link_array_size = links; - } - switch (tc->type) - { - case TOPOLOGYCONTEXT_TYPE_OVERLAY: - { - struct TopologyContextOverlay *overlay; - - overlay = &tc->u.overlay; - if (GNUNET_YES != append) - { - GNUNET_assert (NULL == overlay->link_array); - overlay->link_array = - GNUNET_malloc (sizeof(struct OverlayLink) * tc->link_array_size); - break; - } - GNUNET_assert ((0 < tc->link_array_size) && (NULL != - overlay->link_array)); - overlay->link_array = - GNUNET_realloc (overlay->link_array, - sizeof(struct OverlayLink) * tc->link_array_size); - break; - } - - case TOPOLOGYCONTEXT_TYPE_UNDERLAY: - { - struct TopologyContextUnderlay *underlay; - - underlay = &tc->u.underlay; - if (GNUNET_YES != append) - { - GNUNET_assert (NULL == underlay->link_array); - underlay->link_array = - GNUNET_malloc (sizeof(struct UnderlayLink) * tc->link_array_size); - break; - } - GNUNET_assert ((0 < tc->link_array_size) && (NULL != - underlay->link_array)); - underlay->link_array = - GNUNET_realloc (underlay->link_array, - sizeof(struct UnderlayLink) * tc->link_array_size); - break; - } - } - for (cnt = 0; cnt < links; cnt++) - { - do - { - A_rand = - GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers); - B_rand = - GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers); - } - while (A_rand == B_rand); - make_link (index + cnt, A_rand, B_rand, tc); - } -} - - -/** - * Generates scale free network. Its construction is described in: - * - * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999. - * - * @param tc the topology context - * @param cap maximum allowed node degree - * @param m number of edges to establish for a new node when it is added to the - * network - */ -static void -gen_topo_scale_free (struct TopologyContext *tc, - uint16_t cap, - uint8_t m) -{ - unsigned int *deg; - unsigned int *etab; - unsigned int *used; - unsigned int etaboff; - unsigned int cnt; - unsigned int cnt2; - unsigned int peer; - unsigned int random_peer; - unsigned int links; - unsigned int off; - unsigned int redo_threshold; - - etaboff = 0; - tc->link_array_size = tc->num_peers * m; - switch (tc->type) - { - case TOPOLOGYCONTEXT_TYPE_OVERLAY: - { - struct TopologyContextOverlay *overlay; - - overlay = &tc->u.overlay; - overlay->link_array = GNUNET_malloc_large (sizeof(struct OverlayLink) - * tc->link_array_size); - } - break; - - case TOPOLOGYCONTEXT_TYPE_UNDERLAY: - { - struct TopologyContextUnderlay *underlay; - - underlay = &tc->u.underlay; - underlay->link_array = GNUNET_malloc_large (sizeof(struct UnderlayLink) - * tc->link_array_size); - } - break; - } - etab = GNUNET_malloc_large (sizeof(unsigned int) * 2 * tc->link_array_size); - deg = GNUNET_malloc (sizeof(unsigned int) * tc->num_peers); - used = GNUNET_malloc (sizeof(unsigned int) * m); - /* start by connecting peer 1 to peer 0 */ - make_link (0, 0, 1, tc); - deg[0]++; - deg[1]++; - etab[etaboff++] = 0; - etab[etaboff++] = 1; - links = 1; - for (peer = 2; peer < tc->num_peers; peer++) - { - if (cap < deg[peer]) - continue; - for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++) - { - redo_threshold = 0; -redo: - off = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, etaboff); - random_peer = etab[off]; - if (cap < deg[random_peer]) - { - if (++redo_threshold > GNUNET_MAX (1, cap / 2)) - { - redo_threshold = 0; - off = 0; - for (cnt2 = 0; cnt2 < etaboff; cnt2++) - { - if (random_peer == etab[cnt2]) - { - off++; - continue; - } - etab[cnt2 - off] = etab[cnt2]; - } - etaboff -= off; - } - goto redo; - } - for (cnt2 = 0; cnt2 < cnt; cnt2++) - if (random_peer == used[cnt2]) - goto redo; - make_link (links + cnt, random_peer, peer, tc); - deg[random_peer]++; - deg[peer]++; - used[cnt] = random_peer; - } - for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++) - { - etab[etaboff++] = used[cnt]; - etab[etaboff++] = peer; - } - links += GNUNET_MIN (peer, m); - } - GNUNET_free (etab); - GNUNET_free (used); - GNUNET_free (deg); - GNUNET_assert (links <= tc->link_array_size); - tc->link_array_size = links; - switch (tc->type) - { - case TOPOLOGYCONTEXT_TYPE_OVERLAY: - { - struct TopologyContextOverlay *overlay; - - overlay = &tc->u.overlay; - overlay->link_array = - GNUNET_realloc (overlay->link_array, sizeof(struct OverlayLink) - * tc->link_array_size); - } - break; - - case TOPOLOGYCONTEXT_TYPE_UNDERLAY: - { - struct TopologyContextUnderlay *underlay; - - underlay = &tc->u.underlay; - underlay->link_array = - GNUNET_realloc (underlay->link_array, sizeof(struct UnderlayLink) - * tc->link_array_size); - } - break; - } -} - - -/** - * Generates topology from the given file - * - * @param tc the topology context - * @param filename the filename of the file containing topology data - */ -static void -gen_topo_from_file (struct TopologyContext *tc, - const char *filename) -{ - char *data; - char *end; - char *buf; - uint64_t fs; - uint64_t offset; - unsigned long int peer_id; - unsigned long int other_peer_id; - enum ParseState - { - /** - * We read the peer index - */ - PEER_INDEX, - - /** - * We read the other peer indices - */ - OTHER_PEER_INDEX, - } state; - int status; - - status = GNUNET_SYSERR; - if (GNUNET_YES != GNUNET_DISK_file_test (filename)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Topology file %s not found\n"), - filename); - return; - } - if (GNUNET_OK != - GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Topology file %s has no data\n"), - filename); - return; - } - data = GNUNET_malloc (fs); - if (fs != GNUNET_DISK_fn_read (filename, data, fs)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Topology file %s cannot be read\n"), - filename); - goto _exit; - } - - offset = 0; - peer_id = 0; - state = PEER_INDEX; - while (offset < fs) - { - if (0 != isspace ((unsigned char) data[offset])) - { - offset++; - continue; - } - switch (state) - { - case PEER_INDEX: - buf = strchr (&data[offset], ':'); - if (NULL == buf) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Failed to read peer index from toology file: %s"), filename); - goto _exit; - } - *buf = '\0'; - errno = 0; - peer_id = (unsigned int) strtoul (&data[offset], &end, 10); - if (0 != errno) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Value in given topology file: %s out of range\n"), filename); - goto _exit; - } - if (&data[offset] == end) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Failed to read peer index from topology file: %s"), filename); - goto _exit; - } - if (tc->num_peers <= peer_id) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Topology file needs more peers than given ones\n")); - goto _exit; - } - state = OTHER_PEER_INDEX; - offset += ((unsigned int) (buf - &data[offset])) + 1; - break; - - case OTHER_PEER_INDEX: - errno = 0; - other_peer_id = (unsigned int) strtoul (&data[offset], &end, 10); - if (0 != errno) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Value in given topology file: %s out of range\n"), filename); - goto _exit; - } - if (&data[offset] == end) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Failed to read peer index from topology file: %s"), filename); - goto _exit; - } - if (tc->num_peers <= other_peer_id) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Topology file needs more peers than given ones\n")); - goto _exit; - } - if (peer_id != other_peer_id) - { - tc->link_array_size++; - switch (tc->type) - { - case TOPOLOGYCONTEXT_TYPE_OVERLAY: - { - struct TopologyContextOverlay *overlay; - - overlay = &tc->u.overlay; - overlay->link_array = - GNUNET_realloc (overlay->link_array, - sizeof(struct OverlayLink) * tc->link_array_size); - } - break; - - case TOPOLOGYCONTEXT_TYPE_UNDERLAY: - { - struct TopologyContextUnderlay *underlay; - - underlay = &tc->u.underlay; - underlay->link_array = - GNUNET_realloc (underlay->link_array, - sizeof(struct UnderlayLink) - * tc->link_array_size); - } - break; - } - offset += end - &data[offset]; - make_link (tc->link_array_size - 1, peer_id, other_peer_id, tc); - } - else - LOG (GNUNET_ERROR_TYPE_WARNING, - _ ("Ignoring to connect peer %lu to peer %lu\n"), - peer_id, - other_peer_id); - while (('\n' != data[offset]) && ('|' != data[offset]) && (offset < fs)) - offset++; - if ((offset < fs) && - ('\n' == data[offset])) - state = PEER_INDEX; - else if ((offset < fs) && - ('|' == data[offset])) - { - state = OTHER_PEER_INDEX; - offset++; - } - break; - } - } - status = GNUNET_OK; - -_exit: - GNUNET_free (data); - if (GNUNET_OK != status) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Removing link data read from the file\n"); - tc->link_array_size = 0; - switch (tc->type) - { - case TOPOLOGYCONTEXT_TYPE_OVERLAY: - { - struct TopologyContextOverlay *overlay; - - overlay = &tc->u.overlay; - GNUNET_free (overlay->link_array); - overlay->link_array = NULL; - } - break; - - case TOPOLOGYCONTEXT_TYPE_UNDERLAY: - { - struct TopologyContextUnderlay *underlay; - - underlay = &tc->u.underlay; - GNUNET_free (underlay->link_array); - underlay->link_array = NULL; - } - break; - } - } -} - - -/** - * Generates clique topology - * - * @param tc the topology context - */ -static void -gen_topo_clique (struct TopologyContext *tc) -{ - unsigned int cnt; - unsigned int offset; - unsigned int neighbour; - - tc->link_array_size = tc->num_peers * (tc->num_peers - 1); - switch (tc->type) - { - case TOPOLOGYCONTEXT_TYPE_OVERLAY: - { - struct TopologyContextOverlay *overlay; - - overlay = &tc->u.overlay; - overlay->link_array = GNUNET_new_array (tc->link_array_size, - struct OverlayLink); - } - break; - - case TOPOLOGYCONTEXT_TYPE_UNDERLAY: - { - struct TopologyContextUnderlay *underlay; - - underlay = &tc->u.underlay; - underlay->link_array = GNUNET_new_array (tc->link_array_size, - struct UnderlayLink); - } - } - offset = 0; - for (cnt = 0; cnt < tc->num_peers; cnt++) - { - for (neighbour = 0; neighbour < tc->num_peers; neighbour++) - { - if (neighbour == cnt) - continue; - make_link (offset, cnt, neighbour, tc); - offset++; - } - } -} - - -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_underlay_configure_topology_va (void *op_cls, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer - **peers, - enum - GNUNET_TESTBED_TopologyOption - topo, va_list ap) -{ - GNUNET_break (0); - return NULL; -} - - -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_underlay_configure_topology (void *op_cls, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers, - enum GNUNET_TESTBED_TopologyOption - topo, ...) -{ - GNUNET_break (0); - return NULL; -} - - -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers, - unsigned int *max_connections, - GNUNET_TESTBED_TopologyCompletionCallback - comp_cb, - void *comp_cb_cls, - enum GNUNET_TESTBED_TopologyOption - topo, - va_list va) -{ - struct TopologyContext *tc; - struct TopologyContextOverlay *overlay; - struct GNUNET_TESTBED_Operation *op; - struct GNUNET_TESTBED_Controller *c; - enum GNUNET_TESTBED_TopologyOption secondary_option; - - if (num_peers < 2) - return NULL; - c = peers[0]->controller; - tc = GNUNET_new (struct TopologyContext); - tc->type = TOPOLOGYCONTEXT_TYPE_OVERLAY; - overlay = &tc->u.overlay; - overlay->peers = peers; - tc->num_peers = num_peers; - overlay->op_cls = op_cls; - overlay->retry_cnt = DEFAULT_RETRY_CNT; - overlay->comp_cb = comp_cb; - overlay->comp_cb_cls = comp_cb_cls; - switch (topo) - { - case GNUNET_TESTBED_TOPOLOGY_LINE: - gen_topo_line (tc); - break; - - case GNUNET_TESTBED_TOPOLOGY_STAR: - gen_topo_star (tc); - break; - - case GNUNET_TESTBED_TOPOLOGY_RING: - gen_topo_ring (tc); - break; - - case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: - gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_NO); - break; - - case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: - gen_topo_ring (tc); - gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES); - break; - - case GNUNET_TESTBED_TOPOLOGY_CLIQUE: - gen_topo_clique (tc); - break; - - case GNUNET_TESTBED_TOPOLOGY_2D_TORUS: - gen_topo_2dtorus (tc); - break; - - case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: - gen_topo_2dtorus (tc); - gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES); - - break; - - case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: - { - uint16_t cap; - uint8_t m; - - cap = (uint16_t) va_arg (va, unsigned int); - m = (uint8_t) va_arg (va, unsigned int); - gen_topo_scale_free (tc, cap, m); - } - break; - - case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: - { - const char *filename; - - filename = va_arg (va, const char *); - - GNUNET_assert (NULL != filename); - gen_topo_from_file (tc, filename); - } - break; - - default: - GNUNET_break (0); - GNUNET_free (tc); - return NULL; - } - do - { - secondary_option = GNUNET_VA_ARG_ENUM (va, GNUNET_TESTBED_TopologyOption); - - switch (secondary_option) - { - case GNUNET_TESTBED_TOPOLOGY_RETRY_CNT: - overlay->retry_cnt = va_arg (va, unsigned int); - break; - - case GNUNET_TESTBED_TOPOLOGY_OPTION_END: - break; - - default: - GNUNET_break (0); /* Should not use any other option apart from - * the ones handled here */ - GNUNET_free (overlay->link_array); - GNUNET_free (tc); - return NULL; - } - } - while (GNUNET_TESTBED_TOPOLOGY_OPTION_END != secondary_option); - op = GNUNET_TESTBED_operation_create_ (tc, - &opstart_overlay_configure_topology, - &oprelease_overlay_configure_topology); - GNUNET_TESTBED_operation_queue_insert_ - (c->opq_parallel_topology_config_operations, op); - GNUNET_TESTBED_operation_begin_wait_ (op); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Generated topology with %u connections\n", - tc->link_array_size); - if (NULL != max_connections) - *max_connections = tc->link_array_size; - return op; -} - - -/** - * All peers must have been started before calling this function. - * This function then connects the given peers in the P2P overlay - * using the given topology. - * - * @param op_cls closure argument to give with the peer connect operation events - * generated through this function - * @param num_peers number of peers in 'peers' - * @param peers array of 'num_peers' with the peers to configure - * @param max_connections the maximums number of overlay connections that will - * be made to achieve the given topology - * @param comp_cb the completion callback to call when the topology generation - * is completed - * @param comp_cb_cls closure for the above completion callback - * @param topo desired underlay topology to use - * @param ... topology-specific options - * @return handle to the operation, NULL if connecting these - * peers is fundamentally not possible at this time (peers - * not running or underlay disallows) or if num_peers is less than 2 - */ -struct GNUNET_TESTBED_Operation * -GNUNET_TESTBED_overlay_configure_topology (void *op_cls, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers, - unsigned int *max_connections, - GNUNET_TESTBED_TopologyCompletionCallback - comp_cb, - void *comp_cb_cls, - enum GNUNET_TESTBED_TopologyOption - topo, - ...) -{ - struct GNUNET_TESTBED_Operation *op; - va_list vargs; - - GNUNET_assert (topo < GNUNET_TESTBED_TOPOLOGY_OPTION_END); - va_start (vargs, topo); - op = GNUNET_TESTBED_overlay_configure_topology_va (op_cls, num_peers, peers, - max_connections, - comp_cb, comp_cb_cls, - topo, - vargs); - va_end (vargs); - return op; -} - - -int -GNUNET_TESTBED_topology_get_ (enum GNUNET_TESTBED_TopologyOption *topology, - const char *topology_string) -{ - unsigned int cnt; - - for (cnt = 0; NULL != topology_strings[cnt]; cnt++) - { - if (0 == strcasecmp (topology_string, topology_strings[cnt])) - { - if (NULL != topology) - *topology = (enum GNUNET_TESTBED_TopologyOption) cnt; - GNUNET_assert (GNUNET_TESTBED_TOPOLOGY_OPTION_END != - (enum GNUNET_TESTBED_TopologyOption) cnt); - return GNUNET_YES; - } - } - return GNUNET_NO; -} - - -/** - * Returns the string corresponding to the given topology - * - * @param topology the topology - * @return the string (freshly allocated) of given topology; NULL if topology cannot be - * expressed as a string - */ -char * -GNUNET_TESTBED_topology_to_str_ (enum GNUNET_TESTBED_TopologyOption topology) -{ - if (GNUNET_TESTBED_TOPOLOGY_OPTION_END <= topology) - return NULL; - return GNUNET_strdup (topology_strings[topology]); -} - - -/** - * Function to construct an underlay topology - * - * @param num_peers the number of peers for which the topology should be - * generated - * @param proc the underlay link processor callback. Will be called for each - * underlay link generated unless a previous call to this callback - * returned #GNUNET_SYSERR. Cannot be NULL. - * @param cls closure for @a proc - * @param ... variable arguments denoting the topology and its parameters. They - * should start with the type of topology to generate followed by their - * options. - * @return #GNUNET_OK if underlay link generation is successful; #GNUNET_SYSERR - * upon error in generating the underlay or if any calls to the - * underlay link processor returned #GNUNET_SYSERR - */ -int -GNUNET_TESTBED_underlay_construct_ (int num_peers, - underlay_link_processor proc, - void *cls, - ...) -{ - struct TopologyContext tc; - struct TopologyContextUnderlay *underlay; - struct UnderlayLink *ulink; - va_list vargs; - enum GNUNET_TESTBED_TopologyOption topology; - unsigned int cnt; - int ret; - - GNUNET_assert (NULL != proc); - ret = GNUNET_OK; - memset (&tc, 0, sizeof(tc)); - tc.num_peers = num_peers; - tc.type = TOPOLOGYCONTEXT_TYPE_UNDERLAY; - underlay = &tc.u.underlay; - va_start (vargs, cls); - topology = GNUNET_VA_ARG_ENUM (vargs, GNUNET_TESTBED_TopologyOption); - switch (topology) - { - case GNUNET_TESTBED_TOPOLOGY_LINE: - gen_topo_line (&tc); - break; - - case GNUNET_TESTBED_TOPOLOGY_STAR: - gen_topo_star (&tc); - break; - - case GNUNET_TESTBED_TOPOLOGY_RING: - gen_topo_ring (&tc); - break; - - case GNUNET_TESTBED_TOPOLOGY_CLIQUE: - gen_topo_clique (&tc); - break; - - case GNUNET_TESTBED_TOPOLOGY_2D_TORUS: - gen_topo_2dtorus (&tc); - break; - - case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: - gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_NO); - break; - - case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: - gen_topo_ring (&tc); - gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES); - break; - - case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: - gen_topo_2dtorus (&tc); - gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES); - break; - - case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: - { - const char *filename; - filename = va_arg (vargs, char *); - GNUNET_assert (NULL != filename); - gen_topo_from_file (&tc, filename); - } - break; - - case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: - { - uint16_t cap; - uint8_t m; - cap = (uint16_t) va_arg (vargs, unsigned int); - m = (uint8_t) va_arg (vargs, unsigned int); - gen_topo_scale_free (&tc, cap, m); - } - break; - - default: - GNUNET_assert (0); - } - va_end (vargs); - for (cnt = 0; cnt < tc.link_array_size; cnt++) - { - ulink = &underlay->link_array[cnt]; - if (GNUNET_SYSERR == proc (cls, - ulink->A, - ulink->B, - ulink->bandwidth, - ulink->latency, - ulink->loss)) - { - ret = GNUNET_SYSERR; - break; - } - } - GNUNET_free (underlay->link_array); - return ret; -} - - -/* end of testbed_api_topology.c */ diff --git a/src/testbed/testbed_api_topology.h b/src/testbed/testbed_api_topology.h @@ -1,115 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_topology.h - * @brief header for intra library exported functions - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#ifndef TESTBED_API_TOPOLOGY_H -#define TESTBED_API_TOPOLOGY_H - -/** - * Returns the number of links that are required to generate a 2d torus for the - * given number of peers. Also returns the arrangement (number of rows and the - * length of each row) - * - * @param num_peers number of peers - * @param rows number of rows in the 2d torus. Can be NULL. - * @param rows_len the length of each row. This array will be allocated - * fresh. The caller should free it. Can be NULL. - * @return the number of links that are required to generate a 2d torus for the - * given number of peers - */ -unsigned int -GNUNET_TESTBED_2dtorus_calc_links (unsigned int num_peers, unsigned int *rows, - unsigned int **rows_len); - - -/** - * Get a topology from a string input. - * - * @param topology where to write the retrieved topology - * @param topology_string The string to attempt to - * get a configuration value from - * @return #GNUNET_YES if topology string matched a - * known topology, #GNUNET_NO if not - */ -int -GNUNET_TESTBED_topology_get_ (enum GNUNET_TESTBED_TopologyOption *topology, - const char *topology_string); - - -/** - * Returns the string corresponding to the given topology - * - * @param topology the topology - * @return the string (freshly allocated) of given topology; NULL if topology cannot be - * expressed as a string - */ -char * -GNUNET_TESTBED_topology_to_str_ (enum GNUNET_TESTBED_TopologyOption topology); - - -/** - * Functions of this type are called to process underlay link - * - * @param cls closure - * @param A offset of first peer - * @param B offset of second peer - * @param bandwidth the bandwidth of the link in bytes per second - * @param latency the latency of link in milliseconds - * @param loss the percentage of messages dropped on the link - * @return GNUNET_OK to continue processing; GNUNET_SYSERR to abort - */ -typedef int (*underlay_link_processor) (void *cls, - unsigned int A, - unsigned int B, - unsigned int bandwidth, - unsigned int latency, - unsigned int loss); - - -/** - * Function to construct an underlay topology - * - * @param num_peers the number of peers for which the topology should be - * generated - * @param proc the underlay link processor callback. Will be called for each - * underlay link generated unless a previous call to this callback - * returned GNUNET_SYSERR. Cannot be NULL. - * @param cls closure for proc - * @param ... variable arguments denoting the topology and its parameters. They - * should start with the type of topology to generate followed by their - * options. These arguments should *always* end with - * GNUNET_TESTBED_TOPOLOGY_OPTION_END option - * @return GNUNET_OK if underlay link generation is successful; GNUNET_SYSERR - * upon error in generating the underlay or if any calls to the - * underlay link processor returned GNUNET_SYSERR - */ -int -GNUNET_TESTBED_underlay_construct_ (int num_peers, - underlay_link_processor proc, - void *cls, - ...); - -#endif -/* end of testbed_api_topology.h */ diff --git a/src/testbed/testbed_api_underlay.c b/src/testbed/testbed_api_underlay.c @@ -1,260 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_api_underlay.c - * @brief testbed underlay API implementation - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#include "platform.h" -#include "testbed_api_peers.h" - - -/** - * An underlay link - */ -struct LinkProperty -{ - /** - * next pointer for list - */ - struct LinkProperty *next; - - /** - * the peer whose link is defined by these properties - */ - struct GNUNET_TESTBED_Peer *peer; - - /** - * latency of the link in microseconds - */ - uint32_t latency; - - /** - * data loss on the link expressed as percentage - */ - uint32_t loss; - - /** - * bandwidth of the link in kilobytes per second - */ - uint32_t bandwidth; -}; - - -/** - * Container for holding a peer in whitelist/blacklist - */ -struct ListEntry -{ - /** - * the next pointer - */ - struct ListEntry *next; - - /** - * the peer - */ - struct GNUNET_TESTBED_Peer *peer; -}; - - -/** - * Model for configuring underlay links of a peer - * @ingroup underlay - */ -struct GNUNET_TESTBED_UnderlayLinkModel -{ - /** - * The peer associated with this model - */ - struct GNUNET_TESTBED_Peer *peer; - - /** - * List of peers in the list - */ - struct ListEntry *entries; - - /** - * list of link properties - */ - struct LinkProperty *props; - - /** - * the type of this model - */ - enum GNUNET_TESTBED_UnderlayLinkModelType type; -} - - -/** - * Function to free resources of list entries - * - * @param model the model - */ -static void -free_entries (struct GNUNET_TESTBED_UnderlayLinkModel *model) -{ - struct ListEntry *e; - - while (NULL != (e = model->entries)) - { - model->entries = e->next; - GNUNET_free (e); - } -} - - -/** - * Function to free resources of link properties added to the given model - * - * @param model the model - */ -static void -free_link_properties (struct GNUNET_TESTBED_UnderlayLinkModel *model) -{ - struct LinkProperty *p; - - while (NULL != (p = model->props)) - { - model->props = p->next; - GNUNET_free (p); - } -} - - -/** - * Create a GNUNET_TESTBED_UnderlayLinkModel for the given peer. A peer can - * have ONLY ONE model and it can be either a blacklist or whitelist based one. - * - * @ingroup underlay - * @param peer the peer for which the model has to be created - * @param type the type of the model - * @return the model - */ -struct GNUNET_TESTBED_UnderlayLinkModel * -GNUNET_TESTBED_underlaylinkmodel_create (struct GNUNET_TESTBED_Peer *peer, - enum - GNUNET_TESTBED_UnderlayLinkModelType - type) -{ - struct GNUNET_TESTBED_UnderlayLinkModel *m; - - GNUNET_assert (0 == peer->underlay_model_exists); - m = GNUNET_new (struct GNUNET_TESTBED_UnderlayLinkModel); - peer->underlay_model_exists = 1; - m->type = type; - return m; -} - - -/** - * Add a peer to the given model. Underlay connections to the given peer will - * be permitted if the model is whitelist based; otherwise they will not be - * permitted. - * - * @ingroup underlay - * @param model the model - * @param peer the peer to add - */ -void -GNUNET_TESTBED_underlaylinkmodel_add_peer (struct - GNUNET_TESTBED_UnderlayLinkModel * - model, - struct GNUNET_TESTBED_Peer *peer) -{ - struct ListEntry *entry; - - entry = GNUNET_new (struct ListEntry); - entry->peer = peer; - entry->next = model->entries; - model->entries = entry; -} - - -/** - * Set the metrics for a link to the given peer in the underlay model. The link - * SHOULD be permittable according to the given model. - * - * @ingroup underlay - * @param model the model - * @param peer the other end peer of the link - * @param latency latency of the link in microseconds - * @param loss data loss of the link expressed as a percentage - * @param bandwidth bandwidth of the link in kilobytes per second [kB/s] - */ -void -GNUNET_TESTBED_underlaylinkmodel_set_link (struct - GNUNET_TESTBED_UnderlayLinkModel * - model, - struct GNUNET_TESTBED_Peer *peer, - uint32_t latency, - uint32_t loss, - uint32_t bandwidth) -{ - struct LinkProperty *prop; - - prop = GNUNET_new (struct LinkProperty); - prop->peer = peer; - prop->latency = latency; - prop->loss = loss; - prop->bandwidth = bandwidth; - prop->next = model->props; - model->props = prop; -} - - -/** - * Free the resources of the model. Use this function only if the model has not - * be committed and has to be unallocated. The peer can then have another model - * created. - * - * @ingroup underlay - * @param model the model to unallocate - */ -void -GNUNET_TESTBED_underlaylinkmodel_free (struct - GNUNET_TESTBED_UnderlayLinkModel *model) -{ - model->peer->underlay_model_exists = 0; - free_entries (model); - free_link_properties (model); - gnunet_free (model); -} - - -/** - * Commit the model. The model is freed in this function(!). - * - * @ingroup underlay - * @param model the model to commit - */ -void -GNUNET_TESTBED_underlaylinkmodel_commit (struct - GNUNET_TESTBED_UnderlayLinkModel *model) -{ - /* FIXME: Marshal the model into a message */ - GNUNET_break (0); - /* do not reset the value of model->peer->underlay_model_exists */ - free_entries (model); - free_link_properties (model); - GNUNET_free (model); -} diff --git a/src/testbed/testbed_helper.h b/src/testbed/testbed_helper.h @@ -1,89 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2008--2013 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 <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file testbed/testbed_helper.h - * @brief Message formats for communication between testbed api and - * gnunet-helper-testbed process - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ - -#ifndef TESTBED_HELPER_H -#define TESTBED_HELPER_H - -GNUNET_NETWORK_STRUCT_BEGIN -/** - * Initialization message for gnunet-helper-testbed to start testbed service - */ -struct GNUNET_TESTBED_HelperInit -{ - /** - * Type is GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT - */ - struct GNUNET_MessageHeader header; - - /** - * The controller hostname size excluding the NULL termination character - - * strlen (hostname); cannot be zero - */ - uint16_t trusted_ip_size GNUNET_PACKED; - - /** - * The hostname size excluding the NULL termination character - strlen - * (hostname); cannot be zero - */ - uint16_t hostname_size GNUNET_PACKED; - - /** - * The size of the uncompressed configuration - */ - uint16_t config_size GNUNET_PACKED; - - /* Followed by NULL terminated trusted ip */ - - /* Followed by hostname of the machine on which helper runs. This is not NULL - * terminated */ - - /* Followed by serialized and compressed configuration which should be - * config_size long when un-compressed */ -}; - -/** - * Reply message from helper process - */ -struct GNUNET_TESTBED_HelperReply -{ - /** - * Type is GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY - */ - struct GNUNET_MessageHeader header; - - /** - * Size of the uncompressed configuration - */ - uint16_t config_size GNUNET_PACKED; - - /* Followed by compressed configuration which should be config_size long when - * un-compressed */ -}; - -GNUNET_NETWORK_STRUCT_END -#endif -/* end of testbed_helper.h */ diff --git a/src/testbed/valgrind-zlib.supp b/src/testbed/valgrind-zlib.supp @@ -1,6 +0,0 @@ -{ - <ZlibInflateReset2UninitJump> - Memcheck:Cond - fun:inflateReset2 - ... -} diff --git a/src/testbed/x64_misc.supp b/src/testbed/x64_misc.supp @@ -1,34 +0,0 @@ -{ - <unknown invalid free> - Memcheck:Free - fun:free - fun:free_mem - fun:__libc_freeres - fun:_vgnU_freeres - fun:__run_exit_handlers - fun:exit - fun:(below main) -} -{ - <gnunet_crypto_init> - Memcheck:Leak - fun:malloc - obj:/usr/lib/libgcrypt.so.11.5.3 - ... - obj:/usr/lib/libgcrypt.so.11.5.3 - fun:gcry_control - fun:GNUNET_CRYPTO_random_init - obj:/home/harsha/repos/gnunet/src/util/.libs/libgnunetutil.so.8.0.0 - obj:/home/harsha/repos/gnunet/src/util/.libs/libgnunetutil.so.8.0.0 -} - -{ - <insert_a_suppression_name_here> - Memcheck:Leak - fun:malloc - ... - fun:gcry_control - fun:GNUNET_CRYPTO_random_init - obj:/home/totakura/gnunet/src/util/.libs/libgnunetutil.so.8.0.0 - obj:/home/totakura/gnunet/src/util/.libs/libgnunetutil.so.8.0.0 -}