123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797 |
- /*
- This file is part of GNUnet.
- Copyright (C) 2009, 2018 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 transport/test_plugin_transport.c
- * @brief testcase for transport_api.c
- * @author Sailor Siraj
- * @author Christian Grothoff
- */
- #include "platform.h"
- #include "gnunet_util_lib.h"
- #include "gnunet_hello_lib.h"
- #include "gnunet_peerinfo_service.h"
- #include "gnunet_statistics_service.h"
- #include "gnunet_protocols.h"
- #include "gnunet_transport_plugin.h"
- #include "transport.h"
- /**
- * How long until we give up on transmitting the message?
- */
- #define WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
- #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
- #define HOSTKEY_FILE "test_plugin_hostkey.ecc"
- /**
- * Our public key.
- */
- static struct GNUNET_PeerIdentity my_identity;
- /**
- * Our private key.
- */
- static struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key;
- /**
- * Our configuration.
- */
- const struct GNUNET_CONFIGURATION_Handle *cfg;
- /**
- * Our configuration.
- */
- struct GNUNET_STATISTICS_Handle *stats;
- /**
- * Our HELLO
- */
- struct GNUNET_HELLO_Message *hello;
- /**
- * Number of neighbours we'd like to have.
- */
- static uint32_t max_connect_per_transport;
- /**
- * Environment for this plugin.
- */
- struct GNUNET_TRANSPORT_PluginEnvironment env;
- /**
- * handle for the api provided by this plugin
- */
- struct GNUNET_TRANSPORT_PluginFunctions *api;
- /**
- * Helper handler
- */
- struct GNUNET_HELPER_Handle *suid_helper;
- /**
- * Timeout task
- */
- static struct GNUNET_SCHEDULER_Task *timeout_endbadly;
- /**
- * Timeout task
- */
- static struct GNUNET_SCHEDULER_Task *timeout_wait;
- /**
- * Library name
- */
- static char *libname;
- /**
- * Plugin addresses head
- */
- struct AddressWrapper *head;
- /**
- * Plugin addresses tail
- */
- struct AddressWrapper *tail;
- unsigned int addresses_reported;
- unsigned int pretty_printers_running;
- /**
- * Did the test pass or fail?
- */
- static int ok;
- struct AddressWrapper
- {
- struct AddressWrapper *next;
- struct AddressWrapper *prev;
- struct GNUNET_HELLO_Address *address;
- char *addrstring;
- struct GNUNET_SCHEDULER_Task *test_task;
- };
- static void
- end ()
- {
- struct AddressWrapper *w;
- int c = 0;
- ok = 0;
- if (NULL != timeout_endbadly)
- {
- GNUNET_SCHEDULER_cancel (timeout_endbadly);
- timeout_endbadly = NULL;
- }
- if (NULL != api)
- GNUNET_PLUGIN_unload (libname, api);
- while (NULL != head)
- {
- w = head;
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Plugin did not remove address `%s'\n",
- w->addrstring);
- GNUNET_CONTAINER_DLL_remove (head, tail, w);
- c++;
- GNUNET_HELLO_address_free (w->address);
- GNUNET_free (w->addrstring);
- GNUNET_free (w);
- }
- if (c > 0)
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Plugin did not remove %u addresses \n",
- c);
- ok = 1;
- }
- GNUNET_free (libname);
- libname = NULL;
- GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
- stats = NULL;
- if (NULL != suid_helper)
- {
- GNUNET_HELPER_stop (suid_helper, GNUNET_NO);
- suid_helper = NULL;
- }
- }
- static void
- end_badly (void *cls)
- {
- struct AddressWrapper *w;
- int c = 0;
- timeout_endbadly = NULL;
- if (NULL != timeout_wait)
- {
- GNUNET_SCHEDULER_cancel (timeout_wait);
- timeout_wait = NULL;
- }
- if (pretty_printers_running > 0)
- {
- timeout_endbadly = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
- &end_badly, &ok);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Have pending calls to pretty_printer ... deferring shutdown\n");
- return;
- }
- if (NULL != cls)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Test took too long to execute, timeout .... \n");
- }
- if (NULL != libname)
- {
- if (NULL != api)
- GNUNET_PLUGIN_unload (libname, api);
- GNUNET_free (libname);
- libname = NULL;
- }
- while (NULL != head)
- {
- w = head;
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Plugin did not remove address `%s'\n",
- w->addrstring);
- GNUNET_CONTAINER_DLL_remove (head, tail, w);
- c++;
- GNUNET_HELLO_address_free (w->address);
- if (NULL != w->test_task)
- GNUNET_SCHEDULER_cancel (w->test_task);
- GNUNET_free (w->addrstring);
- GNUNET_free (w);
- }
- if (c > 0)
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Plugin did not remove %u addresses\n",
- c);
- }
- if (NULL != stats)
- {
- GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
- stats = NULL;
- }
- if (NULL != suid_helper)
- {
- GNUNET_HELPER_stop (suid_helper, GNUNET_NO);
- suid_helper = NULL;
- }
- ok = 1;
- }
- static void
- wait_end (void *cls)
- {
- timeout_wait = NULL;
- if (0 == addresses_reported)
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Plugin did not report any addresses, could not check address conversion functions\n");
- end ();
- }
- static void
- end_badly_now ()
- {
- if (NULL != timeout_wait)
- {
- GNUNET_SCHEDULER_cancel (timeout_wait);
- timeout_wait = NULL;
- }
- if (NULL != timeout_endbadly)
- {
- GNUNET_SCHEDULER_cancel (timeout_endbadly);
- timeout_endbadly = NULL;
- }
- timeout_endbadly = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
- }
- static struct GNUNET_TIME_Relative
- env_receive (void *cls,
- const struct GNUNET_HELLO_Address *address,
- struct GNUNET_ATS_Session *session,
- const struct GNUNET_MessageHeader *message)
- {
- /* do nothing */
- return GNUNET_TIME_relative_get_zero_ ();
- }
- static int got_reply;
- /**
- * Take the given address and append it to the set of results sent back to
- * the client.
- *
- * @param cls closure
- * @param address the address to print
- * @param res result code
- */
- static void
- address_pretty_printer_cb (void *cls, const char *address, int res)
- {
- if (NULL != address)
- {
- got_reply = GNUNET_YES;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Pretty address : `%s'\n", address);
- pretty_printers_running--;
- }
- else
- {
- if (GNUNET_NO == got_reply)
- {
- pretty_printers_running--;
- GNUNET_break (0);
- end_badly_now ();
- }
- }
- }
- static void
- test_addr_string (void *cls)
- {
- struct AddressWrapper *w = cls;
- void *s2a;
- size_t s2a_len;
- w->test_task = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Testing: address_to_string \n");
- w->addrstring = GNUNET_strdup (api->address_to_string (api,
- w->address->address,
- w->address->
- address_length));
- if (NULL == w->addrstring)
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Plugin cannot convert address to string!\n");
- end_badly_now ();
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Plugin added address `%s'\n",
- w->addrstring);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Testing address_to_string: OK\n");
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Testing: string_to_address \n");
- s2a = NULL;
- s2a_len = 0;
- if ((GNUNET_OK !=
- api->string_to_address (api, w->addrstring,
- strlen (w->addrstring) + 1,
- &s2a, &s2a_len)) ||
- (NULL == s2a))
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Plugin cannot convert string to address!\n");
- end_badly_now ();
- return;
- }
- /*
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Plugin creates `%s' %u\n",api->address_to_string (api, s2a, s2a_len), s2a_len);
- int c1;
- for (c1 = 0; c1 < s2a_len; c1++ )
- fprintf (stderr, "%u == %u\n", ((char *) s2a)[c1], ((char *) w->addr)[c1]);
- */if (s2a_len != w->address->address_length)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Plugin creates different address length when converting address->string->address: %u != %u\n",
- (unsigned int) w->address->address_length,
- (unsigned int) s2a_len);
- }
- else if (0 != memcmp (s2a, w->address->address, s2a_len))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Plugin creates different address length when converting back and forth %i!\n",
- memcmp (s2a,
- w->address->address,
- s2a_len));
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Testing string_to_address: OK\n");
- }
- GNUNET_free (s2a);
- pretty_printers_running++;
- api->address_pretty_printer (api->cls,
- w->address->transport_name,
- w->address->address,
- w->address->address_length,
- GNUNET_YES,
- GNUNET_TIME_UNIT_MINUTES,
- &address_pretty_printer_cb, w);
- if (GNUNET_OK !=
- api->check_address (api->cls,
- w->address->address,
- w->address->address_length))
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Plugin refuses added address!\n");
- end_badly_now ();
- return;
- }
- if (NULL != timeout_wait)
- {
- GNUNET_SCHEDULER_cancel (timeout_wait);
- timeout_wait = NULL;
- }
- timeout_wait = GNUNET_SCHEDULER_add_delayed (WAIT, &wait_end, NULL);
- }
- static void
- env_notify_address (void *cls,
- int add_remove,
- const struct GNUNET_HELLO_Address *address)
- {
- struct AddressWrapper *w;
- struct AddressWrapper *wtmp;
- if (GNUNET_YES == add_remove)
- {
- addresses_reported++;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Adding address of length %u\n",
- (unsigned int) address->address_length);
- for (wtmp = head; NULL != wtmp; wtmp = wtmp->next)
- {
- if ((address->address_length == wtmp->address->address_length) &&
- (0 == memcmp (address->address, wtmp->address->address,
- address->address_length)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Duplicate address notification .... \n");
- return;
- }
- }
- w = GNUNET_new (struct AddressWrapper);
- w->address = GNUNET_HELLO_address_copy (address);
- GNUNET_CONTAINER_DLL_insert (head, tail, w);
- got_reply = GNUNET_NO;
- w->test_task = GNUNET_SCHEDULER_add_now (&test_addr_string,
- w);
- return;
- }
- if (GNUNET_NO == add_remove)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Removing address of length %u\n",
- (unsigned int) address->address_length);
- w = head;
- while (NULL != w)
- {
- if ((address->address_length == w->address->address_length) &&
- (0 == memcmp (w->address->address, address->address,
- address->address_length)))
- {
- break;
- }
- w = w->next;
- }
- if (w == NULL)
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Plugin removes address never added!\n");
- end_badly_now ();
- return;
- }
- GNUNET_CONTAINER_DLL_remove (head, tail, w);
- GNUNET_HELLO_address_free (w->address);
- GNUNET_free (w->addrstring);
- GNUNET_free (w);
- return;
- }
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Invalid operation: %u\n",
- add_remove);
- end_badly_now ();
- }
- static enum GNUNET_NetworkType
- env_get_address_type (void *cls,
- const struct sockaddr *addr,
- size_t addrlen)
- {
- return GNUNET_NT_LOOPBACK;
- }
- static const struct GNUNET_MessageHeader *
- env_get_our_hello ()
- {
- return (const struct GNUNET_MessageHeader *) hello;
- }
- static void
- env_session_end (void *cls,
- const struct GNUNET_HELLO_Address *address,
- struct GNUNET_ATS_Session *session)
- {
- }
- static void
- env_update_distance (void *cls,
- const struct GNUNET_HELLO_Address *address,
- uint32_t distance)
- {
- }
- static void
- setup_plugin_environment ()
- {
- env.cfg = cfg;
- env.cls = &env;
- env.my_identity = &my_identity;
- env.max_connections = max_connect_per_transport;
- env.stats = stats;
- env.receive = &env_receive;
- env.notify_address = &env_notify_address;
- env.get_address_type = &env_get_address_type;
- env.update_address_distance = &env_update_distance;
- env.get_our_hello = &env_get_our_hello;
- env.session_end = &env_session_end;
- }
- static int
- handle_helper_message (void *cls,
- const struct GNUNET_MessageHeader *hdr)
- {
- return GNUNET_OK;
- }
- /**
- * Runs the test.
- *
- * @param cls closure
- * @param c configuration to use
- */
- static void
- run (void *cls,
- char *const *args,
- const char *cfgfile,
- const struct GNUNET_CONFIGURATION_Handle *c)
- {
- char *const *argv = cls;
- unsigned long long tneigh;
- char *keyfile;
- char *plugin;
- char *sep;
- timeout_endbadly = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
- &end_badly,
- &ok);
- cfg = c;
- /* parse configuration */
- if ((GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (c,
- "TRANSPORT",
- "NEIGHBOUR_LIMIT",
- &tneigh)) ||
- (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (c,
- "PEER",
- "PRIVATE_KEY",
- &keyfile)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Transport service is lacking key configuration settings. Exiting.\n");
- return;
- }
- if (NULL == (stats = GNUNET_STATISTICS_create ("transport",
- cfg)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Could not create statistics. Exiting.\n");
- GNUNET_free (keyfile);
- end_badly_now ();
- return;
- }
- if (GNUNET_OK != GNUNET_DISK_file_test (HOSTKEY_FILE))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Hostkey `%s' missing. Exiting.\n",
- HOSTKEY_FILE);
- GNUNET_free (keyfile);
- end_badly_now ();
- return;
- }
- if (GNUNET_OK !=
- GNUNET_DISK_directory_create_for_file (keyfile))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Could not create a directory for hostkey `%s'. Exiting.\n",
- keyfile);
- GNUNET_free (keyfile);
- end_badly_now ();
- return;
- }
- if (GNUNET_OK !=
- GNUNET_DISK_file_copy (HOSTKEY_FILE,
- keyfile))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Could not copy hostkey `%s' to destination `%s'. Exiting.\n",
- HOSTKEY_FILE,
- keyfile);
- GNUNET_free (keyfile);
- end_badly_now ();
- return;
- }
- max_connect_per_transport = (uint32_t) tneigh;
- if (GNUNET_SYSERR ==
- GNUNET_CRYPTO_eddsa_key_from_file (keyfile,
- GNUNET_YES,
- &my_private_key))
- {
- GNUNET_free (keyfile);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Could not access hostkey. Exiting.\n");
- end_badly_now ();
- return;
- }
- GNUNET_free (keyfile);
- GNUNET_CRYPTO_eddsa_key_get_public (&my_private_key,
- &my_identity.public_key);
- hello = GNUNET_HELLO_create (&my_identity.public_key, NULL, NULL, GNUNET_NO);
- /* load plugins... */
- setup_plugin_environment ();
- GNUNET_assert (strlen (argv[0]) > strlen ("test_plugin_"));
- plugin = strstr (argv[0], "test_plugin_");
- sep = strrchr (argv[0], '.');
- if (NULL == plugin)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Not a valid test name\n");
- end_badly_now ();
- return;
- }
- plugin += strlen ("test_plugin_");
- if (NULL != sep)
- sep[0] = '\0';
- /* Hack for WLAN: start a second helper */
- if (0 == strcmp (plugin, "wlan"))
- {
- char *helper_argv[3];
- helper_argv[0] = (char *) "gnunet-helper-transport-wlan-dummy";
- helper_argv[1] = (char *) "2";
- helper_argv[2] = NULL;
- suid_helper = GNUNET_HELPER_start (GNUNET_NO,
- "gnunet-helper-transport-wlan-dummy",
- helper_argv,
- &handle_helper_message, NULL, NULL);
- }
- /* Loading plugin */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Loading transport plugin %s\n", plugin);
- GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", plugin);
- api = GNUNET_PLUGIN_load (libname, &env);
- if (NULL == api)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to load transport plugin for %s\n", plugin);
- end_badly_now ();
- return;
- }
- timeout_wait = GNUNET_SCHEDULER_add_delayed (WAIT, &wait_end, NULL);
- /* Check if all functions are implemented */
- if (NULL == api->address_pretty_printer)
- {
- GNUNET_break (0);
- end_badly_now ();
- return;
- }
- if (NULL == api->address_to_string)
- {
- GNUNET_break (0);
- end_badly_now ();
- return;
- }
- GNUNET_assert (NULL != api->check_address);
- if (NULL == api->check_address)
- {
- GNUNET_break (0);
- end_badly_now ();
- return;
- }
- GNUNET_assert (NULL != api->disconnect_peer);
- if (NULL == api->disconnect_peer)
- {
- GNUNET_break (0);
- end_badly_now ();
- return;
- }
- GNUNET_assert (NULL != api->get_session);
- if (NULL == api->get_session)
- {
- GNUNET_break (0);
- end_badly_now ();
- return;
- }
- if (NULL == api->address_pretty_printer)
- {
- GNUNET_break (0);
- end_badly_now ();
- return;
- }
- if (NULL == api->string_to_address)
- {
- GNUNET_break (0);
- end_badly_now ();
- return;
- }
- }
- /**
- * The main function for the test
- *
- * @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 struct GNUNET_GETOPT_CommandLineOption options[] = {
- GNUNET_GETOPT_OPTION_END
- };
- int ret;
- char *const argv_prog[] = {
- "test_plugin_transport",
- "-c",
- "test_plugin_transport_data.conf",
- NULL
- };
- GNUNET_log_setup ("test-plugin-transport",
- "WARNING",
- NULL);
- GNUNET_DISK_purge_cfg_dir ("test_plugin_transport_data.conf",
- "GNUNET_TEST_HOME");
- ok = 1; /* set to fail */
- ret =
- (GNUNET_OK
- == GNUNET_PROGRAM_run (3, argv_prog, "test-plugin-transport",
- "testcase", options, &run, (void *) argv)) ? ok : 1;
- GNUNET_DISK_purge_cfg_dir ("test_plugin_transport_data.conf",
- "GNUNET_TEST_HOME");
- return ret;
- }
- /* end of test_plugin_transport.c */
|