123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- /*
- This file is part of GNUnet.
- Copyright (C) 2012, 2017 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 cadet/cadet_test_lib.c
- * @author Bartlomiej Polot
- * @brief library for writing CADET tests
- */
- #include "platform.h"
- #include "gnunet_util_lib.h"
- #include "cadet_test_lib.h"
- #include "gnunet_cadet_service.h"
- /**
- * Test context for a CADET Test.
- */
- struct GNUNET_CADET_TEST_Context {
- /**
- * Array of running peers.
- */
- struct GNUNET_TESTBED_Peer **peers;
- /**
- * Array of handles to the CADET for each peer.
- */
- struct GNUNET_CADET_Handle **cadets;
- /**
- * Operation associated with the connection to the CADET.
- */
- struct GNUNET_TESTBED_Operation **ops;
- /**
- * Number of peers running, size of the arrays above.
- */
- unsigned int num_peers;
- /**
- * Main function of the test to run once all CADETs are available.
- */
- GNUNET_CADET_TEST_AppMain app_main;
- /**
- * Closure for 'app_main'.
- */
- void *app_main_cls;
- /**
- * Handler for incoming tunnels.
- */
- GNUNET_CADET_ConnectEventHandler connects;
- /**
- * Function called when the transmit window size changes.
- */
- GNUNET_CADET_WindowSizeEventHandler window_changes;
- /**
- * Cleaner for destroyed incoming tunnels.
- */
- GNUNET_CADET_DisconnectEventHandler disconnects;
- /**
- * Message handlers.
- */
- struct GNUNET_MQ_MessageHandler *handlers;
- /**
- * Application ports.
- */
- const struct GNUNET_HashCode **ports;
- /**
- * Number of ports in #ports.
- */
- unsigned int port_count;
- };
- /**
- * Context for a cadet adapter callback.
- */
- struct GNUNET_CADET_TEST_AdapterContext {
- /**
- * Peer number for the particular peer.
- */
- unsigned int peer;
- /**
- * Port handlers for open ports.
- */
- struct GNUNET_CADET_Port **ports;
- /**
- * General context.
- */
- struct GNUNET_CADET_TEST_Context *ctx;
- };
- /**
- * Adapter function called to establish a connection to
- * the CADET 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 *
- cadet_connect_adapter(void *cls,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
- {
- struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
- struct GNUNET_CADET_TEST_Context *ctx = actx->ctx;
- struct GNUNET_CADET_Handle *h;
- h = GNUNET_CADET_connect(cfg);
- if (NULL == h)
- {
- GNUNET_break(0);
- return NULL;
- }
- if (NULL == ctx->ports)
- return h;
- actx->ports = GNUNET_new_array(ctx->port_count,
- struct GNUNET_CADET_Port *);
- for (unsigned int i = 0; i < ctx->port_count; i++)
- {
- actx->ports[i] = GNUNET_CADET_open_port(h,
- ctx->ports[i],
- ctx->connects,
- (void *)(long)actx->peer,
- ctx->window_changes,
- ctx->disconnects,
- ctx->handlers);
- }
- return h;
- }
- /**
- * Adapter function called to destroy a connection to
- * the CADET service.
- *
- * @param cls closure
- * @param op_result service handle returned from the connect adapter
- */
- static void
- cadet_disconnect_adapter(void *cls,
- void *op_result)
- {
- struct GNUNET_CADET_Handle *cadet = op_result;
- struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
- if (NULL != actx->ports)
- {
- for (unsigned int i = 0; i < actx->ctx->port_count; i++)
- {
- GNUNET_CADET_close_port(actx->ports[i]);
- actx->ports[i] = NULL;
- }
- GNUNET_free(actx->ports);
- }
- GNUNET_free(actx);
- GNUNET_CADET_disconnect(cadet);
- }
- /**
- * 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() (cadet handle).
- * @param emsg Error message in case the operation has failed.
- * NULL if operation has executed successfully.
- */
- static void
- cadet_connect_cb(void *cls,
- struct GNUNET_TESTBED_Operation *op,
- void *ca_result,
- const char *emsg)
- {
- struct GNUNET_CADET_TEST_Context *ctx = cls;
- if (NULL != emsg)
- {
- fprintf(stderr,
- "Failed to connect to CADET service: %s\n",
- emsg);
- GNUNET_SCHEDULER_shutdown();
- return;
- }
- for (unsigned int i = 0; i < ctx->num_peers; i++)
- if (op == ctx->ops[i])
- {
- ctx->cadets[i] = ca_result;
- GNUNET_log(GNUNET_ERROR_TYPE_INFO,
- "...cadet %u connected\n",
- i);
- }
- for (unsigned int i = 0; i < ctx->num_peers; i++)
- if (NULL == ctx->cadets[i])
- return;
- /* still some CADET connections missing */
- /* all CADET connections ready! */
- ctx->app_main(ctx->app_main_cls,
- ctx,
- ctx->num_peers,
- ctx->peers,
- ctx->cadets);
- }
- void
- GNUNET_CADET_TEST_cleanup(struct GNUNET_CADET_TEST_Context *ctx)
- {
- for (unsigned int i = 0; i < ctx->num_peers; i++)
- {
- GNUNET_assert(NULL != ctx->ops[i]);
- GNUNET_TESTBED_operation_done(ctx->ops[i]);
- ctx->ops[i] = NULL;
- }
- GNUNET_free(ctx->ops);
- GNUNET_free(ctx->cadets);
- GNUNET_free(ctx->handlers);
- GNUNET_free(ctx);
- GNUNET_SCHEDULER_shutdown();
- }
- /**
- * Callback run when the testbed is ready (peers running and connected to
- * each other)
- *
- * @param cls Closure (context).
- * @param h the run handle
- * @param num_peers Number of peers that are running.
- * @param peers Handles to each one of the @c num_peers peers.
- * @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
- cadet_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_CADET_TEST_Context *ctx = cls;
- if (0 != links_failed)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
- "Some links failed (%u), ending\n",
- links_failed);
- exit(77);
- }
- if (num_peers != ctx->num_peers)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
- "Peers started %u/%u, ending\n",
- num_peers,
- ctx->num_peers);
- exit(1);
- }
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Testbed up, %u peers and %u links\n",
- num_peers,
- links_succeeded);
- ctx->peers = peers;
- for (unsigned int i = 0; i < num_peers; i++)
- {
- struct GNUNET_CADET_TEST_AdapterContext *newctx;
- newctx = GNUNET_new(struct GNUNET_CADET_TEST_AdapterContext);
- newctx->peer = i;
- newctx->ctx = ctx;
- GNUNET_log(GNUNET_ERROR_TYPE_INFO,
- "Connecting to cadet %u\n",
- i);
- ctx->ops[i] = GNUNET_TESTBED_service_connect(ctx,
- peers[i],
- "cadet",
- &cadet_connect_cb,
- ctx,
- &cadet_connect_adapter,
- &cadet_disconnect_adapter,
- newctx);
- GNUNET_log(GNUNET_ERROR_TYPE_INFO,
- "op handle %p\n",
- ctx->ops[i]);
- }
- }
- /**
- * Run a test using the given name, configuration file and number of peers.
- * All cadet callbacks will receive the peer number (long) as the closure.
- *
- * @param testname Name of the test (for logging).
- * @param cfgfile 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 @a tmain.
- * @param connects Handler for incoming channels.
- * @param window_changes Handler for the window size change notification.
- * @param disconnects Cleaner for destroyed incoming channels.
- * @param handlers Message handlers.
- * @param ports Ports the peers offer, NULL-terminated.
- */
- void
- GNUNET_CADET_TEST_ruN(const char *testname,
- const char *cfgfile,
- unsigned int num_peers,
- GNUNET_CADET_TEST_AppMain tmain,
- void *tmain_cls,
- GNUNET_CADET_ConnectEventHandler connects,
- GNUNET_CADET_WindowSizeEventHandler window_changes,
- GNUNET_CADET_DisconnectEventHandler disconnects,
- struct GNUNET_MQ_MessageHandler *handlers,
- const struct GNUNET_HashCode **ports)
- {
- struct GNUNET_CADET_TEST_Context *ctx;
- ctx = GNUNET_new(struct GNUNET_CADET_TEST_Context);
- ctx->num_peers = num_peers;
- ctx->ops = GNUNET_new_array(num_peers,
- struct GNUNET_TESTBED_Operation *);
- ctx->cadets = GNUNET_new_array(num_peers,
- struct GNUNET_CADET_Handle *);
- ctx->app_main = tmain;
- ctx->app_main_cls = tmain_cls;
- ctx->connects = connects;
- ctx->window_changes = window_changes;
- ctx->disconnects = disconnects;
- ctx->handlers = GNUNET_MQ_copy_handlers(handlers);
- ctx->ports = ports;
- ctx->port_count = 0;
- while (NULL != ctx->ports[ctx->port_count])
- ctx->port_count++;
- GNUNET_TESTBED_test_run(testname,
- cfgfile,
- num_peers,
- 0LL, NULL, NULL,
- &cadet_test_run,
- ctx);
- }
- /* end of cadet_test_lib.c */
|