2 This file is part of GNUnet.
3 Copyright (C) 2009, 2018 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
16 * @file transport/test_plugin_transport.c
17 * @brief testcase for transport_api.c
18 * @author Sailor Siraj
19 * @author Christian Grothoff
23 #include "gnunet_util_lib.h"
24 #include "gnunet_hello_lib.h"
25 #include "gnunet_peerinfo_service.h"
26 #include "gnunet_statistics_service.h"
27 #include "gnunet_protocols.h"
28 #include "gnunet_transport_plugin.h"
29 #include "transport.h"
32 * How long until we give up on transmitting the message?
34 #define WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
35 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
37 #define HOSTKEY_FILE "test_plugin_hostkey.ecc"
42 static struct GNUNET_PeerIdentity my_identity;
47 static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
52 const struct GNUNET_CONFIGURATION_Handle *cfg;
57 struct GNUNET_STATISTICS_Handle *stats;
62 struct GNUNET_HELLO_Message *hello;
65 * Number of neighbours we'd like to have.
67 static uint32_t max_connect_per_transport;
70 * Environment for this plugin.
72 struct GNUNET_TRANSPORT_PluginEnvironment env;
75 *handle for the api provided by this plugin
77 struct GNUNET_TRANSPORT_PluginFunctions *api;
82 struct GNUNET_HELPER_Handle *suid_helper;
87 static struct GNUNET_SCHEDULER_Task * timeout_endbadly;
92 static struct GNUNET_SCHEDULER_Task * timeout_wait;
100 * Plugin addresses head
102 struct AddressWrapper *head;
105 * Plugin addresses tail
107 struct AddressWrapper *tail;
109 unsigned int addresses_reported;
111 unsigned int pretty_printers_running;
114 * Did the test pass or fail?
118 struct AddressWrapper
120 struct AddressWrapper *next;
122 struct AddressWrapper *prev;
124 struct GNUNET_HELLO_Address *address;
128 struct GNUNET_SCHEDULER_Task *test_task;
136 struct AddressWrapper *w;
140 if (NULL != timeout_endbadly)
142 GNUNET_SCHEDULER_cancel (timeout_endbadly);
143 timeout_endbadly = NULL;
146 GNUNET_PLUGIN_unload (libname, api);
151 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
152 "Plugin did not remove address `%s'\n",
154 GNUNET_CONTAINER_DLL_remove(head, tail, w);
156 GNUNET_HELLO_address_free(w->address);
157 GNUNET_free(w->addrstring);
163 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Plugin did not remove %u addresses \n",
168 GNUNET_free(libname);
170 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
173 if (NULL != suid_helper)
175 GNUNET_HELPER_stop (suid_helper, GNUNET_NO);
182 end_badly (void *cls)
184 struct AddressWrapper *w;
187 timeout_endbadly = NULL;
188 if (NULL != timeout_wait)
190 GNUNET_SCHEDULER_cancel (timeout_wait);
194 if (pretty_printers_running > 0)
196 timeout_endbadly = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
198 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
199 "Have pending calls to pretty_printer ... deferring shutdown\n");
205 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
206 "Test took too long to execute, timeout .... \n");
212 GNUNET_PLUGIN_unload (libname, api);
213 GNUNET_free(libname);
220 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Plugin did not remove address `%s'\n",
222 GNUNET_CONTAINER_DLL_remove(head, tail, w);
224 GNUNET_HELLO_address_free(w->address);
225 if (NULL != w->test_task)
226 GNUNET_SCHEDULER_cancel (w->test_task);
227 GNUNET_free(w->addrstring);
233 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Plugin did not remove %u addresses\n",
239 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
243 if (NULL != suid_helper)
245 GNUNET_HELPER_stop (suid_helper, GNUNET_NO);
256 if (0 == addresses_reported)
257 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
258 "Plugin did not report any addresses, could not check address conversion functions\n");
266 if (NULL != timeout_wait)
268 GNUNET_SCHEDULER_cancel (timeout_wait);
271 if (NULL != timeout_endbadly)
273 GNUNET_SCHEDULER_cancel (timeout_endbadly);
274 timeout_endbadly = NULL;
276 timeout_endbadly = GNUNET_SCHEDULER_add_now (&end_badly, NULL );
280 static struct GNUNET_TIME_Relative
281 env_receive (void *cls,
282 const struct GNUNET_HELLO_Address *address,
283 struct GNUNET_ATS_Session *session,
284 const struct GNUNET_MessageHeader *message)
287 return GNUNET_TIME_relative_get_zero_ ();
290 static int got_reply;
294 * Take the given address and append it to the set of results sent back to
298 * @param address the address to print
299 * @param res result code
302 address_pretty_printer_cb (void *cls, const char *address, int res)
306 got_reply = GNUNET_YES;
307 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Pretty address : `%s'\n", address);
308 pretty_printers_running--;
312 if (GNUNET_NO == got_reply)
314 pretty_printers_running--;
323 test_addr_string (void *cls)
325 struct AddressWrapper *w = cls;
331 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
332 "Testing: address_to_string \n");
333 w->addrstring = GNUNET_strdup (api->address_to_string (api,
335 w->address->address_length));
336 if (NULL == w->addrstring)
339 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
340 "Plugin cannot convert address to string!\n");
344 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
345 "Plugin added address `%s'\n",
347 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
348 "Testing address_to_string: OK\n");
349 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
350 "Testing: string_to_address \n");
354 api->string_to_address (api, w->addrstring,
355 strlen (w->addrstring) + 1,
360 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
361 "Plugin cannot convert string to address!\n");
367 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
368 "Plugin creates `%s' %u\n",api->address_to_string (api, s2a, s2a_len), s2a_len);
371 for (c1 = 0; c1 < s2a_len; c1++ )
372 fprintf (stderr, "%u == %u\n", ((char *) s2a)[c1], ((char *) w->addr)[c1]);
374 if (s2a_len != w->address->address_length)
376 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
377 "Plugin creates different address length when converting address->string->address: %u != %u\n",
378 (unsigned int) w->address->address_length,
379 (unsigned int) s2a_len);
381 else if (0 != memcmp (s2a, w->address->address, s2a_len))
383 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
384 "Plugin creates different address length when converting back and forth %i!\n",
391 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
392 "Testing string_to_address: OK\n");
396 pretty_printers_running++;
397 api->address_pretty_printer (api->cls,
398 w->address->transport_name,
400 w->address->address_length,
402 GNUNET_TIME_UNIT_MINUTES,
403 &address_pretty_printer_cb, w);
406 api->check_address (api->cls,
408 w->address->address_length))
411 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
412 "Plugin refuses added address!\n");
416 if (NULL != timeout_wait)
418 GNUNET_SCHEDULER_cancel (timeout_wait);
421 timeout_wait = GNUNET_SCHEDULER_add_delayed (WAIT, &wait_end, NULL);
426 env_notify_address (void *cls,
428 const struct GNUNET_HELLO_Address *address)
430 struct AddressWrapper *w;
431 struct AddressWrapper *wtmp;
433 if (GNUNET_YES == add_remove)
435 addresses_reported++;
436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
437 "Adding address of length %u\n",
438 (unsigned int) address->address_length);
440 for (wtmp = head; NULL != wtmp; wtmp = wtmp->next)
442 if ((address->address_length == wtmp->address->address_length) &&
443 (0 == memcmp (address->address, wtmp->address->address, address->address_length)))
445 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
446 "Duplicate address notification .... \n");
451 w = GNUNET_new (struct AddressWrapper);
452 w->address = GNUNET_HELLO_address_copy (address);
453 GNUNET_CONTAINER_DLL_insert (head, tail, w);
454 got_reply = GNUNET_NO;
455 w->test_task = GNUNET_SCHEDULER_add_now (&test_addr_string,
460 if (GNUNET_NO == add_remove)
462 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
463 "Removing address of length %u\n",
464 (unsigned int) address->address_length);
468 if ((address->address_length == w->address->address_length) &&
469 (0 == memcmp (w->address->address, address->address, address->address_length)))
479 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
480 "Plugin removes address never added!\n");
485 GNUNET_CONTAINER_DLL_remove(head, tail, w);
486 GNUNET_HELLO_address_free (w->address);
487 GNUNET_free(w->addrstring);
492 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
493 "Invalid operation: %u\n",
499 static enum GNUNET_ATS_Network_Type
500 env_get_address_type (void *cls,
501 const struct sockaddr *addr,
504 return GNUNET_ATS_NET_LOOPBACK;
508 static const struct GNUNET_MessageHeader *
511 return (const struct GNUNET_MessageHeader *) hello;
516 env_session_end (void *cls,
517 const struct GNUNET_HELLO_Address *address,
518 struct GNUNET_ATS_Session *session)
525 env_update_distance (void *cls,
526 const struct GNUNET_HELLO_Address *address,
533 setup_plugin_environment ()
537 env.my_identity = &my_identity;
538 env.max_connections = max_connect_per_transport;
540 env.receive = &env_receive;
541 env.notify_address = &env_notify_address;
542 env.get_address_type = &env_get_address_type;
543 env.update_address_distance = &env_update_distance;
544 env.get_our_hello = &env_get_our_hello;
545 env.session_end = &env_session_end;
550 handle_helper_message (void *cls,
551 const struct GNUNET_MessageHeader *hdr)
561 * @param c configuration to use
567 const struct GNUNET_CONFIGURATION_Handle *c)
569 char * const *argv = cls;
570 unsigned long long tneigh;
575 timeout_endbadly = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
579 /* parse configuration */
581 GNUNET_CONFIGURATION_get_value_number (c,
586 GNUNET_CONFIGURATION_get_value_filename (c,
591 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
592 "Transport service is lacking key configuration settings. Exiting.\n");
596 if (NULL == (stats = GNUNET_STATISTICS_create ("transport",
599 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
600 "Could not create statistics. Exiting.\n");
601 GNUNET_free(keyfile);
606 if (GNUNET_OK != GNUNET_DISK_file_test (HOSTKEY_FILE))
608 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
609 "Hostkey `%s' missing. Exiting.\n",
611 GNUNET_free(keyfile);
617 GNUNET_DISK_directory_create_for_file (keyfile))
619 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
620 "Could not create a directory for hostkey `%s'. Exiting.\n",
622 GNUNET_free(keyfile);
628 GNUNET_DISK_file_copy (HOSTKEY_FILE,
631 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
632 "Could not copy hostkey `%s' to destination `%s'. Exiting.\n",
635 GNUNET_free(keyfile);
640 max_connect_per_transport = (uint32_t) tneigh;
641 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile);
642 GNUNET_free(keyfile);
643 if (NULL == my_private_key)
645 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
646 "Could not access hostkey. Exiting.\n");
650 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_identity.public_key);
652 hello = GNUNET_HELLO_create (&my_identity.public_key, NULL, NULL, GNUNET_NO);
654 /* load plugins... */
655 setup_plugin_environment ();
657 GNUNET_assert(strlen (argv[0]) > strlen ("test_plugin_"));
658 plugin = strstr (argv[0], "test_plugin_");
659 sep = strrchr (argv[0], '.');
662 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Not a valid test name\n");
666 plugin += strlen ("test_plugin_");
670 /* Hack for WLAN: start a second helper */
671 if (0 == strcmp (plugin, "wlan"))
673 char * helper_argv[3];
674 helper_argv[0] = (char *) "gnunet-helper-transport-wlan-dummy";
675 helper_argv[1] = (char *) "2";
676 helper_argv[2] = NULL;
677 suid_helper = GNUNET_HELPER_start (GNUNET_NO,
678 "gnunet-helper-transport-wlan-dummy", helper_argv,
679 &handle_helper_message, NULL, NULL );
683 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Loading transport plugin %s\n", plugin);
684 GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", plugin);
685 api = GNUNET_PLUGIN_load (libname, &env);
688 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
689 "Failed to load transport plugin for %s\n", plugin);
694 timeout_wait = GNUNET_SCHEDULER_add_delayed (WAIT, &wait_end, NULL );
696 /* Check if all functions are implemented */
697 if (NULL == api->address_pretty_printer)
703 if (NULL == api->address_to_string)
709 GNUNET_assert(NULL != api->check_address);
710 if (NULL == api->check_address)
716 GNUNET_assert(NULL != api->disconnect_peer);
717 if (NULL == api->disconnect_peer)
723 GNUNET_assert(NULL != api->get_session);
724 if (NULL == api->get_session)
730 if (NULL == api->address_pretty_printer)
736 if (NULL == api->string_to_address)
746 * The main function for the test
748 * @param argc number of arguments from the command line
749 * @param argv command line arguments
750 * @return 0 ok, 1 on error
756 static struct GNUNET_GETOPT_CommandLineOption options[] = {
757 GNUNET_GETOPT_OPTION_END
760 char * const argv_prog[] = {
761 "test_plugin_transport",
763 "test_plugin_transport_data.conf",
767 GNUNET_log_setup ("test-plugin-transport",
770 GNUNET_DISK_purge_cfg_dir ("test_plugin_transport_data.conf",
772 ok = 1; /* set to fail */
775 == GNUNET_PROGRAM_run (3, argv_prog, "test-plugin-transport",
776 "testcase", options, &run, (void *) argv)) ? ok : 1;
777 GNUNET_DISK_purge_cfg_dir ("test_plugin_transport_data.conf",
782 /* end of test_plugin_transport.c */