diff options
Diffstat (limited to 'src/mesh/test_mesh_regex.c')
-rw-r--r-- | src/mesh/test_mesh_regex.c | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/src/mesh/test_mesh_regex.c b/src/mesh/test_mesh_regex.c new file mode 100644 index 0000000..d7089da --- /dev/null +++ b/src/mesh/test_mesh_regex.c @@ -0,0 +1,444 @@ +/* + This file is part of GNUnet. + (C) 2012 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file mesh/test_mesh_regex.c + * + * @brief Test for regex announce / by_string connect. + * based on the 2dtorus testcase + */ +#include "platform.h" +#include "mesh_test_lib.h" +#include "gnunet_mesh_service.h" + +#define REMOVE_DIR GNUNET_YES +#define MESH_REGEX_PEERS 4 + +/** + * How long until we give up on connecting the peers? + */ +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) + +/** + * Time to wait for stuff that should be rather fast + */ +#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) + +/** + * Which strings have been found & connected. + */ +static int ok[MESH_REGEX_PEERS]; + +/** + * How many connects have happened. + */ +static int regex_peers; + +/** + * Total number of currently running peers. + */ +static unsigned long long peers_running; + +/** + * Task called to disconnect peers + */ +static GNUNET_SCHEDULER_TaskIdentifier disconnect_task; + +/** + * Task called to shutdown test. + */ +static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle; + +/** + * Mesh handle for connecting peer. + */ +static struct GNUNET_MESH_Handle *h1; + +/** + * Mesh handle for announcing peers. + */ +static struct GNUNET_MESH_Handle *h2[MESH_REGEX_PEERS]; + +/** + * Tunnel handles for announcing peer. + */ +static struct GNUNET_MESH_Tunnel *t[MESH_REGEX_PEERS]; + +/** + * Incoming tunnels for announcing peers. + */ +static struct GNUNET_MESH_Tunnel *incoming_t[MESH_REGEX_PEERS]; + +/** + * Test context (to shut down). + */ +struct GNUNET_MESH_TEST_Context *test_ctx; + +/** + * Regular expressions for the announces. + */ +static char *regexes[MESH_REGEX_PEERS] = {"(0|1)" + "(0|1)" + "23456789ABC", + + "0123456789A*BC", + + "1234567890123456789012340*123456789ABC*", + + "GNUNETVPN0001000IPEX401110011101100100000111(0|1)*"}; + + +/** + * Service strings to look for. + */ +static char *strings[MESH_REGEX_PEERS] = {"1123456789ABC", + + "0123456789AABC", + + "12345678901234567890123400123456789ABCCCC", + + "GNUNETVPN0001000IPEX401110011101100100000111"}; + + + +/** + * Task to run for shutdown: stops peers, ends test. + * + * @param cls Closure (not used). + * @param tc TaskContext. + * + */ +static void +shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Ending test.\n"); + shutdown_handle = GNUNET_SCHEDULER_NO_TASK; +} + + +/** + * Ends test: Disconnects peers and calls shutdown. + * @param cls Closure (not used). + * @param tc TaskContext. + */ +static void +disconnect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + unsigned int i; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: disconnecting peers\n"); + + for (i = 0; i < MESH_REGEX_PEERS; i++) + { + GNUNET_MESH_tunnel_destroy (t[i]); + } + if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle) + { + GNUNET_SCHEDULER_cancel (shutdown_handle); + } + GNUNET_MESH_TEST_cleanup (test_ctx); + shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); +} + +/** + * Function called whenever an inbound tunnel is destroyed. Should clean up + * any associated state. + * + * @param cls closure (set from GNUNET_MESH_connect) + * @param tunnel connection to the other end (henceforth invalid) + * @param tunnel_ctx place where local state associated + * with the tunnel is stored + */ +static void +tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, + void *tunnel_ctx) +{ + long i = (long) cls; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Incoming tunnel disconnected at peer %d\n", + i); + return; +} + + +/** + * Method called whenever a tunnel falls apart. + * + * @param cls closure + * @param peer peer identity the tunnel stopped working with + */ +static void +dh (void *cls, const struct GNUNET_PeerIdentity *peer) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "peer %s disconnected\n", + GNUNET_i2s (peer)); + return; +} + +/** + * Function called to notify a client about the connection + * begin ready to queue more data. "buf" will be + * NULL and "size" zero if the connection was closed for + * writing in the meantime. + * + * @param cls closure + * @param size number of bytes available in buf + * @param buf where the callee should write the message + * @return number of bytes written to buf + */ +static size_t +data_ready (void *cls, size_t size, void *buf) +{ + struct GNUNET_MessageHeader *m = buf; + + if (NULL == buf || size < sizeof(struct GNUNET_MessageHeader)) + return 0; + m->type = htons (1); + m->size = htons (sizeof(struct GNUNET_MessageHeader)); + return sizeof(struct GNUNET_MessageHeader); +} + +/** + * Method called whenever a peer connects to a tunnel. + * + * @param cls closure + * @param peer peer identity the tunnel was created to, NULL on timeout + * @param atsi performance data for the connection + */ +static void +ch (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_ATS_Information *atsi) +{ + long i = (long) cls; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Peer connected: %s\n", + GNUNET_i2s (peer)); + regex_peers++; + + GNUNET_MESH_notify_transmit_ready(t[i], GNUNET_NO, + GNUNET_TIME_UNIT_FOREVER_REL, + peer, + sizeof(struct GNUNET_MessageHeader), + &data_ready, NULL); +} + +/** + * Method called whenever another peer has added us to a tunnel + * the other peer initiated. + * + * @param cls closure + * @param tunnel new handle to the tunnel + * @param initiator peer that started the tunnel + * @param atsi performance information for the tunnel + * @return initial tunnel context for the tunnel + * (can be NULL -- that's not an error) + */ +static void * +incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, + const struct GNUNET_PeerIdentity *initiator, + const struct GNUNET_ATS_Information *atsi) +{ + long i = (long) cls; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Incoming tunnel from %s to peer %d\n", + GNUNET_i2s (initiator), i); + if ( (i >= 10L) && (i < 10L + MESH_REGEX_PEERS)) + { + incoming_t[i - 10L] = tunnel; + ok[i - 10L] = GNUNET_OK; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Incoming tunnel for unknown client %lu\n", (long) cls); + } + if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) + { + GNUNET_SCHEDULER_cancel (disconnect_task); + disconnect_task = + GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_peers, NULL); + } + return NULL; +} + +/** + * Function is called whenever a message is received. + * + * @param cls closure (set from GNUNET_MESH_connect) + * @param tunnel connection to the other end + * @param tunnel_ctx place to store local state associated with the tunnel + * @param sender who sent the message + * @param message the actual message + * @param atsi performance data for the connection + * @return GNUNET_OK to keep the connection open, + * GNUNET_SYSERR to close it (signal serious error) + */ +int +data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, + const struct GNUNET_PeerIdentity *sender, + const struct GNUNET_MessageHeader *message, + const struct GNUNET_ATS_Information *atsi) +{ + unsigned int i; + long peer_number = (long) cls; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got data on peer %ld!\n", peer_number); + for (i = 0; i < MESH_REGEX_PEERS; i++) + { + if (GNUNET_OK != ok[i]) { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "data from peer %u still missing!\n", i + 10); + return GNUNET_OK; + } + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "test: EVERYONE GOT DATA, FINISHING!\n"); + if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) + { + GNUNET_SCHEDULER_cancel (disconnect_task); + } + disconnect_task = + GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL); + return GNUNET_OK; +} + +/** + * Handlers, for diverse services + */ +static struct GNUNET_MESH_MessageHandler handlers[] = { + {&data_callback, 1, sizeof (struct GNUNET_MessageHeader)}, + {NULL, 0, 0} +}; + + +/** + * test main: start test when all peers are connected + * + * @param cls Closure. + * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end. + * @param num_peers Number of peers that are running. + * @param peers Array of peers. + * @param meshes Handle to each of the MESHs of the peers. + */ +static void +tmain (void *cls, + struct GNUNET_MESH_TEST_Context *ctx, + unsigned int num_peers, + struct GNUNET_TESTBED_Peer **peers, + struct GNUNET_MESH_Handle **meshes) +{ + unsigned int i; + + shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, + &shutdown_task, NULL); + test_ctx = ctx; + if (16 != num_peers) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "running peers mismatch, aborting test!\n"); + GNUNET_MESH_TEST_cleanup (ctx); + return; + } + peers_running = num_peers; + disconnect_task = + GNUNET_SCHEDULER_add_delayed (TIMEOUT, &disconnect_peers, NULL); + +// h1 = GNUNET_MESH_connect (d->cfg, (void *) 1L, +// NULL, +// NULL, +// handlers, +// &app); + h1 = meshes[0]; + regex_peers = 0; + for (i = 0; i < MESH_REGEX_PEERS; i++) + { + ok[i] = GNUNET_NO; +// h2[i] = GNUNET_MESH_connect (d->cfg, (void *) (long) (i + 2), +// &incoming_tunnel, +// &tunnel_cleaner, +// handlers, +// &app); + h2[i] = meshes[10 + i]; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Announce REGEX %u: %s\n", i, regexes[i]); + GNUNET_MESH_announce_regex (h2[i], regexes[i], 1); + } + + for (i = 0; i < MESH_REGEX_PEERS; i++) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Create tunnel\n"); + t[i] = GNUNET_MESH_tunnel_create (h1, NULL, &ch, &dh, (void *) (long) i); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Connect by string %s\n", strings[i]); + GNUNET_MESH_peer_request_connect_by_string (t[i], strings[i]); + } + /* connect handler = success, timeout = error */ + +} + + +/** + * Main: start test + */ +int +main (int argc, char *argv[]) +{ + int result; + unsigned int i; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Start\n"); + + GNUNET_MESH_TEST_run ("test_mesh_regex", + "test_mesh_2dtorus.conf", + 16, + &tmain, + NULL, + &incoming_tunnel, + &tunnel_cleaner, + handlers, + NULL); + + result = GNUNET_OK; + for (i = 0; i < MESH_REGEX_PEERS; i++) + { + if (GNUNET_OK != ok[i]) + { + result = GNUNET_SYSERR; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "COULD NOT CONNECT TO %u: %s!\n", + i, strings[i]); + } + } + if (GNUNET_OK != result || regex_peers != MESH_REGEX_PEERS) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "FAILED! %u connected peers\n", + regex_peers); + return 1; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "success :)\n"); + return 0; +} + +/* end of test_mesh_regex.c */ |