/* This file is part of GNUnet. Copyright (C) 2012 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . SPDX-License-Identifier: AGPL3.0-or-later */ /** * @file dht/dht_test_lib.c * @author Christian Grothoff * @brief library for writing DHT tests */ #include "platform.h" #include "dht_test_lib.h" /** * Test context for a DHT Test. */ struct GNUNET_DHT_TEST_Context { /** * Array of running peers. */ struct GNUNET_TESTBED_Peer **peers; /** * Array of handles to the DHT for each peer. */ struct GNUNET_DHT_Handle **dhts; /** * Operation associated with the connection to the DHT. */ struct GNUNET_TESTBED_Operation **ops; /** * Main function of the test to run once all DHTs are available. */ GNUNET_DHT_TEST_AppMain app_main; /** * Closure for 'app_main'. */ void *app_main_cls; /** * Number of peers running, size of the arrays above. */ unsigned int num_peers; }; /** * Adapter function called to establish a connection to * the DHT 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 * dht_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { return GNUNET_DHT_connect (cfg, 16); } /** * Adapter function called to destroy a connection to * the DHT service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void dht_disconnect_adapter (void *cls, void *op_result) { struct GNUNET_DHT_Handle *dht = op_result; GNUNET_DHT_disconnect (dht); } /** * 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 dht_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { struct GNUNET_DHT_TEST_Context *ctx = cls; if (NULL != emsg) { fprintf (stderr, "Failed to connect to DHT service: %s\n", emsg); GNUNET_SCHEDULER_shutdown (); return; } for (unsigned int i=0;inum_peers;i++) if (op == ctx->ops[i]) ctx->dhts[i] = ca_result; for (unsigned int i=0;inum_peers;i++) if (NULL == ctx->dhts[i]) return; /* still some DHT connections missing */ /* all DHT connections ready! */ ctx->app_main (ctx->app_main_cls, ctx, ctx->num_peers, ctx->peers, ctx->dhts); } /** * Clean up the testbed. * * @param ctx handle for the testbed */ void GNUNET_DHT_TEST_cleanup (struct GNUNET_DHT_TEST_Context *ctx) { for (unsigned int i=0;inum_peers;i++) GNUNET_TESTBED_operation_done (ctx->ops[i]); GNUNET_free (ctx->ops); GNUNET_free (ctx->dhts); GNUNET_free (ctx); GNUNET_SCHEDULER_shutdown (); } static void dht_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) { struct GNUNET_DHT_TEST_Context *ctx = cls; GNUNET_assert (num_peers == ctx->num_peers); ctx->peers = peers; for (unsigned int i=0;iops[i] = GNUNET_TESTBED_service_connect (ctx, peers[i], "dht", &dht_connect_cb, ctx, &dht_connect_adapter, &dht_disconnect_adapter, ctx); } /** * Run a test using the given name, configuration file and number of * peers. * * @param testname name of the test (for logging) * @param cfgname name of the configuration file * @param num_peers number of peers to start * @param tmain main function to run once the testbed is ready * @param tmain_cls closure for 'tmain' */ void GNUNET_DHT_TEST_run (const char *testname, const char *cfgname, unsigned int num_peers, GNUNET_DHT_TEST_AppMain tmain, void *tmain_cls) { struct GNUNET_DHT_TEST_Context *ctx; ctx = GNUNET_new (struct GNUNET_DHT_TEST_Context); ctx->num_peers = num_peers; ctx->ops = GNUNET_new_array (num_peers, struct GNUNET_TESTBED_Operation *); ctx->dhts = GNUNET_new_array (num_peers, struct GNUNET_DHT_Handle *); ctx->app_main = tmain; ctx->app_main_cls = tmain_cls; (void) GNUNET_TESTBED_test_run (testname, cfgname, num_peers, 0LL, NULL, NULL, &dht_test_run, ctx); } /* end of dht_test_lib.c */