/* This file is part of GNUnet. Copyright (C) 2009, 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 nse/test_nse_multipeer.c * @brief Testcase for the network size estimation service. Starts * a peergroup with a given number of peers, then waits to * receive size estimates from each peer. Expects to wait * for one message from each peer. */ #include "platform.h" #include "gnunet_testbed_service.h" #include "gnunet_nse_service.h" /** * How many peers do we start? */ #define NUM_PEERS 4 /** * How long do we run the test? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) /** * Information we track for each peer. */ struct NSEPeer { /** * Handle for NSE connect operation. */ struct GNUNET_TESTBED_Operation *op; /** * Handle to NSE service. */ struct GNUNET_NSE_Handle *nse_handle; }; /** * Information for all the peers. */ static struct NSEPeer nse_peers[NUM_PEERS]; /** * Return value from 'main'. */ static int ok; /** * Task run on timeout to shut everything down. */ static void shutdown_task (void *cls) { unsigned int i; for (i = 0; i < NUM_PEERS; i++) GNUNET_TESTBED_operation_done (nse_peers[i].op); GNUNET_SCHEDULER_shutdown (); } /** * Callback to call when network size estimate is updated. * * @param cls closure * @param timestamp server timestamp * @param estimate the value of the current network size estimate * @param std_dev standard deviation (rounded down to nearest integer) * of the size estimation values seen * */ static void handle_estimate (void *cls, struct GNUNET_TIME_Absolute timestamp, double estimate, double std_dev) { struct NSEPeer *peer = cls; fprintf (stderr, "Received network size estimate from peer %u. logSize: %f std.dev. %f (%f/%u)\n", (unsigned int) (peer - nse_peers), estimate, std_dev, GNUNET_NSE_log_estimate_to_n (estimate), NUM_PEERS); ok = 0; } /** * Callback to be called when NSE 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 NSE service handle returned from nse_connect_adapter * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void nse_connect_complete_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { struct NSEPeer *peer = cls; struct GNUNET_NSE_Handle *nse = ca_result; GNUNET_assert (op == peer->op); if (NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to NSE service: %s\n", emsg); ok = 1; GNUNET_SCHEDULER_shutdown (); return; } peer->nse_handle = nse; } /** * Adapter function called to establish a connection to * the NSE 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 * nse_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { return GNUNET_NSE_connect (cfg, &handle_estimate, cls); } /** * Adapter function called to destroy connection to * NSE service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void nse_disconnect_adapter (void *cls, void *op_result) { GNUNET_NSE_disconnect (op_result); } /** * Actual "main" function for the 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 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) { unsigned int i; GNUNET_assert (NUM_PEERS == num_peers); for (i = 0; i < num_peers; i++) nse_peers[i].op = GNUNET_TESTBED_service_connect (&nse_peers[i], peers[i], "nse", &nse_connect_complete_cb, &nse_peers[i], &nse_connect_adapter, &nse_disconnect_adapter, &nse_peers[i]); GNUNET_SCHEDULER_add_delayed (TIMEOUT, &shutdown_task, NULL); } /** * Entry point for the testcase, sets up the testbed. * * @param argc unused * @param argv unused * @return 0 on success */ int main (int argc, char *argv[]) { ok = 1; (void) GNUNET_TESTBED_test_run ("test-nse-multipeer", "test_nse.conf", NUM_PEERS, 0, NULL, NULL, &run, NULL); return ok; } /* end of test_nse_multipeer.c */