From e0033c1da56e1889775d7dccf92ea78ee52e4d5c Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 9 Jun 2012 15:35:06 +0000 Subject: -moving old testing code to legacy location --- src/testing/Makefile.am | 267 +- src/testing/gnunet-testing-remote-peer-start.pl | 92 - src/testing/gnunet-testing.c | 291 - src/testing/helper.c | 75 - src/testing/test_testing.c | 126 - src/testing/test_testing_2dtorus.c | 372 -- src/testing/test_testing_2dtorus.conf | 81 - src/testing/test_testing_connect.c | 197 - src/testing/test_testing_connect_peer1.conf | 37 - src/testing/test_testing_connect_peer2.conf | 37 - src/testing/test_testing_data.conf | 7 - src/testing/test_testing_data_remote.conf | 12 - .../test_testing_data_topology_2d_torus.conf | 7 - .../test_testing_data_topology_blacklist.conf | 13 - src/testing/test_testing_data_topology_churn.conf | 10 - src/testing/test_testing_data_topology_clique.conf | 10 - .../test_testing_data_topology_clique_dfs.conf | 13 - .../test_testing_data_topology_clique_minimum.conf | 10 - .../test_testing_data_topology_clique_random.conf | 16 - .../test_testing_data_topology_erdos_renyi.conf | 7 - .../test_testing_data_topology_internat.conf | 7 - src/testing/test_testing_data_topology_none.conf | 37 - src/testing/test_testing_data_topology_ring.conf | 7 - .../test_testing_data_topology_scale_free.conf | 11 - ...est_testing_data_topology_small_world_ring.conf | 8 - ...st_testing_data_topology_small_world_torus.conf | 7 - .../test_testing_data_topology_stability.conf | 9 - src/testing/test_testing_defaults.conf | 78 - src/testing/test_testing_group.c | 166 - src/testing/test_testing_group_remote.c | 263 - src/testing/test_testing_large_topology.c | 1197 ---- src/testing/test_testing_peergroup.c | 157 - src/testing/test_testing_peergroup_data.conf | 22 - src/testing/test_testing_reconnect.c | 249 - src/testing/test_testing_topology.c | 1220 ---- src/testing/test_testing_topology_blacklist.c | 595 -- src/testing/test_testing_topology_churn.c | 322 - src/testing/testing.c | 2204 ------ src/testing/testing_group.c | 7038 -------------------- src/testing/testing_peergroup.c | 1017 --- 40 files changed, 6 insertions(+), 16288 deletions(-) delete mode 100755 src/testing/gnunet-testing-remote-peer-start.pl delete mode 100644 src/testing/gnunet-testing.c delete mode 100644 src/testing/helper.c delete mode 100644 src/testing/test_testing.c delete mode 100644 src/testing/test_testing_2dtorus.c delete mode 100644 src/testing/test_testing_2dtorus.conf delete mode 100644 src/testing/test_testing_connect.c delete mode 100644 src/testing/test_testing_connect_peer1.conf delete mode 100644 src/testing/test_testing_connect_peer2.conf delete mode 100644 src/testing/test_testing_data.conf delete mode 100644 src/testing/test_testing_data_remote.conf delete mode 100644 src/testing/test_testing_data_topology_2d_torus.conf delete mode 100644 src/testing/test_testing_data_topology_blacklist.conf delete mode 100644 src/testing/test_testing_data_topology_churn.conf delete mode 100644 src/testing/test_testing_data_topology_clique.conf delete mode 100644 src/testing/test_testing_data_topology_clique_dfs.conf delete mode 100644 src/testing/test_testing_data_topology_clique_minimum.conf delete mode 100644 src/testing/test_testing_data_topology_clique_random.conf delete mode 100644 src/testing/test_testing_data_topology_erdos_renyi.conf delete mode 100644 src/testing/test_testing_data_topology_internat.conf delete mode 100644 src/testing/test_testing_data_topology_none.conf delete mode 100644 src/testing/test_testing_data_topology_ring.conf delete mode 100644 src/testing/test_testing_data_topology_scale_free.conf delete mode 100644 src/testing/test_testing_data_topology_small_world_ring.conf delete mode 100644 src/testing/test_testing_data_topology_small_world_torus.conf delete mode 100644 src/testing/test_testing_data_topology_stability.conf delete mode 100644 src/testing/test_testing_defaults.conf delete mode 100644 src/testing/test_testing_group.c delete mode 100644 src/testing/test_testing_group_remote.c delete mode 100644 src/testing/test_testing_large_topology.c delete mode 100644 src/testing/test_testing_peergroup.c delete mode 100644 src/testing/test_testing_peergroup_data.conf delete mode 100644 src/testing/test_testing_reconnect.c delete mode 100644 src/testing/test_testing_topology.c delete mode 100644 src/testing/test_testing_topology_blacklist.c delete mode 100644 src/testing/test_testing_topology_churn.c delete mode 100644 src/testing/testing.c delete mode 100644 src/testing/testing_group.c delete mode 100644 src/testing/testing_peergroup.c (limited to 'src/testing') diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am index 455df6989..dcefc34d1 100644 --- a/src/testing/Makefile.am +++ b/src/testing/Makefile.am @@ -14,301 +14,46 @@ pkgcfgdir= $(pkgdatadir)/config.d/ dist_pkgcfg_DATA = \ testing.conf -if HAVE_EXPENSIVE_TESTS - EXPENSIVE_TESTS = \ - test_testing_topology_stability \ - test_testing_topology_clique_random \ - test_testing_topology_clique_minimum \ - test_testing_topology_clique_dfs \ - test_testing_topology_churn \ - test_testing_topology_line \ - test_testing_topology_blacklist \ - test_testing_group_remote \ - test_testing_topology_ring \ - test_testing_topology_2d_torus \ - test_testing_topology_small_world_ring \ - test_testing_topology_small_world_torus \ - test_testing_topology_erdos_renyi \ - test_testing_topology_internat \ - test_testing_topology_scale_free -endif - lib_LTLIBRARIES = \ - libgnunettesting.la \ - libgnunettesting_new.la + libgnunettesting.la libgnunettesting_la_SOURCES = \ - helper.c \ - testing.c \ - testing_group.c \ - testing_peergroup.c -libgnunettesting_la_LIBADD = $(XLIB) \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/transport/libgnunettransport.la \ - $(top_builddir)/src/hello/libgnunethello.la \ - -lm \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(LTLIBINTL) -libgnunettesting_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) \ - -version-info 0:1:0 - - -libgnunettesting_new_la_SOURCES = \ testing_new.c -libgnunettesting_new_la_LIBADD = \ +libgnunettesting_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) -libgnunettesting_new_la_LDFLAGS = \ +libgnunettesting_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:1:0 -bin_PROGRAMS = \ - gnunet-testing - check_PROGRAMS = \ - test_testing \ - test_testing_connect \ - test_testing_reconnect \ - test_testing_group \ - test_testing_peergroup \ - test_testing_topology_stability \ - test_testing_topology_clique \ - test_testing_topology_clique_random \ - test_testing_topology_clique_minimum \ - test_testing_topology_clique_dfs \ - test_testing_topology_churn \ - test_testing_topology_line \ - test_testing_topology_blacklist \ - test_testing_group_remote \ - test_testing_2dtorus \ - test_testing_topology_ring \ - test_testing_topology_2d_torus \ - test_testing_topology_small_world_ring \ - test_testing_topology_small_world_torus \ - test_testing_topology_erdos_renyi \ - test_testing_topology_internat \ - test_testing_topology_none \ - test_testing_topology_scale_free \ test_testing_new_portreservation \ test_testing_new_peerstartup \ test_testing_new_servicestartup if ENABLE_TEST_RUN TESTS = \ - test_testing \ - test_testing_connect \ - test_testing_reconnect \ - test_testing_group \ - test_testing_peergroup \ test_testing_new_portreservation \ test_testing_new_peerstartup \ test_testing_new_servicestartup endif -gnunet_testing_SOURCES = \ - gnunet-testing.c -gnunet_testing_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(GN_LIBINTL) -gnunet_testing_DEPENDENCIES = \ - libgnunettesting.la - - -test_testing_SOURCES = \ - test_testing.c -test_testing_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_connect_SOURCES = \ - test_testing_connect.c -test_testing_connect_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_reconnect_SOURCES = \ - test_testing_reconnect.c -test_testing_reconnect_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_group_SOURCES = \ - test_testing_group.c -test_testing_group_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_peergroup_SOURCES = \ - test_testing_peergroup.c -test_testing_peergroup_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_clique_SOURCES = \ - test_testing_topology.c -test_testing_topology_clique_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_stability_SOURCES = \ - test_testing_topology.c -test_testing_topology_stability_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_blacklist_SOURCES = \ - test_testing_topology_blacklist.c -test_testing_topology_blacklist_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_churn_SOURCES = \ - test_testing_topology_churn.c -test_testing_topology_churn_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_clique_random_SOURCES = \ - test_testing_topology.c -test_testing_topology_clique_random_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_clique_minimum_SOURCES = \ - test_testing_topology.c -test_testing_topology_clique_minimum_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_clique_dfs_SOURCES = \ - test_testing_topology.c -test_testing_topology_clique_dfs_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_line_SOURCES = \ - test_testing_topology.c -test_testing_topology_line_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - - -test_testing_group_remote_SOURCES = \ - test_testing_group_remote.c -test_testing_group_remote_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_2dtorus_SOURCES = \ - test_testing_2dtorus.c -test_testing_2dtorus_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_ring_SOURCES = \ - test_testing_topology.c -test_testing_topology_ring_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_2d_torus_SOURCES = \ - test_testing_topology.c -test_testing_topology_2d_torus_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_small_world_ring_SOURCES = \ - test_testing_topology.c -test_testing_topology_small_world_ring_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_small_world_torus_SOURCES = \ - test_testing_topology.c -test_testing_topology_small_world_torus_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_internat_SOURCES = \ - test_testing_topology.c -test_testing_topology_internat_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_erdos_renyi_SOURCES = \ - test_testing_topology.c -test_testing_topology_erdos_renyi_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_scale_free_SOURCES = \ - test_testing_topology.c -test_testing_topology_scale_free_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_testing_topology_none_SOURCES = \ - test_testing_topology.c -test_testing_topology_none_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/util/libgnunetutil.la - test_testing_new_portreservation_SOURCES = \ test_testing_new_portreservation.c test_testing_new_portreservation_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting_new.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_testing_new_peerstartup_SOURCES = \ test_testing_new_peerstartup.c test_testing_new_peerstartup_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting_new.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_testing_new_servicestartup_SOURCES = \ test_testing_new_servicestartup.c test_testing_new_servicestartup_LDADD = \ - $(top_builddir)/src/testing/libgnunettesting_new.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la -EXTRA_DIST = \ - test_testing_defaults.conf \ - test_testing_data.conf \ - test_testing_connect_peer1.conf \ - test_testing_connect_peer2.conf \ - test_testing_2dtorus.conf \ - test_testing_data_topology_clique.conf \ - test_testing_data_topology_clique_random.conf \ - test_testing_data_topology_clique_minimum.conf \ - test_testing_data_topology_clique_dfs.conf \ - test_testing_data_topology_ring.conf \ - test_testing_data_topology_2d_torus.conf \ - test_testing_data_topology_small_world_ring.conf \ - test_testing_data_topology_small_world_torus.conf \ - test_testing_data_topology_erdos_renyi.conf \ - test_testing_data_topology_internat.conf \ - test_testing_data_topology_scale_free.conf \ - test_testing_data_topology_blacklist.conf \ - test_testing_data_topology_churn.conf \ - test_testing_data_topology_none.conf \ - test_testing_data_remote.conf \ - test_testing_data_topology_stability.conf \ - test_testing_peergroup_data.conf diff --git a/src/testing/gnunet-testing-remote-peer-start.pl b/src/testing/gnunet-testing-remote-peer-start.pl deleted file mode 100755 index e4f72e9d0..000000000 --- a/src/testing/gnunet-testing-remote-peer-start.pl +++ /dev/null @@ -1,92 +0,0 @@ -# -# This file is part of GNUnet -# (C) 2008, 2009 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 contrib/peerStartHelper.pl -# @brief Helper process for starting gnunet-testing peers. -# @author Nathan Evans -# -# Finds configuration files (or any files) of the format -# /path/*/gnunet-testing-config* and runs gnunet-arm with -# each as the given configuration. -# -# usage: peerStartHelper.pl /path/to/testing_dir/ -#!/usr/bin/perl -use strict; - -my $max_outstanding = 300; - -$ARGV[0] || die "No directory provided for peer information, exiting!\n"; - -my $directory = $ARGV[0]; -my @config_files = `find $directory -iname gnunet-testing-config*`; -my @child_arr = {}; -my $count = 0; -my $outstanding = 0; -foreach my $file (@config_files) -{ - chomp($file); - #print "Starting GNUnet peer with config file $file\n"; - my $pid = fork(); - if ($pid == -1) - { - die; - } - elsif ($pid == 0) - { - exec "gnunet-arm -q -c $file -s" or die; - } - - if ($pid != 0) - { - push @child_arr, $pid; - $count++; - $outstanding++; - if ($outstanding > $max_outstanding) - { - for (my $i = 0; $i < $max_outstanding / 5; $i++) - { - #print "Too many outstanding peers, waiting!\n"; - waitpid($child_arr[0], 0); - shift(@child_arr); - $outstanding--; - } - } - } -} - -print "All $count peers started (waiting for them to finish!\n"; - -while ($outstanding > 0) -{ - waitpid($child_arr[0], 0); - shift(@child_arr); - $outstanding--; - if ($outstanding % 50 == 0) - { - print "All $count peers started (waiting for $outstanding to finish!\n"; - } -} - -while (wait() != -1) {sleep 1} - -print "All $count peers started!\n"; - - diff --git a/src/testing/gnunet-testing.c b/src/testing/gnunet-testing.c deleted file mode 100644 index bdbb5e8c5..000000000 --- a/src/testing/gnunet-testing.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 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 testing/gnunet-testing.c - * @brief tool to use testing functionality from cmd line - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_getopt_lib.h" -#include "gnunet_program_lib.h" -#include "gnunet_testing_lib.h" - -#define HOSTKEYFILESIZE 914 - -/** - * Final status code. - */ -static int ret; - -static unsigned int create_hostkey; - -static unsigned int create_cfg; - -static int create_no; - -static char * create_cfg_template; - -static char * create_hostkey_file; - -static int -create_unique_cfgs (const char * template, const unsigned int no) -{ - int fail = GNUNET_NO; - - uint16_t port = 20000; - uint32_t upnum = 1; - uint32_t fdnum = 1; - - if (GNUNET_NO == GNUNET_DISK_file_test(template)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Configuration template `%s': file not found\n", create_cfg_template); - return 1; - } - - int cur = 0; - char * cur_file; - char *service_home = NULL; - char *cur_service_home = NULL; - - struct GNUNET_CONFIGURATION_Handle *cfg_new = NULL; - struct GNUNET_CONFIGURATION_Handle *cfg_tmpl = GNUNET_CONFIGURATION_create(); - - /* load template */ - if ((create_cfg_template != NULL) && (GNUNET_OK != GNUNET_CONFIGURATION_load(cfg_tmpl, create_cfg_template))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load template `%s'\n", create_cfg_template); - GNUNET_CONFIGURATION_destroy(cfg_tmpl); - - return 1; - } - /* load defaults */ - else if (GNUNET_OK != GNUNET_CONFIGURATION_load(cfg_tmpl, NULL)) - { - GNUNET_break (0); - return 1; - } - - if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg_tmpl, "PATHS", "SERVICEHOME", &service_home)) - { - GNUNET_asprintf(&service_home, "%s", "/tmp/testing"); - } - else - { - int s = strlen (service_home); - if (service_home[s-1] == DIR_SEPARATOR) - service_home[s-1] = '\0'; - } - - while (cur < no) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating configuration no. %u \n", cur); - if (create_cfg_template != NULL) - GNUNET_asprintf (&cur_file,"%04u-%s",cur, create_cfg_template); - else - GNUNET_asprintf (&cur_file,"%04u%s",cur, ".conf"); - - - GNUNET_asprintf (&cur_service_home, "%s-%04u%c",service_home, cur, DIR_SEPARATOR); - GNUNET_CONFIGURATION_set_value_string (cfg_tmpl,"PATHS","SERVICEHOME", cur_service_home); - GNUNET_CONFIGURATION_set_value_string (cfg_tmpl,"PATHS","DEFAULTCONFIG", cur_file); - GNUNET_free (cur_service_home); - - cfg_new = GNUNET_TESTING_create_cfg(cfg_tmpl, cur, &port, &upnum, NULL, &fdnum); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing configuration no. %u to file `%s' \n", cur, cur_file); - if (GNUNET_OK != GNUNET_CONFIGURATION_write(cfg_new, cur_file)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write configuration no. %u \n", cur); - fail = GNUNET_YES; - } - - GNUNET_CONFIGURATION_destroy (cfg_new); - GNUNET_free (cur_file); - if (fail == GNUNET_YES) - break; - cur ++; - } - - GNUNET_CONFIGURATION_destroy(cfg_tmpl); - GNUNET_free (service_home); - if (fail == GNUNET_NO) - return 0; - else - return 1; -} - -static int -create_hostkeys (const unsigned int no) -{ - struct GNUNET_DISK_FileHandle *fd; - int cur = 0; - uint64_t fs; - uint64_t total_hostkeys; - char *hostkey_data; - char *hostkey_src_file; - char *hostkey_dest_file; - - /* prepare hostkeys */ - if (create_hostkey_file == NULL) - hostkey_src_file = "../../contrib/testing_hostkeys.dat"; - else - { - hostkey_src_file = create_hostkey_file; - } - - if (GNUNET_YES != GNUNET_DISK_file_test (hostkey_src_file)) - { - if (create_hostkey_file == NULL) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not read hostkeys file, specify hostkey file with -H!\n")); - else - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Specified hostkey file `%s' not found!\n"), create_hostkey_file); - return 1; - } - else - { - /* Check hostkey file size, read entire thing into memory */ - fd = GNUNET_DISK_file_open (hostkey_src_file, GNUNET_DISK_OPEN_READ, - GNUNET_DISK_PERM_NONE); - if (NULL == fd) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", hostkey_src_file); - return 1; - } - - if (GNUNET_OK != GNUNET_DISK_file_size (hostkey_src_file, &fs, GNUNET_YES, GNUNET_YES)) - fs = 0; - - if (0 != (fs % HOSTKEYFILESIZE)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "File size %llu seems incorrect for hostkeys...\n", fs); - } - else - { - total_hostkeys = fs / HOSTKEYFILESIZE; - hostkey_data = GNUNET_malloc_large (fs); - GNUNET_assert (fs == GNUNET_DISK_file_read (fd, hostkey_data, fs)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Read %llu hostkeys from file\n", total_hostkeys); - } - GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd)); - } - - while (cur < no) - { - GNUNET_asprintf (&hostkey_dest_file, "%04u-hostkey",cur); - GNUNET_assert (GNUNET_OK == - GNUNET_DISK_directory_create_for_file (hostkey_dest_file)); - fd = GNUNET_DISK_file_open (hostkey_dest_file, - GNUNET_DISK_OPEN_READWRITE | - GNUNET_DISK_OPEN_CREATE, - GNUNET_DISK_PERM_USER_READ | - GNUNET_DISK_PERM_USER_WRITE); - GNUNET_assert (fd != NULL); - GNUNET_assert (HOSTKEYFILESIZE == - GNUNET_DISK_file_write (fd, &hostkey_data[cur * HOSTKEYFILESIZE], HOSTKEYFILESIZE)); - GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd)); - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", - "Wrote hostkey to file: `%s' \n", hostkey_dest_file); - GNUNET_free (hostkey_dest_file); - cur ++; - } - - GNUNET_free (hostkey_data); - - return 0; -} - -/** - * Main function that will be run by the scheduler. - * - * @param cls closure - * @param args remaining command-line arguments - * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param cfg configuration - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - /* main code here */ - if (create_cfg == GNUNET_YES) - { - if (create_no > 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating %u configuration files based on template `%s'\n", create_no, create_cfg_template); - ret = create_unique_cfgs (create_cfg_template, create_no); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing arguments! \n"); - ret = 1; - } - } - - if (create_hostkey == GNUNET_YES) - { - if (create_no > 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating %u hostkeys \n", create_no); - ret = create_hostkeys (create_no); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing arguments! \n"); - ret = 1; - } - } - - GNUNET_free_non_null (create_cfg_template); -} - - -/** - * The main function. - * - * @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 const struct GNUNET_GETOPT_CommandLineOption options[] = { - {'C', "cfg", NULL, gettext_noop ("create unique configuration files"), - GNUNET_NO, &GNUNET_GETOPT_set_one, &create_cfg}, - {'k', "key", NULL, gettext_noop ("create hostkey files from pre-computed hostkey list"), - GNUNET_NO, &GNUNET_GETOPT_set_one, &create_hostkey}, - {'H', "hostkeys", NULL, gettext_noop ("host key file"), - GNUNET_YES, &GNUNET_GETOPT_set_string, &create_hostkey_file}, - {'n', "number", NULL, gettext_noop ("number of unique configuration files or hostkeys to create"), - GNUNET_YES, &GNUNET_GETOPT_set_uint, &create_no}, - {'t', "template", NULL, gettext_noop ("configuration template"), - GNUNET_YES, &GNUNET_GETOPT_set_string, &create_cfg_template}, - GNUNET_GETOPT_OPTION_END - }; - return (GNUNET_OK == - GNUNET_PROGRAM_run (argc, argv, "gnunet-testing", - gettext_noop ("Command line tool to access the testing library"), options, &run, - NULL)) ? ret : 1; -} - -/* end of gnunet-testing.c */ diff --git a/src/testing/helper.c b/src/testing/helper.c deleted file mode 100644 index ebb37ebe5..000000000 --- a/src/testing/helper.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - 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 testing/helper.c - * @brief helper functions for testing - * @author Christian Grothoff - * - */ -#include "platform.h" -#include "gnunet_testing_lib.h" - - - - -/** - * Obtain the peer identity of the peer with the given configuration - * handle. This function reads the private key of the peer, obtains - * the public key and hashes it. - * - * @param cfg configuration of the peer - * @param pid where to store the peer identity - * @return GNUNET_OK on success, GNUNET_SYSERR on failure - */ -int -GNUNET_TESTING_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_PeerIdentity *pid) -{ - char *keyfile; - struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY", - &keyfile)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("Peer is lacking HOSTKEY configuration setting.\n")); - return GNUNET_SYSERR; - } - my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); - GNUNET_free (keyfile); - if (my_private_key == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Could not access hostkey.\n")); - return GNUNET_SYSERR; - } - GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key); - GNUNET_CRYPTO_rsa_key_free (my_private_key); - GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), - &pid->hashPubKey); - return GNUNET_OK; -} - - -/* end of helper.c */ diff --git a/src/testing/test_testing.c b/src/testing/test_testing.c deleted file mode 100644 index 3e2cd65ee..000000000 --- a/src/testing/test_testing.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009 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 testing/test_testing.c - * @brief testcase for testing.c - */ -#include "platform.h" -#include "gnunet_testing_lib.h" - -#define VERBOSE GNUNET_YES - -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) - -static int ok; - -static void -end_cb (void *cls, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg); - ok = 1; - } - else - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon terminated, will now exit.\n"); -#endif - ok = 0; - } -} - - - -void -do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_TESTING_Daemon *d = cls; - - GNUNET_TESTING_daemon_stop (d, TIMEOUT, &end_cb, NULL, GNUNET_YES, GNUNET_NO); -} - - -static void -my_cb (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - GNUNET_assert (id != NULL); -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Daemon `%s' started, will now stop it.\n", GNUNET_i2s (id)); -#endif - GNUNET_SCHEDULER_add_now (&do_shutdown, d); -} - - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_TESTING_Daemon *d; - - ok = 1; -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n"); -#endif - d = GNUNET_TESTING_daemon_start (cfg, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL, - NULL, NULL, &my_cb, NULL); - GNUNET_assert (d != NULL); -} - -static int -check () -{ - char *const argv[] = { "test-testing", - "-c", - "test_testing_data.conf", -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-testing", "nohelp", options, &run, &ok); - return ok; -} - -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test-testing", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret = check (); - - return ret; -} - -/* end of test_testing.c */ diff --git a/src/testing/test_testing_2dtorus.c b/src/testing/test_testing_2dtorus.c deleted file mode 100644 index 00a66d65c..000000000 --- a/src/testing/test_testing_2dtorus.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2011 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 testing/test_testing_2dtorus.c - * - * @brief Test for creating a 2dtorus. - */ -#include "platform.h" -#include "gnunet_testing_lib.h" - -#define VERBOSE GNUNET_YES -#define REMOVE_DIR GNUNET_YES - -/** - * How long until we give up on connecting the peers? - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500) - -/** - * Time to wait for stuff that should be rather fast - */ -#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) - - -/** - * How many events have happened - */ -static int ok; - -/** - * Be verbose - */ -static int verbose; - -/** - * Total number of peers in the test. - */ -static unsigned long long num_peers; - -/** - * Global configuration file - */ -static struct GNUNET_CONFIGURATION_Handle *testing_cfg; - -/** - * Total number of currently running peers. - */ -static unsigned long long peers_running; - -/** - * Total number of successful connections in the whole network. - */ -static unsigned int total_connections; - -/** - * Total number of counted topo connections - */ -static unsigned int topo_connections; - -/** - * Total number of failed connections in the whole network. - */ -static unsigned int failed_connections; - -/** - * The currently running peer group. - */ -static struct GNUNET_TESTING_PeerGroup *pg; - -/** - * Task called to disconnect peers - */ -static GNUNET_SCHEDULER_TaskIdentifier disconnect_task; - -/** - * Task called to shutdown test. - */ -static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle; - - -/** - * Check whether peers successfully shut down. - */ -static void -shutdown_callback (void *cls, const char *emsg) -{ - if (emsg != NULL) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Shutdown of peers failed!\n"); -#endif - ok--; - } - else - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "test: All peers successfully shut down!\n"); -#endif - } -} - - -static void -shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Ending test.\n"); -#endif - - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - GNUNET_CONFIGURATION_destroy (testing_cfg); -} - - -static void -disconnect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: disconnecting peers\n"); - - if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle) - { - GNUNET_SCHEDULER_cancel (shutdown_handle); - shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); - } -} - - -/** - * Prototype of a callback function indicating that two peers - * are currently connected. - * - * @param cls closure - * @param first peer id for first daemon - * @param second peer id for the second daemon - * @param distance distance between the connected peers - * @param emsg error message (NULL on success) - */ -void -topo_cb (void *cls, const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, const char *emsg) -{ - topo_connections++; - if (NULL != emsg) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: Error by topo %u: %s\n", - topo_connections, emsg); - } - else - { - if (first == NULL || second == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Connection %u NULL\n", - topo_connections); - if (disconnect_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (disconnect_task); - GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL); - } - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Connection %u ok\n", - topo_connections); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: %s\n", GNUNET_i2s (first)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: %s\n", GNUNET_i2s (second)); - } -} - - -/** - * peergroup_ready: start test when all peers are connected - * @param cls closure - * @param emsg error message - */ -static void -peergroup_ready (void *cls, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "test: Peergroup callback called with error, aborting test!\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Error from testing: `%s'\n", - emsg); - ok--; - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - return; - } -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "************************************************************\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "test: Peer Group started successfully!\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Have %u connections\n", - total_connections); -#endif - - peers_running = GNUNET_TESTING_daemons_running (pg); - if (0 < failed_connections) - { - ok = GNUNET_SYSERR; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: %u connections have FAILED!\n", - failed_connections); - disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL); - - } - else - { - GNUNET_TESTING_get_topology (pg, &topo_cb, NULL); - disconnect_task = - GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_peers, NULL); - ok = GNUNET_OK; - } - -} - - -/** - * Function that will be called whenever two daemons are connected by - * the testing library. - * - * @param cls closure - * @param first peer id for first daemon - * @param second peer id for the second daemon - * @param distance distance between the connected peers - * @param first_cfg config for the first daemon - * @param second_cfg config for the second daemon - * @param first_daemon handle for the first daemon - * @param second_daemon handle for the second daemon - * @param emsg error message (NULL on success) - */ -static void -connect_cb (void *cls, const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, uint32_t distance, - const struct GNUNET_CONFIGURATION_Handle *first_cfg, - const struct GNUNET_CONFIGURATION_Handle *second_cfg, - struct GNUNET_TESTING_Daemon *first_daemon, - struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg) -{ - if (emsg == NULL) - { - total_connections++; - } - else - { - failed_connections++; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "test: Problem with new connection (%s)\n", emsg); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: (%s)\n", GNUNET_i2s (first)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: (%s)\n", GNUNET_i2s (second)); - } - -} - - -/** - * run: load configuration options and schedule test to run (start peergroup) - * @param cls closure - * @param args argv - * @param cfgfile configuration file name (can be NULL) - * @param cfg configuration handle - */ -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_TESTING_Host *hosts; - - ok = GNUNET_NO; - total_connections = 0; - failed_connections = 0; - testing_cfg = GNUNET_CONFIGURATION_dup (cfg); - - GNUNET_log_setup ("test_testing_2dtorus", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Starting daemons.\n"); - GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing", - "use_progressbars", "YES"); -#endif - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing", - "num_peers", &num_peers)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Option TESTING:NUM_PEERS is required!\n"); - return; - } - - hosts = GNUNET_TESTING_hosts_load (testing_cfg); - - pg = GNUNET_TESTING_peergroup_start (testing_cfg, num_peers, TIMEOUT, - &connect_cb, &peergroup_ready, NULL, - hosts); - GNUNET_assert (pg != NULL); - shutdown_handle = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, - &shutdown_task, NULL); -} - - -/** - * test_testing_2dtorus command line options - */ -static struct GNUNET_GETOPT_CommandLineOption options[] = { - {'V', "verbose", NULL, - gettext_noop ("be verbose (print progress information)"), - 0, &GNUNET_GETOPT_set_one, &verbose}, - GNUNET_GETOPT_OPTION_END -}; - - -/** - * Main: start test - */ -int -main (int argc, char *argv[]) -{ - char *const argv2[] = { - argv[0], - "-c", - "test_testing_2dtorus.conf", -#if VERBOSE - "-L", - "DEBUG", -#endif - NULL - }; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Start\n"); - - - GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, - "test_testing_2dtorus", - gettext_noop ("Test testing 2d torus."), options, &run, - NULL); -#if REMOVE_DIR - GNUNET_DISK_directory_remove ("/tmp/test_testing_2dtorus"); -#endif - if (GNUNET_OK != ok) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: FAILED!\n"); - return 1; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: success\n"); - return 0; -} - -/* end of test_testing_2dtorus.c */ diff --git a/src/testing/test_testing_2dtorus.conf b/src/testing/test_testing_2dtorus.conf deleted file mode 100644 index 54bb7c5a7..000000000 --- a/src/testing/test_testing_2dtorus.conf +++ /dev/null @@ -1,81 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -SERVICEHOME = /tmp/test_testing_2dtorus/ -DEFAULTCONFIG = test_testing_2dtorus.conf - -[arm] -PORT = 10010 -DEFAULTSERVICES = core -#DEBUG = YES - -[statistics] -AUTOSTART = YES -PORT = 10000 - -[dht] -DEBUG = NO -AUTOSTART = YES -ACCEPT_FROM6 = ::1; -ACCEPT_FROM = 127.0.0.1; -HOSTNAME = localhost -PORT = 10001 - -[nse] -WORKBITS = 0 - -[dns] -AUTOSTART = NO -PORT = 10011 - -[transport] -PORT = 10002 -AUTOSTART = YES -PLUGINS = tcp - -[nat] -DISABLEV6 = YES -BINDTO = 127.0.0.1 -ENABLE_UPNP = NO -BEHIND_NAT = NO -ALLOW_NAT = NO -INTERNAL_ADDRESS = 127.0.0.1 -EXTERNAL_ADDRESS = 127.0.0.1 - -[ats] -WAN_QUOTA_IN = 1 GB -WAN_QUOTA_OUT = 1 GB - -[core] -AUTOSTART = YES -PORT = 10003 - -[peerinfo] -AUTOSTART = YES -PORT = 10004 - -[testing] -NUM_PEERS = 16 -WEAKRANDOM = YES -TOPOLOGY = 2D_TORUS -CONNECT_TOPOLOGY = 2D_TORUS -#TOPOLOGY_FILE = small.dat -CONNECT_TOPOLOGY = 2D_TORUS -#CONNECT_TOPOLOGY_OPTION = CONNECT_MINIMUM -#CONNECT_TOPOLOGY_OPTION_MODIFIER = 25 -#PERCENTAGE = 3 -#PROBABILITY = .1 -F2F = NO -CONNECT_TIMEOUT = 600 s -CONNECT_ATTEMPTS = 2 -DEBUG = YES -HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat -MAX_CONCURRENT_SSH = 10 -USE_PROGRESSBARS = YES -PEERGROUP_TIMEOUT = 2400 s -TOPOLOGY_OUTPUT_FILE = testing_topo_initial -MAX_OUTSTANDING_CONNECTIONS = 75 -#SINGLE_PEERINFO_PER_HOST = YES -#NUM_PEERINFO_PER_HOST = 10 -#SINGLE_STATISTICS_PER_HOST = YES -#NUM_STATISTICS_PER_HOST = 10 -DELETE_FILES = YES diff --git a/src/testing/test_testing_connect.c b/src/testing/test_testing_connect.c deleted file mode 100644 index c69c20326..000000000 --- a/src/testing/test_testing_connect.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009 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 testing/test_testing_connect.c - * @brief testcase for functions to connect two peers in testing.c - */ -#include "platform.h" -#include "gnunet_testing_lib.h" - -#define VERBOSE GNUNET_NO - -/** - * How long until we give up on connecting the peers? - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) - -#define CONNECT_ATTEMPTS 3 - -static int ok; - -static struct GNUNET_TESTING_Daemon *d1; - -static struct GNUNET_TESTING_Daemon *d2; - -static struct GNUNET_CONFIGURATION_Handle *c1; - -static struct GNUNET_CONFIGURATION_Handle *c2; - -static struct GNUNET_TESTING_ConnectContext *cc; - -static void -end2_cb (void *cls, const char *emsg) -{ - - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg); - ok = 1; - } - else - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Both daemons terminated, will now exit.\n"); -#endif - ok = 0; - } -} - -static void -end1_cb (void *cls, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Stopping daemon 1 gave: %s\n", - emsg); - ok = 1; - } - else - { - ok = 0; - } - - GNUNET_TESTING_daemon_stop (d2, TIMEOUT, &end2_cb, NULL, GNUNET_YES, - GNUNET_NO); - d2 = NULL; -} - -static void -finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &end1_cb, NULL, GNUNET_YES, - GNUNET_NO); - d1 = NULL; -} - -static void -my_connect_complete (void *cls, const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, - unsigned int distance, - const struct GNUNET_CONFIGURATION_Handle *first_cfg, - const struct GNUNET_CONFIGURATION_Handle *second_cfg, - struct GNUNET_TESTING_Daemon *first_daemon, - struct GNUNET_TESTING_Daemon *second_daemon, - const char *emsg) -{ - cc = NULL; - GNUNET_SCHEDULER_add_now (&finish_testing, NULL); -} - - -static void -my_cb2 (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - GNUNET_assert (id != NULL); -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n", - GNUNET_i2s (id)); -#endif - cc = GNUNET_TESTING_daemons_connect (d1, d2, TIMEOUT, CONNECT_ATTEMPTS, - GNUNET_YES, &my_connect_complete, NULL); -} - - -static void -my_cb1 (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - GNUNET_assert (id != NULL); -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n", - GNUNET_i2s (id)); -#endif - d2 = GNUNET_TESTING_daemon_start (c2, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL, - NULL, NULL, &my_cb2, NULL); - GNUNET_assert (d2 != NULL); - -} - - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - ok = 1; -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n"); -#endif - c1 = GNUNET_CONFIGURATION_create (); - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_load (c1, - "test_testing_connect_peer1.conf")); - c2 = GNUNET_CONFIGURATION_create (); - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_load (c2, - "test_testing_connect_peer2.conf")); - d1 = GNUNET_TESTING_daemon_start (c1, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL, - NULL, NULL, &my_cb1, NULL); - GNUNET_assert (d1 != NULL); -} - -static int -check () -{ - char *const argv[] = { "test-testing", - "-c", - "test_testing_data.conf", -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-testing-connect", "nohelp", options, &run, &ok); - return ok; -} - -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test-testing-connect", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret = check (); - return ret; -} - -/* end of test_testing_connect.c */ diff --git a/src/testing/test_testing_connect_peer1.conf b/src/testing/test_testing_connect_peer1.conf deleted file mode 100644 index cccda5e2a..000000000 --- a/src/testing/test_testing_connect_peer1.conf +++ /dev/null @@ -1,37 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -SERVICEHOME = /tmp/test-gnunet-testing-connect-peer1/ -DEFAULTCONFIG = test_testing_connect_peer1.conf - -[transport-tcp] -PORT = 12568 - -[arm] -PORT = 12566 -DEFAULTSERVICES = core -UNIXPATH = /tmp/gnunet-p1-service-arm.sock - -[statistics] -PORT = 12567 -UNIXPATH = /tmp/gnunet-p1-service-statistics.sock - -[resolver] -PORT = 12564 -UNIXPATH = /tmp/gnunet-p1-service-resolver.sock - -[peerinfo] -PORT = 12569 -UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock - -[transport] -PORT = 12565 -UNIXPATH = /tmp/gnunet-p1-service-transport.sock - -[core] -PORT = 12570 -UNIXPATH = /tmp/gnunet-p1-service-core.sock - -[ats] -PORT = 12571 -UNIXPATH = /tmp/gnunet-p1-service-ats.sock - diff --git a/src/testing/test_testing_connect_peer2.conf b/src/testing/test_testing_connect_peer2.conf deleted file mode 100644 index 08ec55113..000000000 --- a/src/testing/test_testing_connect_peer2.conf +++ /dev/null @@ -1,37 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -SERVICEHOME = /tmp/test-gnunet-testing-connect-peer2/ -DEFAULTCONFIG = test_testing_connect_peer2.conf - -[transport-tcp] -PORT = 22568 - -[arm] -PORT = 22566 -DEFAULTSERVICES = core -UNIXPATH = /tmp/gnunet-p2-service-arm.sock - -[statistics] -PORT = 22567 -UNIXPATH = /tmp/gnunet-p2-service-statistics.sock - -[resolver] -PORT = 22564 -UNIXPATH = /tmp/gnunet-p2-service-resolver.sock - -[peerinfo] -PORT = 22569 -UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock - -[transport] -PORT = 22565 -UNIXPATH = /tmp/gnunet-p2-service-transport.sock - -[core] -PORT = 22570 -UNIXPATH = /tmp/gnunet-p2-service-core.sock - -[ats] -PORT = 22571 -UNIXPATH = /tmp/gnunet-p2-service-ats.sock - diff --git a/src/testing/test_testing_data.conf b/src/testing/test_testing_data.conf deleted file mode 100644 index c46cb0d42..000000000 --- a/src/testing/test_testing_data.conf +++ /dev/null @@ -1,7 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data.conf - -[arm] -DEFAULTSERVICES = core - diff --git a/src/testing/test_testing_data_remote.conf b/src/testing/test_testing_data_remote.conf deleted file mode 100644 index d58666f31..000000000 --- a/src/testing/test_testing_data_remote.conf +++ /dev/null @@ -1,12 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_remote.conf - -[TESTING] -CONTROL_HOST = 127.0.0.1 -HOSTFILE = remote_hosts.txt -MAX_OUTSTANDING_SSH = 5 - -[statistics] -AUTOSTART = NO - diff --git a/src/testing/test_testing_data_topology_2d_torus.conf b/src/testing/test_testing_data_topology_2d_torus.conf deleted file mode 100644 index cbdaceb5a..000000000 --- a/src/testing/test_testing_data_topology_2d_torus.conf +++ /dev/null @@ -1,7 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_2d_torus.conf - -[TESTING] -NUM_PEERS = 13 -TOPOLOGY = 2D_TORUS diff --git a/src/testing/test_testing_data_topology_blacklist.conf b/src/testing/test_testing_data_topology_blacklist.conf deleted file mode 100644 index 36e378d42..000000000 --- a/src/testing/test_testing_data_topology_blacklist.conf +++ /dev/null @@ -1,13 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_blacklist.conf - -[TESTING] -NUM_PEERS = 4 -TOPOLOGY = CLIQUE -BLACKLIST_TOPOLOGY = RING -BLACKLIST_TRANSPORTS = tcp udp http - -[transport-udp] -PORT = 2568 - diff --git a/src/testing/test_testing_data_topology_churn.conf b/src/testing/test_testing_data_topology_churn.conf deleted file mode 100644 index b3371658d..000000000 --- a/src/testing/test_testing_data_topology_churn.conf +++ /dev/null @@ -1,10 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_churn.conf - -[TESTING] -NUM_PEERS = 12 - -[arm] -DEFAULTSERVICES = peerinfo transport core - diff --git a/src/testing/test_testing_data_topology_clique.conf b/src/testing/test_testing_data_topology_clique.conf deleted file mode 100644 index 69cecb7e9..000000000 --- a/src/testing/test_testing_data_topology_clique.conf +++ /dev/null @@ -1,10 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_clique.conf - -[TESTING] -CONNECT_TIMEOUT = 180 s -CONNECT_ATTEMPTS = 14 -NUM_PEERS = 4 -TOPOLOGY = CLIQUE -SETTLE_TIME = 0 diff --git a/src/testing/test_testing_data_topology_clique_dfs.conf b/src/testing/test_testing_data_topology_clique_dfs.conf deleted file mode 100644 index c7abeae5e..000000000 --- a/src/testing/test_testing_data_topology_clique_dfs.conf +++ /dev/null @@ -1,13 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_clique.conf - -[TESTING] -NUM_PEERS = 7 -TOPOLOGY = CLIQUE -CONNECT_TOPOLOGY_OPTION = CONNECT_DFS -CONNECT_TOPOLOGY_OPTION_MODIFIER = 2.0 - -[arm] -DEFAULTSERVICES = peerinfo transport core - diff --git a/src/testing/test_testing_data_topology_clique_minimum.conf b/src/testing/test_testing_data_topology_clique_minimum.conf deleted file mode 100644 index ef95cb1fd..000000000 --- a/src/testing/test_testing_data_topology_clique_minimum.conf +++ /dev/null @@ -1,10 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_clique.conf - -[TESTING] -NUM_PEERS = 20 -TOPOLOGY = CLIQUE -CONNECT_TOPOLOGY_OPTION = CONNECT_MINIMUM -CONNECT_TOPOLOGY_OPTION_MODIFIER = 2.0 - diff --git a/src/testing/test_testing_data_topology_clique_random.conf b/src/testing/test_testing_data_topology_clique_random.conf deleted file mode 100644 index cd44b65f0..000000000 --- a/src/testing/test_testing_data_topology_clique_random.conf +++ /dev/null @@ -1,16 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_clique.conf - -[TESTING] -NUM_PEERS = 20 -TOPOLOGY = CLIQUE -CONNECT_TOPOLOGY_OPTION = CONNECT_RANDOM_SUBSET -CONNECT_TOPOLOGY_OPTION_MODIFIER = .15 - -[statistics] -AUTOSTART = NO - -[resolver] -AUTOSTART = NO - diff --git a/src/testing/test_testing_data_topology_erdos_renyi.conf b/src/testing/test_testing_data_topology_erdos_renyi.conf deleted file mode 100644 index 8e1741352..000000000 --- a/src/testing/test_testing_data_topology_erdos_renyi.conf +++ /dev/null @@ -1,7 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_clique.conf - -[TESTING] -TOPOLOGY = ERDOS_RENYI - diff --git a/src/testing/test_testing_data_topology_internat.conf b/src/testing/test_testing_data_topology_internat.conf deleted file mode 100644 index af3f62f39..000000000 --- a/src/testing/test_testing_data_topology_internat.conf +++ /dev/null @@ -1,7 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_clique.conf - -[TESTING] -TOPOLOGY = INTERNAT - diff --git a/src/testing/test_testing_data_topology_none.conf b/src/testing/test_testing_data_topology_none.conf deleted file mode 100644 index dbee5d0b9..000000000 --- a/src/testing/test_testing_data_topology_none.conf +++ /dev/null @@ -1,37 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_clique.conf - -[TESTING] -NUM_PEERS = 1000 -TOPOLOGY = NONE -F2F = NO -BLACKLIST_TOPOLOGY = NONE -CONNECT_TOPOLOGY = RING - -[arm] -PORT = 0 - -[statistics] -AUTOSTART = NO -PORT = 0 - -[resolver] -AUTOSTART = NO -PORT = 0 - -[peerinfo] -PORT = 0 - -[transport] -PORT = 0 - -[core] -PORT = 0 - -[topology] -PORT = 0 - -[hostlist] -PORT = 0 - diff --git a/src/testing/test_testing_data_topology_ring.conf b/src/testing/test_testing_data_topology_ring.conf deleted file mode 100644 index 6159030f4..000000000 --- a/src/testing/test_testing_data_topology_ring.conf +++ /dev/null @@ -1,7 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_clique.conf - -[TESTING] -TOPOLOGY = RING - diff --git a/src/testing/test_testing_data_topology_scale_free.conf b/src/testing/test_testing_data_topology_scale_free.conf deleted file mode 100644 index 7690eac29..000000000 --- a/src/testing/test_testing_data_topology_scale_free.conf +++ /dev/null @@ -1,11 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_scale_free.conf - -[TESTING] -NUM_PEERS = 50 -TOPOLOGY = SCALE_FREE - -[arm] -DEFAULTSERVICES = peerinfo transport core - diff --git a/src/testing/test_testing_data_topology_small_world_ring.conf b/src/testing/test_testing_data_topology_small_world_ring.conf deleted file mode 100644 index 01931df6d..000000000 --- a/src/testing/test_testing_data_topology_small_world_ring.conf +++ /dev/null @@ -1,8 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_clique.conf - -[TESTING] -NUM_PEERS = 25 -TOPOLOGY = SMALL_WORLD_RING - diff --git a/src/testing/test_testing_data_topology_small_world_torus.conf b/src/testing/test_testing_data_topology_small_world_torus.conf deleted file mode 100644 index 7c35454de..000000000 --- a/src/testing/test_testing_data_topology_small_world_torus.conf +++ /dev/null @@ -1,7 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_clique.conf - -[TESTING] -TOPOLOGY = SMALL_WORLD - diff --git a/src/testing/test_testing_data_topology_stability.conf b/src/testing/test_testing_data_topology_stability.conf deleted file mode 100644 index 1bfcd1bde..000000000 --- a/src/testing/test_testing_data_topology_stability.conf +++ /dev/null @@ -1,9 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_data_topology_clique.conf - -[TESTING] -SETTLE_TIME = 600 s -NUM_PEERS = 2 -TOPOLOGY = CLIQUE - diff --git a/src/testing/test_testing_defaults.conf b/src/testing/test_testing_defaults.conf deleted file mode 100644 index ba7e269a6..000000000 --- a/src/testing/test_testing_defaults.conf +++ /dev/null @@ -1,78 +0,0 @@ -[PATHS] -SERVICEHOME = /tmp/test-gnunet-testing/ -DEFAULTCONFIG = test_testing_defaults.conf - -[resolver] -PORT = 2564 - -[transport] -PORT = 2565 -PLUGINS = tcp - -[arm] -PORT = 2566 -DEFAULTSERVICES = - -[statistics] -PORT = 2567 - -[transport-tcp] -PORT = 2568 -BINDTO = 127.0.0.1 - -[peerinfo] -PORT = 2569 - -[core] -PORT = 2570 - -[testing] -NUM_PEERS = 5 -WEAKRANDOM = YES -F2F = YES -HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat - -[dht] -AUTOSTART = NO - -[nat] -DISABLEV6 = YES -ENABLE_UPNP = NO -BEHIND_NAT = NO -ALLOW_NAT = NO -INTERNAL_ADDRESS = 127.0.0.1 -EXTERNAL_ADDRESS = 127.0.0.1 -USE_LOCALADDR = NO - -[dns] -AUTOSTART = NO - -[nse] -AUTOSTART = NO - -[mesh] -AUTOSTART = NO - -[datastore] -AUTOSTART = NO - -[fs] -AUTOSTART = NO - -[dv] -AUTOSTART = NO - -[chat] -AUTOSTART = NO - -[vpn] -AUTOSTART = NO - -[gns] -AUTOSTART = NO - -[namestore] -AUTOSTART = NO - -[lockmanager] -AUTOSTART = NO diff --git a/src/testing/test_testing_group.c b/src/testing/test_testing_group.c deleted file mode 100644 index f5df45b19..000000000 --- a/src/testing/test_testing_group.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009 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 testing/test_testing_group.c - * @brief testcase for functions to connect peers in testing.c - */ -#include "platform.h" -#include "gnunet_testing_lib.h" - -#define VERBOSE GNUNET_NO - -#define NUM_PEERS 4 - -/** - * How long until we give up on connecting the peers? - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) - -static int ok; - -static int peers_left; - -static int failed_peers; - -static struct GNUNET_TESTING_PeerGroup *pg; - -/** - * Check whether peers successfully shut down. - */ -void -shutdown_callback (void *cls, const char *emsg) -{ - if (emsg != NULL) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n"); -#endif - if (ok == 0) - ok = 666; - } - else - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); -#endif - } -} - - -static void -my_cb (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - if (id == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Start callback called with error (too long starting peers), aborting test!\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n"); - failed_peers++; - if (failed_peers == peers_left) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Too many peers failed, ending test!\n"); - ok = 1; - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - } - return; - } - - peers_left--; - if (peers_left == 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "All peers started successfully, ending test!\n"); - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - ok = 0; - } - else if (failed_peers == peers_left) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Too many peers failed, ending test!\n"); - ok = 1; - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - } -} - - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - ok = 1; -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n"); -#endif - peers_left = NUM_PEERS; - pg = GNUNET_TESTING_daemons_start (cfg, peers_left, /* Total number of peers */ - peers_left, /* Number of outstanding connections */ - peers_left, /* Number of parallel ssh connections, or peers being started at once */ - TIMEOUT, NULL, NULL, &my_cb, NULL, NULL, - NULL, NULL); - GNUNET_assert (pg != NULL); -} - -static int -check () -{ - char *const argv[] = { "test-testing", - "-c", - "test_testing_data.conf", -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-testing-group", "nohelp", options, &run, &ok); - return ok; -} - -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test-testing-group", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret = check (); - /** - * Still need to remove the base testing directory here, - * because group starts will create subdirectories under this - * main dir. However, we no longer need to sleep, as the - * shutdown sequence won't return until everything is cleaned - * up. - */ - GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing"); - return ret; -} - -/* end of test_testing_group.c */ diff --git a/src/testing/test_testing_group_remote.c b/src/testing/test_testing_group_remote.c deleted file mode 100644 index b06655ca4..000000000 --- a/src/testing/test_testing_group_remote.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009 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 testing/test_testing_group_remote.c - * @brief testcase for testing remote and local starting and connecting - * of hosts from the testing library. The test_testing_data_remote.conf - * file should be modified if this testcase is intended to be used. - */ -#include "platform.h" -#include "gnunet_testing_lib.h" - -#define VERBOSE GNUNET_YES - - -/** - * How long until we give up on connecting the peers? - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) - -#define DEFAULT_NUM_PEERS 8; - -static int ok; - -static int peers_left; - -static int peers_failed; - -static struct GNUNET_TESTING_PeerGroup *pg; - -static unsigned long long num_peers; - - -/** - * Check whether peers successfully shut down. - */ -void -shutdown_callback (void *cls, const char *emsg) -{ - if (emsg != NULL) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Shutdown of peers failed (error %s)!\n", emsg); -#endif - if (ok == 0) - ok = 666; - } - else - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); -#endif - } -} - - -static void -my_cb (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - if (emsg != NULL) - { - peers_failed++; - } - - peers_left--; - if (peers_left == 0) - { - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - ok = 0; - } - else if (peers_failed == peers_left) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Too many peers failed, ending test!\n"); - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - } -} - - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_TESTING_Host *hosts; - struct GNUNET_TESTING_Host *hostpos; - struct GNUNET_TESTING_Host *temphost; - char *hostfile; - struct stat frstat; - char *buf; - char *data; - int count; - int ret; - - ok = 1; -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n"); -#endif - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers", - &num_peers)) - num_peers = DEFAULT_NUM_PEERS; - - GNUNET_assert (num_peers > 0 && num_peers < (unsigned long long) -1); - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "hostfile", - &hostfile)) - hostfile = NULL; - - hosts = NULL; - data = NULL; - if (hostfile != NULL) - { - if (GNUNET_OK != GNUNET_DISK_file_test (hostfile)) - GNUNET_DISK_fn_write (hostfile, NULL, 0, - GNUNET_DISK_PERM_USER_READ | - GNUNET_DISK_PERM_USER_WRITE); - if ((0 != STAT (hostfile, &frstat)) || (frstat.st_size == 0)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not open file specified for host list, ending test!"); - ok = 1119; - GNUNET_free (hostfile); - return; - } - - data = GNUNET_malloc_large (frstat.st_size); - GNUNET_assert (data != NULL); - if (frstat.st_size != GNUNET_DISK_fn_read (hostfile, data, frstat.st_size)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not read file %s specified for host list, ending test!", - hostfile); - GNUNET_free (hostfile); - GNUNET_free (data); - return; - } - - GNUNET_free_non_null (hostfile); - - buf = data; - count = 0; - while (count < frstat.st_size) - { - count++; - if (count >= frstat.st_size) - break; - - /* if (((data[count] == '\n') || (data[count] == '\0')) && (buf != &data[count])) */ - if (((data[count] == '\n')) && (buf != &data[count])) - { - data[count] = '\0'; - temphost = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Host)); - ret = - SSCANF (buf, "%a[a-zA-Z0-9]@%a[a-zA-Z0-9.]:%hd", - &temphost->username, &temphost->hostname, &temphost->port); - if (3 == ret) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Successfully read host %s, port %d and user %s from file\n", - temphost->hostname, temphost->port, temphost->username); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Error reading line `%s' in hostfile\n", buf); - GNUNET_free (temphost); - buf = &data[count + 1]; - continue; - } - /* temphost->hostname = buf; */ - temphost->next = hosts; - hosts = temphost; - buf = &data[count + 1]; - } - else if ((data[count] == '\n') || (data[count] == '\0')) - buf = &data[count + 1]; - } - } - - peers_left = num_peers; - pg = GNUNET_TESTING_daemons_start (cfg, peers_left, /* Total number of peers */ - peers_left, /* Number of outstanding connections */ - peers_left, /* Number of parallel ssh connections, or peers being started at once */ - TIMEOUT, NULL, NULL, &my_cb, NULL, NULL, - NULL, hosts); - hostpos = hosts; - while (hostpos != NULL) - { - temphost = hostpos->next; - GNUNET_free (hostpos->hostname); - GNUNET_free (hostpos->username); - GNUNET_free (hostpos); - hostpos = temphost; - } - GNUNET_free_non_null (data); - GNUNET_assert (pg != NULL); - -} - -static int -check () -{ - char *const argv[] = { "test-testing", - "-c", - "test_testing_data_remote.conf", -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-testing-group", "nohelp", options, &run, &ok); - return ok; -} - -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test-testing-group", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret = check (); - /** - * Still need to remove the base testing directory here, - * because group starts will create subdirectories under this - * main dir. However, we no longer need to sleep, as the - * shutdown sequence won't return until everything is cleaned - * up. - */ - GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing"); - return ret; -} - -/* end of test_testing_group.c */ diff --git a/src/testing/test_testing_large_topology.c b/src/testing/test_testing_large_topology.c deleted file mode 100644 index cd80db195..000000000 --- a/src/testing/test_testing_large_topology.c +++ /dev/null @@ -1,1197 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009 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 testing/test_testing_topology.c - * @brief base testcase for testing all the topologies provided - */ -#include "platform.h" -#include "gnunet_testing_lib.h" -#include "gnunet_core_service.h" -#include "gnunet_os_lib.h" - -#define VERBOSE GNUNET_YES - -#define DELAY_FOR_LOGGING GNUNET_NO - -#define SECONDS_PER_PEER_START 120 - -#define DEFAULT_NUM_PEERS 4 - -#define MAX_OUTSTANDING_CONNECTIONS 100 - -static float fail_percentage = 0.05; - -static int ok; - -struct GNUNET_TIME_Relative connect_timeout; - -static unsigned long long connect_attempts; - -static unsigned long long num_peers; - -static unsigned int topology_connections; - -static unsigned int total_connections; - -static unsigned int failed_connections; - -static unsigned int total_server_connections; - -static unsigned int total_messages_received; - -static unsigned int expected_messages; - -static unsigned int expected_connections; - -static unsigned long long peers_left; - -static struct GNUNET_TESTING_PeerGroup *pg; - -const struct GNUNET_CONFIGURATION_Handle *main_cfg; - -GNUNET_SCHEDULER_TaskIdentifier die_task; - -static char *dotOutFileName; - -static struct GNUNET_TIME_Relative settle_time; - -static FILE *dotOutFile; - -static char *topology_string; - -static char *blacklist_transports; - -static int transmit_ready_scheduled; - -static int transmit_ready_failed; - -static int transmit_ready_called; - -struct GNUNET_TIME_Relative test_timeout; - -struct GNUNET_TIME_Relative timeout; - -static unsigned int modnum; - -static unsigned int dotnum; - -static enum GNUNET_TESTING_Topology topology; - -static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* Don't do any blacklisting */ - -static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */ - -static enum GNUNET_TESTING_TopologyOption connect_topology_option = - GNUNET_TESTING_TOPOLOGY_OPTION_ALL; - -static double connect_topology_option_modifier = 0.0; - -static char *test_directory; - -#define MTYPE 12345 - -GNUNET_NETWORK_STRUCT_BEGIN - -struct GNUNET_TestMessage -{ - /** - * Header of the message - */ - struct GNUNET_MessageHeader header; - - /** - * Unique identifier for this message. - */ - uint32_t uid; -}; -GNUNET_NETWORK_STRUCT_END - -struct TestMessageContext -{ - /* This is a linked list */ - struct TestMessageContext *next; - - /* Handle to the sending peer core */ - struct GNUNET_CORE_Handle *peer1handle; - - /* Handle to the receiving peer core */ - struct GNUNET_CORE_Handle *peer2handle; - - /* Handle to the sending peer daemon */ - struct GNUNET_TESTING_Daemon *peer1; - - /* Handle to the receiving peer daemon */ - struct GNUNET_TESTING_Daemon *peer2; - - /* Identifier for this message, so we don't disconnect other peers! */ - uint32_t uid; - - /* Has peer1 been notified already of a connection to peer2? */ - int peer1notified; - - /* Has the core of peer2 been connected already? */ - int peer2connected; - - /* Task for disconnecting cores, allow task to be cancelled on shutdown */ - GNUNET_SCHEDULER_TaskIdentifier disconnect_task; - -}; - -static struct TestMessageContext *test_messages; - -/** - * Check whether peers successfully shut down. - */ -void -shutdown_callback (void *cls, const char *emsg) -{ - if (emsg != NULL) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n"); -#endif - if (ok == 0) - ok = 666; - } - else - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); -#endif - } -} - -#if DELAY_FOR_LOGGING -static void -gather_log_data () -{ - char *peer_number; - char *connect_number; - struct GNUNET_OS_Process *mem_process; - - GNUNET_asprintf (&peer_number, "%llu", num_peers); - GNUNET_asprintf (&connect_number, "%llu", expected_connections); - mem_process = - GNUNET_OS_start_process (NULL, NULL, "./memsize.pl", "memsize.pl", - "totals.txt", peer_number, connect_number, NULL); - GNUNET_OS_process_wait (mem_process); - GNUNET_OS_process_destroy (mem_process); - mem_process = NULL; -} - -#endif - -static void -finish_testing () -{ - GNUNET_assert (pg != NULL); - struct TestMessageContext *pos; - struct TestMessageContext *free_pos; - -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Called finish testing, stopping daemons.\n"); -#endif - - pos = test_messages; - while (pos != NULL) - { - if (pos->peer1handle != NULL) - { - GNUNET_CORE_disconnect (pos->peer1handle); - pos->peer1handle = NULL; - } - if (pos->peer2handle != NULL) - { - GNUNET_CORE_disconnect (pos->peer2handle); - pos->peer2handle = NULL; - } - free_pos = pos; - pos = pos->next; - if (free_pos->disconnect_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (free_pos->disconnect_task); - } - GNUNET_free (free_pos); - } -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n", - transmit_ready_scheduled, transmit_ready_failed, - transmit_ready_called); -#endif - -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n"); -#endif - GNUNET_TESTING_daemons_stop (pg, timeout, &shutdown_callback, NULL); - - if (dotOutFile != NULL) - { - FPRINTF (dotOutFile, "%s", "}"); - FCLOSE (dotOutFile); - } - - ok = 0; -} - - -static void -disconnect_cores (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct TestMessageContext *pos = cls; - - /* Disconnect from the respective cores */ -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 1 `%4s'\n", - GNUNET_i2s (&pos->peer1->id)); -#endif - if (pos->peer1handle != NULL) - GNUNET_CORE_disconnect (pos->peer1handle); -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 2 `%4s'\n", - GNUNET_i2s (&pos->peer2->id)); -#endif - if (pos->peer2handle != NULL) - GNUNET_CORE_disconnect (pos->peer2handle); - /* Set handles to NULL so test case can be ended properly */ - pos->peer1handle = NULL; - pos->peer2handle = NULL; - pos->disconnect_task = GNUNET_SCHEDULER_NO_TASK; - /* Decrement total connections so new can be established */ - total_server_connections -= 2; -} - - -static void -topology_cb (void *cls, const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, const char *emsg) -{ - FILE *outfile = cls; - - if (first != NULL) - { - if (outfile != NULL) - { - FPRINTF (outfile, "\t\"%s\" -- ", GNUNET_i2s (first)); - FPRINTF (outfile, "\"%s\";\n", GNUNET_i2s (second)); - } - topology_connections++; - } - else - { - FPRINTF (stderr, - "Finished iterating over topology, %d total connections!\n", - topology_connections); - if (outfile != NULL) - { - FPRINTF (outfile, "%s", "}\n"); - FCLOSE (outfile); - GNUNET_SCHEDULER_add_now (&finish_testing, NULL); - } - } -} - -static int -process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi) -{ - char *dotOutFileNameFinished; - FILE *dotOutFileFinished; - struct TestMessageContext *pos = cls; - struct GNUNET_TestMessage *msg = (struct GNUNET_TestMessage *) message; - - if (pos->uid != ntohl (msg->uid)) - return GNUNET_OK; - -#if VERBOSE - if ((total_messages_received) % modnum == 0) - { - if (total_messages_received == 0) - FPRINTF (stdout, "%s", "0%%"); - else - FPRINTF (stdout, "%d%%", - (int) (((float) total_messages_received / expected_messages) * - 100)); - - } - else if (total_messages_received % dotnum == 0) - { - FPRINTF (stdout, "%s", "."); - } - fflush (stdout); -#endif - - total_messages_received++; - -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received message from `%4s', type %d.\n", GNUNET_i2s (peer), - ntohs (message->type)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Total messages received %d, expected %d.\n", - total_messages_received, expected_messages); -#endif - - if (total_messages_received == expected_messages) - { -#if VERBOSE - FPRINTF (stdout, "%s", "100%%]\n"); -#endif - GNUNET_SCHEDULER_cancel (die_task); - GNUNET_asprintf (&dotOutFileNameFinished, "%s.dot", "final_topology"); - dotOutFileFinished = FOPEN (dotOutFileNameFinished, "w"); - GNUNET_free (dotOutFileNameFinished); - if (dotOutFileFinished != NULL) - { - FPRINTF (dotOutFileFinished, "%s", "strict graph G {\n"); - } - topology_connections = 0; - GNUNET_TESTING_get_topology (pg, &topology_cb, dotOutFileFinished); - //GNUNET_SCHEDULER_add_now (&finish_testing, NULL); - } - else - { - pos->disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cores, pos); - } - - return GNUNET_OK; -} - -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - char *msg = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "End badly was called (%s)... stopping daemons.\n", msg); - struct TestMessageContext *pos; - struct TestMessageContext *free_pos; - - pos = test_messages; - while (pos != NULL) - { - if (pos->peer1handle != NULL) - { - GNUNET_CORE_disconnect (pos->peer1handle); - pos->peer1handle = NULL; - } - if (pos->peer2handle != NULL) - { - GNUNET_CORE_disconnect (pos->peer2handle); - pos->peer2handle = NULL; - } - free_pos = pos; - pos = pos->next; - GNUNET_free (free_pos); - } - -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n", - transmit_ready_scheduled, transmit_ready_failed, - transmit_ready_called); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Total messages received %d, expected %d.\n", - total_messages_received, expected_messages); -#endif - - if (pg != NULL) - { - GNUNET_TESTING_daemons_stop (pg, timeout, &shutdown_callback, NULL); - ok = 7331; /* Opposite of leet */ - } - else - ok = 401; /* Never got peers started */ - - if (dotOutFile != NULL) - { - FPRINTF (dotOutFile, "%s", "}"); - FCLOSE (dotOutFile); - } -} - -static size_t -transmit_ready (void *cls, size_t size, void *buf) -{ - struct GNUNET_TestMessage *m; - struct TestMessageContext *pos = cls; - - GNUNET_assert (buf != NULL); - m = (struct GNUNET_TestMessage *) buf; - m->header.type = htons (MTYPE); - m->header.size = htons (sizeof (struct GNUNET_TestMessage)); - m->uid = htonl (pos->uid); - transmit_ready_called++; -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "transmit ready for peer %s\ntransmit_ready's scheduled %d, transmit_ready's called %d\n", - GNUNET_i2s (&pos->peer1->id), transmit_ready_scheduled, - transmit_ready_called); -#endif - return sizeof (struct GNUNET_TestMessage); -} - - -static struct GNUNET_CORE_MessageHandler no_handlers[] = { - {NULL, 0, 0} -}; - -static struct GNUNET_CORE_MessageHandler handlers[] = { - {&process_mtype, MTYPE, sizeof (struct GNUNET_TestMessage)}, - {NULL, 0, 0} -}; - -static void -init_notify_peer2 (void *cls, struct GNUNET_CORE_Handle *server, - const struct GNUNET_PeerIdentity *my_identity) -{ - struct TestMessageContext *pos = cls; - - total_server_connections++; - - pos->peer2connected = GNUNET_YES; - if (pos->peer1notified == GNUNET_YES) /* Peer 1 has been notified of connection to peer 2 */ - { -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n", - GNUNET_i2s (my_identity), - GNUNET_h2s (&pos->peer1->id.hashPubKey)); -#endif - if (NULL == - GNUNET_CORE_notify_transmit_ready (pos->peer1handle, 0, timeout, - &pos->peer2->id, - sizeof (struct GNUNET_TestMessage), - &transmit_ready, pos)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", - GNUNET_i2s (&pos->peer2->id)); - transmit_ready_failed++; - } - else - { - transmit_ready_scheduled++; - } - } -} - -/** - * Method called whenever a given peer connects. - * - * @param cls closure - * @param peer peer identity this notification is about - * @param atsi performance data for the connection - */ -static void -connect_notify_peers (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_ATS_Information *atsi) -{ - struct TestMessageContext *pos = cls; - - if (0 == memcmp (peer, &pos->peer2->id, sizeof (struct GNUNET_PeerIdentity))) - { - pos->peer1notified = GNUNET_YES; -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Peer `%s' notified of connection to peer `%s'\n", - GNUNET_i2s (&pos->peer1->id), GNUNET_h2s (&peer->hashPubKey)); -#endif - } - else - return; - - if (pos->peer2connected == GNUNET_YES) /* Already connected and notified of connection, send message! */ - { -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n", - GNUNET_i2s (&pos->peer2->id), - GNUNET_h2s (&pos->peer1->id.hashPubKey)); -#endif - if (NULL == - GNUNET_CORE_notify_transmit_ready (pos->peer1handle, 0, timeout, - &pos->peer2->id, - sizeof (struct GNUNET_TestMessage), - &transmit_ready, pos)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", - GNUNET_i2s (&pos->peer2->id)); - transmit_ready_failed++; - } - else - { - transmit_ready_scheduled++; - } - } -} - -static void -init_notify_peer1 (void *cls, struct GNUNET_CORE_Handle *server, - const struct GNUNET_PeerIdentity *my_identity) -{ - struct TestMessageContext *pos = cls; - - total_server_connections++; - -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Core connection to `%4s' established, setting up handles\n", - GNUNET_i2s (my_identity)); -#endif - - /* - * Connect to the receiving peer - */ - pos->peer2handle = - GNUNET_CORE_connect (pos->peer2->cfg, pos, &init_notify_peer2, NULL, - NULL, NULL, NULL, GNUNET_YES, NULL, GNUNET_YES, - handlers); - -} - - -static void -send_test_messages (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct TestMessageContext *pos = cls; - - if ((pos == test_messages) && (settle_time.rel_value > 0)) - { - topology_connections = 0; - GNUNET_TESTING_get_topology (pg, &topology_cb, NULL); - } - if (((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) || (cls == NULL)) - return; - - if (die_task == GNUNET_SCHEDULER_NO_TASK) - { - die_task = - GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly, - "from send test messages (timeout)"); - } - - if (total_server_connections >= MAX_OUTSTANDING_CONNECTIONS) - { - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 1), - &send_test_messages, pos); - return; /* Otherwise we'll double schedule messages here! */ - } - - /* - * Connect to the sending peer - */ - pos->peer1handle = - GNUNET_CORE_connect (pos->peer1->cfg, pos, &init_notify_peer1, - &connect_notify_peers, NULL, NULL, NULL, GNUNET_NO, - NULL, GNUNET_NO, no_handlers); - - GNUNET_assert (pos->peer1handle != NULL); - - if (total_server_connections < MAX_OUTSTANDING_CONNECTIONS) - { - GNUNET_SCHEDULER_add_now (&send_test_messages, pos->next); - } - else - { - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 1), - &send_test_messages, pos->next); - } -} - - -void -topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, uint32_t distance, - const struct GNUNET_CONFIGURATION_Handle *first_cfg, - const struct GNUNET_CONFIGURATION_Handle *second_cfg, - struct GNUNET_TESTING_Daemon *first_daemon, - struct GNUNET_TESTING_Daemon *second_daemon, - const char *emsg) -{ - struct TestMessageContext *temp_context; - - if (emsg == NULL) - { -#if VERBOSE - if ((total_connections) % modnum == 0) - { - if (total_connections == 0) - FPRINTF (stdout, "%s", "0%%"); - else - FPRINTF (stdout, "%d%%", - (int) (((float) total_connections / expected_connections) * - 100)); - - } - else if (total_connections % dotnum == 0) - { - FPRINTF (stdout, "%s", "."); - } - fflush (stdout); -#endif - total_connections++; -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "connected peer %s to peer %s\n", - first_daemon->shortname, second_daemon->shortname); -#endif - temp_context = GNUNET_malloc (sizeof (struct TestMessageContext)); - temp_context->peer1 = first_daemon; - temp_context->peer2 = second_daemon; - temp_context->next = test_messages; - temp_context->uid = total_connections; - temp_context->disconnect_task = GNUNET_SCHEDULER_NO_TASK; - test_messages = temp_context; - - expected_messages++; - if (dotOutFile != NULL) - FPRINTF (dotOutFile, "\tn%s -- n%s;\n", first_daemon->shortname, - second_daemon->shortname); - } -#if VERBOSE - else - { - failed_connections++; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Failed to connect peer %s to peer %s with error :\n%s\n", - first_daemon->shortname, second_daemon->shortname, emsg); - } -#endif - - if (total_connections == expected_connections) - { -#if VERBOSE - FPRINTF (stdout, "%s", "100%%]\n"); -#endif -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Created %d total connections, which is our target number! Calling send messages.\n", - total_connections); -#endif - modnum = expected_messages / 4; - dotnum = (expected_messages / 50) + 1; - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; -#if DELAY_FOR_LOGGING - FPRINTF (stdout, "%s", "Sending test messages in 10 seconds.\n"); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 10), - &send_test_messages, test_messages); - gather_log_data (); -#else - if (settle_time.rel_value > 0) - { - GNUNET_TESTING_get_topology (pg, &topology_cb, NULL); - } - GNUNET_SCHEDULER_add_delayed (settle_time, &send_test_messages, - test_messages); -#endif -#if VERBOSE - FPRINTF (stdout, "%s", "Test message progress: ["); -#endif - - } - else if (total_connections + failed_connections == expected_connections) - { - if (failed_connections < - (unsigned int) (fail_percentage * total_connections)) - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_SCHEDULER_add_now (&send_test_messages, test_messages); - } - else - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = - GNUNET_SCHEDULER_add_now (&end_badly, - "from topology_callback (too many failed connections)"); - } - } - else - { -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Have %d total connections, %d failed connections, Want %d (at least %d)\n", - total_connections, failed_connections, expected_connections, - expected_connections - - (unsigned int) (fail_percentage * expected_connections)); -#endif - } -} - -static void -topology_creation_finished (void *cls, const char *emsg) -{ -#if VERBOSE - if (emsg == NULL) - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "All topology connections created successfully!\n"); -#endif -} - -static void -connect_topology () -{ - expected_connections = -1; - if ((pg != NULL) && (peers_left == 0)) - { - expected_connections = - GNUNET_TESTING_connect_topology (pg, connection_topology, - connect_topology_option, - connect_topology_option_modifier, - connect_timeout, connect_attempts, - &topology_creation_finished, NULL); -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n", - expected_connections); -#endif - } - - GNUNET_SCHEDULER_cancel (die_task); - if (expected_connections == GNUNET_SYSERR) - { - die_task = - GNUNET_SCHEDULER_add_now (&end_badly, - "from connect topology (bad return)"); - } - - die_task = - GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly, - "from connect topology (timeout)"); - modnum = expected_connections / 4; - dotnum = (expected_connections / 50) + 1; -#if VERBOSE - FPRINTF (stdout, "%s", "Peer connection progress: ["); -#endif -} - -static void -create_topology () -{ - peers_left = num_peers; /* Reset counter */ - if (GNUNET_TESTING_create_topology - (pg, topology, blacklist_topology, blacklist_transports) != GNUNET_SYSERR) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Topology set up, now starting peers!\n"); - FPRINTF (stdout, "%s", "Daemon start progress ["); -#endif - GNUNET_TESTING_daemons_continue_startup (pg); - } - else - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = - GNUNET_SCHEDULER_add_now (&end_badly, - "from create topology (bad return)"); - } - GNUNET_SCHEDULER_cancel (die_task); - die_task = - GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly, - "from continue startup (timeout)"); -} - - -static void -peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Failed to start daemon with error: `%s'\n", emsg); - return; - } - GNUNET_assert (id != NULL); -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n", - (num_peers - peers_left) + 1, num_peers); -#endif -#if VERBOSE - if ((num_peers - peers_left) % modnum == 0) - { - if (num_peers - peers_left == 0) - FPRINTF (stdout, "%s", "0%%"); - else - FPRINTF (stdout, "%d%%", - (int) (((float) (num_peers - peers_left) / num_peers) * 100)); - - } - else if ((num_peers - peers_left) % dotnum == 0) - { - FPRINTF (stdout, "%s", "."); - } - fflush (stdout); -#endif - peers_left--; - if (peers_left == 0) - { -#if VERBOSE - FPRINTF (stdout, "%s", "100%%]\n"); -#endif -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "All %d daemons started, now connecting peers!\n", num_peers); -#endif - GNUNET_SCHEDULER_cancel (die_task); - /* Set up task in case topology creation doesn't finish - * within a reasonable amount of time */ - die_task = - GNUNET_SCHEDULER_add_delayed (timeout, &end_badly, - "from peers_started_callback"); -#if DELAY_FOR_LOGGING - FPRINTF (stdout, "%s", "Connecting topology in 10 seconds\n"); - gather_log_data (); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 10), - &connect_topology, NULL); -#else - connect_topology (); -#endif - ok = 0; - } -} - -/** - * Callback indicating that the hostkey was created for a peer. - * - * @param cls NULL - * @param id the peer identity - * @param d the daemon handle (pretty useless at this point, remove?) - * @param emsg non-null on failure - */ -void -hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Hostkey callback received error: %s\n", emsg); - } - -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Hostkey (%d/%d) created for peer `%s'\n", num_peers - peers_left, - num_peers, GNUNET_i2s (id)); -#endif - -#if VERBOSE - if ((num_peers - peers_left) % modnum == 0) - { - if (num_peers - peers_left == 0) - FPRINTF (stdout, "%s", "0%%"); - else - FPRINTF (stdout, "%d%%", - (int) (((float) (num_peers - peers_left) / num_peers) * 100)); - - } - else if ((num_peers - peers_left) % dotnum == 0) - { - FPRINTF (stdout, "%s", "."); - } - fflush (stdout); -#endif - peers_left--; - if (peers_left == 0) - { -#if VERBOSE - FPRINTF (stdout, "%s", "100%%]\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "All %d hostkeys created, now creating topology!\n", num_peers); -#endif - GNUNET_SCHEDULER_cancel (die_task); - /* Set up task in case topology creation doesn't finish - * within a reasonable amount of time */ - die_task = - GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly, - "from create_topology"); - GNUNET_SCHEDULER_add_now (&create_topology, NULL); - ok = 0; - } -} - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - char *topology_str; - char *connect_topology_str; - char *blacklist_topology_str; - char *connect_topology_option_str; - char *connect_topology_option_modifier_string; - unsigned long long temp_settle; - - ok = 1; - - dotOutFile = FOPEN (dotOutFileName, "w"); - if (dotOutFile != NULL) - { - FPRINTF (dotOutFile, "%s", "strict graph G {\n"); - } - -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting daemons based on config file %s\n", cfgfile); -#endif - - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - return; - } - - if ((GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "topology", - &topology_str)) && - (GNUNET_NO == GNUNET_TESTING_topology_get (&topology, topology_str))) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid topology `%s' given for section %s option %s\n", - topology_str, "TESTING", "TOPOLOGY"); - topology = GNUNET_TESTING_TOPOLOGY_CLIQUE; /* Defaults to NONE, so set better default here */ - } - - if ((GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "connect_topology", - &connect_topology_str)) && - (GNUNET_NO == - GNUNET_TESTING_topology_get (&connection_topology, - connect_topology_str))) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid connect topology `%s' given for section %s option %s\n", - connect_topology_str, "TESTING", "CONNECT_TOPOLOGY"); - } - GNUNET_free_non_null (connect_topology_str); - if ((GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "connect_topology_option", - &connect_topology_option_str)) && - (GNUNET_NO == - GNUNET_TESTING_topology_option_get (&connect_topology_option, - connect_topology_option_str))) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid connect topology option `%s' given for section %s option %s\n", - connect_topology_option_str, "TESTING", - "CONNECT_TOPOLOGY_OPTION"); - connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Defaults to NONE, set to ALL */ - } - GNUNET_free_non_null (connect_topology_option_str); - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "connect_topology_option_modifier", - &connect_topology_option_modifier_string)) - { - if (SSCANF - (connect_topology_option_modifier_string, "%lf", - &connect_topology_option_modifier) != 1) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), - connect_topology_option_modifier_string, - "connect_topology_option_modifier", "TESTING"); - } - GNUNET_free (connect_topology_option_modifier_string); - } - - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "blacklist_transports", - &blacklist_transports)) - blacklist_transports = NULL; - - if ((GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "blacklist_topology", - &blacklist_topology_str)) && - (GNUNET_NO == - GNUNET_TESTING_topology_get (&blacklist_topology, - blacklist_topology_str))) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid topology `%s' given for section %s option %s\n", - topology_str, "TESTING", "BLACKLIST_TOPOLOGY"); - } - GNUNET_free_non_null (topology_str); - GNUNET_free_non_null (blacklist_topology_str); - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "SETTLE_TIME", - &settle_time)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "SETTLE_TIME"); - return; - } - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers", - &num_peers)) - num_peers = DEFAULT_NUM_PEERS; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "CONNECT_TIMEOUT", - &connect_timeout)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "CONNECT_TIMEOUT"); - return; - } - - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts", - &connect_attempts)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "connect_attempts"); - return; - } - - main_cfg = cfg; - - peers_left = num_peers; - - /** - * How long until we fail the whole testcase? - */ - test_timeout = - GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, - SECONDS_PER_PEER_START), num_peers * 2); - - /** - * How long until we give up on starting the peers? - */ - timeout = - GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, - SECONDS_PER_PEER_START), num_peers); - - modnum = num_peers / 4; - dotnum = (num_peers / 50) + 1; -#if VERBOSE - FPRINTF (stdout, "%s", "Hostkey generation progress: ["); -#endif - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (timeout, &end_badly, - "didn't generate all hostkeys within a reasonable amount of time!!!"); - - GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1); - pg = GNUNET_TESTING_daemons_start (cfg, peers_left, peers_left / 2, - peers_left, timeout, &hostkey_callback, - NULL, &peers_started_callback, NULL, - &topology_callback, NULL, NULL); - -} - -static int -check () -{ - char *binary_name; - char *config_file_name; - - GNUNET_asprintf (&binary_name, "test-testing-topology-%s", topology_string); - GNUNET_asprintf (&config_file_name, "test_testing_data_topology_%s.conf", - topology_string); - int ret; - - char *const argv[] = { binary_name, - "-c", - config_file_name, -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - binary_name, "nohelp", options, &run, &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-testing-topology-%s': Failed with error code %d\n", - topology_string, ret); - } - GNUNET_free (binary_name); - GNUNET_free (config_file_name); - return ok; -} - -int -main (int argc, char *argv[]) -{ - int ret; - char *binary_start_pos; - char *our_binary_name; - - binary_start_pos = rindex (argv[0], '/'); - GNUNET_assert (binary_start_pos != NULL); - topology_string = strstr (binary_start_pos, "_topology"); - GNUNET_assert (topology_string != NULL); - topology_string++; - topology_string = strstr (topology_string, "_"); - GNUNET_assert (topology_string != NULL); - topology_string++; - - GNUNET_asprintf (&our_binary_name, "test-testing-large-topology_%s", - topology_string); - GNUNET_asprintf (&dotOutFileName, "large_topology_%s.dot", topology_string); - - GNUNET_log_setup (our_binary_name, -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret = check (); - - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to remove testing directory %s\n", test_directory); - } - GNUNET_free (our_binary_name); - return ret; -} - -/* end of test_testing_topology.c */ diff --git a/src/testing/test_testing_peergroup.c b/src/testing/test_testing_peergroup.c deleted file mode 100644 index 061a0ca75..000000000 --- a/src/testing/test_testing_peergroup.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009 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 testing/test_testing_peergroup.c - * @brief testcase for functions to connect peers in testing_peergroup.c - */ -#include "platform.h" -#include "gnunet_testing_lib.h" - -#define VERBOSE GNUNET_NO - -#define NUM_PEERS 4 - -/** - * How long until we give up on connecting the peers? - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) - -static int ok; - -static int peers_left; - -static struct GNUNET_TESTING_PeerGroup *pg; - -/** - * Check whether peers successfully shut down. - */ -void -shutdown_callback (void *cls, const char *emsg) -{ - if (emsg != NULL) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n"); -#endif - if (ok == 0) - ok = 666; - } - else - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); -#endif - ok = 0; - } -} - - -static void -my_cb (void *cls, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Peergroup callback called with error, aborting test!\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n"); - ok = 1; - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - return; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Peer Group started successfully, ending test!\n"); - /** - * If something is to actually be DONE with the testcase, it should - * be put in here. Usually there will be a struct declared (or global - * variables can be used) to keep track of the state, statistics, - * handles to peers, etc. The example here is the opaque "TestCaseData" - * struct that could be passed into a function "additional_code_for_testing" - * which can be used to perform actions on the peers in the peergroup. - * Also, the GNUNET_TESTING_daemons_stop call would need to be removed, - * and only called once all of the testing is complete. - */ - - /** - * struct TestcaseData *state_closure; - * GNUNET_SCHEDULER_add_now(&additional_code_for_testing, state_closure); - */ - - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); -} - - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_CONFIGURATION_Handle *testing_cfg; - - ok = 1; - testing_cfg = GNUNET_CONFIGURATION_create (); - GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (testing_cfg, cfgfile)); -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n"); - GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing", - "use_progressbars", "YES"); -#endif - peers_left = NUM_PEERS; - pg = GNUNET_TESTING_peergroup_start (testing_cfg, peers_left, TIMEOUT, NULL, - &my_cb, NULL, NULL); - GNUNET_assert (pg != NULL); -} - -static int -check () -{ - char *const argv[] = { "test-testing-peergroup", - "-c", - "test_testing_peergroup_data.conf", -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-testing-peergroup", "nohelp", options, &run, &ok); - return ok; -} - -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test-testing-peergroup", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret = check (); - GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing"); - return ret; -} - -/* end of test_testing_peergroup.c */ diff --git a/src/testing/test_testing_peergroup_data.conf b/src/testing/test_testing_peergroup_data.conf deleted file mode 100644 index 6eadede95..000000000 --- a/src/testing/test_testing_peergroup_data.conf +++ /dev/null @@ -1,22 +0,0 @@ -@INLINE@ test_testing_defaults.conf -[PATHS] -DEFAULTCONFIG = test_testing_peergroup_data.conf - -[TESTING] -CONNECT_ATTEMPTS = 2 -MAX_OUTSTANDING_CONNECTIONS = 20 -MAX_CONCURRENT_SSH = 1 -PEERGROUP_TIMEOUT = 300 s -TOPOLOGY = CLIQUE -PERCENTAGE = 0.5 -PROBABILITY = 0.5 -CONNECT_TOPOLOGY = CLIQUE -CONNECT_TOPOLOGY_OPTION = CONNECT_NONE -CONNECT_TOPOLOGY_OPTION_MODIFIER = 0.0 -BLACKLIST_TOPOLOGY = NONE -BLACKLIST_TRANSPORTS = tcp udp -USE_PROGRESSBARS = NO - -[arm] -DEFAULTSERVICES = core - diff --git a/src/testing/test_testing_reconnect.c b/src/testing/test_testing_reconnect.c deleted file mode 100644 index bcee38659..000000000 --- a/src/testing/test_testing_reconnect.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2010 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 testing/test_testing_reconnect.c - * @brief testcase for functions to connect two peers in testing.c - */ -#include "platform.h" -#include "gnunet_testing_lib.h" - -#define VERBOSE GNUNET_YES - -/** - * How long until we give up on connecting the peers? - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) - -#define CONNECT_ATTEMPTS 3 - -static int ok; - -static struct GNUNET_TESTING_Daemon *d1; - -static struct GNUNET_TESTING_Daemon *d2; - -static struct GNUNET_CONFIGURATION_Handle *c1; - -static struct GNUNET_CONFIGURATION_Handle *c2; - -static struct GNUNET_TESTING_ConnectContext *cc; - -/** - * How many start-connect-stop iterations should we do? - */ -#define NUM_PHASES 2 - -static int phase; - -/** - * Run the next phase of starting daemons, connecting them and - * stopping them again. - */ -static void -run_phase (void); - -static void -end2_cb (void *cls, const char *emsg) -{ - - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg); - ok = 1; - } - else - { - if (phase < NUM_PHASES) - { - FPRINTF (stderr, "%s", "."); - run_phase (); - return; - } - FPRINTF (stderr, "%s", ".\n"); -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Both daemons terminated, will now exit.\n"); -#endif - ok = 0; - } -} - -static void -end1_cb (void *cls, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Stopping daemon 1 gave: %s\n", - emsg); - ok = 1; - } - else - { - ok = 0; - } - if (d2 != NULL) - { - GNUNET_TESTING_daemon_stop (d2, TIMEOUT, &end2_cb, NULL, - (phase == NUM_PHASES) ? GNUNET_YES : GNUNET_NO, - GNUNET_NO); - d2 = NULL; - } -} - -static void -finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &end1_cb, NULL, - (phase == NUM_PHASES) ? GNUNET_YES : GNUNET_NO, - GNUNET_NO); - d1 = NULL; -} - - -static void -my_connect_complete (void *cls, const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, - unsigned int distance, - const struct GNUNET_CONFIGURATION_Handle *first_cfg, - const struct GNUNET_CONFIGURATION_Handle *second_cfg, - struct GNUNET_TESTING_Daemon *first_daemon, - struct GNUNET_TESTING_Daemon *second_daemon, - const char *emsg) -{ - cc = NULL; -#if VERBOSE - FPRINTF (stderr, "Peer %s ", GNUNET_i2s (first)); - FPRINTF (stderr, "connected to %s\n", GNUNET_i2s (second)); -#endif - GNUNET_SCHEDULER_add_now (&finish_testing, NULL); -} - - - - -static void -my_cb2 (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Starting daemon 2 gave: %s\n", - emsg); - GNUNET_assert (0); - return; - } - GNUNET_assert (id != NULL); -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n", - GNUNET_i2s (id)); -#endif - cc = GNUNET_TESTING_daemons_connect (d1, d2, TIMEOUT, CONNECT_ATTEMPTS, - GNUNET_YES, &my_connect_complete, NULL); -} - - -static void -my_cb1 (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Starting daemon 1 gave: %s\n", - emsg); - GNUNET_assert (0); - return; - } - GNUNET_assert (id != NULL); -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n", - GNUNET_i2s (id)); -#endif - d2 = GNUNET_TESTING_daemon_start (c2, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL, - NULL, NULL, &my_cb2, NULL); - GNUNET_assert (d2 != NULL); -} - - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - ok = 1; -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n"); -#endif - c1 = GNUNET_CONFIGURATION_create (); - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_load (c1, - "test_testing_connect_peer1.conf")); - c2 = GNUNET_CONFIGURATION_create (); - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_load (c2, - "test_testing_connect_peer2.conf")); - run_phase (); -} - -static void -run_phase () -{ - phase++; - d1 = GNUNET_TESTING_daemon_start (c1, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL, - NULL, NULL, &my_cb1, NULL); - GNUNET_assert (d1 != NULL); -} - -static int -check () -{ - char *const argv[] = { "test-testing-reconnect", - "-c", - "test_testing_data.conf", -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-testing-reconnect", "nohelp", options, &run, &ok); - return ok; -} - -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test-testing-reconnect", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret = check (); - return ret; -} - -/* end of test_testing_reconnect.c */ diff --git a/src/testing/test_testing_topology.c b/src/testing/test_testing_topology.c deleted file mode 100644 index 94cbc0df6..000000000 --- a/src/testing/test_testing_topology.c +++ /dev/null @@ -1,1220 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009 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 testing/test_testing_topology.c - * @brief base testcase for testing all the topologies provided - */ -#include "platform.h" -#include "gnunet_testing_lib.h" -#include "gnunet_core_service.h" -#include "gnunet_os_lib.h" - - -#define PROGRESS_BARS GNUNET_YES - -#define DELAY_FOR_LOGGING GNUNET_NO - -/** - * How long until we fail the whole testcase? - */ -#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 240) - -/** - * How long until we give up on starting the peers? - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 500) - -#define SECONDS_PER_PEER_START 120 - -#define DEFAULT_NUM_PEERS 4 - -#define MAX_OUTSTANDING_CONNECTIONS 100 - -static float fail_percentage = 0.05; - -static int ok; - -static unsigned long long num_peers; - -struct GNUNET_TIME_Relative connect_timeout; - -static unsigned long long connect_attempts; - -static unsigned int topology_connections; - -static unsigned int total_connections; - -static unsigned int failed_connections; - -static unsigned int total_server_connections; - -static unsigned int total_messages_received; - -static unsigned int expected_messages; - -static unsigned int expected_connections; - -static unsigned long long peers_left; - -static struct GNUNET_TESTING_PeerGroup *pg; - -const struct GNUNET_CONFIGURATION_Handle *main_cfg; - -GNUNET_SCHEDULER_TaskIdentifier die_task; - -static char *dotOutFileName; - -static struct GNUNET_TIME_Relative settle_time; - -static FILE *dotOutFile; - -static char *topology_string; - -static char *blacklist_transports; - -static int transmit_ready_scheduled; - -static int transmit_ready_failed; - -static int transmit_ready_called; - -static unsigned int modnum; - -static unsigned int dotnum; - -static enum GNUNET_TESTING_Topology topology; - -static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* Don't do any blacklisting */ - -static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */ - -static enum GNUNET_TESTING_TopologyOption connect_topology_option = - GNUNET_TESTING_TOPOLOGY_OPTION_ALL; - -static double connect_topology_option_modifier = 0.0; - -static char *test_directory; - -#define MTYPE 12345 - -GNUNET_NETWORK_STRUCT_BEGIN - -struct GNUNET_TestMessage -{ - /** - * Header of the message - */ - struct GNUNET_MessageHeader header; - - /** - * Unique identifier for this message. - */ - uint32_t uid; -}; -GNUNET_NETWORK_STRUCT_END - -struct TestMessageContext -{ - /* This is a linked list */ - struct TestMessageContext *next; - - /* Handle to the sending peer core */ - struct GNUNET_CORE_Handle *peer1handle; - - /* Handle to the receiving peer core */ - struct GNUNET_CORE_Handle *peer2handle; - - /* Handle to the sending peer daemon */ - struct GNUNET_TESTING_Daemon *peer1; - - /* Handle to the receiving peer daemon */ - struct GNUNET_TESTING_Daemon *peer2; - - /* Identifier for this message, so we don't disconnect other peers! */ - uint32_t uid; - - /* Has peer1 been notified already of a connection to peer2? */ - int peer1notified; - - /* Has the core of peer2 been connected already? */ - int peer2connected; - - /* Task for disconnecting cores, allow task to be cancelled on shutdown */ - GNUNET_SCHEDULER_TaskIdentifier disconnect_task; - -}; - -static struct TestMessageContext *test_messages; - -/** - * Check whether peers successfully shut down. - */ -static void -shutdown_callback (void *cls, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Shutdown of peers failed: %s!\n", - emsg); - if (ok == 0) - ok = 666; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); - } -} - - -#if DELAY_FOR_LOGGING -static void -gather_log_data () -{ - char *peer_number; - char *connect_number; - struct GNUNET_OS_Process *mem_process; - - GNUNET_asprintf (&peer_number, "%llu", num_peers); - GNUNET_asprintf (&connect_number, "%llu", expected_connections); - mem_process = - GNUNET_OS_start_process (NULL, NULL, "./memsize.pl", "memsize.pl", - "totals.txt", peer_number, connect_number, NULL); - GNUNET_OS_process_wait (mem_process); - GNUNET_OS_process_destroy (mem_process); - mem_process = NULL; -} -#endif - - -static void -finish_testing () -{ - GNUNET_assert (pg != NULL); - struct TestMessageContext *pos; - struct TestMessageContext *free_pos; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Called finish testing, stopping daemons.\n"); - pos = test_messages; - while (pos != NULL) - { - if (pos->peer1handle != NULL) - { - GNUNET_CORE_disconnect (pos->peer1handle); - pos->peer1handle = NULL; - } - if (pos->peer2handle != NULL) - { - GNUNET_CORE_disconnect (pos->peer2handle); - pos->peer2handle = NULL; - } - free_pos = pos; - pos = pos->next; - if (free_pos->disconnect_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (free_pos->disconnect_task); - } - GNUNET_free (free_pos); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n", - transmit_ready_scheduled, transmit_ready_failed, - transmit_ready_called); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n"); - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - - if (dotOutFile != NULL) - { - FPRINTF (dotOutFile, "%s", "}"); - FCLOSE (dotOutFile); - } - ok = 0; -} - - -static void -disconnect_cores (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct TestMessageContext *pos = cls; - - /* Disconnect from the respective cores */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 1 `%4s'\n", - GNUNET_i2s (&pos->peer1->id)); - if (pos->peer1handle != NULL) - { - GNUNET_CORE_disconnect (pos->peer1handle); - pos->peer1handle = NULL; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 2 `%4s'\n", - GNUNET_i2s (&pos->peer2->id)); - if (pos->peer2handle != NULL) - { - GNUNET_CORE_disconnect (pos->peer2handle); - pos->peer2handle = NULL; - } - pos->disconnect_task = GNUNET_SCHEDULER_NO_TASK; - /* Decrement total connections so new can be established */ - total_server_connections -= 2; -} - -#if DO_STATS -static void -stats_finished (void *cls, int result) -{ - GNUNET_SCHEDULER_add_now (&finish_testing, NULL); -} - -/** - * Callback function to process statistic values. - * - * @param cls closure - * @param peer the peer the statistics belong to - * @param subsystem name of subsystem that created the statistic - * @param name the name of the datum - * @param value the current value - * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not - * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration - */ -static int -stats_print (void *cls, const struct GNUNET_PeerIdentity *peer, - const char *subsystem, const char *name, uint64_t value, - int is_persistent) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s:%s:%s -- %llu\n", GNUNET_i2s (peer), - subsystem, name, value); - return GNUNET_OK; -} -#endif - - -static void -topology_cb (void *cls, const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, const char *emsg) -{ - FILE *outfile = cls; - - if (first != NULL) - { - if (outfile != NULL) - { - FPRINTF (outfile, "\t\"%s\" -- ", GNUNET_i2s (first)); - FPRINTF (outfile, "\"%s\";\n", GNUNET_i2s (second)); - } - topology_connections++; - } - else - { - FPRINTF (stderr, - "Finished iterating over topology, %d total connections!\n", - topology_connections); - if (outfile != NULL) - { - FPRINTF (outfile, "%s", "}\n"); - FCLOSE (outfile); -#if DO_STATS - GNUNET_TESTING_get_statistics (pg, &stats_finished, &stats_print, NULL); -#endif - GNUNET_SCHEDULER_add_now (&finish_testing, NULL); - } - } -} - - -static int -process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi, - unsigned int atsi_count) -{ - char *dotOutFileNameFinished; - FILE *dotOutFileFinished; - struct TestMessageContext *pos = cls; - struct GNUNET_TestMessage *msg = (struct GNUNET_TestMessage *) message; - - if (pos->uid != ntohl (msg->uid)) - return GNUNET_OK; - -#if PROGRESS_BARS - if ((total_messages_received) % modnum == 0) - { - if (total_messages_received == 0) - FPRINTF (stdout, "%s", "0%%"); - else - FPRINTF (stdout, "%d%%", - (int) (((float) total_messages_received / expected_messages) * - 100)); - - } - else if (total_messages_received % dotnum == 0) - { - FPRINTF (stdout, "%s", "."); - } - fflush (stdout); -#endif - - total_messages_received++; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received message from `%4s', type %d.\n", GNUNET_i2s (peer), - ntohs (message->type)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Total messages received %d, expected %d.\n", - total_messages_received, expected_messages); - - if (total_messages_received == expected_messages) - { -#if PROGRESS_BARS - FPRINTF (stdout, "%s", "100%%]\n"); -#endif - GNUNET_SCHEDULER_cancel (die_task); - GNUNET_asprintf (&dotOutFileNameFinished, "%s.dot", "final_topology"); - dotOutFileFinished = FOPEN (dotOutFileNameFinished, "w"); - GNUNET_free (dotOutFileNameFinished); - if (dotOutFileFinished != NULL) - { - FPRINTF (dotOutFileFinished, "%s", "strict graph G {\n"); - } - topology_connections = 0; - GNUNET_TESTING_get_topology (pg, &topology_cb, dotOutFileFinished); - //GNUNET_SCHEDULER_add_now (&finish_testing, NULL); - } - else - { - pos->disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cores, pos); - } - - return GNUNET_OK; -} - - -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - char *msg = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Ending with error: %s\n", msg); - struct TestMessageContext *pos; - struct TestMessageContext *free_pos; - - pos = test_messages; - while (pos != NULL) - { - if (pos->peer1handle != NULL) - { - GNUNET_CORE_disconnect (pos->peer1handle); - pos->peer1handle = NULL; - } - if (pos->peer2handle != NULL) - { - GNUNET_CORE_disconnect (pos->peer2handle); - pos->peer2handle = NULL; - } - free_pos = pos; - pos = pos->next; - GNUNET_free (free_pos); - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n", - transmit_ready_scheduled, transmit_ready_failed, - transmit_ready_called); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Total messages received %d, expected %d.\n", - total_messages_received, expected_messages); - - if (pg != NULL) - { - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - ok = 7331; /* Opposite of leet */ - } - else - ok = 401; /* Never got peers started */ - - if (dotOutFile != NULL) - { - FPRINTF (dotOutFile, "%s", "}"); - FCLOSE (dotOutFile); - } -} - - -static size_t -transmit_ready (void *cls, size_t size, void *buf) -{ - struct GNUNET_TestMessage *m; - struct TestMessageContext *pos = cls; - - GNUNET_assert (buf != NULL); - m = (struct GNUNET_TestMessage *) buf; - m->header.type = htons (MTYPE); - m->header.size = htons (sizeof (struct GNUNET_TestMessage)); - m->uid = htonl (pos->uid); - transmit_ready_called++; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "transmit ready for peer %s\ntransmit_ready's scheduled %d, transmit_ready's called %d\n", - GNUNET_i2s (&pos->peer1->id), transmit_ready_scheduled, - transmit_ready_called); - return sizeof (struct GNUNET_TestMessage); -} - - -static struct GNUNET_CORE_MessageHandler no_handlers[] = { - {NULL, 0, 0} -}; - - -static struct GNUNET_CORE_MessageHandler handlers[] = { - {&process_mtype, MTYPE, sizeof (struct GNUNET_TestMessage)}, - {NULL, 0, 0} -}; - - -static void -init_notify_peer2 (void *cls, struct GNUNET_CORE_Handle *server, - const struct GNUNET_PeerIdentity *my_identity) -{ - struct TestMessageContext *pos = cls; - - total_server_connections++; - - pos->peer2connected = GNUNET_YES; - if (pos->peer1notified == GNUNET_YES) /* Peer 1 has been notified of connection to peer 2 */ - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n", - GNUNET_i2s (my_identity), - GNUNET_h2s (&pos->peer1->id.hashPubKey)); - if (NULL == - GNUNET_CORE_notify_transmit_ready (pos->peer1handle, GNUNET_YES, 0, - TIMEOUT, &pos->peer2->id, - sizeof (struct GNUNET_TestMessage), - &transmit_ready, pos)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", - GNUNET_i2s (&pos->peer2->id)); - transmit_ready_failed++; - } - else - { - transmit_ready_scheduled++; - } - } -} - - -/** - * Method called whenever a given peer connects. - * - * @param cls closure - * @param peer peer identity this notification is about - * @param atsi performance data for the connection - * @param atsi_count number of records in 'atsi' - */ -static void -connect_notify_peers (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_ATS_Information *atsi, - unsigned int atsi_count) -{ - struct TestMessageContext *pos = cls; - - if (0 == memcmp (peer, &pos->peer2->id, sizeof (struct GNUNET_PeerIdentity))) - { - pos->peer1notified = GNUNET_YES; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Peer `%s' notified of connection to peer `%s'\n", - GNUNET_i2s (&pos->peer1->id), GNUNET_h2s (&peer->hashPubKey)); - } - else - return; - - if (pos->peer2connected == GNUNET_YES) /* Already connected and notified of connection, send message! */ - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n", - GNUNET_i2s (&pos->peer2->id), - GNUNET_h2s (&pos->peer1->id.hashPubKey)); - if (NULL == - GNUNET_CORE_notify_transmit_ready (pos->peer1handle, GNUNET_YES, 0, - TIMEOUT, &pos->peer2->id, - sizeof (struct GNUNET_TestMessage), - &transmit_ready, pos)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", - GNUNET_i2s (&pos->peer2->id)); - transmit_ready_failed++; - } - else - { - transmit_ready_scheduled++; - } - } -} - - -static void -init_notify_peer1 (void *cls, struct GNUNET_CORE_Handle *server, - const struct GNUNET_PeerIdentity *my_identity) -{ - struct TestMessageContext *pos = cls; - - total_server_connections++; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Core connection to `%4s' established, setting up handles\n", - GNUNET_i2s (my_identity)); - /* - * Connect to the receiving peer - */ - pos->peer2handle = - GNUNET_CORE_connect (pos->peer2->cfg, pos, &init_notify_peer2, NULL, - NULL, NULL, GNUNET_YES, NULL, GNUNET_YES, handlers); - -} - - -static void -send_test_messages (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct TestMessageContext *pos = cls; - - if ((pos == test_messages) && (settle_time.rel_value > 0)) - { - topology_connections = 0; - GNUNET_TESTING_get_topology (pg, &topology_cb, NULL); - } - if (((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) || (cls == NULL)) - return; - - if (die_task == GNUNET_SCHEDULER_NO_TASK) - { - die_task = - GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &end_badly, - "from send test messages (timeout)"); - } - - if (total_server_connections >= MAX_OUTSTANDING_CONNECTIONS) - { - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 1), - &send_test_messages, pos); - return; /* Otherwise we'll double schedule messages here! */ - } - - /* - * Connect to the sending peer - */ - pos->peer1handle = - GNUNET_CORE_connect (pos->peer1->cfg, pos, &init_notify_peer1, - &connect_notify_peers, NULL, NULL, GNUNET_NO, NULL, - GNUNET_NO, no_handlers); - - GNUNET_assert (pos->peer1handle != NULL); - - if (total_server_connections < MAX_OUTSTANDING_CONNECTIONS) - { - GNUNET_SCHEDULER_add_now (&send_test_messages, pos->next); - } - else - { - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 1), - &send_test_messages, pos->next); - } -} - - -static void -topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, uint32_t distance, - const struct GNUNET_CONFIGURATION_Handle *first_cfg, - const struct GNUNET_CONFIGURATION_Handle *second_cfg, - struct GNUNET_TESTING_Daemon *first_daemon, - struct GNUNET_TESTING_Daemon *second_daemon, - const char *emsg) -{ - struct TestMessageContext *temp_context; - - if (emsg == NULL) - { -#if PROGRESS_BARS - if ((total_connections) % modnum == 0) - { - if (total_connections == 0) - FPRINTF (stdout, "%s", "0%%"); - else - FPRINTF (stdout, "%d%%", - (int) (((float) total_connections / expected_connections) * - 100)); - - } - else if (total_connections % dotnum == 0) - { - FPRINTF (stdout, "%s", "."); - } - fflush (stdout); -#endif - total_connections++; - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "connected peer %s to peer %s\n", - first_daemon->shortname, second_daemon->shortname); - temp_context = GNUNET_malloc (sizeof (struct TestMessageContext)); - temp_context->peer1 = first_daemon; - temp_context->peer2 = second_daemon; - temp_context->next = test_messages; - temp_context->uid = total_connections; - temp_context->disconnect_task = GNUNET_SCHEDULER_NO_TASK; - test_messages = temp_context; - - expected_messages++; - if (dotOutFile != NULL) - FPRINTF (dotOutFile, "\tn%s -- n%s;\n", first_daemon->shortname, - second_daemon->shortname); - } - else - { - failed_connections++; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to connect peer %s to peer %s with error :\n%s\n", - first_daemon->shortname, second_daemon->shortname, emsg); - } - - if (total_connections == expected_connections) - { -#if PROGRESS_BARS - FPRINTF (stdout, "%s", "100%%]\n"); -#endif - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Created %d total connections, which is our target number! Calling send messages.\n", - total_connections); - modnum = expected_messages / 4; - dotnum = (expected_messages / 50) + 1; - if (modnum == 0) - modnum = 1; - if (dotnum == 0) - dotnum = 1; - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; -#if DELAY_FOR_LOGGING - FPRINTF (stdout, "%s", "Sending test messages in 10 seconds.\n"); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 10), - &send_test_messages, test_messages); - gather_log_data (); -#else - if (settle_time.rel_value > 0) - { - GNUNET_TESTING_get_topology (pg, &topology_cb, NULL); - } - GNUNET_SCHEDULER_add_delayed (settle_time, &send_test_messages, - test_messages); -#endif -#if PROGRESS_BARS - FPRINTF (stdout, "%s", "Test message progress: ["); -#endif - - } - else if (total_connections + failed_connections == expected_connections) - { - if (failed_connections < - (unsigned int) (fail_percentage * total_connections)) - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_SCHEDULER_add_now (&send_test_messages, test_messages); - } - else - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = - GNUNET_SCHEDULER_add_now (&end_badly, - "from topology_callback (too many failed connections)"); - } - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Have %d total connections, %d failed connections, Want %d (at least %d)\n", - total_connections, failed_connections, expected_connections, - expected_connections - - (unsigned int) (fail_percentage * expected_connections)); - } -} - - -static void -topology_creation_finished (void *cls, const char *emsg) -{ - if (emsg == NULL) - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "All topology connections created successfully!\n"); -} - - -static void -connect_topology () -{ - expected_connections = -1; - if ((pg != NULL) && (peers_left == 0)) - { - expected_connections = - GNUNET_TESTING_connect_topology (pg, connection_topology, - connect_topology_option, - connect_topology_option_modifier, - connect_timeout, connect_attempts, - &topology_creation_finished, NULL); -#if PROGRESS_BARS - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n", - expected_connections); -#endif - } - - GNUNET_SCHEDULER_cancel (die_task); - if (expected_connections < 1) - { - die_task = - GNUNET_SCHEDULER_add_now (&end_badly, - "from connect topology (bad return)"); - return; - } - - die_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, - SECONDS_PER_PEER_START * num_peers), - &end_badly, - "from connect topology (timeout)"); - modnum = expected_connections / 4; - dotnum = (expected_connections / 50) + 1; - if (modnum == 0) - modnum = 1; - if (dotnum == 0) - dotnum = 1; -#if PROGRESS_BARS - FPRINTF (stdout, "%s", "Peer connection progress: ["); -#endif -} - -static void -create_topology () -{ - peers_left = num_peers; /* Reset counter */ - if (GNUNET_TESTING_create_topology - (pg, topology, blacklist_topology, blacklist_transports) != GNUNET_SYSERR) - { -#if PROGRESS_BARS - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Topology set up, now starting peers!\n"); - FPRINTF (stdout, "%s", "Daemon start progress ["); -#endif - GNUNET_TESTING_daemons_continue_startup (pg); - } - else - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = - GNUNET_SCHEDULER_add_now (&end_badly, - "from create topology (bad return)"); - } - GNUNET_SCHEDULER_cancel (die_task); - die_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, - SECONDS_PER_PEER_START * num_peers), - &end_badly, - "from continue startup (timeout)"); -} - - -static void -peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Failed to start daemon with error: `%s'\n", emsg); - return; - } - GNUNET_assert (id != NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n", - (num_peers - peers_left) + 1, num_peers); -#if PROGRESS_BARS - if ((num_peers - peers_left) % modnum == 0) - { - if (num_peers - peers_left == 0) - FPRINTF (stdout, "%s", "0%%"); - else - FPRINTF (stdout, "%d%%", - (int) (((float) (num_peers - peers_left) / num_peers) * 100)); - - } - else if ((num_peers - peers_left) % dotnum == 0) - { - FPRINTF (stdout, "%s", "."); - } - fflush (stdout); -#endif - peers_left--; - if (peers_left == 0) - { -#if PROGRESS_BARS - FPRINTF (stdout, "%s", "100%%]\n"); -#endif - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "All %d daemons started, now connecting peers!\n", num_peers); - GNUNET_SCHEDULER_cancel (die_task); - /* Set up task in case topology creation doesn't finish - * within a reasonable amount of time */ - die_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MINUTES, 8), &end_badly, - "from peers_started_callback"); -#if DELAY_FOR_LOGGING - FPRINTF (stdout, "%s", "Connecting topology in 10 seconds\n"); - gather_log_data (); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 10), - &connect_topology, NULL); -#else - connect_topology (); -#endif - ok = 0; - } -} - -/** - * Callback indicating that the hostkey was created for a peer. - * - * @param cls NULL - * @param id the peer identity - * @param d the daemon handle (pretty useless at this point, remove?) - * @param emsg non-null on failure - */ -void -hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Hostkey callback received error: %s\n", emsg); - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Hostkey (%d/%d) created for peer `%s'\n", num_peers - peers_left, - num_peers, GNUNET_i2s (id)); -#if PROGRESS_BARS - if ((num_peers - peers_left) % modnum == 0) - { - if (num_peers - peers_left == 0) - FPRINTF (stdout, "%s", "0%%"); - else - FPRINTF (stdout, "%d%%", - (int) (((float) (num_peers - peers_left) / num_peers) * 100)); - - } - else if ((num_peers - peers_left) % dotnum == 0) - { - FPRINTF (stdout, "%s", "."); - } - fflush (stdout); -#endif - peers_left--; - if (peers_left == 0) - { -#if PROGRESS_BARS - FPRINTF (stdout, "%s", "100%%]\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "All %d hostkeys created, now creating topology!\n", num_peers); -#endif - GNUNET_SCHEDULER_cancel (die_task); - /* Set up task in case topology creation doesn't finish - * within a reasonable amount of time */ - die_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, - "from create_topology"); - GNUNET_SCHEDULER_add_now (&create_topology, NULL); - ok = 0; - } -} - - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - char *topology_str; - char *connect_topology_str; - char *blacklist_topology_str; - char *connect_topology_option_str; - char *connect_topology_option_modifier_string; - unsigned long long max_outstanding_connections; - - ok = 1; - - dotOutFile = FOPEN (dotOutFileName, "w"); - if (dotOutFile != NULL) - { - FPRINTF (dotOutFile, "%s", "strict graph G {\n"); - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting daemons based on config file %s\n", cfgfile); - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - return; - } - - if ((GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "topology", - &topology_str)) && - (GNUNET_NO == GNUNET_TESTING_topology_get (&topology, topology_str))) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid topology `%s' given for section %s option %s\n", - topology_str, "TESTING", "TOPOLOGY"); - topology = GNUNET_TESTING_TOPOLOGY_CLIQUE; /* Defaults to NONE, so set better default here */ - } - - if ((GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "connect_topology", - &connect_topology_str)) && - (GNUNET_NO == - GNUNET_TESTING_topology_get (&connection_topology, - connect_topology_str))) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid connect topology `%s' given for section %s option %s\n", - connect_topology_str, "TESTING", "CONNECT_TOPOLOGY"); - } - GNUNET_free_non_null (connect_topology_str); - if ((GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "connect_topology_option", - &connect_topology_option_str)) && - (GNUNET_NO == - GNUNET_TESTING_topology_option_get (&connect_topology_option, - connect_topology_option_str))) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid connect topology option `%s' given for section %s option %s\n", - connect_topology_option_str, "TESTING", - "CONNECT_TOPOLOGY_OPTION"); - connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Defaults to NONE, set to ALL */ - } - GNUNET_free_non_null (connect_topology_option_str); - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "connect_topology_option_modifier", - &connect_topology_option_modifier_string)) - { - if (SSCANF - (connect_topology_option_modifier_string, "%lf", - &connect_topology_option_modifier) != 1) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), - connect_topology_option_modifier_string, - "connect_topology_option_modifier", "TESTING"); - } - GNUNET_free (connect_topology_option_modifier_string); - } - - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "blacklist_transports", - &blacklist_transports)) - blacklist_transports = NULL; - - if ((GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "blacklist_topology", - &blacklist_topology_str)) && - (GNUNET_NO == - GNUNET_TESTING_topology_get (&blacklist_topology, - blacklist_topology_str))) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid topology `%s' given for section %s option %s\n", - topology_str, "TESTING", "BLACKLIST_TOPOLOGY"); - } - GNUNET_free_non_null (topology_str); - GNUNET_free_non_null (blacklist_topology_str); - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "SETTLE_TIME", - &settle_time)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "SETTLE_TIME"); - return; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "CONNECT_TIMEOUT", - &connect_timeout)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "CONNECT_TIMEOUT"); - return; - } - - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts", - &connect_attempts)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "connect_attempts"); - return; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", - "max_outstanding_connections", - &max_outstanding_connections)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "max_outstanding_connections"); - return; - } - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers", - &num_peers)) - num_peers = DEFAULT_NUM_PEERS; - - main_cfg = cfg; - - peers_left = num_peers; - modnum = num_peers / 4; - dotnum = (num_peers / 50) + 1; - if (modnum == 0) - modnum = 1; - if (dotnum == 0) - dotnum = 1; -#if PROGRESS_BARS - FPRINTF (stdout, "%s", "Hostkey generation progress: ["); -#endif - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, - SECONDS_PER_PEER_START * num_peers), - &end_badly, - "didn't generate all hostkeys within a reasonable amount of time!!!"); - - GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1); - pg = GNUNET_TESTING_daemons_start (cfg, peers_left, - max_outstanding_connections, peers_left, - GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, - SECONDS_PER_PEER_START * num_peers), - &hostkey_callback, NULL, - &peers_started_callback, NULL, - &topology_callback, NULL, NULL); - -} - - -static int -check () -{ - char *binary_name; - char *config_file_name; - - GNUNET_asprintf (&binary_name, "test-testing-topology-%s", topology_string); - GNUNET_asprintf (&config_file_name, "test_testing_data_topology_%s.conf", - topology_string); - int ret; - - char *const argv[] = { binary_name, - "-c", - config_file_name, - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - binary_name, "nohelp", options, &run, &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-testing-topology-%s': Failed with error code %d\n", - topology_string, ret); - } - GNUNET_free (binary_name); - GNUNET_free (config_file_name); - return ok; -} - - -int -main (int argc, char *argv[]) -{ - int ret; - char *binary_start_pos; - char *our_binary_name; - char *dotexe; - - binary_start_pos = strchr (argv[0], '/'); - GNUNET_assert (binary_start_pos != NULL); - topology_string = strstr (binary_start_pos, "_topology"); - GNUNET_assert (topology_string != NULL); - topology_string++; - topology_string = strstr (topology_string, "_"); - GNUNET_assert (topology_string != NULL); - topology_string++; - topology_string = GNUNET_strdup (topology_string); - if (NULL != (dotexe = strstr (topology_string, ".exe"))) - dotexe[0] = '\0'; - GNUNET_asprintf (&our_binary_name, "test-testing-topology_%s", - topology_string); - GNUNET_asprintf (&dotOutFileName, "topology_%s.dot", topology_string); - - GNUNET_log_setup (our_binary_name, - "WARNING", - NULL); - ret = check (); - GNUNET_free (topology_string); - - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to remove testing directory %s\n", test_directory); - } - GNUNET_free (our_binary_name); - return ret; -} - -/* end of test_testing_topology.c */ diff --git a/src/testing/test_testing_topology_blacklist.c b/src/testing/test_testing_topology_blacklist.c deleted file mode 100644 index c90f48d9b..000000000 --- a/src/testing/test_testing_topology_blacklist.c +++ /dev/null @@ -1,595 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009 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 testing/test_testing_topology_blacklist.c - * @brief base testcase for testing transport level blacklisting - */ -#include "platform.h" -#include "gnunet_testing_lib.h" -#include "gnunet_core_service.h" - -#define VERBOSE GNUNET_NO - -/** - * How long until we fail the whole testcase? - */ -#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600) - -/** - * How long until we give up on starting the peers? (Must be longer than the connect timeout!) - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) - -#define DEFAULT_NUM_PEERS 4 - -#define MAX_OUTSTANDING_CONNECTIONS 300 - -static int ok; - -struct GNUNET_TIME_Relative connect_timeout; - -static unsigned long long connect_attempts; - -static unsigned long long num_peers; - -static unsigned int total_connections; - -static unsigned int failed_connections; - -static unsigned int expected_connections; - -static unsigned int expected_failed_connections; - -static unsigned long long peers_left; - -static struct GNUNET_TESTING_PeerGroup *pg; - -const struct GNUNET_CONFIGURATION_Handle *main_cfg; - -GNUNET_SCHEDULER_TaskIdentifier die_task; - -static char *dotOutFileName; - -static FILE *dotOutFile; - -static char *blacklist_transports; - -static enum GNUNET_TESTING_Topology topology = GNUNET_TESTING_TOPOLOGY_CLIQUE; /* Overlay should allow all connections */ - -static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_RING; /* Blacklist underlay into a ring */ - -static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */ - -static enum GNUNET_TESTING_TopologyOption connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Try to connect all possible OVERLAY connections */ - -static double connect_topology_option_modifier = 0.0; - -static char *test_directory; - -#define MTYPE 12345 - -GNUNET_NETWORK_STRUCT_BEGIN - -struct GNUNET_TestMessage -{ - /** - * Header of the message - */ - struct GNUNET_MessageHeader header; - - /** - * Unique identifier for this message. - */ - uint32_t uid; -}; -GNUNET_NETWORK_STRUCT_END - -/** - * Check whether peers successfully shut down. - */ -void -shutdown_callback (void *cls, const char *emsg) -{ - if (emsg != NULL) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n"); -#endif - if (ok == 0) - ok = 666; - } - else - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); -#endif - } -} - -static void -finish_testing () -{ - GNUNET_assert (pg != NULL); - -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Called finish testing, stopping daemons.\n"); -#endif - sleep (1); -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n"); -#endif - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "daemons_stop finished\n"); -#endif - if (dotOutFile != NULL) - { - FPRINTF (dotOutFile, "%s", "}"); - FCLOSE (dotOutFile); - } - - ok = 0; -} - -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - char *msg = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "End badly was called (%s)... stopping daemons.\n", msg); - - if (pg != NULL) - { - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - ok = 7331; /* Opposite of leet */ - } - else - ok = 401; /* Never got peers started */ - - if (dotOutFile != NULL) - { - FPRINTF (dotOutFile, "%s", "}"); - FCLOSE (dotOutFile); - } -} - - - -void -topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, uint32_t distance, - const struct GNUNET_CONFIGURATION_Handle *first_cfg, - const struct GNUNET_CONFIGURATION_Handle *second_cfg, - struct GNUNET_TESTING_Daemon *first_daemon, - struct GNUNET_TESTING_Daemon *second_daemon, - const char *emsg) -{ - if (emsg == NULL) - { - total_connections++; -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected peer %s to peer %s\n", - first_daemon->shortname, second_daemon->shortname); -#endif - if (dotOutFile != NULL) - FPRINTF (dotOutFile, "\tn%s -- n%s;\n", first_daemon->shortname, - second_daemon->shortname); - } - - else - { - failed_connections++; -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Failed to connect peer %s to peer %s with error :\n%s\n", - first_daemon->shortname, second_daemon->shortname, emsg); -#endif - } - - - if (total_connections == expected_connections) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Created %d total connections, which is our target number (that's bad)!\n", - total_connections); -#endif - - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; - die_task = - GNUNET_SCHEDULER_add_now (&end_badly, - "from topology_callback (too many successful connections)"); - } - else if (total_connections + failed_connections == expected_connections) - { - if ((failed_connections == expected_failed_connections) && - (total_connections == - expected_connections - expected_failed_connections)) - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; - die_task = GNUNET_SCHEDULER_add_now (&finish_testing, NULL); - } - else - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = - GNUNET_SCHEDULER_add_now (&end_badly, - "from topology_callback (wrong number of failed connections)"); - } - } - else - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Have %d total connections, %d failed connections, Want %d (failed) and %d (successful)\n", - total_connections, failed_connections, - expected_failed_connections, - expected_connections - expected_failed_connections); -#endif - } -} - -static void -connect_topology () -{ - expected_connections = -1; - if ((pg != NULL) && (peers_left == 0)) - { - expected_connections = - GNUNET_TESTING_connect_topology (pg, connection_topology, - connect_topology_option, - connect_topology_option_modifier, - connect_timeout, connect_attempts, - NULL, NULL); -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n", - expected_connections); -#endif - } - - GNUNET_SCHEDULER_cancel (die_task); - if (expected_connections == GNUNET_SYSERR) - { - die_task = - GNUNET_SCHEDULER_add_now (&end_badly, - "from connect topology (bad return)"); - } - - die_task = - GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &end_badly, - "from connect topology (timeout)"); -} - -static void -create_topology () -{ - peers_left = num_peers; /* Reset counter */ - if (GNUNET_TESTING_create_topology - (pg, topology, blacklist_topology, blacklist_transports) != GNUNET_SYSERR) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Topology set up, now starting peers!\n"); -#endif - GNUNET_TESTING_daemons_continue_startup (pg); - } - else - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = - GNUNET_SCHEDULER_add_now (&end_badly, - "from create topology (bad return)"); - } - GNUNET_SCHEDULER_cancel (die_task); - die_task = - GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &end_badly, - "from continue startup (timeout)"); -} - - -static void -peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Failed to start daemon with error: `%s'\n", emsg); - return; - } - GNUNET_assert (id != NULL); -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n", - (num_peers - peers_left) + 1, num_peers); -#endif - peers_left--; - if (peers_left == 0) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "All %d daemons started, now creating topology!\n", num_peers); -#endif - GNUNET_SCHEDULER_cancel (die_task); - /* Set up task in case topology creation doesn't finish - * within a reasonable amount of time */ - die_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly, - "from peers_started_callback"); - connect_topology (); - ok = 0; - } -} - -/** - * Callback indicating that the hostkey was created for a peer. - * - * @param cls NULL - * @param id the peer identity - * @param d the daemon handle (pretty useless at this point, remove?) - * @param emsg non-null on failure - */ -void -hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Hostkey callback received error: %s\n", emsg); - } - -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostkey created for peer `%s'\n", - GNUNET_i2s (id)); -#endif - peers_left--; - if (peers_left == 0) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "All %d hostkeys created, now creating topology!\n", num_peers); -#endif - GNUNET_SCHEDULER_cancel (die_task); - /* Set up task in case topology creation doesn't finish - * within a reasonable amount of time */ - die_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly, - "from hostkey_callback"); - GNUNET_SCHEDULER_add_now (&create_topology, NULL); - ok = 0; - } -} - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - unsigned long long topology_num; - unsigned long long connect_topology_num; - unsigned long long blacklist_topology_num; - unsigned long long connect_topology_option_num; - char *connect_topology_option_modifier_string; - - ok = 1; - - dotOutFile = FOPEN (dotOutFileName, "w"); - if (dotOutFile != NULL) - { - FPRINTF (dotOutFile, "%s", "strict graph G {\n"); - } - -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting daemons based on config file %s\n", cfgfile); -#endif - - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - if (dotOutFile != NULL) - { - FCLOSE (dotOutFile); - } - return; - } - - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "topology", - &topology_num)) - topology = topology_num; - - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_topology", - &connect_topology_num)) - connection_topology = connect_topology_num; - - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", - "connect_topology_option", - &connect_topology_option_num)) - connect_topology_option = connect_topology_option_num; - - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "connect_topology_option_modifier", - &connect_topology_option_modifier_string)) - { - if (SSCANF - (connect_topology_option_modifier_string, "%lf", - &connect_topology_option_modifier) != 1) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), - connect_topology_option_modifier_string, - "connect_topology_option_modifier", "TESTING"); - GNUNET_free (connect_topology_option_modifier_string); - ok = 707; - if (dotOutFile != NULL) - { - FCLOSE (dotOutFile); - } - return; - } - GNUNET_free (connect_topology_option_modifier_string); - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "blacklist_transports", - &blacklist_transports)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "No transports specified for blacklisting in blacklist testcase (this shouldn't happen!)\n"); - ok = 808; - if (dotOutFile != NULL) - { - FCLOSE (dotOutFile); - } - return; - } - - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", - "blacklist_topology", - &blacklist_topology_num)) - blacklist_topology = blacklist_topology_num; - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers", - &num_peers)) - num_peers = DEFAULT_NUM_PEERS; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "CONNECT_TIMEOUT", - &connect_timeout)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "CONNECT_TIMEOUT"); - return; - } - - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts", - &connect_attempts)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "connect_attempts"); - return; - } - - main_cfg = cfg; - - GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1); - peers_left = num_peers; - - /* For this specific test we only really want a CLIQUE topology as the - * overlay allowed topology, and a RING topology as the underlying connection - * allowed topology. So we will expect only num_peers * 2 connections to - * work, and (num_peers * (num_peers - 1)) - (num_peers * 2) to fail. - */ - expected_connections = num_peers * (num_peers - 1); - expected_failed_connections = expected_connections - (num_peers * 2); - - - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly, - "didn't start all daemons in reasonable amount of time!!!"); - - pg = GNUNET_TESTING_daemons_start (cfg, peers_left, peers_left, peers_left, - TIMEOUT, &hostkey_callback, NULL, - &peers_started_callback, NULL, - &topology_callback, NULL, NULL); - -} - -static int -check () -{ - int ret; - - char *const argv[] = { "test-testing-topology-blacklist", - "-c", - "test_testing_data_topology_blacklist.conf", -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-testing-topology-blacklist", "nohelp", options, - &run, &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-testing-topology-blacklist': Failed with error code %d\n", - ret); - } - - return ok; -} - -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test_testing_topology_blacklist", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret = check (); - - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - if (test_directory != NULL) - { - if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to remove testing directory %s\n", test_directory); - } - } - - return ret; -} - -/* end of test_testing_topology_blacklist.c */ diff --git a/src/testing/test_testing_topology_churn.c b/src/testing/test_testing_topology_churn.c deleted file mode 100644 index 9c0bbf27d..000000000 --- a/src/testing/test_testing_topology_churn.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009 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 testing/test_testing_topology_churn.c - * @brief base testcase for testing simple churn functionality - */ -#include "platform.h" -#include "gnunet_testing_lib.h" -#include "gnunet_core_service.h" - - -/** - * How long until we fail the whole testcase? - */ -#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600) - -/** - * How long until we give up on starting the peers? (Must be longer than the connect timeout!) - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) - -#define DEFAULT_NUM_PEERS 4 - -static int ok; - -static unsigned long long num_peers; - -static unsigned int expected_connections; - -static unsigned int expected_failed_connections; - -static unsigned long long peers_left; - -static struct GNUNET_TESTING_PeerGroup *pg; - -const struct GNUNET_CONFIGURATION_Handle *main_cfg; - -GNUNET_SCHEDULER_TaskIdentifier die_task; - -static char *test_directory; - -#define MTYPE 12345 - -GNUNET_NETWORK_STRUCT_BEGIN - -struct GNUNET_TestMessage -{ - /** - * Header of the message - */ - struct GNUNET_MessageHeader header; - - /** - * Unique identifier for this message. - */ - uint32_t uid; -}; -GNUNET_NETWORK_STRUCT_END - -/** - * Check whether peers successfully shut down. - */ -void -shutdown_callback (void *cls, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n"); - if (ok == 0) - ok = 666; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); - } -} - -static void -finish_testing () -{ - GNUNET_assert (pg != NULL); - - if (die_task != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (die_task); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Called finish testing, stopping daemons.\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n"); - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "daemons_stop finished\n"); - ok = 0; -} - -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - char *msg = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "End badly was called (%s)... stopping daemons.\n", msg); - - if (pg != NULL) - { - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - ok = 7331; /* Opposite of leet */ - } - else - ok = 401; /* Never got peers started */ - -} - -struct ChurnTestContext -{ - GNUNET_SCHEDULER_Task next_task; - -}; - -static struct ChurnTestContext churn_ctx; - -/** - * Churn callback, report on success or failure of churn operation. - * - * @param cls closure - * @param emsg NULL on success - */ -void -churn_callback (void *cls, const char *emsg) -{ - if (emsg == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Successfully churned peers!\n", - emsg); - GNUNET_SCHEDULER_add_now (churn_ctx.next_task, NULL); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to churn peers with error `%s'\n", emsg); - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); - } -} - - -static void -churn_peers_both () -{ - churn_ctx.next_task = &finish_testing; - GNUNET_TESTING_daemons_churn (pg, NULL, 1, 1, TIMEOUT, &churn_callback, NULL); -} - -static void -churn_peers_off_again () -{ - churn_ctx.next_task = &churn_peers_both; - GNUNET_TESTING_daemons_churn (pg, NULL, 2, 0, TIMEOUT, &churn_callback, NULL); -} - -static void -churn_peers_on () -{ - churn_ctx.next_task = &churn_peers_off_again; - GNUNET_TESTING_daemons_churn (pg, NULL, 0, 2, TIMEOUT, &churn_callback, NULL); -} - -static void -churn_peers_off () -{ - churn_ctx.next_task = &churn_peers_on; - GNUNET_TESTING_daemons_churn (pg, NULL, 2, 0, TIMEOUT, &churn_callback, NULL); -} - -static void -peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Failed to start daemon with error: `%s'\n", emsg); - return; - } - GNUNET_assert (id != NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n", - (num_peers - peers_left) + 1, num_peers); - peers_left--; - if (peers_left == 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "All %d daemons started, now testing churn!\n", num_peers); - GNUNET_SCHEDULER_cancel (die_task); - /* Set up task in case topology creation doesn't finish - * within a reasonable amount of time */ - die_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly, - "from peers_started_callback"); - churn_peers_off (); - ok = 0; - } -} - - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - ok = 1; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting daemons based on config file %s\n", cfgfile); - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - return; - } - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers", - &num_peers)) - num_peers = DEFAULT_NUM_PEERS; - - main_cfg = cfg; - - peers_left = num_peers; - GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1); - - /* For this specific test we only really want a CLIQUE topology as the - * overlay allowed topology, and a RING topology as the underlying connection - * allowed topology. So we will expect only num_peers * 2 connections to - * work, and (num_peers * (num_peers - 1)) - (num_peers * 2) to fail. - */ - expected_connections = num_peers * (num_peers - 1); - expected_failed_connections = expected_connections - (num_peers * 2); - - - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly, - "didn't start all daemons in reasonable amount of time!!!"); - - pg = GNUNET_TESTING_daemons_start (cfg, peers_left, peers_left, peers_left, - TIMEOUT, NULL, NULL, - &peers_started_callback, NULL, NULL, NULL, - NULL); - -} - -static int -check () -{ - int ret; - - char *const argv[] = { "test-testing-topology-churn", - "-c", - "test_testing_data_topology_churn.conf", - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-testing-topology-churn", "nohelp", options, - &run, &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-testing-topology-churn': Failed with error code %d\n", - ret); - } - - return ok; -} - -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test_testing_topology_churn", - "WARNING", - NULL); - ret = check (); - - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - if (test_directory != NULL) - { - if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to remove testing directory %s\n", test_directory); - } - } - - return ret; -} - -/* end of test_testing_topology_churn.c */ diff --git a/src/testing/testing.c b/src/testing/testing.c deleted file mode 100644 index a80ad25cf..000000000 --- a/src/testing/testing.c +++ /dev/null @@ -1,2204 +0,0 @@ -/* - This file is part of GNUnet - (C) 2008, 2009 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 testing/testing.c - * @brief convenience API for writing testcases for GNUnet - * Many testcases need to start and stop gnunetd, - * and this library is supposed to make that easier - * for TESTCASES. Normal programs should always - * use functions from gnunet_{util,arm}_lib.h. This API is - * ONLY for writing testcases! - * @author Christian Grothoff - * - */ -#include "platform.h" -#include "gnunet_arm_service.h" -#include "gnunet_core_service.h" -#include "gnunet_constants.h" -#include "gnunet_testing_lib.h" -#include "gnunet_transport_service.h" -#include "gnunet_hello_lib.h" - -/** - * Hack to deal with initial HELLO's being often devoid of addresses. - * This hack causes 'process_hello' to ignore HELLOs without addresses. - * The correct implementation would continue with 'process_hello' until - * the connection could be established... - */ -#define EMPTY_HACK GNUNET_YES - -/** - * How long do we wait after starting gnunet-service-arm - * for the core service to be alive? - */ -#define ARM_START_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) - -/** - * How many times are we willing to try to wait for "scp" or - * "gnunet-service-arm" to complete (waitpid) before giving up? - */ -#define MAX_EXEC_WAIT_RUNS 250 - -static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} }; - -#if EMPTY_HACK -static int -test_address (void *cls, const struct GNUNET_HELLO_Address *address, - struct GNUNET_TIME_Absolute expiration) -{ - int *empty = cls; - - *empty = GNUNET_NO; - return GNUNET_OK; -} -#endif - -/** - * Receive the HELLO from one peer, give it to the other - * and ask them to connect. - * - * @param cls Closure (daemon whose hello is this). - * @param message HELLO message of peer - */ -static void -process_hello (void *cls, const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_TESTING_Daemon *daemon = cls; - int msize; - -#if EMPTY_HACK - int empty; - - empty = GNUNET_YES; - GNUNET_assert (message != NULL); - GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *) message, - GNUNET_NO, &test_address, &empty); - if (GNUNET_YES == empty) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Skipping empty HELLO address of peer %s\n", - GNUNET_i2s (&daemon->id)); - return; - } -#endif - GNUNET_assert (daemon->phase == SP_GET_HELLO || - daemon->phase == SP_START_DONE); - daemon->cb = NULL; // FIXME: why??? (see fsm:SP_START_CORE, notify_daemon_started) - if (daemon->task != GNUNET_SCHEDULER_NO_TASK) /* Assertion here instead? */ - GNUNET_SCHEDULER_cancel (daemon->task); - - if (daemon->server != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received `%s' from transport service of `%4s', disconnecting core!\n", - "HELLO", GNUNET_i2s (&daemon->id)); - GNUNET_CORE_disconnect (daemon->server); - daemon->server = NULL; - } - - msize = ntohs (message->size); - if (msize < 1) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "HELLO message of peer %s is of size 0\n", - GNUNET_i2s (&daemon->id)); - return; - } - if (daemon->ghh != NULL) - { - GNUNET_TRANSPORT_get_hello_cancel (daemon->ghh); - daemon->ghh = NULL; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received `%s' from transport service of `%4s'\n", "HELLO", - GNUNET_i2s (&daemon->id)); - GNUNET_free_non_null (daemon->hello); - daemon->hello = GNUNET_malloc (msize); - memcpy (daemon->hello, message, msize); - - if (daemon->th != NULL) - { - GNUNET_TRANSPORT_disconnect (daemon->th); - daemon->th = NULL; - } - daemon->phase = SP_START_DONE; -} - - -/** - * Notify of a peer being up and running. Scheduled as a task - * so that variables which may need to be set are set before - * the connect callback can set up new operations. - * FIXME: what variables?????? where from???? - * - * @param cls the testing daemon - * @param tc task scheduler context - */ -static void -notify_daemon_started (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_TESTING_Daemon *d = cls; - GNUNET_TESTING_NotifyDaemonRunning cb; - - cb = d->cb; - d->cb = NULL; - if (NULL != cb) - cb (d->cb_cls, &d->id, d->cfg, d, NULL); -} - - -/** - * Finite-state machine for starting GNUnet. - * - * @param cls our "struct GNUNET_TESTING_Daemon" - * @param tc unused - */ -static void -start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_TESTING_Daemon *d = cls; - GNUNET_TESTING_NotifyDaemonRunning cb; - enum GNUNET_OS_ProcessStatusType type; - unsigned long code; - char *dst; - int bytes_read; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %s FSM is in phase %u.\n", - GNUNET_i2s (&d->id), d->phase); - d->task = GNUNET_SCHEDULER_NO_TASK; - switch (d->phase) - { - case SP_COPYING: - /* confirm copying complete */ - if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_copying, &type, &code)) - { - if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) - { - cb = d->cb; - d->cb = NULL; - if (NULL != cb) - cb (d->cb_cls, NULL, d->cfg, d, - _ - ("`scp' does not seem to terminate (timeout copying config).\n")); - return; - } - /* wait some more */ - d->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, - d); - return; - } - if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0)) - { - cb = d->cb; - d->cb = NULL; - if (NULL != cb) - cb (d->cb_cls, NULL, d->cfg, d, _("`scp' did not complete cleanly.\n")); - return; - } - GNUNET_OS_process_destroy (d->proc_arm_copying); - d->proc_arm_copying = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Successfully copied configuration file.\n"); - d->phase = SP_COPIED; - /* fall-through */ - case SP_COPIED: - /* Start create hostkey process if we don't already know the peer identity! */ - if (GNUNET_NO == d->have_hostkey) - { - GNUNET_assert (NULL == d->proc_arm_peerinfo); - d->pipe_stdout = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_YES); - if (d->pipe_stdout == NULL) - { - cb = d->cb; - d->cb = NULL; - if (NULL != cb) - cb (d->cb_cls, NULL, d->cfg, d, - (NULL == - d->hostname) ? - _("Failed to create pipe for `gnunet-peerinfo' process.\n") : - _("Failed to create pipe for `ssh' process.\n")); - return; - } - if (NULL == d->hostname) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting `%s', with command `%s %s %s %s'.\n", - "gnunet-peerinfo", "gnunet-peerinfo", "-c", d->cfgfile, - "-sq"); - d->proc_arm_peerinfo = - GNUNET_OS_start_process (GNUNET_YES, NULL, d->pipe_stdout, "gnunet-peerinfo", - "gnunet-peerinfo", "-c", d->cfgfile, "-sq", - NULL); - GNUNET_DISK_pipe_close_end (d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE); - } - else - { - if (d->username != NULL) - GNUNET_asprintf (&dst, "%s@%s", d->username, d->hostname); - else - dst = GNUNET_strdup (d->hostname); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting `%s', with command `%s %s %s %s %s %s'.\n", - "gnunet-peerinfo", "ssh", dst, "gnunet-peerinfo", "-c", - d->cfgfile, "-sq"); - if (d->ssh_port_str == NULL) - { - d->proc_arm_peerinfo = GNUNET_OS_start_process (GNUNET_NO, NULL, d->pipe_stdout, "ssh", "ssh", - "-q", - dst, "gnunet-peerinfo", "-c", - d->cfgfile, "-sq", NULL); - } - else - { - d->proc_arm_peerinfo = - GNUNET_OS_start_process (GNUNET_NO, NULL, d->pipe_stdout, "ssh", "ssh", "-p", - d->ssh_port_str, - "-q", - dst, "gnunet-peerinfo", "-c", d->cfgfile, - "-sq", NULL); - } - GNUNET_DISK_pipe_close_end (d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE); - GNUNET_free (dst); - } - if (NULL == d->proc_arm_peerinfo) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Could not start `%s' process to create hostkey.\n"), - (NULL == d->hostname) ? "gnunet-peerinfo" : "ssh"); - cb = d->cb; - d->cb = NULL; - if (NULL != cb) - cb (d->cb_cls, NULL, d->cfg, d, - (NULL == - d->hostname) ? _("Failed to start `gnunet-peerinfo' process.\n") - : _("Failed to start `ssh' process.\n")); - GNUNET_DISK_pipe_close (d->pipe_stdout); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Started `%s', waiting for hostkey.\n", "gnunet-peerinfo"); - d->phase = SP_HOSTKEY_CREATE; - d->task = - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining - (d->max_timeout), - GNUNET_DISK_pipe_handle - (d->pipe_stdout, - GNUNET_DISK_PIPE_END_READ), - &start_fsm, d); - } - else /* Already have a hostkey! */ - { - if (d->hostkey_callback != NULL) - { - d->hostkey_callback (d->hostkey_cls, &d->id, d, NULL); - d->hostkey_callback = NULL; - d->phase = SP_HOSTKEY_CREATED; - } - else - d->phase = SP_TOPOLOGY_SETUP; - - /* wait some more */ - d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d); - } - break; - case SP_HOSTKEY_CREATE: - bytes_read = - GNUNET_DISK_file_read (GNUNET_DISK_pipe_handle - (d->pipe_stdout, GNUNET_DISK_PIPE_END_READ), - &d->hostkeybuf[d->hostkeybufpos], - sizeof (d->hostkeybuf) - d->hostkeybufpos); - if (bytes_read > 0) - d->hostkeybufpos += bytes_read; - - if ((d->hostkeybufpos < 104) && (bytes_read > 0)) - { - /* keep reading */ - d->task = - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining - (d->max_timeout), - GNUNET_DISK_pipe_handle - (d->pipe_stdout, - GNUNET_DISK_PIPE_END_READ), - &start_fsm, d); - return; - } - d->hostkeybuf[103] = '\0'; - - if ((bytes_read < 0) || - (GNUNET_OK != - GNUNET_CRYPTO_hash_from_string (d->hostkeybuf, &d->id.hashPubKey))) - { - /* error */ - if (bytes_read < 0) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Error reading from gnunet-peerinfo: %s\n"), - STRERROR (errno)); - else - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Malformed output from gnunet-peerinfo!\n")); - cb = d->cb; - d->cb = NULL; - GNUNET_DISK_pipe_close (d->pipe_stdout); - d->pipe_stdout = NULL; - (void) GNUNET_OS_process_kill (d->proc_arm_peerinfo, SIGKILL); - GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (d->proc_arm_peerinfo)); - GNUNET_OS_process_destroy (d->proc_arm_peerinfo); - d->proc_arm_peerinfo = NULL; - if (NULL != cb) - cb (d->cb_cls, NULL, d->cfg, d, _("Failed to get hostkey!\n")); - return; - } - d->shortname = GNUNET_strdup (GNUNET_i2s (&d->id)); - GNUNET_DISK_pipe_close (d->pipe_stdout); - d->pipe_stdout = NULL; - (void) GNUNET_OS_process_kill (d->proc_arm_peerinfo, SIGKILL); - GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (d->proc_arm_peerinfo)); - GNUNET_OS_process_destroy (d->proc_arm_peerinfo); - d->proc_arm_peerinfo = NULL; - d->have_hostkey = GNUNET_YES; - if (d->hostkey_callback != NULL) - { - d->hostkey_callback (d->hostkey_cls, &d->id, d, NULL); - d->hostkey_callback = NULL; - d->phase = SP_HOSTKEY_CREATED; - } - else - { - d->phase = SP_TOPOLOGY_SETUP; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully got hostkey!\n"); - /* Fall through */ - case SP_HOSTKEY_CREATED: - /* wait for topology finished */ - if ((GNUNET_YES == d->dead) || - (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)) - { - cb = d->cb; - d->cb = NULL; - if (NULL != cb) - cb (d->cb_cls, NULL, d->cfg, d, - _("`Failed while waiting for topology setup!\n")); - return; - } - - d->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, - d); - break; - case SP_TOPOLOGY_SETUP: /* Indicates topology setup has completed! */ - /* start GNUnet on remote host */ - if (NULL == d->hostname) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting `%s', with command `%s %s %s %s'.\n", - "gnunet-arm", "gnunet-arm", "-c", d->cfgfile, - "-s"); - d->proc_arm_start = - GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm", "-c", - d->cfgfile, - "-s", "-q", "-T", - GNUNET_TIME_relative_to_string - (GNUNET_TIME_absolute_get_remaining - (d->max_timeout)), NULL); - } - else - { - if (d->username != NULL) - GNUNET_asprintf (&dst, "%s@%s", d->username, d->hostname); - else - dst = GNUNET_strdup (d->hostname); - - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Starting `%s', with command `%s %s %s %s %s %s %s'.\n", - "gnunet-arm", "ssh", dst, "gnunet-arm", "-c", d->cfgfile, - "-s", "-q"); - if (d->ssh_port_str == NULL) - { - d->proc_arm_start = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", - "-q", - dst, "gnunet-arm", - "-c", d->cfgfile, "-s", "-q", "-T", - GNUNET_TIME_relative_to_string - (GNUNET_TIME_absolute_get_remaining - (d->max_timeout)), NULL); - } - else - { - - d->proc_arm_start = - GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", "-p", - d->ssh_port_str, - "-q", - dst, "gnunet-arm", - "-c", d->cfgfile, "-s", "-q", "-T", - GNUNET_TIME_relative_to_string - (GNUNET_TIME_absolute_get_remaining - (d->max_timeout)), NULL); - } - GNUNET_free (dst); - } - if (NULL == d->proc_arm_start) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Could not start `%s' process to start GNUnet.\n"), - (NULL == d->hostname) ? "gnunet-arm" : "ssh"); - cb = d->cb; - d->cb = NULL; - if (NULL != cb) - cb (d->cb_cls, NULL, d->cfg, d, - (NULL == - d->hostname) ? _("Failed to start `gnunet-arm' process.\n") : - _("Failed to start `ssh' process.\n")); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Started `%s', waiting for `%s' to be up.\n", "gnunet-arm", - "gnunet-service-core"); - d->phase = SP_START_ARMING; - d->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, - d); - // FIXME: busy wait? - break; - case SP_START_ARMING: - if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_start, &type, &code)) - { - if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) - { - cb = d->cb; - d->cb = NULL; - if (NULL != cb) - cb (d->cb_cls, NULL, d->cfg, d, - (NULL == - d->hostname) ? _("`gnunet-arm' does not seem to terminate.\n") : - _("`ssh' does not seem to terminate.\n")); - if (d->cfg != NULL) - { - GNUNET_CONFIGURATION_destroy (d->cfg); - d->cfg = NULL; - } - if (d->cfgfile != NULL) - { - GNUNET_free (d->cfgfile); - d->cfgfile = NULL; - } - GNUNET_free_non_null (d->hostname); - GNUNET_free_non_null (d->username); - GNUNET_OS_process_destroy (d->proc_arm_start); - d->proc_arm_start = NULL; - d->username = NULL; - d->hostname = NULL; // Quick hack to avoid crashing (testing need to be - d->cfg = NULL; // overhauled anyway, and the error managing is - // GNUNET_free (d); // FIXME (could this leak) - // pretty broken anyway. - return; - } - /* wait some more */ - d->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, - d); - // FIXME: busy wait? - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully started `%s'.\n", - "gnunet-arm"); - GNUNET_OS_process_destroy (d->proc_arm_start); - d->proc_arm_start = NULL; - d->phase = SP_START_CORE; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling CORE_connect\n"); - /* Fall through */ - case SP_START_CORE: - if (d->server != NULL) - GNUNET_CORE_disconnect (d->server); - - d->th = GNUNET_TRANSPORT_connect (d->cfg, &d->id, d, NULL, NULL, NULL); - if (d->th == NULL) - { - if (GNUNET_YES == d->dead) - GNUNET_TESTING_daemon_stop (d, - GNUNET_TIME_absolute_get_remaining - (d->max_timeout), d->dead_cb, - d->dead_cb_cls, GNUNET_YES, GNUNET_NO); - else if (NULL != d->cb) - d->cb (d->cb_cls, &d->id, d->cfg, d, - _("Failed to connect to transport service!\n")); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connected to transport service `%s', getting HELLO\n", - GNUNET_i2s (&d->id)); - d->ghh = GNUNET_TRANSPORT_get_hello (d->th, &process_hello, d); - /* FIXME: store task ID somewhere! */ - GNUNET_SCHEDULER_add_now (¬ify_daemon_started, d); - /*cb = d->cb; - * d->cb = NULL; - * if (NULL != cb) - * cb (d->cb_cls, &d->id, d->cfg, d, NULL); */ - d->running = GNUNET_YES; - d->phase = SP_GET_HELLO; - break; - case SP_GET_HELLO: - if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) - { - if (d->server != NULL) - GNUNET_CORE_disconnect (d->server); - if (d->th != NULL) - GNUNET_TRANSPORT_disconnect (d->th); - cb = d->cb; - d->cb = NULL; - if (NULL != cb) - cb (d->cb_cls, NULL, d->cfg, d, _("Unable to get HELLO for peer!\n")); - GNUNET_CONFIGURATION_destroy (d->cfg); - GNUNET_free (d->cfgfile); - GNUNET_free_non_null (d->hostname); - GNUNET_free_non_null (d->username); - GNUNET_free (d); - return; - } - if (d->hello != NULL) - return; - GNUNET_assert (d->task == GNUNET_SCHEDULER_NO_TASK); - d->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_CONSTANTS_SERVICE_RETRY, 2), - &start_fsm, d); - break; - case SP_START_DONE: - GNUNET_break (0); - break; - case SP_SERVICE_START: - /* confirm gnunet-arm exited */ - if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_srv_start, &type, &code)) - { - if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) - { - cb = d->cb; - d->cb = NULL; - if (NULL != cb) - cb (d->cb_cls, NULL, d->cfg, d, - (NULL == - d->hostname) ? _("`gnunet-arm' does not seem to terminate.\n") : - _("`ssh' does not seem to terminate.\n")); - return; - } - /* wait some more */ - d->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, - d); - return; - } -#if EXTRA_CHECKS - if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0)) - { - cb = d->cb; - d->cb = NULL; - if (NULL != cb) - cb (d->cb_cls, NULL, d->cfg, d, - (NULL == - d->hostname) ? - _ - ("`gnunet-arm' terminated with non-zero exit status (or timed out)!\n") - : _("`ssh' does not seem to terminate.\n")); - return; - } -#endif - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service startup complete!\n"); - cb = d->cb; - d->cb = NULL; - d->phase = SP_START_DONE; - if (NULL != cb) - cb (d->cb_cls, &d->id, d->cfg, d, NULL); - GNUNET_OS_process_destroy (d->proc_arm_srv_start); - d->proc_arm_srv_start = NULL; - break; - case SP_SERVICE_SHUTDOWN_START: - /* confirm copying complete */ - if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_srv_stop, &type, &code)) - { - if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) - { - if (NULL != d->dead_cb) - d->dead_cb (d->dead_cb_cls, - _ - ("either `gnunet-arm' or `ssh' does not seem to terminate.\n")); - return; - } - /* wait some more */ - d->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, - d); - return; - } -#if EXTRA_CHECKS - if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0)) - { - if (NULL != d->dead_cb) - d->dead_cb (d->dead_cb_cls, - _ - ("shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n")); - return; - } -#endif - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service shutdown complete.\n"); - if (NULL != d->dead_cb) - d->dead_cb (d->dead_cb_cls, NULL); - break; - case SP_SHUTDOWN_START: - /* confirm copying complete !??? */ - if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_stop, &type, &code)) - { - if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) - { - if (NULL != d->dead_cb) - d->dead_cb (d->dead_cb_cls, - _ - ("either `gnunet-arm' or `ssh' does not seem to terminate.\n")); - if (d->th != NULL) - { - GNUNET_TRANSPORT_get_hello_cancel (d->ghh); - d->ghh = NULL; - GNUNET_TRANSPORT_disconnect (d->th); - d->th = NULL; - } - if (d->cfg != NULL) - { - GNUNET_CONFIGURATION_destroy (d->cfg); - d->cfg = NULL; - } - if (d->cfgfile != NULL) - { - GNUNET_free (d->cfgfile); - d->cfgfile = NULL; - } - GNUNET_free_non_null (d->hello); - GNUNET_free_non_null (d->hostname); - GNUNET_free_non_null (d->username); - GNUNET_free_non_null (d->shortname); - GNUNET_OS_process_destroy (d->proc_arm_stop); - d->proc_arm_stop = NULL; - GNUNET_free (d); - return; - } - /* wait some more */ - d->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, - d); - return; - } - if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0)) - { - if (NULL != d->dead_cb) - d->dead_cb (d->dead_cb_cls, - _ - ("shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n")); - if (d->th != NULL) - { - GNUNET_TRANSPORT_get_hello_cancel (d->ghh); - d->ghh = NULL; - GNUNET_TRANSPORT_disconnect (d->th); - d->th = NULL; - } - if (d->server != NULL) - { - GNUNET_CORE_disconnect (d->server); - d->server = NULL; - } - GNUNET_CONFIGURATION_destroy (d->cfg); - d->cfg = NULL; - GNUNET_free (d->cfgfile); - GNUNET_free_non_null (d->hello); - GNUNET_free_non_null (d->hostname); - GNUNET_free_non_null (d->username); - GNUNET_free_non_null (d->shortname); - GNUNET_OS_process_destroy (d->proc_arm_stop); - d->proc_arm_stop = NULL; - GNUNET_free (d); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer shutdown complete.\n"); - if (d->server != NULL) - { - GNUNET_CORE_disconnect (d->server); - d->server = NULL; - } - - if (d->th != NULL) - { - GNUNET_TRANSPORT_get_hello_cancel (d->ghh); - d->ghh = NULL; - GNUNET_TRANSPORT_disconnect (d->th); - d->th = NULL; - } - - if (NULL != d->dead_cb) - d->dead_cb (d->dead_cb_cls, NULL); - - /* state clean up and notifications */ - if (d->churn == GNUNET_NO) - { - GNUNET_CONFIGURATION_destroy (d->cfg); - d->cfg = NULL; - GNUNET_free (d->cfgfile); - GNUNET_free_non_null (d->hostname); - GNUNET_free_non_null (d->username); - } - - GNUNET_free_non_null (d->hello); - d->hello = NULL; - GNUNET_free_non_null (d->shortname); - GNUNET_OS_process_destroy (d->proc_arm_stop); - d->proc_arm_stop = NULL; - d->shortname = NULL; - if (d->churn == GNUNET_NO) - GNUNET_free (d); - - break; - case SP_CONFIG_UPDATE: - /* confirm copying complete */ - if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_copying, &type, &code)) - { - if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) /* FIXME: config update should take timeout parameter! */ - { - cb = d->cb; - d->cb = NULL; - if (NULL != cb) - cb (d->cb_cls, NULL, d->cfg, d, - _("`scp' does not seem to terminate.\n")); - return; - } - /* wait some more */ - d->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, - d); - return; - } - if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0)) - { - if (NULL != d->update_cb) - d->update_cb (d->update_cb_cls, _("`scp' did not complete cleanly.\n")); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Successfully copied configuration file.\n"); - if (NULL != d->update_cb) - d->update_cb (d->update_cb_cls, NULL); - d->phase = SP_START_DONE; - break; - } -} - -/** - * Continues GNUnet daemon startup when user wanted to be notified - * once a hostkey was generated (for creating friends files, blacklists, - * etc.). - * - * @param daemon the daemon to finish starting - */ -void -GNUNET_TESTING_daemon_continue_startup (struct GNUNET_TESTING_Daemon *daemon) -{ - GNUNET_assert (daemon->phase == SP_HOSTKEY_CREATED); - daemon->phase = SP_TOPOLOGY_SETUP; -} - -/** - * Check whether the given daemon is running. - * - * @param daemon the daemon to check - * - * @return GNUNET_YES if the daemon is up, GNUNET_NO if the - * daemon is down, GNUNET_SYSERR on error. - */ -int -GNUNET_TESTING_test_daemon_running (struct GNUNET_TESTING_Daemon *daemon) -{ - if (daemon == NULL) - return GNUNET_SYSERR; - - if (daemon->running == GNUNET_YES) - return GNUNET_YES; - return GNUNET_NO; -} - - -/** - * Starts a GNUnet daemon service which has been previously stopped. - * - * @param d the daemon for which the service should be started - * @param service the name of the service to start - * @param timeout how long to wait for process for shutdown to complete - * @param cb function called once the service starts - * @param cb_cls closure for cb - */ -void -GNUNET_TESTING_daemon_start_stopped_service (struct GNUNET_TESTING_Daemon *d, - char *service, - struct GNUNET_TIME_Relative - timeout, - GNUNET_TESTING_NotifyDaemonRunning - cb, void *cb_cls) -{ - char *arg; - - d->cb = cb; - d->cb_cls = cb_cls; - - GNUNET_assert (d->running == GNUNET_YES); - - if (d->phase == SP_CONFIG_UPDATE) - { - GNUNET_SCHEDULER_cancel (d->task); - d->phase = SP_START_DONE; - } - - if (d->churned_services == NULL) - { - d->cb (d->cb_cls, &d->id, d->cfg, d, - "No service has been churned off yet!!"); - return; - } - d->phase = SP_SERVICE_START; - GNUNET_free (d->churned_services); - d->churned_services = NULL; - d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); - /* Check if this is a local or remote process */ - if (NULL != d->hostname) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting gnunet-arm with config `%s' on host `%s'.\n", - d->cfgfile, d->hostname); - if (d->username != NULL) - GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname); - else - arg = GNUNET_strdup (d->hostname); - - d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", - "-q", - arg, "gnunet-arm", - "-c", d->cfgfile, "-i", service, "-q", - "-T", - GNUNET_TIME_relative_to_string (timeout), - NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting gnunet-arm with command ssh %s gnunet-arm -c %s -i %s -q\n", - arg, "gnunet-arm", d->cfgfile, service); - GNUNET_free (arg); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting gnunet-arm with config `%s' locally.\n", d->cfgfile); - d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm", - "-c", d->cfgfile, "-i", service, "-q", - "-T", - GNUNET_TIME_relative_to_string (timeout), - NULL); - } - - d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); - d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d); -} - -/** - * Starts a GNUnet daemon's service. - * - * @param d the daemon for which the service should be started - * @param service the name of the service to start - * @param timeout how long to wait for process for startup - * @param cb function called once gnunet-arm returns - * @param cb_cls closure for cb - */ -void -GNUNET_TESTING_daemon_start_service (struct GNUNET_TESTING_Daemon *d, - const char *service, - struct GNUNET_TIME_Relative timeout, - GNUNET_TESTING_NotifyDaemonRunning cb, - void *cb_cls) -{ - char *arg; - - d->cb = cb; - d->cb_cls = cb_cls; - - GNUNET_assert (service != NULL); - GNUNET_assert (d->running == GNUNET_YES); - GNUNET_assert (d->phase == SP_START_DONE); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - _("Starting service %s for peer `%4s'\n"), service, - GNUNET_i2s (&d->id)); - d->phase = SP_SERVICE_START; - d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); - /* Check if this is a local or remote process */ - if (NULL != d->hostname) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting gnunet-arm with config `%s' on host `%s'.\n", - d->cfgfile, d->hostname); - if (d->username != NULL) - GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname); - else - arg = GNUNET_strdup (d->hostname); - - d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", - "-q", - arg, "gnunet-arm", - "-c", d->cfgfile, "-i", service, "-q", - "-T", - GNUNET_TIME_relative_to_string (timeout), - NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting gnunet-arm with command ssh %s gnunet-arm -c %s -i %s -q -T %s\n", - arg, "gnunet-arm", d->cfgfile, service, - GNUNET_TIME_relative_to_string (timeout)); - GNUNET_free (arg); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting gnunet-arm with config `%s' locally.\n", d->cfgfile); - d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm", - "-c", d->cfgfile, "-i", service, "-q", - "-T", - GNUNET_TIME_relative_to_string (timeout), - NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting gnunet-arm with command %s -c %s -i %s -q -T %s\n", - "gnunet-arm", d->cfgfile, service, - GNUNET_TIME_relative_to_string (timeout)); - } - - d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); - d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d); -} - -/** - * Start a peer that has previously been stopped using the daemon_stop - * call (and files weren't deleted and the allow restart flag) - * - * @param daemon the daemon to start (has been previously stopped) - * @param timeout how long to wait for restart - * @param cb the callback for notification when the peer is running - * @param cb_cls closure for the callback - */ -void -GNUNET_TESTING_daemon_start_stopped (struct GNUNET_TESTING_Daemon *daemon, - struct GNUNET_TIME_Relative timeout, - GNUNET_TESTING_NotifyDaemonRunning cb, - void *cb_cls) -{ - if (daemon->running == GNUNET_YES) - { - cb (cb_cls, &daemon->id, daemon->cfg, daemon, - "Daemon already running, can't restart!"); - return; - } - - daemon->cb = cb; - daemon->cb_cls = cb_cls; - daemon->phase = SP_TOPOLOGY_SETUP; - daemon->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); - /* FIXME: why add_continuation? */ - GNUNET_SCHEDULER_add_continuation (&start_fsm, daemon, - GNUNET_SCHEDULER_REASON_PREREQ_DONE); -} - -/** - * Starts a GNUnet daemon. GNUnet must be installed on the target - * system and available in the PATH. The machine must furthermore be - * reachable via "ssh" (unless the hostname is "NULL") without the - * need to enter a password. - * - * @param cfg configuration to use - * @param timeout how long to wait starting up peers - * @param pretend GNUNET_YES to set up files but not start peer GNUNET_NO - * to really start the peer (default) - * @param hostname name of the machine where to run GNUnet - * (use NULL for localhost). - * @param ssh_username ssh username to use when connecting to hostname - * @param sshport port to pass to ssh process when connecting to hostname - * @param hostkey pointer to a hostkey to be written to disk (instead of being generated) - * @param hostkey_callback function to call once the hostkey has been - * generated for this peer, but it hasn't yet been started - * (NULL to start immediately, otherwise waits on GNUNET_TESTING_daemon_continue_start) - * @param hostkey_cls closure for hostkey callback - * @param cb function to call once peer is up, or failed to start - * @param cb_cls closure for cb - * @return handle to the daemon (actual start will be completed asynchronously) - */ -struct GNUNET_TESTING_Daemon * -GNUNET_TESTING_daemon_start (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TIME_Relative timeout, int pretend, - const char *hostname, const char *ssh_username, - uint16_t sshport, const char *hostkey, - GNUNET_TESTING_NotifyHostkeyCreated - hostkey_callback, void *hostkey_cls, - GNUNET_TESTING_NotifyDaemonRunning cb, - void *cb_cls) -{ - struct GNUNET_TESTING_Daemon *ret; - char *arg; - char *username; - char *servicehome; - char *baseservicehome; - char *slash; - char *hostkeyfile; - char *temp_file_name; - struct GNUNET_DISK_FileHandle *fn; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded public_key; - struct GNUNET_CRYPTO_RsaPrivateKey *private_key; - - ret = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Daemon)); - ret->hostname = (hostname == NULL) ? NULL : GNUNET_strdup (hostname); - if (sshport != 0) - { - GNUNET_asprintf (&ret->ssh_port_str, "%d", sshport); - } - else - ret->ssh_port_str = NULL; - - /* Find service home and base service home directories, create it if it doesn't exist */ - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", - "SERVICEHOME", - &servicehome)); - - GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_create (servicehome)); - GNUNET_asprintf (&temp_file_name, "%s/gnunet-testing-config", servicehome); - ret->cfgfile = GNUNET_DISK_mktemp (temp_file_name); - GNUNET_free (temp_file_name); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Setting up peer with configuration file `%s'.\n", ret->cfgfile); - if (NULL == ret->cfgfile) - { - GNUNET_free_non_null (ret->ssh_port_str); - GNUNET_free_non_null (ret->hostname); - GNUNET_free (ret); - return NULL; - } - ret->hostkey_callback = hostkey_callback; - ret->hostkey_cls = hostkey_cls; - ret->cb = cb; - ret->cb_cls = cb_cls; - ret->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); - ret->cfg = GNUNET_CONFIGURATION_dup (cfg); - GNUNET_CONFIGURATION_set_value_string (ret->cfg, "PATHS", "DEFAULTCONFIG", - ret->cfgfile); - - if (hostkey != NULL) /* Get the peer identity from the hostkey */ - { - private_key = GNUNET_CRYPTO_rsa_decode_key (hostkey, HOSTKEYFILESIZE); - GNUNET_assert (private_key != NULL); - GNUNET_CRYPTO_rsa_key_get_public (private_key, &public_key); - GNUNET_CRYPTO_hash (&public_key, - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &ret->id.hashPubKey); - ret->shortname = GNUNET_strdup (GNUNET_i2s (&ret->id)); - ret->have_hostkey = GNUNET_YES; - GNUNET_CRYPTO_rsa_key_free (private_key); - } - - /* Write hostkey to file, if we were given one */ - hostkeyfile = NULL; - if (hostkey != NULL) - { - GNUNET_asprintf (&hostkeyfile, "%s/.hostkey", servicehome); - fn = GNUNET_DISK_file_open (hostkeyfile, - GNUNET_DISK_OPEN_READWRITE | - GNUNET_DISK_OPEN_CREATE, - GNUNET_DISK_PERM_USER_READ | - GNUNET_DISK_PERM_USER_WRITE); - GNUNET_assert (fn != NULL); - GNUNET_assert (HOSTKEYFILESIZE == - GNUNET_DISK_file_write (fn, hostkey, HOSTKEYFILESIZE)); - GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fn)); - } - - /* write configuration to temporary file */ - if (GNUNET_OK != GNUNET_CONFIGURATION_write (ret->cfg, ret->cfgfile)) - { - if (0 != UNLINK (ret->cfgfile)) - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", - ret->cfgfile); - GNUNET_CONFIGURATION_destroy (ret->cfg); - GNUNET_free_non_null (ret->hostname); - GNUNET_free (ret->cfgfile); - GNUNET_free (ret); - return NULL; - } - if (ssh_username != NULL) - username = GNUNET_strdup (ssh_username); - if ((ssh_username == NULL) && - (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, "TESTING", "USERNAME", - &username))) - { - if (NULL != getenv ("USER")) - username = GNUNET_strdup (getenv ("USER")); - else - username = NULL; - } - ret->username = username; - - if (GNUNET_NO == pretend) /* Copy files, enter finite state machine */ - { - /* copy directory to remote host */ - if (NULL != hostname) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Copying configuration directory to host `%s'.\n", hostname); - baseservicehome = GNUNET_strdup (servicehome); - /* Remove trailing /'s */ - while (baseservicehome[strlen (baseservicehome) - 1] == '/') - baseservicehome[strlen (baseservicehome) - 1] = '\0'; - /* Find next directory /, jump one ahead */ - slash = strrchr (baseservicehome, '/'); - if (slash != NULL) - *(++slash) = '\0'; - - ret->phase = SP_COPYING; - if (NULL != username) - GNUNET_asprintf (&arg, "%s@%s:%s", username, hostname, baseservicehome); - else - GNUNET_asprintf (&arg, "%s:%s", hostname, baseservicehome); - GNUNET_free (baseservicehome); - if (ret->ssh_port_str == NULL) - { - ret->proc_arm_copying = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "scp", "scp", "-r", - "-q", - servicehome, arg, NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "copying directory with command scp -r %s %s\n", - servicehome, arg); - } - else - { - ret->proc_arm_copying = - GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "scp", "scp", "-r", "-P", - ret->ssh_port_str, - "-q", - servicehome, arg, NULL); - } - GNUNET_free (arg); - if (NULL == ret->proc_arm_copying) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("Could not start `%s' process to copy configuration directory.\n"), - "scp"); - if (0 != UNLINK (ret->cfgfile)) - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", - ret->cfgfile); - GNUNET_CONFIGURATION_destroy (ret->cfg); - GNUNET_free_non_null (ret->hostname); - GNUNET_free_non_null (ret->username); - GNUNET_free (ret->cfgfile); - GNUNET_free (ret); - if ((hostkey != NULL) && (0 != UNLINK (hostkeyfile))) - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", - hostkeyfile); - GNUNET_free_non_null (hostkeyfile); - GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (servicehome)); - GNUNET_free (servicehome); - return NULL; - } - - ret->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, - ret); - GNUNET_free_non_null (hostkeyfile); - GNUNET_free (servicehome); - return ret; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "No need to copy configuration file since we are running locally.\n"); - ret->phase = SP_COPIED; - /* FIXME: why add_cont? */ - GNUNET_SCHEDULER_add_continuation (&start_fsm, ret, - GNUNET_SCHEDULER_REASON_PREREQ_DONE); - } - GNUNET_free_non_null (hostkeyfile); - GNUNET_free (servicehome); - return ret; -} - - -/** - * Restart (stop and start) a GNUnet daemon. - * - * @param d the daemon that should be restarted - * @param cb function called once the daemon is (re)started - * @param cb_cls closure for cb - */ -void -GNUNET_TESTING_daemon_restart (struct GNUNET_TESTING_Daemon *d, - GNUNET_TESTING_NotifyDaemonRunning cb, - void *cb_cls) -{ - char *arg; - char *del_arg; - - del_arg = NULL; - if (NULL != d->cb) - { - d->dead = GNUNET_YES; - return; - } - - d->cb = cb; - d->cb_cls = cb_cls; - - if (d->phase == SP_CONFIG_UPDATE) - { - GNUNET_SCHEDULER_cancel (d->task); - d->phase = SP_START_DONE; - } - if (d->server != NULL) - { - GNUNET_CORE_disconnect (d->server); - d->server = NULL; - } - - if (d->th != NULL) - { - GNUNET_TRANSPORT_get_hello_cancel (d->ghh); - d->ghh = NULL; - GNUNET_TRANSPORT_disconnect (d->th); - d->th = NULL; - } - /* state clean up and notifications */ - GNUNET_free_non_null (d->hello); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Terminating peer `%4s'\n"), - GNUNET_i2s (&d->id)); - d->phase = SP_START_ARMING; - - /* Check if this is a local or remote process */ - if (NULL != d->hostname) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Stopping gnunet-arm with config `%s' on host `%s'.\n", - d->cfgfile, d->hostname); - if (d->username != NULL) - GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname); - else - arg = GNUNET_strdup (d->hostname); - - d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", - "-q", - arg, "gnunet-arm", - "-c", d->cfgfile, "-e", "-r", NULL); - /* Use -r to restart arm and all services */ - - GNUNET_free (arg); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile); - d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm", - "-c", d->cfgfile, "-e", "-r", NULL); - } - - GNUNET_free_non_null (del_arg); - d->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, d); - -} - - -/** - * Stops a GNUnet daemon. - * - * @param d the daemon that should be stopped - * @param service the name of the service to stop - * @param timeout how long to wait for process for shutdown to complete - * @param cb function called once the daemon was stopped - * @param cb_cls closure for cb - */ -void -GNUNET_TESTING_daemon_stop_service (struct GNUNET_TESTING_Daemon *d, - const char *service, - struct GNUNET_TIME_Relative timeout, - GNUNET_TESTING_NotifyCompletion cb, - void *cb_cls) -{ - char *arg; - - d->dead_cb = cb; - d->dead_cb_cls = cb_cls; - - GNUNET_assert (d->running == GNUNET_YES); - - if (d->phase == SP_CONFIG_UPDATE) - { - GNUNET_SCHEDULER_cancel (d->task); - d->phase = SP_START_DONE; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Terminating peer `%4s'\n"), - GNUNET_i2s (&d->id)); - if (d->churned_services != NULL) - { - d->dead_cb (d->dead_cb_cls, "A service has already been turned off!!"); - return; - } - d->phase = SP_SERVICE_SHUTDOWN_START; - d->churned_services = GNUNET_strdup (service); - d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); - /* Check if this is a local or remote process */ - if (NULL != d->hostname) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Stopping gnunet-arm with config `%s' on host `%s'.\n", - d->cfgfile, d->hostname); - if (d->username != NULL) - GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname); - else - arg = GNUNET_strdup (d->hostname); - - d->proc_arm_srv_stop = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", - "-q", - arg, "gnunet-arm", - "-c", d->cfgfile, "-k", service, "-q", - "-T", - GNUNET_TIME_relative_to_string (timeout), - NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Stopping gnunet-arm with command ssh %s gnunet-arm -c %s -k %s -q\n", - arg, "gnunet-arm", d->cfgfile, service); - GNUNET_free (arg); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile); - d->proc_arm_srv_stop = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm", - "-c", d->cfgfile, "-k", service, "-q", - "-T", - GNUNET_TIME_relative_to_string (timeout), - NULL); - } - - d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); - d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d); -} - - -/** - * Forcefully terminate a process and clean up the child. - * - * @param proc handle to process to kill - */ -static void -kill_and_close_process (struct GNUNET_OS_Process *proc) -{ - (void) GNUNET_OS_process_kill (proc, SIGKILL); - GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (proc)); - GNUNET_OS_process_destroy (proc); -} - - -/** - * Stops a GNUnet daemon. - * - * @param d the daemon that should be stopped - * @param timeout how long to wait for process for shutdown to complete - * @param cb function called once the daemon was stopped - * @param cb_cls closure for cb - * @param delete_files GNUNET_YES to remove files, GNUNET_NO - * to leave them - * @param allow_restart GNUNET_YES to restart peer later (using this API) - * GNUNET_NO to kill off and clean up for good - */ -void -GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d, - struct GNUNET_TIME_Relative timeout, - GNUNET_TESTING_NotifyCompletion cb, void *cb_cls, - int delete_files, int allow_restart) -{ - char *arg; - char *del_arg; - - d->dead_cb = cb; - d->dead_cb_cls = cb_cls; - - if (NULL != d->cb) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Setting d->dead on peer `%4s'\n"), - GNUNET_i2s (&d->id)); - d->dead = GNUNET_YES; - return; - } - if (NULL != d->proc_arm_start) - { - kill_and_close_process (d->proc_arm_start); - d->proc_arm_start = NULL; - } - if (NULL != d->proc_arm_srv_start) - { - kill_and_close_process (d->proc_arm_srv_start); - d->proc_arm_srv_start = NULL; - } - if (NULL != d->proc_arm_srv_stop) - { - kill_and_close_process (d->proc_arm_srv_stop); - d->proc_arm_srv_stop = NULL; - } - if (NULL != d->proc_arm_copying) - { - kill_and_close_process (d->proc_arm_copying); - d->proc_arm_copying = NULL; - } - if (NULL != d->proc_arm_peerinfo) - { - kill_and_close_process (d->proc_arm_peerinfo); - d->proc_arm_peerinfo = NULL; - } - if ((d->running == GNUNET_NO) && (d->churn == GNUNET_YES)) - { - /* Peer has already been stopped in churn context! - * Free what was left from churning! */ - GNUNET_assert (d->cfg != NULL); - GNUNET_CONFIGURATION_destroy (d->cfg); - if (delete_files == GNUNET_YES) - { - if (0 != UNLINK (d->cfgfile)) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "unlink"); - } - } - GNUNET_free (d->cfgfile); - GNUNET_free_non_null (d->hostname); - GNUNET_free_non_null (d->username); - if (NULL != d->dead_cb) - d->dead_cb (d->dead_cb_cls, NULL); - /* FIXME: this should be an assert and the test below - should not be required, but testing is broken... */ - GNUNET_break (NULL == d->proc_arm_stop); - if (NULL == d->proc_arm_stop) - GNUNET_free (d); - return; - } - - del_arg = NULL; - if (delete_files == GNUNET_YES) - { - GNUNET_asprintf (&del_arg, "-d"); - } - - if (d->phase == SP_CONFIG_UPDATE) - { - GNUNET_SCHEDULER_cancel (d->task); - d->phase = SP_START_DONE; - } - /** Move this call to scheduled shutdown as fix for CORE_connect calling daemon_stop? - if (d->server != NULL) - { - GNUNET_CORE_disconnect (d->server); - d->server = NULL; - } - */ - /* shutdown ARM process (will terminate others) */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Terminating peer `%4s'\n" , - GNUNET_i2s (&d->id)); - d->phase = SP_SHUTDOWN_START; - d->running = GNUNET_NO; - if (allow_restart == GNUNET_YES) - d->churn = GNUNET_YES; - if (d->th != NULL) - { - GNUNET_TRANSPORT_get_hello_cancel (d->ghh); - d->ghh = NULL; - GNUNET_TRANSPORT_disconnect (d->th); - d->th = NULL; - } - /* Check if this is a local or remote process */ - - - if (NULL != d->hostname) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Stopping gnunet-arm with config `%s' on host `%s'.\n", - d->cfgfile, d->hostname); - if (d->username != NULL) - GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname); - else - arg = GNUNET_strdup (d->hostname); - - d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", - "-q", - arg, "gnunet-arm", - "-c", d->cfgfile, "-e", "-q", "-T", - GNUNET_TIME_relative_to_string (timeout), - del_arg, NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Stopping gnunet-arm with command ssh %s gnunet-arm -c %s -e -q %s\n", - arg, "gnunet-arm", d->cfgfile, del_arg); - /* Use -e to end arm, and -d to remove temp files */ - GNUNET_free (arg); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile); - d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "gnunet-arm", "gnunet-arm", - "-c", d->cfgfile, "-e", "-q", "-T", - GNUNET_TIME_relative_to_string (timeout), - del_arg, NULL); - GNUNET_assert (NULL != d->proc_arm_stop); - } - - GNUNET_free_non_null (del_arg); - d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); - if (GNUNET_SCHEDULER_NO_TASK != d->task) - GNUNET_SCHEDULER_cancel(d->task); - d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d); -} - - -/** - * Changes the configuration of a GNUnet daemon. - * - * @param d the daemon that should be modified - * @param cfg the new configuration for the daemon - * @param cb function called once the configuration was changed - * @param cb_cls closure for cb - */ -void -GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d, - struct GNUNET_CONFIGURATION_Handle *cfg, - GNUNET_TESTING_NotifyCompletion cb, - void *cb_cls) -{ - char *arg; - - if (d->phase != SP_START_DONE) - { - if (NULL != cb) - cb (cb_cls, - _ - ("Peer not yet running, can not change configuration at this point.")); - return; - } - - /* 1) write configuration to temporary file */ - if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, d->cfgfile)) - { - if (NULL != cb) - cb (cb_cls, _("Failed to write new configuration to disk.")); - return; - } - - /* 2) copy file to remote host (if necessary) */ - if (NULL == d->hostname) - { - /* signal success */ - if (NULL != cb) - cb (cb_cls, NULL); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Copying updated configuration file to remote host `%s'.\n", - d->hostname); - d->phase = SP_CONFIG_UPDATE; - if (NULL != d->username) - GNUNET_asprintf (&arg, "%s@%s:%s", d->username, d->hostname, d->cfgfile); - else - GNUNET_asprintf (&arg, "%s:%s", d->hostname, d->cfgfile); - d->proc_arm_copying = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "scp", "scp", - "-q", - d->cfgfile, arg, NULL); - GNUNET_free (arg); - if (NULL == d->proc_arm_copying) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Could not start `%s' process to copy configuration file.\n"), - "scp"); - if (NULL != cb) - cb (cb_cls, _("Failed to copy new configuration to remote machine.")); - d->phase = SP_START_DONE; - return; - } - d->update_cb = cb; - d->update_cb_cls = cb_cls; - d->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, d); -} - - -/** - * Data kept for each pair of peers that we try - * to connect. - */ -struct GNUNET_TESTING_ConnectContext -{ - /** - * Testing handle to the first daemon. - */ - struct GNUNET_TESTING_Daemon *d1; - - /** - * Handle to core of first daemon (to check connect) - */ - struct GNUNET_CORE_Handle *d1core; - - /** - * Have we actually connected to the core of the first daemon yet? - */ - int d1core_ready; - - /** - * Testing handle to the second daemon. - */ - struct GNUNET_TESTING_Daemon *d2; - - /** - * Transport handle to the first daemon (to offer the HELLO of the second daemon to). - */ - struct GNUNET_TRANSPORT_Handle *d1th; - - /** - * Function to call once we are done (or have timed out). - */ - GNUNET_TESTING_NotifyConnection cb; - - /** - * Closure for "nb". - */ - void *cb_cls; - - /** - * The relative timeout from whence this connect attempt was - * started. Allows for reconnect attempts. - */ - struct GNUNET_TIME_Relative relative_timeout; - - /** - * Maximum number of connect attempts, will retry connection - * this number of times on failures. - */ - unsigned int connect_attempts; - - /** - * Hello timeout task - */ - GNUNET_SCHEDULER_TaskIdentifier hello_send_task; - - /** - * Connect timeout task - */ - GNUNET_SCHEDULER_TaskIdentifier timeout_task; - - /** - * When should this operation be complete (or we must trigger - * a timeout). - */ - struct GNUNET_TIME_Relative timeout_hello; - - /** - * Was the connection attempt successful? - */ - int connected; - - /** - * When connecting, do we need to send the HELLO? - */ - int send_hello; - - /** - * The distance between the two connected peers - */ - uint32_t distance; -}; - - -/** Forward declaration **/ -static void -reattempt_daemons_connect (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc); - - -/** - * Notify callback about success or failure of the attempt - * to connect the two peers - * - * @param cls our "struct GNUNET_TESTING_ConnectContext" (freed) - * @param tc reason tells us if we succeeded or failed - */ -static void -notify_connect_result (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_TESTING_ConnectContext *ctx = cls; - - ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK; - if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (ctx->hello_send_task); - ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK; - } - - if (ctx->d1th != NULL) - GNUNET_TRANSPORT_disconnect (ctx->d1th); - ctx->d1th = NULL; - if (ctx->d1core != NULL) - GNUNET_CORE_disconnect (ctx->d1core); - ctx->d1core = NULL; - - if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - { - GNUNET_free (ctx); - return; - } - - if (ctx->connected == GNUNET_YES) - { - if (ctx->cb != NULL) - { - ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->distance, - ctx->d1->cfg, ctx->d2->cfg, ctx->d1, ctx->d2, NULL); - } - } - else if (ctx->connect_attempts > 0) - { - ctx->d1core_ready = GNUNET_NO; - ctx->timeout_task = - GNUNET_SCHEDULER_add_now (&reattempt_daemons_connect, ctx); - return; - } - else - { - if (ctx->cb != NULL) - { - ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, - ctx->d2->cfg, ctx->d1, ctx->d2, _("Peers failed to connect")); - } - } - GNUNET_free (ctx); -} - - -/** - * Success, connection is up. Signal client our success. - * - * @param cls our "struct GNUNET_TESTING_ConnectContext" - * @param peer identity of the peer that has connected - * @param atsi performance information - * @param atsi_count number of records in 'atsi' - * - */ -static void -connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_ATS_Information *atsi, - unsigned int atsi_count) -{ - struct GNUNET_TESTING_ConnectContext *ctx = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected peer %s to peer %s\n", - ctx->d1->shortname, GNUNET_i2s (peer)); - if (0 != memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity))) - return; - ctx->connected = GNUNET_YES; - ctx->distance = 0; /* FIXME: distance */ - if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (ctx->hello_send_task); - ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK; - } - GNUNET_SCHEDULER_cancel (ctx->timeout_task); - ctx->timeout_task = GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); -} - - -static void -send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_TESTING_ConnectContext *ctx = cls; - struct GNUNET_MessageHeader *hello; - - ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK; - if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - return; - if ((ctx->d1core_ready == GNUNET_YES) && (ctx->d2->hello != NULL) && - (NULL != GNUNET_HELLO_get_header (ctx->d2->hello)) && - (ctx->d1->phase == SP_START_DONE) && (ctx->d2->phase == SP_START_DONE)) - { - hello = GNUNET_HELLO_get_header (ctx->d2->hello); - GNUNET_assert (hello != NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Offering hello of %s to %s\n", - ctx->d2->shortname, ctx->d1->shortname); - GNUNET_TRANSPORT_offer_hello (ctx->d1th, hello, NULL, NULL); - GNUNET_assert (ctx->d1core != NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending connect request to TRANSPORT of %s for peer %s\n", - GNUNET_i2s (&ctx->d1->id), - GNUNET_h2s (&ctx->d2->id.hashPubKey)); - GNUNET_TRANSPORT_try_connect (ctx->d1th, &ctx->d2->id); - ctx->timeout_hello = - GNUNET_TIME_relative_add (ctx->timeout_hello, - GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, 500)); - } - ctx->hello_send_task = - GNUNET_SCHEDULER_add_delayed (ctx->timeout_hello, &send_hello, ctx); -} - -/** - * Notify of a successful connection to the core service. - * - * @param cls a ConnectContext - * @param server handle to the core service - * @param my_identity the peer identity of this peer - */ -void -core_init_notify (void *cls, struct GNUNET_CORE_Handle *server, - const struct GNUNET_PeerIdentity *my_identity) -{ - struct GNUNET_TESTING_ConnectContext *connect_ctx = cls; - - connect_ctx->d1core_ready = GNUNET_YES; - - if (connect_ctx->send_hello == GNUNET_NO) - { - GNUNET_TRANSPORT_try_connect (connect_ctx->d1th, &connect_ctx->d2->id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending connect request to TRANSPORT of %s for peer %s\n", - connect_ctx->d1->shortname, connect_ctx->d2->shortname); - } -} - - -/** - * Try to connect again some peers that failed in an earlier attempt. This will - * be tried as many times as connection_attempts in the configuration file. - * - * @param cls Closure (connection context between the two peers). - * @param tc TaskContext. - */ -static void -reattempt_daemons_connect (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_TESTING_ConnectContext *ctx = cls; - - ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK; - if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - return; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "re-attempting connect of peer %s to peer %s\n", - ctx->d1->shortname, ctx->d2->shortname); - ctx->connect_attempts--; - GNUNET_assert (ctx->d1core == NULL); - ctx->d1core_ready = GNUNET_NO; - ctx->d1core = - GNUNET_CORE_connect (ctx->d1->cfg, ctx, &core_init_notify, - &connect_notify, NULL, NULL, GNUNET_NO, NULL, - GNUNET_NO, no_handlers); - if (ctx->d1core == NULL) - { - if (NULL != ctx->cb) - ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, - ctx->d2->cfg, ctx->d1, ctx->d2, - _("Failed to connect to core service of first peer!\n")); - GNUNET_free (ctx); - return; - } - - /* Don't know reason for initial connect failure, update the HELLO for the second peer */ - if (NULL != ctx->d2->hello) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "updating %s's HELLO\n", - ctx->d2->shortname); - GNUNET_free (ctx->d2->hello); - ctx->d2->hello = NULL; - if (NULL != ctx->d2->th) - { - GNUNET_TRANSPORT_get_hello_cancel (ctx->d2->ghh); - ctx->d2->ghh = NULL; - GNUNET_TRANSPORT_disconnect (ctx->d2->th); - } - ctx->d2->th = - GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL, - NULL); - GNUNET_assert (ctx->d2->th != NULL); - ctx->d2->ghh = - GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "didn't have %s's HELLO\n", - ctx->d2->shortname); - } - - if ((NULL == ctx->d2->hello) && (ctx->d2->th == NULL)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "didn't have %s's HELLO, trying to get it now\n", - ctx->d2->shortname); - ctx->d2->th = - GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL, - NULL); - if (NULL == ctx->d2->th) - { - GNUNET_CORE_disconnect (ctx->d1core); - GNUNET_free (ctx); - if (NULL != ctx->cb) - ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, - ctx->d2->cfg, ctx->d1, ctx->d2, - _("Failed to connect to transport service!\n")); - return; - } - ctx->d2->ghh = - GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2); - } - else - { - if (NULL == ctx->d2->hello) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "didn't have %s's HELLO but th wasn't NULL, not trying!!\n", - ctx->d2->shortname); - } - } - - if (ctx->send_hello == GNUNET_YES) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %s's HELLO to %s\n", - ctx->d1->shortname, ctx->d2->shortname); - ctx->d1th = - GNUNET_TRANSPORT_connect (ctx->d1->cfg, &ctx->d1->id, ctx->d1, NULL, - NULL, NULL); - if (ctx->d1th == NULL) - { - GNUNET_CORE_disconnect (ctx->d1core); - GNUNET_free (ctx); - if (NULL != ctx->cb) - ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, - ctx->d2->cfg, ctx->d1, ctx->d2, - _("Failed to connect to transport service!\n")); - return; - } - GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->hello_send_task); - ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to reconnect %s to %s\n", - ctx->d1->shortname, ctx->d2->shortname); - GNUNET_TRANSPORT_try_connect (ctx->d1th, &ctx->d2->id); - } - ctx->timeout_task = - GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout, - ¬ify_connect_result, ctx); -} - -/** - * Iterator for currently known peers, to ensure - * that we don't try to send duplicate connect - * requests to core. - * - * @param cls our "struct GNUNET_TESTING_ConnectContext" - * @param peer identity of the peer that has connected, - * NULL when iteration has finished - * @param atsi performance information - * @param atsi_count number of records in 'atsi' - * - */ -static void -core_initial_iteration (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_ATS_Information *atsi, - unsigned int atsi_count) -{ - struct GNUNET_TESTING_ConnectContext *ctx = cls; - - if ((peer != NULL) && - (0 == memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity)))) - { - ctx->connected = GNUNET_YES; - ctx->distance = 0; /* FIXME: distance */ - return; - } - if (peer != NULL) - return; /* ignore other peers */ - /* peer == NULL: End of iteration over peers */ - - GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->timeout_task); - if (ctx->connected == GNUNET_YES) - { - ctx->timeout_task = GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); - return; - } - - /* Peer not already connected, need to schedule connect request! */ - if (ctx->d1core == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Peers are NOT connected, connecting to core!\n"); - ctx->d1core = - GNUNET_CORE_connect (ctx->d1->cfg, ctx, &core_init_notify, - &connect_notify, NULL, NULL, GNUNET_NO, NULL, - GNUNET_NO, no_handlers); - } - - if (ctx->d1core == NULL) - { - ctx->timeout_task = GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); - return; - } - - if ((NULL == ctx->d2->hello) && (ctx->d2->th == NULL)) /* Do not yet have the second peer's hello, set up a task to get it */ - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Don't have d2's HELLO, trying to get it!\n"); - ctx->d2->th = - GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL, - NULL); - if (ctx->d2->th == NULL) - { - GNUNET_CORE_disconnect (ctx->d1core); - ctx->d1core = NULL; - ctx->timeout_task = - GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); - return; - } - ctx->d2->ghh = - GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2); - } - - if (ctx->send_hello == GNUNET_YES) - { - ctx->d1th = - GNUNET_TRANSPORT_connect (ctx->d1->cfg, &ctx->d1->id, ctx->d1, NULL, - NULL, NULL); - if (ctx->d1th == NULL) - { - GNUNET_CORE_disconnect (ctx->d1core); - ctx->d1core = NULL; - ctx->timeout_task = - GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); - return; - } - GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->hello_send_task); - ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx); - } - - ctx->timeout_task = - GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout, - ¬ify_connect_result, ctx); - -} - - -/** - * Establish a connection between two GNUnet daemons. The daemons - * must both be running and not be stopped until either the - * 'cb' callback is called OR the connection request has been - * explicitly cancelled. - * - * @param d1 handle for the first daemon - * @param d2 handle for the second daemon - * @param timeout how long is the connection attempt - * allowed to take? - * @param max_connect_attempts how many times should we try to reconnect - * (within timeout) - * @param send_hello GNUNET_YES to send the HELLO, GNUNET_NO to assume - * the HELLO has already been exchanged - * @param cb function to call at the end - * @param cb_cls closure for cb - * @return handle to cancel the request - */ -struct GNUNET_TESTING_ConnectContext * -GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, - struct GNUNET_TESTING_Daemon *d2, - struct GNUNET_TIME_Relative timeout, - unsigned int max_connect_attempts, - int send_hello, - GNUNET_TESTING_NotifyConnection cb, - void *cb_cls) -{ - struct GNUNET_TESTING_ConnectContext *ctx; - - if ((d1->running == GNUNET_NO) || (d2->running == GNUNET_NO)) - { - if (NULL != cb) - cb (cb_cls, &d1->id, &d2->id, 0, d1->cfg, d2->cfg, d1, d2, - _("Peers are not fully running yet, can not connect!\n")); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Peers are not up!\n"); - return NULL; - } - - ctx = GNUNET_malloc (sizeof (struct GNUNET_TESTING_ConnectContext)); - ctx->d1 = d1; - ctx->d2 = d2; - ctx->timeout_hello = - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500); - ctx->relative_timeout = - GNUNET_TIME_relative_divide (timeout, max_connect_attempts); - ctx->cb = cb; - ctx->cb_cls = cb_cls; - ctx->connect_attempts = max_connect_attempts; - ctx->connected = GNUNET_NO; - ctx->send_hello = send_hello; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asked to connect peer %s to peer %s\n", - d1->shortname, d2->shortname); - /* Core is up! Iterate over all _known_ peers first to check if we are already connected to the peer! */ - GNUNET_assert (NULL != - GNUNET_CORE_is_peer_connected (ctx->d1->cfg, &ctx->d2->id, - &core_initial_iteration, ctx)); - return ctx; -} - - -/** - * Cancel an attempt to connect two daemons. - * - * @param cc connect context - */ -void -GNUNET_TESTING_daemons_connect_cancel (struct GNUNET_TESTING_ConnectContext *cc) -{ - if (GNUNET_SCHEDULER_NO_TASK != cc->timeout_task) - { - GNUNET_SCHEDULER_cancel (cc->timeout_task); - cc->timeout_task = GNUNET_SCHEDULER_NO_TASK; - } - if (GNUNET_SCHEDULER_NO_TASK != cc->hello_send_task) - { - GNUNET_SCHEDULER_cancel (cc->hello_send_task); - cc->hello_send_task = GNUNET_SCHEDULER_NO_TASK; - } - if (NULL != cc->d1core) - { - GNUNET_CORE_disconnect (cc->d1core); - cc->d1core = NULL; - } - if (NULL != cc->d1th) - { - GNUNET_TRANSPORT_disconnect (cc->d1th); - cc->d1th = NULL; - } - GNUNET_free (cc); -} - - -/* end of testing.c */ diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c deleted file mode 100644 index 75c0e617d..000000000 --- a/src/testing/testing_group.c +++ /dev/null @@ -1,7038 +0,0 @@ -/* - This file is part of GNUnet - (C) 2008, 2009 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 testing/testing_group.c - * @brief convenience API for writing testcases for GNUnet - * @author Nathan Evans - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_constants.h" -#include "gnunet_arm_service.h" -#include "gnunet_testing_lib.h" -#include "gnunet_core_service.h" - -#define USE_START_HELPER GNUNET_YES - -#define OLD 1 - -/* Before connecting peers, send all of the HELLOs */ -#define USE_SEND_HELLOS GNUNET_NO - -#define TOPOLOGY_HACK GNUNET_YES - - -/** - * Lowest port used for GNUnet testing. Should be high enough to not - * conflict with other applications running on the hosts but be low - * enough to not conflict with client-ports (typically starting around - * 32k). - */ -#define LOW_PORT 12000 - -/** - * Highest port used for GNUnet testing. Should be low enough to not - * conflict with the port range for "local" ports (client apps; see - * /proc/sys/net/ipv4/ip_local_port_range on Linux for example). - */ -#define HIGH_PORT 56000 - -/* Maximum time to delay connect attempt */ -#define MAX_CONNECT_DELAY 300 - -/** - * Which list of peers do we need to modify? - */ -enum PeerLists -{ - /** Modify allowed peers */ - ALLOWED, - - /** Modify connect peers */ - CONNECT, - - /** Modify blacklist peers */ - BLACKLIST, - - /** Modify workingset peers */ - WORKING_SET -}; - -/** - * Prototype of a function called whenever two peers would be connected - * in a certain topology. - */ -typedef unsigned int (*GNUNET_TESTING_ConnectionProcessor) (struct - GNUNET_TESTING_PeerGroup - * pg, - unsigned int first, - unsigned int second, - enum PeerLists list, - unsigned int check); - -/** - * Context for handling churning a peer group - */ -struct ChurnContext -{ - /** - * The peergroup we are dealing with. - */ - struct GNUNET_TESTING_PeerGroup *pg; - - /** - * Name of the service to churn on/off, NULL - * to churn entire peer. - */ - char *service; - - /** - * Callback used to notify of churning finished - */ - GNUNET_TESTING_NotifyCompletion cb; - - /** - * Closure for callback - */ - void *cb_cls; - - /** - * Number of peers that still need to be started - */ - unsigned int num_to_start; - - /** - * Number of peers that still need to be stopped - */ - unsigned int num_to_stop; - - /** - * Number of peers that failed to start - */ - unsigned int num_failed_start; - - /** - * Number of peers that failed to stop - */ - unsigned int num_failed_stop; -}; - -struct RestartContext -{ - /** - * The group of peers being restarted - */ - struct GNUNET_TESTING_PeerGroup *peer_group; - - /** - * How many peers have been restarted thus far - */ - unsigned int peers_restarted; - - /** - * How many peers got an error when restarting - */ - unsigned int peers_restart_failed; - - /** - * The function to call once all peers have been restarted - */ - GNUNET_TESTING_NotifyCompletion callback; - - /** - * Closure for callback function - */ - void *callback_cls; - -}; - -struct SendHelloContext -{ - /** - * Global handle to the peer group. - */ - struct GNUNET_TESTING_PeerGroup *pg; - - /** - * The data about this specific peer. - */ - struct PeerData *peer; - - /** - * The next HELLO that needs sent to this peer. - */ - struct PeerConnection *peer_pos; - - /** - * Are we connected to CORE yet? - */ - unsigned int core_ready; - - /** - * How many attempts should we make for failed connections? - */ - unsigned int connect_attempts; - - /** - * Task for scheduling core connect requests to be sent. - */ - GNUNET_SCHEDULER_TaskIdentifier core_connect_task; -}; - -struct ShutdownContext -{ - struct GNUNET_TESTING_PeerGroup *pg; - /** - * Total peers to wait for - */ - unsigned int total_peers; - - /** - * Number of peers successfully shut down - */ - unsigned int peers_down; - - /** - * Number of peers failed to shut down - */ - unsigned int peers_failed; - - /** - * Number of peers we have started shutting - * down. If too many, wait on them. - */ - unsigned int outstanding; - - /** - * Timeout for shutdown. - */ - struct GNUNET_TIME_Relative timeout; - - /** - * Callback to call when all peers either - * shutdown or failed to shutdown - */ - GNUNET_TESTING_NotifyCompletion cb; - - /** - * Closure for cb - */ - void *cb_cls; - - /** - * Should we delete all of the files from the peers? - */ - int delete_files; -}; - -/** - * Individual shutdown context for a particular peer. - */ -struct PeerShutdownContext -{ - /** - * Pointer to the high level shutdown context. - */ - struct ShutdownContext *shutdown_ctx; - - /** - * The daemon handle for the peer to shut down. - */ - struct GNUNET_TESTING_Daemon *daemon; -}; - -/** - * Individual shutdown context for a particular peer. - */ -struct PeerRestartContext -{ - /** - * Pointer to the high level restart context. - */ - struct ChurnRestartContext *churn_restart_ctx; - - /** - * The daemon handle for the peer to shut down. - */ - struct GNUNET_TESTING_Daemon *daemon; -}; - -struct ServiceStartContext -{ - struct GNUNET_TESTING_PeerGroup *pg; - unsigned int remaining; - GNUNET_TESTING_NotifyCompletion cb; - unsigned int outstanding; - char *service; - struct GNUNET_TIME_Relative timeout; - void *cb_cls; -}; - -/** - * Individual shutdown context for a particular peer. - */ -struct PeerServiceStartContext -{ - /** - * Pointer to the high level start context. - */ - struct ServiceStartContext *start_ctx; - - /** - * The daemon handle for the peer to start the service on. - */ - struct GNUNET_TESTING_Daemon *daemon; -}; - -struct CreateTopologyContext -{ - - /** - * Function to call with number of connections - */ - GNUNET_TESTING_NotifyConnections cont; - - /** - * Closure for connection notification - */ - void *cls; -}; - -enum States -{ - /** Waiting to read number of peers */ - NUM_PEERS, - - /** Should find next peer index */ - PEER_INDEX, - - /** Should find colon */ - COLON, - - /** Should read other peer index, space, or endline */ - OTHER_PEER_INDEX -}; - -#if OLD -struct PeerConnection -{ - /** - * Doubly Linked list - */ - struct PeerConnection *prev; - - /* - * Doubly Linked list - */ - struct PeerConnection *next; - - /* - * Index of daemon in pg->peers - */ - uint32_t index; - -}; -#endif - -struct InternalStartContext -{ - /** - * Pointer to peerdata - */ - struct PeerData *peer; - - /** - * Timeout for peer startup - */ - struct GNUNET_TIME_Relative timeout; - - /** - * Client callback for hostkey notification - */ - GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback; - - /** - * Closure for hostkey_callback - */ - void *hostkey_cls; - - /** - * Client callback for peer start notification - */ - GNUNET_TESTING_NotifyDaemonRunning start_cb; - - /** - * Closure for cb - */ - void *start_cb_cls; - - /** - * Hostname, where to start the peer - */ - const char *hostname; - - /** - * Username to use when connecting to the - * host via ssh. - */ - const char *username; - - /** - * Pointer to starting memory location of a hostkey - */ - const char *hostkey; - - /** - * Port to use for ssh. - */ - uint16_t sshport; - -}; - -struct ChurnRestartContext -{ - /** - * PeerGroup that we are working with. - */ - struct GNUNET_TESTING_PeerGroup *pg; - - /** - * Number of restarts currently in flight. - */ - unsigned int outstanding; - - /** - * Handle to the underlying churn context. - */ - struct ChurnContext *churn_ctx; - - /** - * How long to allow the operation to take. - */ - struct GNUNET_TIME_Relative timeout; -}; - -struct OutstandingSSH -{ - struct OutstandingSSH *next; - - struct OutstandingSSH *prev; - - /** - * Number of current ssh connections. - */ - uint32_t outstanding; - - /** - * The hostname of this peer. - */ - const char *hostname; -}; - -/** - * Data we keep per peer. - */ -struct PeerData -{ - /** - * (Initial) configuration of the host. - * (initial because clients could change - * it and we would not know about those - * updates). - */ - struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Handle for controlling the daemon. - */ - struct GNUNET_TESTING_Daemon *daemon; - - /** - * The peergroup this peer belongs to. - */ - struct GNUNET_TESTING_PeerGroup *pg; - -#if OLD - /** - * Linked list of allowed peer connections. - */ - struct PeerConnection *allowed_peers_head; - - /** - * Linked list of allowed peer connections. - */ - struct PeerConnection *allowed_peers_tail; - - /** - * Linked list of blacklisted peer connections. - */ - struct PeerConnection *blacklisted_peers_head; - - /** - * Linked list of blacklisted peer connections. - */ - struct PeerConnection *blacklisted_peers_tail; - - /** - * Linked list of connect peer connections. - */ - struct PeerConnection *connect_peers_head; - - /** - * Linked list of connect peer connections. - */ - struct PeerConnection *connect_peers_tail; - - /** - * Linked list of connect peer connections. - */ - struct PeerConnection *connect_peers_working_set_head; - - /** - * Linked list of connect peer connections. - */ - struct PeerConnection *connect_peers_working_set_tail; - -#else - /** - * Hash map of allowed peer connections (F2F created topology) - */ - struct GNUNET_CONTAINER_MultiHashMap *allowed_peers; - - /** - * Hash map of blacklisted peers - */ - struct GNUNET_CONTAINER_MultiHashMap *blacklisted_peers; - - /** - * Hash map of peer connections - */ - struct GNUNET_CONTAINER_MultiHashMap *connect_peers; - - /** - * Temporary hash map of peer connections - */ - struct GNUNET_CONTAINER_MultiHashMap *connect_peers_working_set; -#endif - - /** - * Temporary variable for topology creation, should be reset before - * creating any topology so the count is valid once finished. - */ - int num_connections; - - /** - * Context to keep track of peers being started, to - * stagger hostkey generation and peer startup. - */ - struct InternalStartContext internal_context; - - /** - * Task ID for the queued internal_continue_startup task - */ - GNUNET_SCHEDULER_TaskIdentifier startup_task; - -}; - -/** - * Linked list of per-host data. - */ -struct HostData -{ - /** - * Name of the host. - */ - char *hostname; - - /** - * SSH username to use when connecting to this host. - */ - char *username; - - /** - * SSH port to use when connecting to this host. - */ - uint16_t sshport; - - /** - * Lowest port that we have not yet used - * for GNUnet. - */ - uint16_t minport; -}; - -struct TopologyIterateContext -{ - /** - * The peergroup we are working with. - */ - struct GNUNET_TESTING_PeerGroup *pg; - - /** - * Callback for notifying of two connected peers. - */ - GNUNET_TESTING_NotifyTopology topology_cb; - - /** - * Closure for topology_cb - */ - void *cls; - - /** - * Number of peers currently connected to. - */ - unsigned int connected; - - /** - * Number of peers we have finished iterating. - */ - unsigned int completed; - - /** - * Number of peers total. - */ - unsigned int total; -}; - -struct StatsIterateContext -{ - /** - * The peergroup that we are dealing with. - */ - struct GNUNET_TESTING_PeerGroup *pg; - - /** - * Continuation to call once all stats information has been retrieved. - */ - GNUNET_STATISTICS_Callback cont; - - /** - * Proc function to call on each value received. - */ - GNUNET_TESTING_STATISTICS_Iterator proc; - - /** - * Closure for topology_cb - */ - void *cls; - - /** - * Number of peers currently connected to. - */ - unsigned int connected; - - /** - * Number of peers we have finished iterating. - */ - unsigned int completed; - - /** - * Number of peers total. - */ - unsigned int total; -}; - -struct CoreContext -{ - void *iter_context; - struct GNUNET_TESTING_Daemon *daemon; -}; - -struct StatsCoreContext -{ - void *iter_context; - struct GNUNET_TESTING_Daemon *daemon; - /** - * Handle to the statistics service. - */ - struct GNUNET_STATISTICS_Handle *stats_handle; - - /** - * Handle for getting statistics. - */ - struct GNUNET_STATISTICS_GetHandle *stats_get_handle; -}; - -struct ConnectTopologyContext -{ - /** - * How many connections are left to create. - */ - unsigned int remaining_connections; - - /** - * Handle to group of peers. - */ - struct GNUNET_TESTING_PeerGroup *pg; - - /** - * How long to try this connection before timing out. - */ - struct GNUNET_TIME_Relative connect_timeout; - - /** - * How many times to retry connecting the two peers. - */ - unsigned int connect_attempts; - - /** - * Temp value set for each iteration. - */ - //struct PeerData *first; - - /** - * Notification that all peers are connected. - */ - GNUNET_TESTING_NotifyCompletion notify_connections_done; - - /** - * Closure for notify. - */ - void *notify_cls; -}; - -struct ConnectContext; - -/** - * Handle to a group of GNUnet peers. - */ -struct GNUNET_TESTING_PeerGroup -{ - /** - * Configuration template. - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - struct ConnectContext *cc_head; - - struct ConnectContext *cc_tail; - - /** - * Function to call on each started daemon. - */ - //GNUNET_TESTING_NotifyDaemonRunning cb; - - /** - * Closure for cb. - */ - //void *cb_cls; - - /* - * Function to call on each topology connection created - */ - GNUNET_TESTING_NotifyConnection notify_connection; - - /* - * Callback for notify_connection - */ - void *notify_connection_cls; - - /** - * Array of information about hosts. - */ - struct HostData *hosts; - - /** - * Number of hosts (size of HostData) - */ - unsigned int num_hosts; - - /** - * Array of "total" peers. - */ - struct PeerData *peers; - - /** - * Number of peers in this group. - */ - unsigned int total; - - /** - * At what time should we fail the peer startup process? - */ - struct GNUNET_TIME_Absolute max_timeout; - - /** - * How many peers are being started right now? - */ - unsigned int starting; - - /** - * How many peers have already been started? - */ - unsigned int started; - - /** - * Number of possible connections to peers - * at a time. - */ - unsigned int max_outstanding_connections; - - /** - * Number of ssh connections to peers (max). - */ - unsigned int max_concurrent_ssh; - - /** - * Number of connects we are waiting on, allows us to rate limit - * connect attempts. - */ - unsigned int outstanding_connects; - - /** - * Number of HELLOs we have yet to send. - */ - unsigned int remaining_hellos; - - /** - * How many connects have already been scheduled? - */ - unsigned int total_connects_scheduled; - - /** - * Hostkeys loaded from a file. - */ - char *hostkey_data; - - /** - * Head of DLL to keep track of the number of outstanding - * ssh connections per peer. - */ - struct OutstandingSSH *ssh_head; - - /** - * Tail of DLL to keep track of the number of outstanding - * ssh connections per peer. - */ - struct OutstandingSSH *ssh_tail; - - /** - * Stop scheduling peers connecting. - */ - unsigned int stop_connects; - - /** - * Connection context for peer group. - */ - struct ConnectTopologyContext ct_ctx; -}; - -struct UpdateContext -{ - /** - * The altered configuration. - */ - struct GNUNET_CONFIGURATION_Handle *ret; - - /** - * The original configuration to alter. - */ - const struct GNUNET_CONFIGURATION_Handle *orig; - - /** - * The hostname that this peer will run on. - */ - const char *hostname; - - /** - * The next possible port to assign. - */ - unsigned int nport; - - /** - * Unique number for unix domain sockets. - */ - unsigned int upnum; - - /** - * Unique number for this peer/host to offset - * things that are grouped by host. - */ - unsigned int fdnum; -}; - -struct ConnectContext -{ - - struct ConnectContext *next; - - struct ConnectContext *prev; - - /** - * Index of peer to connect second to. - */ - uint32_t first_index; - - /** - * Index of peer to connect first to. - */ - uint32_t second_index; - - /** - * Task associated with the attempt to connect. - */ - GNUNET_SCHEDULER_TaskIdentifier task; - - /** - * Context in 'testing.c', to cancel connection attempt. - */ - struct GNUNET_TESTING_ConnectContext *cc; - - /** - * Higher level topology connection context. - */ - struct ConnectTopologyContext *ct_ctx; - - /** - * Whether this connection has been accounted for in the schedule_connect call. - */ - int counted; -}; - -struct UnblacklistContext -{ - /** - * The peergroup - */ - struct GNUNET_TESTING_PeerGroup *pg; - - /** - * uid of the first peer - */ - uint32_t first_uid; -}; - -struct RandomContext -{ - /** - * The peergroup - */ - struct GNUNET_TESTING_PeerGroup *pg; - - /** - * uid of the first peer - */ - uint32_t first_uid; - - /** - * Peer data for first peer. - */ - struct PeerData *first; - - /** - * Random percentage to use - */ - double percentage; -}; - -struct MinimumContext -{ - /** - * The peergroup - */ - struct GNUNET_TESTING_PeerGroup *pg; - - /** - * uid of the first peer - */ - uint32_t first_uid; - - /** - * Peer data for first peer. - */ - struct PeerData *first; - - /** - * Number of conns per peer - */ - unsigned int num_to_add; - - /** - * Permuted array of all possible connections. Only add the Nth - * peer if it's in the Nth position. - */ - unsigned int *pg_array; - - /** - * What number is the current element we are iterating over? - */ - unsigned int current; -}; - -struct DFSContext -{ - /** - * The peergroup - */ - struct GNUNET_TESTING_PeerGroup *pg; - - /** - * uid of the first peer - */ - uint32_t first_uid; - - /** - * uid of the second peer - */ - uint32_t second_uid; - - /** - * Peer data for first peer. - */ - struct PeerData *first; - - /** - * Which peer has been chosen as the one to add? - */ - unsigned int chosen; - - /** - * What number is the current element we are iterating over? - */ - unsigned int current; -}; - -/** - * Simple struct to keep track of progress, and print a - * nice little percentage meter for long running tasks. - */ -struct ProgressMeter -{ - unsigned int total; - - unsigned int modnum; - - unsigned int dotnum; - - unsigned int completed; - - int print; - - char *startup_string; -}; - -#if !OLD -/** - * Convert unique ID to hash code. - * - * @param uid unique ID to convert - * @param hash set to uid (extended with zeros) - */ -static void -hash_from_uid (uint32_t uid, GNUNET_HashCode * hash) -{ - memset (hash, 0, sizeof (GNUNET_HashCode)); - *((uint32_t *) hash) = uid; -} - -/** - * Convert hash code to unique ID. - * - * @param uid unique ID to convert - * @param hash set to uid (extended with zeros) - */ -static void -uid_from_hash (const GNUNET_HashCode * hash, uint32_t * uid) -{ - memcpy (uid, hash, sizeof (uint32_t)); -} -#endif - -#if USE_SEND_HELLOS -static struct GNUNET_CORE_MessageHandler no_handlers[] = { - {NULL, 0, 0} -}; -#endif - -/** - * Create a meter to keep track of the progress of some task. - * - * @param total the total number of items to complete - * @param start_string a string to prefix the meter with (if printing) - * @param print GNUNET_YES to print the meter, GNUNET_NO to count - * internally only - * - * @return the progress meter - */ -static struct ProgressMeter * -create_meter (unsigned int total, char *start_string, int print) -{ - struct ProgressMeter *ret; - - ret = GNUNET_malloc (sizeof (struct ProgressMeter)); - ret->print = print; - ret->total = total; - ret->modnum = total / 4; - if (ret->modnum == 0) /* Divide by zero check */ - ret->modnum = 1; - ret->dotnum = (total / 50) + 1; - if (start_string != NULL) - ret->startup_string = GNUNET_strdup (start_string); - else - ret->startup_string = GNUNET_strdup (""); - - return ret; -} - -/** - * Update progress meter (increment by one). - * - * @param meter the meter to update and print info for - * - * @return GNUNET_YES if called the total requested, - * GNUNET_NO if more items expected - */ -static int -update_meter (struct ProgressMeter *meter) -{ - if (meter->print == GNUNET_YES) - { - if (meter->completed % meter->modnum == 0) - { - if (meter->completed == 0) - { - FPRINTF (stdout, "%sProgress: [0%%", meter->startup_string); - } - else - FPRINTF (stdout, "%d%%", - (int) (((float) meter->completed / meter->total) * 100)); - } - else if (meter->completed % meter->dotnum == 0) - FPRINTF (stdout, "%s", "."); - - if (meter->completed + 1 == meter->total) - FPRINTF (stdout, "%d%%]\n", 100); - fflush (stdout); - } - meter->completed++; - - if (meter->completed == meter->total) - return GNUNET_YES; - if (meter->completed > meter->total) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Progress meter overflow!!\n"); - return GNUNET_NO; -} - -/** - * Reset progress meter. - * - * @param meter the meter to reset - * - * @return GNUNET_YES if meter reset, - * GNUNET_SYSERR on error - */ -static int -reset_meter (struct ProgressMeter *meter) -{ - if (meter == NULL) - return GNUNET_SYSERR; - - meter->completed = 0; - return GNUNET_YES; -} - -/** - * Release resources for meter - * - * @param meter the meter to free - */ -static void -free_meter (struct ProgressMeter *meter) -{ - GNUNET_free_non_null (meter->startup_string); - GNUNET_free (meter); -} - -/** - * Get a topology from a string input. - * - * @param topology where to write the retrieved topology - * @param topology_string The string to attempt to - * get a configuration value from - * @return GNUNET_YES if topology string matched a - * known topology, GNUNET_NO if not - */ -int -GNUNET_TESTING_topology_get (enum GNUNET_TESTING_Topology *topology, - const char *topology_string) -{ - /** - * Strings representing topologies in enum - */ - static const char *topology_strings[] = { - /** - * A clique (everyone connected to everyone else). - */ - "CLIQUE", - - /** - * Small-world network (2d torus plus random links). - */ - "SMALL_WORLD", - - /** - * Small-world network (ring plus random links). - */ - "SMALL_WORLD_RING", - - /** - * Ring topology. - */ - "RING", - - /** - * 2-d torus. - */ - "2D_TORUS", - - /** - * Random graph. - */ - "ERDOS_RENYI", - - /** - * Certain percentage of peers are unable to communicate directly - * replicating NAT conditions - */ - "INTERNAT", - - /** - * Scale free topology. - */ - "SCALE_FREE", - - /** - * Straight line topology. - */ - "LINE", - - /** - * All peers are disconnected. - */ - "NONE", - - /** - * Read the topology from a file. - */ - "FROM_FILE", - - NULL - }; - - int curr = 0; - - if (topology_string == NULL) - return GNUNET_NO; - while (topology_strings[curr] != NULL) - { - if (strcasecmp (topology_strings[curr], topology_string) == 0) - { - *topology = curr; - return GNUNET_YES; - } - curr++; - } - *topology = GNUNET_TESTING_TOPOLOGY_NONE; - return GNUNET_NO; -} - -/** - * Get connect topology option from string input. - * - * @param topology_option where to write the retrieved topology - * @param topology_string The string to attempt to - * get a configuration value from - * @return GNUNET_YES if string matched a known - * topology option, GNUNET_NO if not - */ -int -GNUNET_TESTING_topology_option_get (enum GNUNET_TESTING_TopologyOption - *topology_option, - const char *topology_string) -{ - /** - * Options for connecting a topology as strings. - */ - static const char *topology_option_strings[] = { - /** - * Try to connect all peers specified in the topology. - */ - "CONNECT_ALL", - - /** - * Choose a random subset of connections to create. - */ - "CONNECT_RANDOM_SUBSET", - - /** - * Create at least X connections for each peer. - */ - "CONNECT_MINIMUM", - - /** - * Using a depth first search, create one connection - * per peer. If any are missed (graph disconnected) - * start over at those peers until all have at least one - * connection. - */ - "CONNECT_DFS", - - /** - * Find the N closest peers to each allowed peer in the - * topology and make sure a connection to those peers - * exists in the connect topology. - */ - "CONNECT_CLOSEST", - - /** - * No options specified. - */ - "CONNECT_NONE", - - NULL - }; - int curr = 0; - - if (topology_string == NULL) - return GNUNET_NO; - while (NULL != topology_option_strings[curr]) - { - if (strcasecmp (topology_option_strings[curr], topology_string) == 0) - { - *topology_option = curr; - return GNUNET_YES; - } - curr++; - } - *topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_NONE; - return GNUNET_NO; -} - -/** - * Function to iterate over options. Copies - * the options to the target configuration, - * updating PORT values as needed. - * - * @param cls closure - * @param section name of the section - * @param option name of the option - * @param value value of the option - */ -static void -update_config (void *cls, const char *section, const char *option, - const char *value) -{ - struct UpdateContext *ctx = cls; - unsigned int ival; - char cval[12]; - char uval[128]; - char *single_variable; - char *per_host_variable; - unsigned long long num_per_host; - - GNUNET_asprintf (&single_variable, "single_%s_per_host", section); - GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section); - - if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival))) - { - if ((ival != 0) && - (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing", - single_variable))) - { - GNUNET_snprintf (cval, sizeof (cval), "%u", ctx->nport++); - value = cval; - } - else if ((ival != 0) && - (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing", - single_variable)) && - GNUNET_CONFIGURATION_get_value_number (ctx->orig, "testing", - per_host_variable, - &num_per_host)) - { - GNUNET_snprintf (cval, sizeof (cval), "%u", - ival + ctx->fdnum % num_per_host); - value = cval; - } - - /* FIXME: REMOVE FOREVER HACK HACK HACK */ - if (0 == strcasecmp (section, "transport-tcp")) - GNUNET_CONFIGURATION_set_value_string (ctx->ret, section, - "ADVERTISED_PORT", value); - } - - if (0 == strcmp (option, "UNIXPATH")) - { - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing", - single_variable)) - { - GNUNET_snprintf (uval, sizeof (uval), "/tmp/test-service-%s-%u", section, - ctx->upnum++); - value = uval; - } - else if ((GNUNET_YES == - GNUNET_CONFIGURATION_get_value_number (ctx->orig, "testing", - per_host_variable, - &num_per_host)) && - (num_per_host > 0)) - - { - GNUNET_snprintf (uval, sizeof (uval), "/tmp/test-service-%s-%u", section, - ctx->fdnum % num_per_host); - value = uval; - } - } - - if ((0 == strcmp (option, "HOSTNAME")) && (ctx->hostname != NULL)) - { - value = ctx->hostname; - } - GNUNET_free (single_variable); - GNUNET_free (per_host_variable); - GNUNET_CONFIGURATION_set_value_string (ctx->ret, section, option, value); -} - -/** - * Create a new configuration using the given configuration - * as a template; however, each PORT in the existing cfg - * must be renumbered by incrementing "*port". If we run - * out of "*port" numbers, return NULL. - * - * @param cfg template configuration - * @param off the current peer offset - * @param port port numbers to use, update to reflect - * port numbers that were used - * @param upnum number to make unix domain socket names unique - * @param hostname hostname of the controlling host, to allow control connections from - * @param fdnum number used to offset the unix domain socket for grouped processes - * (such as statistics or peerinfo, which can be shared among others) - * - * @return new configuration, NULL on error - */ -struct GNUNET_CONFIGURATION_Handle * -GNUNET_TESTING_create_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg, uint32_t off, - uint16_t * port, uint32_t * upnum, const char *hostname, - uint32_t * fdnum) -{ - struct UpdateContext uc; - uint16_t orig; - char *control_host; - char *allowed_hosts; - unsigned long long skew_variance; - unsigned long long skew_offset; - long long actual_offset; - - orig = *port; - uc.nport = *port; - uc.upnum = *upnum; - uc.fdnum = *fdnum; - uc.ret = GNUNET_CONFIGURATION_create (); - uc.hostname = hostname; - uc.orig = cfg; - - GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc); - if (uc.nport >= HIGH_PORT) - { - *port = orig; - GNUNET_CONFIGURATION_destroy (uc.ret); - return NULL; - } - - if ((GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "skew_variance", - &skew_variance)) && - (skew_variance > 0)) - { - skew_offset = - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, - skew_variance + 1); - actual_offset = - skew_offset - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, - skew_variance + 1); - /* Min is -skew_variance, Max is skew_variance */ - skew_offset = skew_variance + actual_offset; /* Normal distribution around 0 */ - GNUNET_CONFIGURATION_set_value_number (uc.ret, "testing", "skew_offset", - skew_offset); - } - - if (GNUNET_CONFIGURATION_get_value_string - (cfg, "testing", "control_host", &control_host) == GNUNET_OK) - { - if (hostname != NULL) - GNUNET_asprintf (&allowed_hosts, "%s; 127.0.0.1; %s;", control_host, - hostname); - else - GNUNET_asprintf (&allowed_hosts, "%s; 127.0.0.1;", control_host); - - GNUNET_CONFIGURATION_set_value_string (uc.ret, "core", "ACCEPT_FROM", - allowed_hosts); - - GNUNET_CONFIGURATION_set_value_string (uc.ret, "nse", "ACCEPT_FROM", - allowed_hosts); - - GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport", "ACCEPT_FROM", - allowed_hosts); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "dht", "ACCEPT_FROM", - allowed_hosts); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "statistics", "ACCEPT_FROM", - allowed_hosts); - - GNUNET_CONFIGURATION_set_value_string (uc.ret, "core", "UNIXPATH", ""); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport", "UNIXPATH", ""); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "dht", "UNIXPATH", ""); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "statistics", "UNIXPATH", - ""); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "nse", "UNIXPATH", ""); - - GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", - "USE_LOCALADDR", "YES"); - GNUNET_free_non_null (control_host); - GNUNET_free (allowed_hosts); - } - - /* arm needs to know to allow connections from the host on which it is running, - * otherwise gnunet-arm is unable to connect to it in some instances */ - if (hostname != NULL) - { - GNUNET_asprintf (&allowed_hosts, "%s; 127.0.0.1;", hostname); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "BINDTO", hostname); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "INTERNAL_ADDRESS", - hostname); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "EXTERNAL_ADDRESS", - hostname); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "disablev6", "BINDTO", - "YES"); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport-tcp", - "USE_LOCALADDR", "YES"); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport-udp", - "USE_LOCALADDR", "YES"); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "arm", "ACCEPT_FROM", - allowed_hosts); - GNUNET_free (allowed_hosts); - } - else - { - GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", - "USE_LOCALADDR", "YES"); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "BINDTO", - "127.0.0.1"); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "INTERNAL_ADDRESS", - "127.0.0.1"); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "EXTERNAL_ADDRESS", - "127.0.0.1"); - GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "disablev6", - "YES"); - } - - *port = (uint16_t) uc.nport; - *upnum = uc.upnum; - uc.fdnum++; - *fdnum = uc.fdnum; - return uc.ret; -} - -/* - * Remove entries from the peer connection list - * - * @param pg the peer group we are working with - * @param first index of the first peer - * @param second index of the second peer - * @param list the peer list to use - * @param check UNUSED - * - * @return the number of connections added (can be 0, 1 or 2) - * - */ -static unsigned int -remove_connections (struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, - unsigned int second, enum PeerLists list, - unsigned int check) -{ - int removed; - -#if OLD - struct PeerConnection **first_list; - struct PeerConnection **second_list; - struct PeerConnection *first_iter; - struct PeerConnection *second_iter; - struct PeerConnection **first_tail; - struct PeerConnection **second_tail; - -#else - GNUNET_HashCode hash_first; - GNUNET_HashCode hash_second; - - hash_from_uid (first, &hash_first); - hash_from_uid (second, &hash_second); -#endif - - removed = 0; -#if OLD - switch (list) - { - case ALLOWED: - first_list = &pg->peers[first].allowed_peers_head; - second_list = &pg->peers[second].allowed_peers_head; - first_tail = &pg->peers[first].allowed_peers_tail; - second_tail = &pg->peers[second].allowed_peers_tail; - break; - case CONNECT: - first_list = &pg->peers[first].connect_peers_head; - second_list = &pg->peers[second].connect_peers_head; - first_tail = &pg->peers[first].connect_peers_tail; - second_tail = &pg->peers[second].connect_peers_tail; - break; - case BLACKLIST: - first_list = &pg->peers[first].blacklisted_peers_head; - second_list = &pg->peers[second].blacklisted_peers_head; - first_tail = &pg->peers[first].blacklisted_peers_tail; - second_tail = &pg->peers[second].blacklisted_peers_tail; - break; - case WORKING_SET: - first_list = &pg->peers[first].connect_peers_working_set_head; - second_list = &pg->peers[second].connect_peers_working_set_head; - first_tail = &pg->peers[first].connect_peers_working_set_tail; - second_tail = &pg->peers[second].connect_peers_working_set_tail; - break; - default: - GNUNET_break (0); - return 0; - } - - first_iter = *first_list; - while (first_iter != NULL) - { - if (first_iter->index == second) - { - GNUNET_CONTAINER_DLL_remove (*first_list, *first_tail, first_iter); - GNUNET_free (first_iter); - removed++; - break; - } - first_iter = first_iter->next; - } - - second_iter = *second_list; - while (second_iter != NULL) - { - if (second_iter->index == first) - { - GNUNET_CONTAINER_DLL_remove (*second_list, *second_tail, second_iter); - GNUNET_free (second_iter); - removed++; - break; - } - second_iter = second_iter->next; - } -#else - if (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (pg-> - peers[first].blacklisted_peers, - &hash_second)) - { - GNUNET_CONTAINER_multihashmap_remove_all (pg-> - peers[first].blacklisted_peers, - &hash_second); - } - - if (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (pg-> - peers[second].blacklisted_peers, - &hash_first)) - { - GNUNET_CONTAINER_multihashmap_remove_all (pg-> - peers[second].blacklisted_peers, - &hash_first); - } -#endif - - return removed; -} - -/** - * Add entries to the some list - * - * @param pg the peer group we are working with - * @param first index of the first peer - * @param second index of the second peer - * @param list the list type that we should modify - * @param check GNUNET_YES to check lists before adding - * GNUNET_NO to force add - * - * @return the number of connections added (can be 0, 1 or 2) - * - */ -static unsigned int -add_connections (struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, - unsigned int second, enum PeerLists list, unsigned int check) -{ - int added; - int add_first; - int add_second; - - struct PeerConnection **first_list; - struct PeerConnection **second_list; - struct PeerConnection *first_iter; - struct PeerConnection *second_iter; - struct PeerConnection *new_first; - struct PeerConnection *new_second; - struct PeerConnection **first_tail; - struct PeerConnection **second_tail; - - switch (list) - { - case ALLOWED: - first_list = &pg->peers[first].allowed_peers_head; - second_list = &pg->peers[second].allowed_peers_head; - first_tail = &pg->peers[first].allowed_peers_tail; - second_tail = &pg->peers[second].allowed_peers_tail; - break; - case CONNECT: - first_list = &pg->peers[first].connect_peers_head; - second_list = &pg->peers[second].connect_peers_head; - first_tail = &pg->peers[first].connect_peers_tail; - second_tail = &pg->peers[second].connect_peers_tail; - break; - case BLACKLIST: - first_list = &pg->peers[first].blacklisted_peers_head; - second_list = &pg->peers[second].blacklisted_peers_head; - first_tail = &pg->peers[first].blacklisted_peers_tail; - second_tail = &pg->peers[second].blacklisted_peers_tail; - break; - case WORKING_SET: - first_list = &pg->peers[first].connect_peers_working_set_head; - second_list = &pg->peers[second].connect_peers_working_set_head; - first_tail = &pg->peers[first].connect_peers_working_set_tail; - second_tail = &pg->peers[second].connect_peers_working_set_tail; - break; - default: - GNUNET_break (0); - return 0; - } - - add_first = GNUNET_YES; - add_second = GNUNET_YES; - - if (check == GNUNET_YES) - { - first_iter = *first_list; - while (first_iter != NULL) - { - if (first_iter->index == second) - { - add_first = GNUNET_NO; - break; - } - first_iter = first_iter->next; - } - - second_iter = *second_list; - while (second_iter != NULL) - { - if (second_iter->index == first) - { - add_second = GNUNET_NO; - break; - } - second_iter = second_iter->next; - } - } - - added = 0; - if (add_first) - { - new_first = GNUNET_malloc (sizeof (struct PeerConnection)); - new_first->index = second; - GNUNET_CONTAINER_DLL_insert (*first_list, *first_tail, new_first); - pg->peers[first].num_connections++; - added++; - } - - if (add_second) - { - new_second = GNUNET_malloc (sizeof (struct PeerConnection)); - new_second->index = first; - GNUNET_CONTAINER_DLL_insert (*second_list, *second_tail, new_second); - pg->peers[second].num_connections++; - added++; - } - - return added; -} - -/** - * Scale free network construction as described in: - * - * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999. - * - * Start with a network of "one" peer, then progressively add - * peers up to the total number. At each step, iterate over - * all possible peers and connect new peer based on number of - * existing connections of the target peer. - * - * @param pg the peer group we are dealing with - * @param proc the connection processor to use - * @param list the peer list to use - * - * @return the number of connections created - */ -static unsigned int -create_scale_free (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list) -{ - - unsigned int total_connections; - unsigned int outer_count; - unsigned int i; - unsigned int previous_total_connections; - double random; - double probability; - - GNUNET_assert (pg->total > 1); - - /* Add a connection between the first two nodes */ - total_connections = proc (pg, 0, 1, list, GNUNET_YES); - - for (outer_count = 1; outer_count < pg->total; outer_count++) - { - previous_total_connections = total_connections; - for (i = 0; i < outer_count; i++) - { - probability = - pg->peers[i].num_connections / (double) previous_total_connections; - random = - ((double) - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, - UINT64_MAX)) / ((double) UINT64_MAX); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Considering connecting peer %d to peer %d\n", outer_count, - i); - if (random < probability) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", - outer_count, i); - total_connections += proc (pg, outer_count, i, list, GNUNET_YES); - } - } - } - - return total_connections; -} - -/** - * Create a topology given a peer group (set of running peers) - * and a connection processor. Creates a small world topology - * according to the rewired ring construction. The basic - * behavior is that a ring topology is created, but with some - * probability instead of connecting a peer to the next - * neighbor in the ring a connection will be created to a peer - * selected uniformly at random. We use the TESTING - * PERCENTAGE option to specify what number of - * connections each peer should have. Default is 2, - * which makes the ring, any given number is multiplied by - * the log of the network size; i.e. a PERCENTAGE of 2 makes - * each peer have on average 2logn connections. The additional - * connections are made at increasing distance around the ring - * from the original peer, or to random peers based on the re- - * wiring probability. The TESTING - * PROBABILITY option is used as the probability that a given - * connection is rewired. - * - * @param pg the peergroup to create the topology on - * @param proc the connection processor to call to actually set - * up connections between two peers - * @param list the peer list to use - * - * @return the number of connections that were set up - * - */ -static unsigned int -create_small_world_ring (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_TESTING_ConnectionProcessor proc, - enum PeerLists list) -{ - unsigned int i, j; - int nodeToConnect; - unsigned int natLog; - unsigned int randomPeer; - double random, logNModifier, probability; - unsigned int smallWorldConnections; - int connsPerPeer; - char *p_string; - int max; - int min; - unsigned int useAnd; - int connect_attempts; - - logNModifier = 0.5; /* FIXME: default value? */ - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PERCENTAGE", - &p_string)) - { - if (SSCANF (p_string, "%lf", &logNModifier) != 1) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), - p_string, "LOGNMODIFIER", "TESTING"); - GNUNET_free (p_string); - } - probability = 0.5; /* FIXME: default percentage? */ - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PROBABILITY", - &p_string)) - { - if (SSCANF (p_string, "%lf", &probability) != 1) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), - p_string, "PERCENTAGE", "TESTING"); - GNUNET_free (p_string); - } - natLog = log (pg->total); - connsPerPeer = ceil (natLog * logNModifier); - - if (connsPerPeer % 2 == 1) - connsPerPeer += 1; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Target is %d connections per peer.", - connsPerPeer); - - smallWorldConnections = 0; - connect_attempts = 0; - for (i = 0; i < pg->total; i++) - { - useAnd = 0; - max = i + connsPerPeer / 2; - min = i - connsPerPeer / 2; - - if (max > pg->total - 1) - { - max = max - pg->total; - useAnd = 1; - } - - if (min < 0) - { - min = pg->total - 1 + min; - useAnd = 1; - } - - for (j = 0; j < connsPerPeer / 2; j++) - { - random = - ((double) - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, - UINT64_MAX) / ((double) UINT64_MAX)); - if (random < probability) - { - /* Connect to uniformly selected random peer */ - randomPeer = - GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total); - while ((((randomPeer < max) && (randomPeer > min)) && (useAnd == 0)) || - (((randomPeer > min) || (randomPeer < max)) && (useAnd == 1))) - { - randomPeer = - GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total); - } - smallWorldConnections += proc (pg, i, randomPeer, list, GNUNET_YES); - } - else - { - nodeToConnect = i + j + 1; - if (nodeToConnect > pg->total - 1) - { - nodeToConnect = nodeToConnect - pg->total; - } - connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES); - } - } - - } - - connect_attempts += smallWorldConnections; - - return connect_attempts; -} - -/** - * Create a topology given a peer group (set of running peers) - * and a connection processor. - * - * @param pg the peergroup to create the topology on - * @param proc the connection processor to call to actually set - * up connections between two peers - * @param list the peer list to use - * - * @return the number of connections that were set up - * - */ -static unsigned int -create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_TESTING_ConnectionProcessor proc, - enum PeerLists list) -{ - unsigned int outer_count, inner_count; - unsigned int cutoff; - int connect_attempts; - double nat_percentage; - char *p_string; - - nat_percentage = 0.6; /* FIXME: default percentage? */ - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PERCENTAGE", - &p_string)) - { - if (SSCANF (p_string, "%lf", &nat_percentage) != 1) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), - p_string, "PERCENTAGE", "TESTING"); - GNUNET_free (p_string); - } - - cutoff = (unsigned int) (nat_percentage * pg->total); - connect_attempts = 0; - for (outer_count = 0; outer_count < pg->total - 1; outer_count++) - { - for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++) - { - if ((outer_count > cutoff) || (inner_count > cutoff)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", - outer_count, inner_count); - connect_attempts += - proc (pg, outer_count, inner_count, list, GNUNET_YES); - } - } - } - return connect_attempts; -} - -#if TOPOLOGY_HACK -/** - * Create a topology given a peer group (set of running peers) - * and a connection processor. - * - * @param pg the peergroup to create the topology on - * @param proc the connection processor to call to actually set - * up connections between two peers - * @param list the peer list to use - * - * @return the number of connections that were set up - * - */ -static unsigned int -create_nated_internet_copy (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_TESTING_ConnectionProcessor proc, - enum PeerLists list) -{ - unsigned int outer_count, inner_count; - unsigned int cutoff; - int connect_attempts; - double nat_percentage; - char *p_string; - unsigned int count; - struct ProgressMeter *conn_meter; - - nat_percentage = 0.6; /* FIXME: default percentage? */ - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PERCENTAGE", - &p_string)) - { - if (SSCANF (p_string, "%lf", &nat_percentage) != 1) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), - p_string, "PERCENTAGE", "TESTING"); - GNUNET_free (p_string); - } - - cutoff = (unsigned int) (nat_percentage * pg->total); - count = 0; - for (outer_count = 0; outer_count < pg->total - 1; outer_count++) - { - for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++) - { - if ((outer_count > cutoff) || (inner_count > cutoff)) - { - count++; - } - } - } - conn_meter = create_meter (count, "NAT COPY", GNUNET_YES); - connect_attempts = 0; - for (outer_count = 0; outer_count < pg->total - 1; outer_count++) - { - for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++) - { - if ((outer_count > cutoff) || (inner_count > cutoff)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", - outer_count, inner_count); - connect_attempts += - proc (pg, outer_count, inner_count, list, GNUNET_YES); - add_connections (pg, outer_count, inner_count, ALLOWED, GNUNET_NO); - update_meter (conn_meter); - } - } - } - free_meter (conn_meter); - - return connect_attempts; -} -#endif - -/** - * Create a topology given a peer group (set of running peers) - * and a connection processor. - * - * @param pg the peergroup to create the topology on - * @param proc the connection processor to call to actually set - * up connections between two peers - * @param list the peer list to use - * - * @return the number of connections that were set up - * - */ -static unsigned int -create_small_world (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_TESTING_ConnectionProcessor proc, - enum PeerLists list) -{ - unsigned int i, j, k; - unsigned int square; - unsigned int rows; - unsigned int cols; - unsigned int toggle = 1; - unsigned int nodeToConnect; - unsigned int natLog; - unsigned int node1Row; - unsigned int node1Col; - unsigned int node2Row; - unsigned int node2Col; - unsigned int distance; - double probability, random, percentage; - unsigned int smallWorldConnections; - unsigned int small_world_it; - char *p_string; - int connect_attempts; - - square = floor (sqrt (pg->total)); - rows = square; - cols = square; - - percentage = 0.5; /* FIXME: default percentage? */ - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PERCENTAGE", - &p_string)) - { - if (SSCANF (p_string, "%lf", &percentage) != 1) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), - p_string, "PERCENTAGE", "TESTING"); - GNUNET_free (p_string); - } - if (percentage < 0.0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Invalid value `%s' for option `%s' in section `%s': got %f, needed value greater than 0\n"), - "PERCENTAGE", "TESTING", percentage); - percentage = 0.5; - } - probability = 0.5; /* FIXME: default percentage? */ - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PROBABILITY", - &p_string)) - { - if (SSCANF (p_string, "%lf", &probability) != 1) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), - p_string, "PROBABILITY", "TESTING"); - GNUNET_free (p_string); - } - if (square * square != pg->total) - { - while (rows * cols < pg->total) - { - if (toggle % 2 == 0) - rows++; - else - cols++; - - toggle++; - } - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connecting nodes in 2d torus topology: %u rows %u columns\n", - rows, cols); - connect_attempts = 0; - /* Rows and columns are all sorted out, now iterate over all nodes and connect each - * to the node to its right and above. Once this is over, we'll have our torus! - * Special case for the last node (if the rows and columns are not equal), connect - * to the first in the row to maintain topology. - */ - for (i = 0; i < pg->total; i++) - { - /* First connect to the node to the right */ - if (((i + 1) % cols != 0) && (i + 1 != pg->total)) - nodeToConnect = i + 1; - else if (i + 1 == pg->total) - nodeToConnect = rows * cols - cols; - else - nodeToConnect = i - cols + 1; - - connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES); - - if (i < cols) - { - nodeToConnect = (rows * cols) - cols + i; - if (nodeToConnect >= pg->total) - nodeToConnect -= cols; - } - else - nodeToConnect = i - cols; - - if (nodeToConnect < pg->total) - connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES); - } - natLog = log (pg->total); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "natural log of %d is %d, will run %d iterations\n", pg->total, - natLog, (int) (natLog * percentage)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Total connections added thus far: %u!\n", connect_attempts); - smallWorldConnections = 0; - small_world_it = (unsigned int) (natLog * percentage); - if (small_world_it < 1) - small_world_it = 1; - GNUNET_assert (small_world_it > 0 && small_world_it < (unsigned int) -1); - for (i = 0; i < small_world_it; i++) - { - for (j = 0; j < pg->total; j++) - { - /* Determine the row and column of node at position j on the 2d torus */ - node1Row = j / cols; - node1Col = j - (node1Row * cols); - for (k = 0; k < pg->total; k++) - { - /* Determine the row and column of node at position k on the 2d torus */ - node2Row = k / cols; - node2Col = k - (node2Row * cols); - /* Simple Cartesian distance */ - distance = abs (node1Row - node2Row) + abs (node1Col - node2Col); - if (distance > 1) - { - /* Calculate probability as 1 over the square of the distance */ - probability = 1.0 / (distance * distance); - /* Choose a random value between 0 and 1 */ - random = - ((double) - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, - UINT64_MAX)) / ((double) UINT64_MAX); - /* If random < probability, then connect the two nodes */ - if (random < probability) - smallWorldConnections += proc (pg, j, k, list, GNUNET_YES); - - } - } - } - } - connect_attempts += smallWorldConnections; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Total connections added for small world: %d!\n", - smallWorldConnections); - return connect_attempts; -} - -/** - * Create a topology given a peer group (set of running peers) - * and a connection processor. - * - * @param pg the peergroup to create the topology on - * @param proc the connection processor to call to actually set - * up connections between two peers - * @param list the peer list to use - * - * @return the number of connections that were set up - * - */ -static unsigned int -create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_TESTING_ConnectionProcessor proc, - enum PeerLists list) -{ - double temp_rand; - unsigned int outer_count; - unsigned int inner_count; - int connect_attempts; - double probability; - char *p_string; - - probability = 0.5; /* FIXME: default percentage? */ - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PROBABILITY", - &p_string)) - { - if (SSCANF (p_string, "%lf", &probability) != 1) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), - p_string, "PROBABILITY", "TESTING"); - GNUNET_free (p_string); - } - connect_attempts = 0; - for (outer_count = 0; outer_count < pg->total - 1; outer_count++) - { - for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++) - { - temp_rand = - ((double) - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, - UINT64_MAX)) / ((double) UINT64_MAX); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "rand is %f probability is %f\n", - temp_rand, probability); - if (temp_rand < probability) - { - connect_attempts += - proc (pg, outer_count, inner_count, list, GNUNET_YES); - } - } - } - - return connect_attempts; -} - -/** - * Create a topology given a peer group (set of running peers) - * and a connection processor. This particular function creates - * the connections for a 2d-torus, plus additional "closest" - * connections per peer. - * - * @param pg the peergroup to create the topology on - * @param proc the connection processor to call to actually set - * up connections between two peers - * @param list the peer list to use - * - * @return the number of connections that were set up - * - */ -static unsigned int -create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list) -{ - unsigned int i; - unsigned int square; - unsigned int rows; - unsigned int cols; - unsigned int toggle = 1; - unsigned int nodeToConnect; - int connect_attempts; - - connect_attempts = 0; - - square = floor (sqrt (pg->total)); - rows = square; - cols = square; - - if (square * square != pg->total) - { - while (rows * cols < pg->total) - { - if (toggle % 2 == 0) - rows++; - else - cols++; - - toggle++; - } - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connecting nodes in 2d torus topology: %u rows %u columns\n", - rows, cols); - /* Rows and columns are all sorted out, now iterate over all nodes and connect each - * to the node to its right and above. Once this is over, we'll have our torus! - * Special case for the last node (if the rows and columns are not equal), connect - * to the first in the row to maintain topology. - */ - for (i = 0; i < pg->total; i++) - { - /* First connect to the node to the right */ - if (((i + 1) % cols != 0) && (i + 1 != pg->total)) - nodeToConnect = i + 1; - else if (i + 1 == pg->total) - nodeToConnect = rows * cols - cols; - else - nodeToConnect = i - cols + 1; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", i, - nodeToConnect); - connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES); - - /* Second connect to the node immediately above */ - if (i < cols) - { - nodeToConnect = (rows * cols) - cols + i; - if (nodeToConnect >= pg->total) - nodeToConnect -= cols; - } - else - nodeToConnect = i - cols; - - if (nodeToConnect < pg->total) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", i, - nodeToConnect); - connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES); - } - - } - - return connect_attempts; -} - -/** - * Create a topology given a peer group (set of running peers) - * and a connection processor. - * - * @param pg the peergroup to create the topology on - * @param proc the connection processor to call to actually set - * up connections between two peers - * @param list the peer list to use - * @param check does the connection processor need to check before - * performing an action on the list? - * - * @return the number of connections that were set up - * - */ -static unsigned int -create_clique (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list, - unsigned int check) -{ - unsigned int outer_count; - unsigned int inner_count; - int connect_attempts; - struct ProgressMeter *conn_meter; - - connect_attempts = 0; - - conn_meter = - create_meter ((((pg->total * pg->total) + pg->total) / 2) - pg->total, - "Create Clique ", GNUNET_NO); - for (outer_count = 0; outer_count < pg->total - 1; outer_count++) - { - for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", - outer_count, inner_count); - connect_attempts += proc (pg, outer_count, inner_count, list, check); - update_meter (conn_meter); - } - } - reset_meter (conn_meter); - free_meter (conn_meter); - return connect_attempts; -} - -#if !OLD -/** - * Iterator over hash map entries. - * - * @param cls closure the peer group - * @param key the key stored in the hashmap is the - * index of the peer to connect to - * @param value value in the hash map, handle to the peer daemon - * @return GNUNET_YES if we should continue to - * iterate, - * GNUNET_NO if not. - */ -static int -unblacklist_iterator (void *cls, const GNUNET_HashCode * key, void *value) -{ - struct UnblacklistContext *un_ctx = cls; - uint32_t second_pos; - - uid_from_hash (key, &second_pos); - - unblacklist_connections (un_ctx->pg, un_ctx->first_uid, second_pos); - - return GNUNET_YES; -} -#endif - -#if !OLD -/** - * Create a blacklist topology based on the allowed topology - * which disallows any connections not in the allowed topology - * at the transport level. - * - * @param pg the peergroup to create the topology on - * @param proc the connection processor to call to allow - * up connections between two peers - * - * @return the number of connections that were set up - * - */ -static unsigned int -copy_allowed (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_TESTING_ConnectionProcessor proc) -{ - unsigned int count; - unsigned int total; - struct PeerConnection *iter; - -#if !OLD - struct UnblacklistContext un_ctx; - - un_ctx.pg = pg; -#endif - total = 0; - for (count = 0; count < pg->total - 1; count++) - { -#if OLD - iter = pg->peers[count].allowed_peers_head; - while (iter != NULL) - { - remove_connections (pg, count, iter->index, BLACKLIST, GNUNET_YES); - //unblacklist_connections(pg, count, iter->index); - iter = iter->next; - } -#else - un_ctx.first_uid = count; - total += - GNUNET_CONTAINER_multihashmap_iterate (pg->peers[count].allowed_peers, - &unblacklist_iterator, &un_ctx); -#endif - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unblacklisted %u peers\n", total); - return total; -} -#endif - -/** - * Create a topology given a peer group (set of running peers) - * and a connection processor. - * - * @param pg the peergroup to create the topology on - * @param proc the connection processor to call to actually set - * up connections between two peers - * @param list which list should be modified - * - * @return the number of connections that were set up - * - */ -static unsigned int -create_line (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list) -{ - unsigned int count; - unsigned int connect_attempts; - - connect_attempts = 0; - /* Connect each peer to the next highest numbered peer */ - for (count = 0; count < pg->total - 1; count++) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", - count, count + 1); - connect_attempts += proc (pg, count, count + 1, list, GNUNET_YES); - } - - return connect_attempts; -} - -/** - * Create a topology given a peer group (set of running peers) - * and a connection processor. - * - * @param pg the peergroup to create the topology on - * @param filename the file to read topology information from - * @param proc the connection processor to call to actually set - * up connections between two peers - * @param list the peer list to use - * - * @return the number of connections that were set up - * - */ -static unsigned int -create_from_file (struct GNUNET_TESTING_PeerGroup *pg, char *filename, - GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list) -{ - int connect_attempts; - unsigned int first_peer_index; - unsigned int second_peer_index; - struct stat frstat; - int count; - char *data; - const char *buf; - unsigned int total_peers; - enum States curr_state; - - connect_attempts = 0; - if (GNUNET_OK != GNUNET_DISK_file_test (filename)) - GNUNET_DISK_fn_write (filename, NULL, 0, GNUNET_DISK_PERM_USER_READ); - - if ((0 != STAT (filename, &frstat)) || (frstat.st_size == 0)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not open file `%s' specified for topology!", filename); - return connect_attempts; - } - - data = GNUNET_malloc_large (frstat.st_size); - GNUNET_assert (data != NULL); - if (frstat.st_size != GNUNET_DISK_fn_read (filename, data, frstat.st_size)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not read file %s specified for host list, ending test!", - filename); - GNUNET_free (data); - return connect_attempts; - } - - buf = data; - count = 0; - first_peer_index = 0; - /* First line should contain a single integer, specifying the number of peers */ - /* Each subsequent line should contain this format PEER_INDEX:OTHER_PEER_INDEX[,...] */ - curr_state = NUM_PEERS; - while (count < frstat.st_size - 1) - { - if ((buf[count] == '\n') || (buf[count] == ' ')) - { - count++; - continue; - } - - switch (curr_state) - { - case NUM_PEERS: - errno = 0; - total_peers = strtoul (&buf[count], NULL, 10); - if (errno != 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to read number of peers from topology file!\n"); - GNUNET_free (data); - return connect_attempts; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u total peers in topology\n", - total_peers); - GNUNET_assert (total_peers == pg->total); - curr_state = PEER_INDEX; - while ((buf[count] != '\n') && (count < frstat.st_size - 1)) - count++; - count++; - break; - case PEER_INDEX: - errno = 0; - first_peer_index = strtoul (&buf[count], NULL, 10); - if (errno != 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to read peer index from topology file!\n"); - GNUNET_free (data); - return connect_attempts; - } - while ((buf[count] != ':') && (count < frstat.st_size - 1)) - count++; - count++; - curr_state = OTHER_PEER_INDEX; - break; - case COLON: - if (1 == sscanf (&buf[count], ":")) - curr_state = OTHER_PEER_INDEX; - count++; - break; - case OTHER_PEER_INDEX: - errno = 0; - second_peer_index = strtoul (&buf[count], NULL, 10); - if (errno != 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to peer index from topology file!\n"); - GNUNET_free (data); - return connect_attempts; - } - /* Assume file is written with first peer 1, but array index is 0 */ - connect_attempts += - proc (pg, first_peer_index - 1, second_peer_index - 1, list, - GNUNET_YES); - while ((buf[count] != '\n') && (buf[count] != ',') && - (count < frstat.st_size - 1)) - count++; - if (buf[count] == '\n') - { - curr_state = PEER_INDEX; - } - else if (buf[count] != ',') - { - curr_state = OTHER_PEER_INDEX; - } - count++; - break; - default: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Found bad data in topology file while in state %d!\n", - curr_state); - GNUNET_break (0); - GNUNET_free (data); - return connect_attempts; - } - } - GNUNET_free (data); - return connect_attempts; -} - -/** - * Create a topology given a peer group (set of running peers) - * and a connection processor. - * - * @param pg the peergroup to create the topology on - * @param proc the connection processor to call to actually set - * up connections between two peers - * @param list the peer list to use - * - * @return the number of connections that were set up - * - */ -static unsigned int -create_ring (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list) -{ - unsigned int count; - int connect_attempts; - - connect_attempts = 0; - - /* Connect each peer to the next highest numbered peer */ - for (count = 0; count < pg->total - 1; count++) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", - count, count + 1); - connect_attempts += proc (pg, count, count + 1, list, GNUNET_YES); - } - - /* Connect the last peer to the first peer */ - connect_attempts += proc (pg, pg->total - 1, 0, list, GNUNET_YES); - - return connect_attempts; -} - -#if !OLD -/** - * Iterator for writing friends of a peer to a file. - * - * @param cls closure, an open writable file handle - * @param key the key the daemon was stored under - * @param value the GNUNET_TESTING_Daemon that needs to be written. - * - * @return GNUNET_YES to continue iteration - * - * TODO: Could replace friend_file_iterator and blacklist_file_iterator - * with a single file_iterator that takes a closure which contains - * the prefix to write before the peer. Then this could be used - * for blacklisting multiple transports and writing the friend - * file. I'm sure *someone* will complain loudly about other - * things that negate these functions even existing so no point in - * "fixing" now. - */ -static int -friend_file_iterator (void *cls, const GNUNET_HashCode * key, void *value) -{ - FILE *temp_friend_handle = cls; - struct GNUNET_TESTING_Daemon *peer = value; - struct GNUNET_PeerIdentity *temppeer; - struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc; - - temppeer = &peer->id; - GNUNET_CRYPTO_hash_to_enc (&temppeer->hashPubKey, &peer_enc); - FPRINTF (temp_friend_handle, "%s\n", (char *) &peer_enc); - - return GNUNET_YES; -} - -struct BlacklistContext -{ - /* - * The (open) file handle to write to - */ - FILE *temp_file_handle; - - /* - * The transport that this peer will be blacklisted on. - */ - char *transport; -}; - -/** - * Iterator for writing blacklist data to appropriate files. - * - * @param cls closure, an open writable file handle - * @param key the key the daemon was stored under - * @param value the GNUNET_TESTING_Daemon that needs to be written. - * - * @return GNUNET_YES to continue iteration - */ -static int -blacklist_file_iterator (void *cls, const GNUNET_HashCode * key, void *value) -{ - struct BlacklistContext *blacklist_ctx = cls; - struct GNUNET_TESTING_Daemon *peer = value; - struct GNUNET_PeerIdentity *temppeer; - struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc; - - temppeer = &peer->id; - GNUNET_CRYPTO_hash_to_enc (&temppeer->hashPubKey, &peer_enc); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing entry %s:%s to file\n", - blacklist_ctx->transport, (char *) &peer_enc); - FPRINTF (blacklist_ctx->temp_file_handle, "%s:%s\n", blacklist_ctx->transport, - (char *) &peer_enc); - - return GNUNET_YES; -} -#endif - -/* - * Create the friend files based on the PeerConnection's - * of each peer in the peer group, and copy the files - * to the appropriate place - * - * @param pg the peer group we are dealing with - */ -static int -create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg) -{ - FILE *temp_friend_handle; - unsigned int pg_iter; - char *temp_service_path; - struct GNUNET_OS_Process **procarr; - char *arg; - char *mytemp; - -#if NOT_STUPID - enum GNUNET_OS_ProcessStatusType type; - unsigned long return_code; - int count; - int max_wait = 10; -#endif - int ret; - - ret = GNUNET_OK; -#if OLD - struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc; - struct PeerConnection *conn_iter; -#endif - procarr = GNUNET_malloc (sizeof (struct GNUNET_OS_Process *) * pg->total); - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - mytemp = GNUNET_DISK_mktemp ("friends"); - GNUNET_assert (mytemp != NULL); - temp_friend_handle = FOPEN (mytemp, "wt"); - GNUNET_assert (temp_friend_handle != NULL); -#if OLD - conn_iter = pg->peers[pg_iter].allowed_peers_head; - while (conn_iter != NULL) - { - GNUNET_CRYPTO_hash_to_enc (&pg->peers[conn_iter->index].daemon-> - id.hashPubKey, &peer_enc); - FPRINTF (temp_friend_handle, "%s\n", (char *) &peer_enc); - conn_iter = conn_iter->next; - } -#else - GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].allowed_peers, - &friend_file_iterator, - temp_friend_handle); -#endif - FCLOSE (temp_friend_handle); - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (pg->peers[pg_iter].daemon->cfg, - "PATHS", "SERVICEHOME", - &temp_service_path)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("No `%s' specified in peer configuration in section `%s', cannot copy friends file!\n"), - "SERVICEHOME", "PATHS"); - if (UNLINK (mytemp) != 0) - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", mytemp); - GNUNET_free (mytemp); - break; - } - - if (pg->peers[pg_iter].daemon->hostname == NULL) /* Local, just copy the file */ - { - GNUNET_asprintf (&arg, "%s/friends", temp_service_path); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Copying file with RENAME(%s,%s)\n", mytemp, arg); - RENAME (mytemp, arg); - procarr[pg_iter] = NULL; - GNUNET_free (arg); - } - else /* Remote, scp the file to the correct place */ - { - if (NULL != pg->peers[pg_iter].daemon->username) - GNUNET_asprintf (&arg, "%s@%s:%s/friends", - pg->peers[pg_iter].daemon->username, - pg->peers[pg_iter].daemon->hostname, - temp_service_path); - else - GNUNET_asprintf (&arg, "%s:%s/friends", - pg->peers[pg_iter].daemon->hostname, - temp_service_path); - procarr[pg_iter] = - GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "scp", "scp", mytemp, arg, NULL); - GNUNET_assert (procarr[pg_iter] != NULL); - ret = GNUNET_OS_process_wait (procarr[pg_iter]); /* FIXME: schedule this, throttle! */ - GNUNET_OS_process_destroy (procarr[pg_iter]); - if (ret != GNUNET_OK) - { - /* FIXME: free contents of 'procarr' array */ - GNUNET_free (procarr); - GNUNET_free (temp_service_path); - GNUNET_free (mytemp); - GNUNET_free (arg); - return ret; - } - procarr[pg_iter] = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Copying file with command scp %s %s\n", mytemp, arg); - GNUNET_free (arg); - } - GNUNET_free (temp_service_path); - GNUNET_free (mytemp); - } - -#if NOT_STUPID - count = 0; - ret = GNUNET_SYSERR; - while ((count < max_wait) && (ret != GNUNET_OK)) - { - ret = GNUNET_OK; - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking copy status of file %d\n", - pg_iter); - if (procarr[pg_iter] != NULL) /* Check for already completed! */ - { - if (GNUNET_OS_process_status (procarr[pg_iter], &type, &return_code) != - GNUNET_OK) - { - ret = GNUNET_SYSERR; - } - else if ((type != GNUNET_OS_PROCESS_EXITED) || (return_code != 0)) - { - ret = GNUNET_SYSERR; - } - else - { - GNUNET_OS_process_destroy (procarr[pg_iter]); - procarr[pg_iter] = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "File %d copied\n", pg_iter); - } - } - } - count++; - if (ret == GNUNET_SYSERR) - { - /* FIXME: why sleep here? -CG */ - sleep (1); - } - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Finished copying all friend files!\n"); -#endif - GNUNET_free (procarr); - return ret; -} - -/* - * Create the blacklist files based on the PeerConnection's - * of each peer in the peer group, and copy the files - * to the appropriate place. - * - * @param pg the peer group we are dealing with - * @param transports space delimited list of transports to blacklist - */ -static int -create_and_copy_blacklist_files (struct GNUNET_TESTING_PeerGroup *pg, - const char *transports) -{ - FILE *temp_file_handle; - unsigned int pg_iter; - char *temp_service_path; - struct GNUNET_OS_Process **procarr; - char *arg; - char *mytemp; - enum GNUNET_OS_ProcessStatusType type; - unsigned long return_code; - int count; - int ret; - int max_wait = 10; - int transport_len; - unsigned int i; - char *pos; - char *temp_transports; - -#if OLD - struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc; - struct PeerConnection *conn_iter; -#else - static struct BlacklistContext blacklist_ctx; -#endif - - procarr = GNUNET_malloc (sizeof (struct GNUNET_OS_Process *) * pg->total); - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - mytemp = GNUNET_DISK_mktemp ("blacklist"); - GNUNET_assert (mytemp != NULL); - temp_file_handle = FOPEN (mytemp, "wt"); - GNUNET_assert (temp_file_handle != NULL); - temp_transports = GNUNET_strdup (transports); -#if !OLD - blacklist_ctx.temp_file_handle = temp_file_handle; -#endif - transport_len = strlen (temp_transports) + 1; - pos = NULL; - - for (i = 0; i < transport_len; i++) - { - if ((temp_transports[i] == ' ') && (pos == NULL)) - continue; /* At start of string (whitespace) */ - else if ((temp_transports[i] == ' ') || (temp_transports[i] == '\0')) /* At end of string */ - { - temp_transports[i] = '\0'; -#if OLD - conn_iter = pg->peers[pg_iter].blacklisted_peers_head; - while (conn_iter != NULL) - { - GNUNET_CRYPTO_hash_to_enc (&pg->peers[conn_iter->index].daemon-> - id.hashPubKey, &peer_enc); - FPRINTF (temp_file_handle, "%s:%s\n", pos, (char *) &peer_enc); - conn_iter = conn_iter->next; - } -#else - blacklist_ctx.transport = pos; - (void) GNUNET_CONTAINER_multihashmap_iterate (pg-> - peers - [pg_iter].blacklisted_peers, - &blacklist_file_iterator, - &blacklist_ctx); -#endif - pos = NULL; - } /* At beginning of actual string */ - else if (pos == NULL) - { - pos = &temp_transports[i]; - } - } - - GNUNET_free (temp_transports); - FCLOSE (temp_file_handle); - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (pg->peers[pg_iter].daemon->cfg, - "PATHS", "SERVICEHOME", - &temp_service_path)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("No `%s' specified in peer configuration in section `%s', cannot copy friends file!\n"), - "SERVICEHOME", "PATHS"); - if (UNLINK (mytemp) != 0) - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", mytemp); - GNUNET_free (mytemp); - break; - } - - if (pg->peers[pg_iter].daemon->hostname == NULL) /* Local, just copy the file */ - { - GNUNET_asprintf (&arg, "%s/blacklist", temp_service_path); - RENAME (mytemp, arg); - procarr[pg_iter] = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Copying file with RENAME (%s,%s)\n", mytemp, arg); - GNUNET_free (arg); - } - else /* Remote, scp the file to the correct place */ - { - if (NULL != pg->peers[pg_iter].daemon->username) - GNUNET_asprintf (&arg, "%s@%s:%s/blacklist", - pg->peers[pg_iter].daemon->username, - pg->peers[pg_iter].daemon->hostname, - temp_service_path); - else - GNUNET_asprintf (&arg, "%s:%s/blacklist", - pg->peers[pg_iter].daemon->hostname, - temp_service_path); - procarr[pg_iter] = - GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "scp", "scp", mytemp, arg, NULL); - GNUNET_assert (procarr[pg_iter] != NULL); - GNUNET_OS_process_wait (procarr[pg_iter]); /* FIXME: add scheduled blacklist file copy that parallelizes file copying! */ - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Copying file with command scp %s %s\n", mytemp, arg); - GNUNET_free (arg); - } - GNUNET_free (temp_service_path); - GNUNET_free (mytemp); - } - - count = 0; - ret = GNUNET_SYSERR; - while ((count < max_wait) && (ret != GNUNET_OK)) - { - ret = GNUNET_OK; - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Checking copy status of file %d\n", pg_iter); - if (procarr[pg_iter] != NULL) /* Check for already completed! */ - { - if (GNUNET_OS_process_status (procarr[pg_iter], &type, &return_code) != - GNUNET_OK) - { - ret = GNUNET_SYSERR; - } - else if ((type != GNUNET_OS_PROCESS_EXITED) || (return_code != 0)) - { - ret = GNUNET_SYSERR; - } - else - { - GNUNET_OS_process_destroy (procarr[pg_iter]); - procarr[pg_iter] = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "File %d copied\n", pg_iter); - } - } - } - count++; - if (ret == GNUNET_SYSERR) - { - /* FIXME: why sleep here? -CG */ - sleep (1); - } - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Finished copying all blacklist files!\n"); - GNUNET_free (procarr); - return ret; -} - -/* Forward Declaration */ -static void -schedule_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); - -/** - * Choose a random peer's next connection to create, and - * call schedule_connect to set up the connect task. - * - * @param pg the peer group to connect - */ -static void -preschedule_connect (struct GNUNET_TESTING_PeerGroup *pg) -{ - struct ConnectTopologyContext *ct_ctx = &pg->ct_ctx; - struct PeerConnection *connection_iter; - struct ConnectContext *connect_context; - uint32_t random_peer; - - if (ct_ctx->remaining_connections == 0) - return; - random_peer = - GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total); - while (pg->peers[random_peer].connect_peers_head == NULL) - random_peer = - GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total); - - connection_iter = pg->peers[random_peer].connect_peers_head; - connect_context = GNUNET_malloc (sizeof (struct ConnectContext)); - connect_context->first_index = random_peer; - connect_context->second_index = connection_iter->index; - connect_context->ct_ctx = ct_ctx; - connect_context->task = - GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context); - GNUNET_CONTAINER_DLL_insert (pg->cc_head, pg->cc_tail, connect_context); - GNUNET_CONTAINER_DLL_remove (pg->peers[random_peer].connect_peers_head, - pg->peers[random_peer].connect_peers_tail, - connection_iter); - GNUNET_free (connection_iter); - ct_ctx->remaining_connections--; -} - -#if USE_SEND_HELLOS -/* Forward declaration */ -static void -schedule_send_hellos (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); - -/** - * Close connections and free the hello context. - * - * @param cls the 'struct SendHelloContext *' - * @param tc scheduler context - */ -static void -free_hello_context (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct SendHelloContext *send_hello_context = cls; - - if (send_hello_context->peer->daemon->server != NULL) - { - GNUNET_CORE_disconnect (send_hello_context->peer->daemon->server); - send_hello_context->peer->daemon->server = NULL; - } - if (send_hello_context->peer->daemon->th != NULL) - { - GNUNET_TRANSPORT_disconnect (send_hello_context->peer->daemon->th); - send_hello_context->peer->daemon->th = NULL; - } - if (send_hello_context->core_connect_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (send_hello_context->core_connect_task); - send_hello_context->core_connect_task = GNUNET_SCHEDULER_NO_TASK; - } - send_hello_context->pg->outstanding_connects--; - GNUNET_free (send_hello_context); -} - -/** - * For peers that haven't yet connected, notify - * the caller that they have failed (timeout). - * - * @param cls the 'struct SendHelloContext *' - * @param tc scheduler context - */ -static void -notify_remaining_connections_failed (void *cls, - const struct GNUNET_SCHEDULER_TaskContext - *tc) -{ - struct SendHelloContext *send_hello_context = cls; - struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg; - struct PeerConnection *connection; - - GNUNET_CORE_disconnect (send_hello_context->peer->daemon->server); - send_hello_context->peer->daemon->server = NULL; - - connection = send_hello_context->peer->connect_peers_head; - - while (connection != NULL) - { - if (pg->notify_connection != NULL) - { - pg->notify_connection (pg->notify_connection_cls, &send_hello_context->peer->daemon->id, &pg->peers[connection->index].daemon->id, 0, /* FIXME */ - send_hello_context->peer->daemon->cfg, - pg->peers[connection->index].daemon->cfg, - send_hello_context->peer->daemon, - pg->peers[connection->index].daemon, - "Peers failed to connect (timeout)"); - } - GNUNET_CONTAINER_DLL_remove (send_hello_context->peer->connect_peers_head, - send_hello_context->peer->connect_peers_tail, - connection); - GNUNET_free (connection); - connection = connection->next; - } - GNUNET_SCHEDULER_add_now (&free_hello_context, send_hello_context); -#if BAD - other_peer = &pg->peers[connection->index]; -#endif -} - -/** - * For peers that haven't yet connected, send - * CORE connect requests. - * - * @param cls the 'struct SendHelloContext *' - * @param tc scheduler context - */ -static void -send_core_connect_requests (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct SendHelloContext *send_hello_context = cls; - struct PeerConnection *conn; - - GNUNET_assert (send_hello_context->peer->daemon->server != NULL); - - send_hello_context->core_connect_task = GNUNET_SCHEDULER_NO_TASK; - - send_hello_context->connect_attempts++; - if (send_hello_context->connect_attempts < - send_hello_context->pg->ct_ctx.connect_attempts) - { - conn = send_hello_context->peer->connect_peers_head; - while (conn != NULL) - { - GNUNET_TRANSPORT_try_connect (send_hello_context->peer->daemon->th, - &send_hello_context->pg->peers[conn-> - index].daemon-> - id); - conn = conn->next; - } - send_hello_context->core_connect_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide - (send_hello_context->pg-> - ct_ctx.connect_timeout, - send_hello_context->pg-> - ct_ctx.connect_attempts), - &send_core_connect_requests, - send_hello_context); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Timeout before all connections created, marking rest as failed!\n"); - GNUNET_SCHEDULER_add_now (¬ify_remaining_connections_failed, - send_hello_context); - } - -} - -/** - * Success, connection is up. Signal client our success. - * - * @param cls our "struct SendHelloContext" - * @param peer identity of the peer that has connected - * @param atsi performance information - * - * FIXME: remove peers from BOTH lists, call notify twice, should - * double the speed of connections as long as the list iteration - * doesn't take too long! - */ -static void -core_connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_ATS_Information *atsi) -{ - struct SendHelloContext *send_hello_context = cls; - struct PeerConnection *connection; - struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg; - -#if BAD - struct PeerData *other_peer; -#endif - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected peer %s to peer %s\n", - ctx->d1->shortname, GNUNET_i2s (peer)); - if (0 == - memcmp (&send_hello_context->peer->daemon->id, peer, - sizeof (struct GNUNET_PeerIdentity))) - return; - - connection = send_hello_context->peer->connect_peers_head; -#if BAD - other_peer = NULL; -#endif - - while ((connection != NULL) && - (0 != - memcmp (&pg->peers[connection->index].daemon->id, peer, - sizeof (struct GNUNET_PeerIdentity)))) - { - connection = connection->next; - } - - if (connection == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connected peer %s to %s, not in list (no problem(?))\n", - GNUNET_i2s (peer), send_hello_context->peer->daemon->shortname); - } - else - { -#if BAD - other_peer = &pg->peers[connection->index]; -#endif - if (pg->notify_connection != NULL) - { - pg->notify_connection (pg->notify_connection_cls, &send_hello_context->peer->daemon->id, peer, 0, /* FIXME */ - send_hello_context->peer->daemon->cfg, - pg->peers[connection->index].daemon->cfg, - send_hello_context->peer->daemon, - pg->peers[connection->index].daemon, NULL); - } - GNUNET_CONTAINER_DLL_remove (send_hello_context->peer->connect_peers_head, - send_hello_context->peer->connect_peers_tail, - connection); - GNUNET_free (connection); - } - -#if BAD - /* Notify of reverse connection and remove from other peers list of outstanding */ - if (other_peer != NULL) - { - connection = other_peer->connect_peers_head; - while ((connection != NULL) && - (0 != - memcmp (&send_hello_context->peer->daemon->id, - &pg->peers[connection->index].daemon->id, - sizeof (struct GNUNET_PeerIdentity)))) - { - connection = connection->next; - } - if (connection != NULL) - { - if (pg->notify_connection != NULL) - { - pg->notify_connection (pg->notify_connection_cls, peer, &send_hello_context->peer->daemon->id, 0, /* FIXME */ - pg->peers[connection->index].daemon->cfg, - send_hello_context->peer->daemon->cfg, - pg->peers[connection->index].daemon, - send_hello_context->peer->daemon, NULL); - } - - GNUNET_CONTAINER_DLL_remove (other_peer->connect_peers_head, - other_peer->connect_peers_tail, connection); - GNUNET_free (connection); - } - } -#endif - - if (send_hello_context->peer->connect_peers_head == NULL) - { - GNUNET_SCHEDULER_add_now (&free_hello_context, send_hello_context); - } -} - -/** - * Notify of a successful connection to the core service. - * - * @param cls a struct SendHelloContext * - * @param server handle to the core service - * @param my_identity the peer identity of this peer - */ -void -core_init (void *cls, struct GNUNET_CORE_Handle *server, - struct GNUNET_PeerIdentity *my_identity) -{ - struct SendHelloContext *send_hello_context = cls; - - send_hello_context->core_ready = GNUNET_YES; -} - -/** - * Function called once a hello has been sent - * to the transport, move on to the next one - * or go away forever. - * - * @param cls the 'struct SendHelloContext *' - * @param tc scheduler context - */ -static void -hello_sent_callback (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct SendHelloContext *send_hello_context = cls; - - //unsigned int pg_iter; - if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - { - GNUNET_free (send_hello_context); - return; - } - - send_hello_context->pg->remaining_hellos--; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent HELLO, have %d remaining!\n", - send_hello_context->pg->remaining_hellos); - if (send_hello_context->peer_pos == NULL) /* All HELLOs (for this peer!) have been transmitted! */ - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "All hellos for this peer sent, disconnecting transport!\n"); - GNUNET_assert (send_hello_context->peer->daemon->th != NULL); - GNUNET_TRANSPORT_disconnect (send_hello_context->peer->daemon->th); - send_hello_context->peer->daemon->th = NULL; - GNUNET_assert (send_hello_context->peer->daemon->server == NULL); - send_hello_context->peer->daemon->server = - GNUNET_CORE_connect (send_hello_context->peer->cfg, 1, - send_hello_context, &core_init, - &core_connect_notify, NULL, NULL, NULL, GNUNET_NO, - NULL, GNUNET_NO, no_handlers); - - send_hello_context->core_connect_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide - (send_hello_context->pg-> - ct_ctx.connect_timeout, - send_hello_context->pg-> - ct_ctx.connect_attempts), - &send_core_connect_requests, - send_hello_context); - } - else - GNUNET_SCHEDULER_add_now (&schedule_send_hellos, send_hello_context); -} - -/** - * Connect to a peer, give it all the HELLO's of those peers - * we will later ask it to connect to. - * - * @param ct_ctx the overall connection context - */ -static void -schedule_send_hellos (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct SendHelloContext *send_hello_context = cls; - struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg; - - if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - { - GNUNET_free (send_hello_context); - return; - } - - GNUNET_assert (send_hello_context->peer_pos != NULL); /* All of the HELLO sends to be scheduled have been scheduled! */ - - if (((send_hello_context->peer->daemon->th == NULL) && - (pg->outstanding_connects > pg->max_outstanding_connections)) || - (pg->stop_connects == GNUNET_YES)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Delaying connect, we have too many outstanding connections!\n"); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, 100), - &schedule_send_hellos, send_hello_context); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating connection, outstanding_connections is %d\n", - outstanding_connects); - if (send_hello_context->peer->daemon->th == NULL) - { - pg->outstanding_connects++; /* Actual TRANSPORT, CORE connections! */ - send_hello_context->peer->daemon->th = - GNUNET_TRANSPORT_connect (send_hello_context->peer->cfg, NULL, - send_hello_context, NULL, NULL, NULL); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Offering HELLO of peer %s to peer %s\n", - send_hello_context->peer->daemon->shortname, - pg->peers[send_hello_context->peer_pos->index]. - daemon->shortname); - GNUNET_TRANSPORT_offer_hello (send_hello_context->peer->daemon->th, - (const struct GNUNET_MessageHeader *) - pg->peers[send_hello_context->peer_pos-> - index].daemon->hello, - &hello_sent_callback, send_hello_context); - send_hello_context->peer_pos = send_hello_context->peer_pos->next; - GNUNET_assert (send_hello_context->peer->daemon->th != NULL); - } -} -#endif - -/** - * Internal notification of a connection, kept so that we can ensure some connections - * happen instead of flooding all testing daemons with requests to connect. - */ -static void -internal_connect_notify (void *cls, const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, - uint32_t distance, - const struct GNUNET_CONFIGURATION_Handle *first_cfg, - const struct GNUNET_CONFIGURATION_Handle *second_cfg, - struct GNUNET_TESTING_Daemon *first_daemon, - struct GNUNET_TESTING_Daemon *second_daemon, - const char *emsg) -{ - struct ConnectContext *connect_ctx = cls; - struct ConnectTopologyContext *ct_ctx = connect_ctx->ct_ctx; - struct GNUNET_TESTING_PeerGroup *pg = ct_ctx->pg; - struct PeerConnection *connection; - - GNUNET_assert (NULL != connect_ctx->cc); - connect_ctx->cc = NULL; - GNUNET_assert (0 < pg->outstanding_connects); - pg->outstanding_connects--; - GNUNET_CONTAINER_DLL_remove (pg->cc_head, pg->cc_tail, connect_ctx); - /* - * Check whether the inverse connection has been scheduled yet, - * if not, we can remove it from the other peers list and avoid - * even trying to connect them again! - */ - connection = pg->peers[connect_ctx->second_index].connect_peers_head; -#if BAD - other_peer = NULL; -#endif - - while ((connection != NULL) && - (0 != - memcmp (first, &pg->peers[connection->index].daemon->id, - sizeof (struct GNUNET_PeerIdentity)))) - connection = connection->next; - - if (connection != NULL) /* Can safely remove! */ - { - GNUNET_assert (0 < ct_ctx->remaining_connections); - ct_ctx->remaining_connections--; - if (pg->notify_connection != NULL) /* Notify of reverse connection */ - pg->notify_connection (pg->notify_connection_cls, second, first, distance, - second_cfg, first_cfg, second_daemon, first_daemon, - emsg); - - GNUNET_CONTAINER_DLL_remove (pg-> - peers[connect_ctx-> - second_index].connect_peers_head, - pg->peers[connect_ctx-> - second_index].connect_peers_tail, - connection); - GNUNET_free (connection); - } - - if (ct_ctx->remaining_connections == 0) - { - if (ct_ctx->notify_connections_done != NULL) - { - ct_ctx->notify_connections_done (ct_ctx->notify_cls, NULL); - ct_ctx->notify_connections_done = NULL; - } - } - else - preschedule_connect (pg); - - if (pg->notify_connection != NULL) - pg->notify_connection (pg->notify_connection_cls, first, second, distance, - first_cfg, second_cfg, first_daemon, second_daemon, - emsg); - GNUNET_free (connect_ctx); -} - -/** - * Either delay a connection (because there are too many outstanding) - * or schedule it for right now. - * - * @param cls a connection context - * @param tc the task runtime context - */ -static void -schedule_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct ConnectContext *connect_context = cls; - struct GNUNET_TESTING_PeerGroup *pg = connect_context->ct_ctx->pg; - - connect_context->task = GNUNET_SCHEDULER_NO_TASK; - if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - return; - - if ((pg->outstanding_connects > pg->max_outstanding_connections) || - (pg->stop_connects == GNUNET_YES)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Delaying connect, we have too many outstanding connections!\n"); - connect_context->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, 100), - &schedule_connect, connect_context); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating connection, outstanding_connections is %d (max %d)\n", - pg->outstanding_connects, pg->max_outstanding_connections); - pg->outstanding_connects++; - pg->total_connects_scheduled++; - GNUNET_assert (NULL == connect_context->cc); - connect_context->cc = - GNUNET_TESTING_daemons_connect (pg-> - peers[connect_context-> - first_index].daemon, - pg->peers[connect_context-> - second_index].daemon, - connect_context->ct_ctx->connect_timeout, - connect_context->ct_ctx->connect_attempts, -#if USE_SEND_HELLOS - GNUNET_NO, -#else - GNUNET_YES, -#endif - &internal_connect_notify, - connect_context); - -} - -#if !OLD -/** - * Iterator for actually scheduling connections to be created - * between two peers. - * - * @param cls closure, a GNUNET_TESTING_Daemon - * @param key the key the second Daemon was stored under - * @param value the GNUNET_TESTING_Daemon that the first is to connect to - * - * @return GNUNET_YES to continue iteration - */ -static int -connect_iterator (void *cls, const GNUNET_HashCode * key, void *value) -{ - struct ConnectTopologyContext *ct_ctx = cls; - struct PeerData *first = ct_ctx->first; - struct GNUNET_TESTING_Daemon *second = value; - struct ConnectContext *connect_context; - - connect_context = GNUNET_malloc (sizeof (struct ConnectContext)); - connect_context->first = first->daemon; - connect_context->second = second; - connect_context->ct_ctx = ct_ctx; - connect_context->task = - GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context); - GNUNET_CONTAINER_DLL_insert (ct_ctx->pg->cc_head, ct_ctx->pg->cc_tail, - connect_context); - return GNUNET_YES; -} -#endif - -#if !OLD -/** - * Iterator for copying all entries in the allowed hashmap to the - * connect hashmap. - * - * @param cls closure, a GNUNET_TESTING_Daemon - * @param key the key the second Daemon was stored under - * @param value the GNUNET_TESTING_Daemon that the first is to connect to - * - * @return GNUNET_YES to continue iteration - */ -static int -copy_topology_iterator (void *cls, const GNUNET_HashCode * key, void *value) -{ - struct PeerData *first = cls; - - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (first->connect_peers, key, - value, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - - return GNUNET_YES; -} -#endif - -/** - * Make the peers to connect the same as those that are allowed to be - * connected. - * - * @param pg the peer group - */ -static int -copy_allowed_topology (struct GNUNET_TESTING_PeerGroup *pg) -{ - unsigned int pg_iter; - int ret; - int total; - -#if OLD - struct PeerConnection *iter; -#endif - total = 0; - ret = 0; - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { -#if OLD - iter = pg->peers[pg_iter].allowed_peers_head; - while (iter != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating connection between %d and %d\n", pg_iter, - iter->index); - total += add_connections (pg, pg_iter, iter->index, CONNECT, GNUNET_YES); - //total += add_actual_connections(pg, pg_iter, iter->index); - iter = iter->next; - } -#else - ret = - GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].allowed_peers, - ©_topology_iterator, - &pg->peers[pg_iter]); -#endif - if (GNUNET_SYSERR == ret) - return GNUNET_SYSERR; - - total = total + ret; - } - - return total; -} - -/** - * Connect the topology as specified by the PeerConnection's - * of each peer in the peer group - * - * @param pg the peer group we are dealing with - * @param connect_timeout how long try connecting two peers - * @param connect_attempts how many times (max) to attempt - * @param notify_callback callback to notify when finished - * @param notify_cls closure for notify callback - * - * @return the number of connections that will be attempted - */ -static int -connect_topology (struct GNUNET_TESTING_PeerGroup *pg, - struct GNUNET_TIME_Relative connect_timeout, - unsigned int connect_attempts, - GNUNET_TESTING_NotifyCompletion notify_callback, - void *notify_cls) -{ - unsigned int pg_iter; - unsigned int total; - -#if OLD - struct PeerConnection *connection_iter; -#endif -#if USE_SEND_HELLOS - struct SendHelloContext *send_hello_context; -#endif - - total = 0; - pg->ct_ctx.notify_connections_done = notify_callback; - pg->ct_ctx.notify_cls = notify_cls; - pg->ct_ctx.pg = pg; - - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { -#if OLD - connection_iter = pg->peers[pg_iter].connect_peers_head; - while (connection_iter != NULL) - { - connection_iter = connection_iter->next; - total++; - } -#else - total += - GNUNET_CONTAINER_multihashmap_size (pg->peers[pg_iter].connect_peers); -#endif - } - - if (total == 0) - return total; - - pg->ct_ctx.connect_timeout = connect_timeout; - pg->ct_ctx.connect_attempts = connect_attempts; - pg->ct_ctx.remaining_connections = total; - -#if USE_SEND_HELLOS - /* First give all peers the HELLO's of other peers (connect to first peer's transport service, give HELLO's of other peers, continue...) */ - pg->remaining_hellos = total; - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - send_hello_context = GNUNET_malloc (sizeof (struct SendHelloContext)); - send_hello_context->peer = &pg->peers[pg_iter]; - send_hello_context->peer_pos = pg->peers[pg_iter].connect_peers_head; - send_hello_context->pg = pg; - GNUNET_SCHEDULER_add_now (&schedule_send_hellos, send_hello_context); - } -#else - for (pg_iter = 0; pg_iter < pg->max_outstanding_connections; pg_iter++) - { - preschedule_connect (pg); - } -#endif - return total; - -} - -/** - * Takes a peer group and creates a topology based on the - * one specified. Creates a topology means generates friend - * files for the peers so they can only connect to those allowed - * by the topology. This will only have an effect once peers - * are started if the FRIENDS_ONLY option is set in the base - * config. Also takes an optional restrict topology which - * disallows connections based on particular transports - * UNLESS they are specified in the restricted topology. - * - * @param pg the peer group struct representing the running peers - * @param topology which topology to connect the peers in - * @param restrict_topology disallow restrict_transports transport - * connections to peers NOT in this topology - * use GNUNET_TESTING_TOPOLOGY_NONE for no restrictions - * @param restrict_transports space delimited list of transports to blacklist - * to create restricted topology - * - * @return the maximum number of connections were all allowed peers - * connected to each other - */ -unsigned int -GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, - enum GNUNET_TESTING_Topology topology, - enum GNUNET_TESTING_Topology restrict_topology, - const char *restrict_transports) -{ - int ret; - - unsigned int num_connections; - int unblacklisted_connections; - char *filename; - struct PeerConnection *conn_iter; - struct PeerConnection *temp_conn; - unsigned int off; - -#if !OLD - unsigned int i; - - for (i = 0; i < pg->total; i++) - { - pg->peers[i].allowed_peers = GNUNET_CONTAINER_multihashmap_create (100); - pg->peers[i].connect_peers = GNUNET_CONTAINER_multihashmap_create (100); - pg->peers[i].blacklisted_peers = GNUNET_CONTAINER_multihashmap_create (100); - pg->peers[i].pg = pg; - } -#endif - - switch (topology) - { - case GNUNET_TESTING_TOPOLOGY_CLIQUE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating clique topology\n"); - num_connections = create_clique (pg, &add_connections, ALLOWED, GNUNET_NO); - break; - case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating small world (ring) topology\n"); - num_connections = create_small_world_ring (pg, &add_connections, ALLOWED); - break; - case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating small world (2d-torus) topology\n"); - num_connections = create_small_world (pg, &add_connections, ALLOWED); - break; - case GNUNET_TESTING_TOPOLOGY_RING: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating ring topology\n"); - num_connections = create_ring (pg, &add_connections, ALLOWED); - break; - case GNUNET_TESTING_TOPOLOGY_2D_TORUS: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating 2d torus topology\n"); - num_connections = create_2d_torus (pg, &add_connections, ALLOWED); - break; - case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating Erdos-Renyi topology\n"); - num_connections = create_erdos_renyi (pg, &add_connections, ALLOWED); - break; - case GNUNET_TESTING_TOPOLOGY_INTERNAT: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating InterNAT topology\n"); - num_connections = create_nated_internet (pg, &add_connections, ALLOWED); - break; - case GNUNET_TESTING_TOPOLOGY_SCALE_FREE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating Scale Free topology\n"); - num_connections = create_scale_free (pg, &add_connections, ALLOWED); - break; - case GNUNET_TESTING_TOPOLOGY_LINE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating straight line topology\n"); - num_connections = create_line (pg, &add_connections, ALLOWED); - break; - case GNUNET_TESTING_TOPOLOGY_FROM_FILE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating topology from file!\n"); - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (pg->cfg, "testing", - "topology_file", &filename)) - num_connections = - create_from_file (pg, filename, &add_connections, ALLOWED); - else - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Missing configuration option TESTING:TOPOLOGY_FILE for creating topology from file!\n"); - num_connections = 0; - } - break; - case GNUNET_TESTING_TOPOLOGY_NONE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - _ - ("Creating no allowed topology (all peers can connect at core level)\n")); - num_connections = pg->total * pg->total; /* Clique is allowed! */ - break; - default: - num_connections = 0; - break; - } - - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING", "F2F")) - { - ret = create_and_copy_friend_files (pg); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Failed during friend file copying!\n"); - return GNUNET_SYSERR; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Friend files created/copied successfully!\n"); - } - } - - /* Use the create clique method to initially set all connections as blacklisted. */ - if ((restrict_topology != GNUNET_TESTING_TOPOLOGY_NONE) && - (restrict_topology != GNUNET_TESTING_TOPOLOGY_FROM_FILE)) - create_clique (pg, &add_connections, BLACKLIST, GNUNET_NO); - else - return num_connections; - - unblacklisted_connections = 0; - /* Un-blacklist connections as per the topology specified */ - switch (restrict_topology) - { - case GNUNET_TESTING_TOPOLOGY_CLIQUE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Blacklisting all but clique topology\n"); - unblacklisted_connections = - create_clique (pg, &remove_connections, BLACKLIST, GNUNET_NO); - break; - case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Blacklisting all but small world (ring) topology\n"); - unblacklisted_connections = - create_small_world_ring (pg, &remove_connections, BLACKLIST); - break; - case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Blacklisting all but small world (2d-torus) topology\n"); - unblacklisted_connections = - create_small_world (pg, &remove_connections, BLACKLIST); - break; - case GNUNET_TESTING_TOPOLOGY_RING: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Blacklisting all but ring topology\n"); - unblacklisted_connections = - create_ring (pg, &remove_connections, BLACKLIST); - break; - case GNUNET_TESTING_TOPOLOGY_2D_TORUS: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Blacklisting all but 2d torus topology\n"); - unblacklisted_connections = - create_2d_torus (pg, &remove_connections, BLACKLIST); - break; - case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Blacklisting all but Erdos-Renyi topology\n"); - unblacklisted_connections = - create_erdos_renyi (pg, &remove_connections, BLACKLIST); - break; - case GNUNET_TESTING_TOPOLOGY_INTERNAT: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Blacklisting all but InterNAT topology\n"); - -#if TOPOLOGY_HACK - for (off = 0; off < pg->total; off++) - { - conn_iter = pg->peers[off].allowed_peers_head; - while (conn_iter != NULL) - { - temp_conn = conn_iter->next; - GNUNET_free (conn_iter); - conn_iter = temp_conn; - } - pg->peers[off].allowed_peers_head = NULL; - pg->peers[off].allowed_peers_tail = NULL; - - conn_iter = pg->peers[off].connect_peers_head; - while (conn_iter != NULL) - { - temp_conn = conn_iter->next; - GNUNET_free (conn_iter); - conn_iter = temp_conn; - } - pg->peers[off].connect_peers_head = NULL; - pg->peers[off].connect_peers_tail = NULL; - } - unblacklisted_connections = - create_nated_internet_copy (pg, &remove_connections, BLACKLIST); -#else - unblacklisted_connections = - create_nated_internet (pg, &remove_connections, BLACKLIST); -#endif - - break; - case GNUNET_TESTING_TOPOLOGY_SCALE_FREE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Blacklisting all but Scale Free topology\n"); - unblacklisted_connections = - create_scale_free (pg, &remove_connections, BLACKLIST); - break; - case GNUNET_TESTING_TOPOLOGY_LINE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Blacklisting all but straight line topology\n"); - unblacklisted_connections = - create_line (pg, &remove_connections, BLACKLIST); - default: - break; - } - - if ((unblacklisted_connections > 0) && (restrict_transports != NULL)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating blacklist with `%s'\n", - restrict_transports); - ret = create_and_copy_blacklist_files (pg, restrict_transports); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Failed during blacklist file copying!\n"); - return 0; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Blacklist files created/copied successfully!\n"); - } - } - return num_connections; -} - -#if !OLD -/** - * Iterator for choosing random peers to connect. - * - * @param cls closure, a RandomContext - * @param key the key the second Daemon was stored under - * @param value the GNUNET_TESTING_Daemon that the first is to connect to - * - * @return GNUNET_YES to continue iteration - */ -static int -random_connect_iterator (void *cls, const GNUNET_HashCode * key, void *value) -{ - struct RandomContext *random_ctx = cls; - double random_number; - uint32_t second_pos; - GNUNET_HashCode first_hash; - - random_number = - ((double) - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, - UINT64_MAX)) / ((double) UINT64_MAX); - if (random_number < random_ctx->percentage) - { - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (random_ctx-> - first->connect_peers_working_set, - key, value, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - } - - /* Now we have considered this particular connection, remove it from the second peer so it's not double counted */ - uid_from_hash (key, &second_pos); - hash_from_uid (random_ctx->first_uid, &first_hash); - GNUNET_assert (random_ctx->pg->total > second_pos); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (random_ctx-> - pg->peers - [second_pos].connect_peers, - &first_hash, - random_ctx-> - first->daemon)); - - return GNUNET_YES; -} - -/** - * Iterator for adding at least X peers to a peers connection set. - * - * @param cls closure, MinimumContext - * @param key the key the second Daemon was stored under - * @param value the GNUNET_TESTING_Daemon that the first is to connect to - * - * @return GNUNET_YES to continue iteration - */ -static int -minimum_connect_iterator (void *cls, const GNUNET_HashCode * key, void *value) -{ - struct MinimumContext *min_ctx = cls; - uint32_t second_pos; - GNUNET_HashCode first_hash; - unsigned int i; - - if (GNUNET_CONTAINER_multihashmap_size - (min_ctx->first->connect_peers_working_set) < min_ctx->num_to_add) - { - for (i = 0; i < min_ctx->num_to_add; i++) - { - if (min_ctx->pg_array[i] == min_ctx->current) - { - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (min_ctx-> - first->connect_peers_working_set, - key, value, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - uid_from_hash (key, &second_pos); - hash_from_uid (min_ctx->first_uid, &first_hash); - GNUNET_assert (min_ctx->pg->total > second_pos); - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (min_ctx-> - pg->peers - [second_pos].connect_peers_working_set, - &first_hash, - min_ctx->first-> - daemon, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - /* Now we have added this particular connection, remove it from the second peer's map so it's not double counted */ - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (min_ctx-> - pg->peers - [second_pos].connect_peers, - &first_hash, - min_ctx-> - first->daemon)); - } - } - min_ctx->current++; - return GNUNET_YES; - } - else - return GNUNET_NO; /* We can stop iterating, we have enough peers! */ - -} - -/** - * Iterator for adding peers to a connection set based on a depth first search. - * - * @param cls closure, MinimumContext - * @param key the key the second daemon was stored under - * @param value the GNUNET_TESTING_Daemon that the first is to connect to - * - * @return GNUNET_YES to continue iteration - */ -static int -dfs_connect_iterator (void *cls, const GNUNET_HashCode * key, void *value) -{ - struct DFSContext *dfs_ctx = cls; - GNUNET_HashCode first_hash; - - if (dfs_ctx->current == dfs_ctx->chosen) - { - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (dfs_ctx-> - first->connect_peers_working_set, - key, value, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - uid_from_hash (key, &dfs_ctx->second_uid); - hash_from_uid (dfs_ctx->first_uid, &first_hash); - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (dfs_ctx-> - pg->peers[dfs_ctx-> - second_uid].connect_peers_working_set, - &first_hash, - dfs_ctx->first->daemon, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (dfs_ctx-> - pg->peers - [dfs_ctx->second_uid].connect_peers, - &first_hash, - dfs_ctx-> - first->daemon)); - /* Can't remove second from first yet because we are currently iterating, hence the return value in the DFSContext! */ - return GNUNET_NO; /* We have found our peer, don't iterate more */ - } - - dfs_ctx->current++; - return GNUNET_YES; -} -#endif - -/** - * From the set of connections possible, choose percentage percent of connections - * to actually connect. - * - * @param pg the peergroup we are dealing with - * @param percentage what percent of total connections to make - */ -void -choose_random_connections (struct GNUNET_TESTING_PeerGroup *pg, - double percentage) -{ - uint32_t pg_iter; - -#if OLD - struct PeerConnection *conn_iter; - double random_number; -#else - struct RandomContext random_ctx; -#endif - - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { -#if OLD - conn_iter = pg->peers[pg_iter].connect_peers_head; - while (conn_iter != NULL) - { - random_number = - ((double) - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, - UINT64_MAX)) / ((double) UINT64_MAX); - if (random_number < percentage) - { - add_connections (pg, pg_iter, conn_iter->index, WORKING_SET, - GNUNET_YES); - } - conn_iter = conn_iter->next; - } -#else - random_ctx.first_uid = pg_iter; - random_ctx.first = &pg->peers[pg_iter]; - random_ctx.percentage = percentage; - random_ctx.pg = pg; - pg->peers[pg_iter].connect_peers_working_set = - GNUNET_CONTAINER_multihashmap_create (pg->total); - GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].connect_peers, - &random_connect_iterator, - &random_ctx); - /* Now remove the old connections */ - GNUNET_CONTAINER_multihashmap_destroy (pg->peers[pg_iter].connect_peers); - /* And replace with the random set */ - pg->peers[pg_iter].connect_peers = - pg->peers[pg_iter].connect_peers_working_set; -#endif - } - - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - conn_iter = pg->peers[pg_iter].connect_peers_head; - while (pg->peers[pg_iter].connect_peers_head != NULL) - remove_connections (pg, pg_iter, - pg->peers[pg_iter].connect_peers_head->index, CONNECT, - GNUNET_YES); - - pg->peers[pg_iter].connect_peers_head = - pg->peers[pg_iter].connect_peers_working_set_head; - pg->peers[pg_iter].connect_peers_tail = - pg->peers[pg_iter].connect_peers_working_set_tail; - pg->peers[pg_iter].connect_peers_working_set_head = NULL; - pg->peers[pg_iter].connect_peers_working_set_tail = NULL; - } -} - -/** - * Count the number of connections in a linked list of connections. - * - * @param conn_list the connection list to get the count of - * - * @return the number of elements in the list - */ -static unsigned int -count_connections (struct PeerConnection *conn_list) -{ - struct PeerConnection *iter; - unsigned int count; - - count = 0; - iter = conn_list; - while (iter != NULL) - { - iter = iter->next; - count++; - } - return count; -} - -static unsigned int -count_workingset_connections (struct GNUNET_TESTING_PeerGroup *pg) -{ - unsigned int count; - unsigned int pg_iter; - -#if OLD - struct PeerConnection *conn_iter; -#endif - count = 0; - - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { -#if OLD - conn_iter = pg->peers[pg_iter].connect_peers_working_set_head; - while (conn_iter != NULL) - { - count++; - conn_iter = conn_iter->next; - } -#else - count += - GNUNET_CONTAINER_multihashmap_size (pg-> - peers - [pg_iter].connect_peers_working_set); -#endif - } - - return count; -} - -static unsigned int -count_allowed_connections (struct GNUNET_TESTING_PeerGroup *pg) -{ - unsigned int count; - unsigned int pg_iter; - -#if OLD - struct PeerConnection *conn_iter; -#endif - - count = 0; - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { -#if OLD - conn_iter = pg->peers[pg_iter].allowed_peers_head; - while (conn_iter != NULL) - { - count++; - conn_iter = conn_iter->next; - } -#else - count += - GNUNET_CONTAINER_multihashmap_size (pg->peers[pg_iter].allowed_peers); -#endif - } - - return count; -} - -/** - * From the set of connections possible, choose at least num connections per - * peer. - * - * @param pg the peergroup we are dealing with - * @param num how many connections at least should each peer have (if possible)? - */ -static void -choose_minimum (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num) -{ -#if !OLD - struct MinimumContext minimum_ctx; -#else - struct PeerConnection *conn_iter; - unsigned int temp_list_size; - unsigned int i; - unsigned int count; - uint32_t random; /* Random list entry to connect peer to */ -#endif - uint32_t pg_iter; - -#if OLD - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - temp_list_size = count_connections (pg->peers[pg_iter].connect_peers_head); - if (temp_list_size == 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Peer %d has 0 connections!?!?\n", - pg_iter); - break; - } - for (i = 0; i < num; i++) - { - random = - GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, temp_list_size); - conn_iter = pg->peers[pg_iter].connect_peers_head; - for (count = 0; count < random; count++) - conn_iter = conn_iter->next; - /* We now have a random connection, connect it! */ - GNUNET_assert (conn_iter != NULL); - add_connections (pg, pg_iter, conn_iter->index, WORKING_SET, GNUNET_YES); - } - } -#else - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - pg->peers[pg_iter].connect_peers_working_set = - GNUNET_CONTAINER_multihashmap_create (num); - } - - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - minimum_ctx.first_uid = pg_iter; - minimum_ctx.pg_array = - GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, - GNUNET_CONTAINER_multihashmap_size - (pg->peers[pg_iter].connect_peers)); - minimum_ctx.first = &pg->peers[pg_iter]; - minimum_ctx.pg = pg; - minimum_ctx.num_to_add = num; - minimum_ctx.current = 0; - GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].connect_peers, - &minimum_connect_iterator, - &minimum_ctx); - } - - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - /* Remove the "old" connections */ - GNUNET_CONTAINER_multihashmap_destroy (pg->peers[pg_iter].connect_peers); - /* And replace with the working set */ - pg->peers[pg_iter].connect_peers = - pg->peers[pg_iter].connect_peers_working_set; - } -#endif - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - while (pg->peers[pg_iter].connect_peers_head != NULL) - { - conn_iter = pg->peers[pg_iter].connect_peers_head; - GNUNET_CONTAINER_DLL_remove (pg->peers[pg_iter].connect_peers_head, - pg->peers[pg_iter].connect_peers_tail, - conn_iter); - GNUNET_free (conn_iter); - /*remove_connections(pg, pg_iter, pg->peers[pg_iter].connect_peers_head->index, CONNECT, GNUNET_YES); */ - } - - pg->peers[pg_iter].connect_peers_head = - pg->peers[pg_iter].connect_peers_working_set_head; - pg->peers[pg_iter].connect_peers_tail = - pg->peers[pg_iter].connect_peers_working_set_tail; - pg->peers[pg_iter].connect_peers_working_set_head = NULL; - pg->peers[pg_iter].connect_peers_working_set_tail = NULL; - } -} - -#if !OLD -struct FindClosestContext -{ - /** - * The currently known closest peer. - */ - struct GNUNET_TESTING_Daemon *closest; - - /** - * The info for the peer we are adding connections for. - */ - struct PeerData *curr_peer; - - /** - * The distance (bits) between the current - * peer and the currently known closest. - */ - unsigned int closest_dist; - - /** - * The offset of the closest known peer in - * the peer group. - */ - unsigned int closest_num; -}; - -/** - * Iterator over hash map entries of the allowed - * peer connections. Find the closest, not already - * connected peer and return it. - * - * @param cls closure (struct FindClosestContext) - * @param key current key code (hash of offset in pg) - * @param value value in the hash map - a GNUNET_TESTING_Daemon - * @return GNUNET_YES if we should continue to - * iterate, - * GNUNET_NO if not. - */ -static int -find_closest_peers (void *cls, const GNUNET_HashCode * key, void *value) -{ - struct FindClosestContext *closest_ctx = cls; - struct GNUNET_TESTING_Daemon *daemon = value; - - if (((closest_ctx->closest == NULL) || - (GNUNET_CRYPTO_hash_matching_bits - (&daemon->id.hashPubKey, - &closest_ctx->curr_peer->daemon->id.hashPubKey) > - closest_ctx->closest_dist)) && - (GNUNET_YES != - GNUNET_CONTAINER_multihashmap_contains (closest_ctx-> - curr_peer->connect_peers, key))) - { - closest_ctx->closest_dist = - GNUNET_CRYPTO_hash_matching_bits (&daemon->id.hashPubKey, - &closest_ctx->curr_peer->daemon-> - id.hashPubKey); - closest_ctx->closest = daemon; - uid_from_hash (key, &closest_ctx->closest_num); - } - return GNUNET_YES; -} - -/** - * From the set of connections possible, choose at num connections per - * peer based on depth which are closest out of those allowed. Guaranteed - * to add num peers to connect to, provided there are that many peers - * in the underlay topology to connect to. - * - * @param pg the peergroup we are dealing with - * @param num how many connections at least should each peer have (if possible)? - * @param proc processor to actually add the connections - * @param list the peer list to use - */ -void -add_closest (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num, - GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list) -{ -#if OLD - -#else - struct FindClosestContext closest_ctx; -#endif - uint32_t pg_iter; - uint32_t i; - - for (i = 0; i < num; i++) /* Each time find a closest peer (from those available) */ - { - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - closest_ctx.curr_peer = &pg->peers[pg_iter]; - closest_ctx.closest = NULL; - closest_ctx.closest_dist = 0; - closest_ctx.closest_num = 0; - GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].allowed_peers, - &find_closest_peers, &closest_ctx); - if (closest_ctx.closest != NULL) - { - GNUNET_assert (closest_ctx.closest_num < pg->total); - proc (pg, pg_iter, closest_ctx.closest_num, list); - } - } - } -} -#endif - -/** - * From the set of connections possible, choose at least num connections per - * peer based on depth first traversal of peer connections. If DFS leaves - * peers unconnected, ensure those peers get connections. - * - * @param pg the peergroup we are dealing with - * @param num how many connections at least should each peer have (if possible)? - */ -void -perform_dfs (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num) -{ - uint32_t pg_iter; - uint32_t dfs_count; - uint32_t starting_peer; - uint32_t least_connections; - uint32_t random_connection; - -#if OLD - unsigned int temp_count; - struct PeerConnection *peer_iter; -#else - struct DFSContext dfs_ctx; - GNUNET_HashCode second_hash; -#endif - -#if OLD - starting_peer = 0; - dfs_count = 0; - while ((count_workingset_connections (pg) < num * pg->total) && - (count_allowed_connections (pg) > 0)) - { - if (dfs_count % pg->total == 0) /* Restart the DFS at some weakly connected peer */ - { - least_connections = -1; /* Set to very high number */ - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - temp_count = - count_connections (pg-> - peers[pg_iter].connect_peers_working_set_head); - if (temp_count < least_connections) - { - starting_peer = pg_iter; - least_connections = temp_count; - } - } - } - - temp_count = - count_connections (pg->peers[starting_peer].connect_peers_head); - if (temp_count == 0) - continue; /* FIXME: infinite loop? */ - - random_connection = - GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, temp_count); - temp_count = 0; - peer_iter = pg->peers[starting_peer].connect_peers_head; - while (temp_count < random_connection) - { - peer_iter = peer_iter->next; - temp_count++; - } - GNUNET_assert (peer_iter != NULL); - add_connections (pg, starting_peer, peer_iter->index, WORKING_SET, - GNUNET_NO); - remove_connections (pg, starting_peer, peer_iter->index, CONNECT, - GNUNET_YES); - starting_peer = peer_iter->index; - dfs_count++; - } - -#else - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - pg->peers[pg_iter].connect_peers_working_set = - GNUNET_CONTAINER_multihashmap_create (num); - } - - starting_peer = 0; - dfs_count = 0; - while ((count_workingset_connections (pg) < num * pg->total) && - (count_allowed_connections (pg) > 0)) - { - if (dfs_count % pg->total == 0) /* Restart the DFS at some weakly connected peer */ - { - least_connections = -1; /* Set to very high number */ - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - if (GNUNET_CONTAINER_multihashmap_size - (pg->peers[pg_iter].connect_peers_working_set) < least_connections) - { - starting_peer = pg_iter; - least_connections = - GNUNET_CONTAINER_multihashmap_size (pg-> - peers - [pg_iter].connect_peers_working_set); - } - } - } - - if (GNUNET_CONTAINER_multihashmap_size (pg->peers[starting_peer].connect_peers) == 0) /* Ensure there is at least one peer left to connect! */ - { - dfs_count = 0; - continue; - } - - /* Choose a random peer from the chosen peers set of connections to add */ - dfs_ctx.chosen = - GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, - GNUNET_CONTAINER_multihashmap_size (pg->peers - [starting_peer].connect_peers)); - dfs_ctx.first_uid = starting_peer; - dfs_ctx.first = &pg->peers[starting_peer]; - dfs_ctx.pg = pg; - dfs_ctx.current = 0; - - GNUNET_CONTAINER_multihashmap_iterate (pg-> - peers[starting_peer].connect_peers, - &dfs_connect_iterator, &dfs_ctx); - /* Remove the second from the first, since we will be continuing the search and may encounter the first peer again! */ - hash_from_uid (dfs_ctx.second_uid, &second_hash); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (pg->peers - [starting_peer].connect_peers, - &second_hash, - pg-> - peers - [dfs_ctx.second_uid].daemon)); - starting_peer = dfs_ctx.second_uid; - } - - for (pg_iter = 0; pg_iter < pg->total; pg_iter++) - { - /* Remove the "old" connections */ - GNUNET_CONTAINER_multihashmap_destroy (pg->peers[pg_iter].connect_peers); - /* And replace with the working set */ - pg->peers[pg_iter].connect_peers = - pg->peers[pg_iter].connect_peers_working_set; - } -#endif -} - -/** - * Internal callback for topology information for a particular peer. - */ -static void -internal_topology_callback (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_ATS_Information *atsi, - unsigned int atsi_count) -{ - struct CoreContext *core_ctx = cls; - struct TopologyIterateContext *iter_ctx = core_ctx->iter_context; - - if (peer == NULL) /* Either finished, or something went wrong */ - { - iter_ctx->completed++; - iter_ctx->connected--; - /* One core context allocated per iteration, must free! */ - GNUNET_free (core_ctx); - } - else - { - iter_ctx->topology_cb (iter_ctx->cls, &core_ctx->daemon->id, peer, NULL); - } - - if (iter_ctx->completed == iter_ctx->total) - { - iter_ctx->topology_cb (iter_ctx->cls, NULL, NULL, NULL); - /* Once all are done, free the iteration context */ - GNUNET_free (iter_ctx); - } -} - -/** - * Check running topology iteration tasks, if below max start a new one, otherwise - * schedule for some time in the future. - */ -static void -schedule_get_topology (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct CoreContext *core_context = cls; - struct TopologyIterateContext *topology_context = - (struct TopologyIterateContext *) core_context->iter_context; - if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - return; - - if (topology_context->connected > - topology_context->pg->max_outstanding_connections) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Delaying connect, we have too many outstanding connections!\n"); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, 100), - &schedule_get_topology, core_context); - } - else - { - topology_context->connected++; - - if (GNUNET_OK != - GNUNET_CORE_iterate_peers (core_context->daemon->cfg, - &internal_topology_callback, core_context)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Topology iteration failed.\n"); - internal_topology_callback (core_context, NULL, NULL, 0); - } - } -} - -/** - * Iterate over all (running) peers in the peer group, retrieve - * all connections that each currently has. - */ -void -GNUNET_TESTING_get_topology (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_TESTING_NotifyTopology cb, void *cls) -{ - struct TopologyIterateContext *topology_context; - struct CoreContext *core_ctx; - unsigned int i; - unsigned int total_count; - - /* Allocate a single topology iteration context */ - topology_context = GNUNET_malloc (sizeof (struct TopologyIterateContext)); - topology_context->topology_cb = cb; - topology_context->cls = cls; - topology_context->pg = pg; - total_count = 0; - for (i = 0; i < pg->total; i++) - { - if (pg->peers[i].daemon->running == GNUNET_YES) - { - /* Allocate one core context per core we need to connect to */ - core_ctx = GNUNET_malloc (sizeof (struct CoreContext)); - core_ctx->daemon = pg->peers[i].daemon; - /* Set back pointer to topology iteration context */ - core_ctx->iter_context = topology_context; - GNUNET_SCHEDULER_add_now (&schedule_get_topology, core_ctx); - total_count++; - } - } - if (total_count == 0) - { - cb (cls, NULL, NULL, "Cannot iterate over topology, no running peers!"); - GNUNET_free (topology_context); - } - else - topology_context->total = total_count; - return; -} - -/** - * Callback function to process statistic values. - * This handler is here only really to insert a peer - * identity (or daemon) so the statistics can be uniquely - * tied to a single running peer. - * - * @param cls closure - * @param subsystem name of subsystem that created the statistic - * @param name the name of the datum - * @param value the current value - * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not - * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration - */ -static int -internal_stats_callback (void *cls, const char *subsystem, const char *name, - uint64_t value, int is_persistent) -{ - struct StatsCoreContext *core_context = cls; - struct StatsIterateContext *stats_context = - (struct StatsIterateContext *) core_context->iter_context; - - return stats_context->proc (stats_context->cls, &core_context->daemon->id, - subsystem, name, value, is_persistent); -} - - -/** - * We don't need the statistics handle anymore, destroy it. - * - * @param cls Closure (the statistics handle to destroy) - * @param tc Task Context - */ -static void -internal_destroy_statistics (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_STATISTICS_Handle *h = cls; - - GNUNET_STATISTICS_destroy (h, GNUNET_NO); -} - - -/** - * Internal continuation call for statistics iteration. - * - * @param cls closure, the CoreContext for this iteration - * @param success whether or not the statistics iterations - * was canceled or not (we don't care) - */ -static void -internal_stats_cont (void *cls, int success) -{ - struct StatsCoreContext *core_context = cls; - struct StatsIterateContext *stats_context = - (struct StatsIterateContext *) core_context->iter_context; - - stats_context->connected--; - stats_context->completed++; - - if (stats_context->completed == stats_context->total) - { - stats_context->cont (stats_context->cls, GNUNET_YES); - GNUNET_free (stats_context); - } - - if (core_context->stats_handle != NULL) - /* Cannot destroy handle inside the continuation */ - GNUNET_SCHEDULER_add_now (&internal_destroy_statistics, - core_context->stats_handle); - - GNUNET_free (core_context); -} - -/** - * Check running topology iteration tasks, if below max start a new one, otherwise - * schedule for some time in the future. - */ -static void -schedule_get_statistics (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct StatsCoreContext *core_context = cls; - struct StatsIterateContext *stats_context = - (struct StatsIterateContext *) core_context->iter_context; - - if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - return; - - if (stats_context->connected > stats_context->pg->max_outstanding_connections) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Delaying connect, we have too many outstanding connections!\n"); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, 100), - &schedule_get_statistics, core_context); - } - else - { - stats_context->connected++; - core_context->stats_handle = - GNUNET_STATISTICS_create ("testing", core_context->daemon->cfg); - if (core_context->stats_handle == NULL) - { - internal_stats_cont (core_context, GNUNET_NO); - return; - } - - core_context->stats_get_handle = - GNUNET_STATISTICS_get (core_context->stats_handle, NULL, NULL, - GNUNET_TIME_UNIT_FOREVER_REL, - &internal_stats_cont, &internal_stats_callback, - core_context); - if (core_context->stats_get_handle == NULL) - internal_stats_cont (core_context, GNUNET_NO); - - } -} - -struct DuplicateStats -{ - /** - * Next item in the list - */ - struct DuplicateStats *next; - - /** - * Nasty string, concatenation of relevant information. - */ - char *unique_string; -}; - -/** - * Check whether the combination of port/host/unix domain socket - * already exists in the list of peers being checked for statistics. - * - * @param pg the peergroup in question - * @param specific_peer the peer we're concerned with - * @param stats_list the list to return to the caller - * - * @return GNUNET_YES if the statistics instance has been seen already, - * GNUNET_NO if not (and we may have added it to the list) - */ -static int -stats_check_existing (struct GNUNET_TESTING_PeerGroup *pg, - struct PeerData *specific_peer, - struct DuplicateStats **stats_list) -{ - struct DuplicateStats *pos; - char *unix_domain_socket; - unsigned long long port; - char *to_match; - - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "testing", - "single_statistics_per_host")) - return GNUNET_NO; /* Each peer has its own statistics instance, do nothing! */ - - pos = *stats_list; - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (specific_peer->cfg, "statistics", - "unixpath", &unix_domain_socket)) - return GNUNET_NO; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (specific_peer->cfg, "statistics", - "port", &port)) - { - GNUNET_free (unix_domain_socket); - return GNUNET_NO; - } - - if (specific_peer->daemon->hostname != NULL) - GNUNET_asprintf (&to_match, "%s%s%llu", specific_peer->daemon->hostname, - unix_domain_socket, port); - else - GNUNET_asprintf (&to_match, "%s%llu", unix_domain_socket, port); - - while (pos != NULL) - { - if (0 == strcmp (to_match, pos->unique_string)) - { - GNUNET_free (unix_domain_socket); - GNUNET_free (to_match); - return GNUNET_YES; - } - pos = pos->next; - } - pos = GNUNET_malloc (sizeof (struct DuplicateStats)); - pos->unique_string = to_match; - pos->next = *stats_list; - *stats_list = pos; - GNUNET_free (unix_domain_socket); - return GNUNET_NO; -} - -/** - * Iterate over all (running) peers in the peer group, retrieve - * all statistics from each. - * - * @param pg the peergroup to iterate statistics of - * @param cont continuation to call once all stats have been retrieved - * @param proc processing function for each statistic from each peer - * @param cls closure to pass to proc - * - */ -void -GNUNET_TESTING_get_statistics (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_STATISTICS_Callback cont, - GNUNET_TESTING_STATISTICS_Iterator proc, - void *cls) -{ - struct StatsIterateContext *stats_context; - struct StatsCoreContext *core_ctx; - unsigned int i; - unsigned int total_count; - struct DuplicateStats *stats_list; - struct DuplicateStats *pos; - - stats_list = NULL; - - /* Allocate a single stats iteration context */ - stats_context = GNUNET_malloc (sizeof (struct StatsIterateContext)); - stats_context->cont = cont; - stats_context->proc = proc; - stats_context->cls = cls; - stats_context->pg = pg; - total_count = 0; - - for (i = 0; i < pg->total; i++) - { - if ((pg->peers[i].daemon->running == GNUNET_YES) && - (GNUNET_NO == stats_check_existing (pg, &pg->peers[i], &stats_list))) - { - /* Allocate one core context per core we need to connect to */ - core_ctx = GNUNET_malloc (sizeof (struct StatsCoreContext)); - core_ctx->daemon = pg->peers[i].daemon; - /* Set back pointer to topology iteration context */ - core_ctx->iter_context = stats_context; - GNUNET_SCHEDULER_add_now (&schedule_get_statistics, core_ctx); - total_count++; - } - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Retrieving stats from %u total instances.\n", total_count); - if (0 != total_count) - stats_context->total = total_count; - else - GNUNET_free (stats_context); - if (stats_list != NULL) - { - pos = stats_list; - while (pos != NULL) - { - GNUNET_free (pos->unique_string); - stats_list = pos->next; - GNUNET_free (pos); - pos = stats_list->next; - } - } - return; -} - -/** - * Stop the connection process temporarily. - * - * @param pg the peer group to stop connecting - */ -void -GNUNET_TESTING_stop_connections (struct GNUNET_TESTING_PeerGroup *pg) -{ - pg->stop_connects = GNUNET_YES; -} - -/** - * Resume the connection process temporarily. - * - * @param pg the peer group to resume connecting - */ -void -GNUNET_TESTING_resume_connections (struct GNUNET_TESTING_PeerGroup *pg) -{ - pg->stop_connects = GNUNET_NO; -} - -/** - * There are many ways to connect peers that are supported by this function. - * To connect peers in the same topology that was created via the - * GNUNET_TESTING_create_topology, the topology variable must be set to - * GNUNET_TESTING_TOPOLOGY_NONE. If the topology variable is specified, - * a new instance of that topology will be generated and attempted to be - * connected. This could result in some connections being impossible, - * because some topologies are non-deterministic. - * - * @param pg the peer group struct representing the running peers - * @param topology which topology to connect the peers in - * @param options options for connecting the topology - * @param option_modifier modifier for options that take a parameter - * @param connect_timeout how long to wait before giving up on connecting - * two peers - * @param connect_attempts how many times to attempt to connect two peers - * over the connect_timeout duration - * @param notify_callback notification to be called once all connections completed - * @param notify_cls closure for notification callback - * - * @return the number of connections that will be attempted, GNUNET_SYSERR on error - */ -int -GNUNET_TESTING_connect_topology (struct GNUNET_TESTING_PeerGroup *pg, - enum GNUNET_TESTING_Topology topology, - enum GNUNET_TESTING_TopologyOption options, - double option_modifier, - struct GNUNET_TIME_Relative connect_timeout, - unsigned int connect_attempts, - GNUNET_TESTING_NotifyCompletion - notify_callback, void *notify_cls) -{ - switch (topology) - { - case GNUNET_TESTING_TOPOLOGY_CLIQUE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating clique CONNECT topology\n"); - create_clique (pg, &add_connections, CONNECT, GNUNET_NO); - break; - case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating small world (ring) CONNECT topology\n"); - create_small_world_ring (pg, &add_connections, CONNECT); - break; - case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating small world (2d-torus) CONNECT topology\n"); - create_small_world (pg, &add_connections, CONNECT); - break; - case GNUNET_TESTING_TOPOLOGY_RING: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating ring CONNECT topology\n"); - create_ring (pg, &add_connections, CONNECT); - break; - case GNUNET_TESTING_TOPOLOGY_2D_TORUS: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating 2d torus CONNECT topology\n"); - create_2d_torus (pg, &add_connections, CONNECT); - break; - case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating Erdos-Renyi CONNECT topology\n"); - create_erdos_renyi (pg, &add_connections, CONNECT); - break; - case GNUNET_TESTING_TOPOLOGY_INTERNAT: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating InterNAT CONNECT topology\n"); - create_nated_internet (pg, &add_connections, CONNECT); - break; - case GNUNET_TESTING_TOPOLOGY_SCALE_FREE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating Scale Free CONNECT topology\n"); - create_scale_free (pg, &add_connections, CONNECT); - break; - case GNUNET_TESTING_TOPOLOGY_LINE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating straight line CONNECT topology\n"); - create_line (pg, &add_connections, CONNECT); - break; - case GNUNET_TESTING_TOPOLOGY_NONE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating no CONNECT topology\n"); - copy_allowed_topology (pg); - break; - default: - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Unknown topology specification, can't connect peers!\n")); - return GNUNET_SYSERR; - } - - switch (options) - { - case GNUNET_TESTING_TOPOLOGY_OPTION_RANDOM: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connecting random subset (%'.2f percent) of possible peers\n", - 100 * option_modifier); - choose_random_connections (pg, option_modifier); - break; - case GNUNET_TESTING_TOPOLOGY_OPTION_MINIMUM: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connecting a minimum of %u peers each (if possible)\n", - (unsigned int) option_modifier); - choose_minimum (pg, (unsigned int) option_modifier); - break; - case GNUNET_TESTING_TOPOLOGY_OPTION_DFS: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Using DFS to connect a minimum of %u peers each (if possible)\n", - (unsigned int) option_modifier); -#if FIXME - perform_dfs (pg, (int) option_modifier); -#endif - break; - case GNUNET_TESTING_TOPOLOGY_OPTION_ADD_CLOSEST: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Finding additional %u closest peers each (if possible)\n", - (unsigned int) option_modifier); -#if FIXME - add_closest (pg, (unsigned int) option_modifier, &add_connections, CONNECT); -#endif - break; - case GNUNET_TESTING_TOPOLOGY_OPTION_NONE: - break; - case GNUNET_TESTING_TOPOLOGY_OPTION_ALL: - break; - default: - break; - } - - return connect_topology (pg, connect_timeout, connect_attempts, - notify_callback, notify_cls); -} - -/** - * Lookup and return the number of SSH connections to a host. - * - * @param hostname the hostname to lookup in the list - * @param pg the peergroup that the host belongs to - * - * @return the number of current ssh connections to the host - */ -static unsigned int -count_outstanding_at_host (const char *hostname, - struct GNUNET_TESTING_PeerGroup *pg) -{ - struct OutstandingSSH *pos; - - pos = pg->ssh_head; - while ((pos != NULL) && (strcmp (pos->hostname, hostname) != 0)) - pos = pos->next; - GNUNET_assert (pos != NULL); - return pos->outstanding; -} - -/** - * Increment the number of SSH connections to a host by one. - * - * @param hostname the hostname to lookup in the list - * @param pg the peergroup that the host belongs to - * - */ -static void -increment_outstanding_at_host (const char *hostname, - struct GNUNET_TESTING_PeerGroup *pg) -{ - struct OutstandingSSH *pos; - - pos = pg->ssh_head; - while ((NULL != pos) && (strcmp (pos->hostname, hostname) != 0)) - pos = pos->next; - GNUNET_assert (NULL != pos); - pos->outstanding++; -} - -/** - * Decrement the number of SSH connections to a host by one. - * - * @param hostname the hostname to lookup in the list - * @param pg the peergroup that the host belongs to - * - */ -static void -decrement_outstanding_at_host (const char *hostname, - struct GNUNET_TESTING_PeerGroup *pg) -{ - struct OutstandingSSH *pos; - - pos = pg->ssh_head; - while ((pos != NULL) && (strcmp (pos->hostname, hostname) != 0)) - pos = pos->next; - GNUNET_assert (pos != NULL); - pos->outstanding--; -} - -/** - * Callback that is called whenever a hostkey is generated - * for a peer. Call the real callback and decrement the - * starting counter for the peergroup. - * - * @param cls closure - * @param id identifier for the daemon, NULL on error - * @param d handle for the daemon - * @param emsg error message (NULL on success) - */ -static void -internal_hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - struct InternalStartContext *internal_context = cls; - - internal_context->peer->pg->starting--; - internal_context->peer->pg->started++; - if (internal_context->hostname != NULL) - decrement_outstanding_at_host (internal_context->hostname, - internal_context->peer->pg); - if (internal_context->hostkey_callback != NULL) - internal_context->hostkey_callback (internal_context->hostkey_cls, id, d, - emsg); - else if (internal_context->peer->pg->started == - internal_context->peer->pg->total) - { - internal_context->peer->pg->started = 0; /* Internal startup may use this counter! */ - GNUNET_TESTING_daemons_continue_startup (internal_context->peer->pg); - } -} - -/** - * Callback that is called whenever a peer has finished starting. - * Call the real callback and decrement the starting counter - * for the peergroup. - * - * @param cls closure - * @param id identifier for the daemon, NULL on error - * @param cfg config - * @param d handle for the daemon - * @param emsg error message (NULL on success) - */ -static void -internal_startup_callback (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - struct InternalStartContext *internal_context = cls; - - internal_context->peer->pg->starting--; - if (internal_context->hostname != NULL) - decrement_outstanding_at_host (internal_context->hostname, - internal_context->peer->pg); - if (internal_context->start_cb != NULL) - internal_context->start_cb (internal_context->start_cb_cls, id, cfg, d, - emsg); -} - - -/** - * Calls GNUNET_TESTING_daemon_continue_startup to set the daemon's state - * from HOSTKEY_CREATED to TOPOLOGY_SETUP. Makes sure not to saturate a host - * with requests delaying them when needed. - * - * @param cls closure: internal context of the daemon. - * @param tc TaskContext - */ -static void -internal_continue_startup (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct InternalStartContext *internal_context = cls; - - internal_context->peer->startup_task = GNUNET_SCHEDULER_NO_TASK; - - if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - { - return; - } - - if ((internal_context->peer->pg->starting < - internal_context->peer->pg->max_concurrent_ssh) || - ((internal_context->hostname != NULL) && - (count_outstanding_at_host - (internal_context->hostname, - internal_context->peer->pg) < - internal_context->peer->pg->max_concurrent_ssh))) - { - if (internal_context->hostname != NULL) - increment_outstanding_at_host (internal_context->hostname, - internal_context->peer->pg); - internal_context->peer->pg->starting++; - GNUNET_TESTING_daemon_continue_startup (internal_context->peer->daemon); - } - else - { - internal_context->peer->startup_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, 100), - &internal_continue_startup, - internal_context); - } -} - -/** - * Callback for informing us about a successful - * or unsuccessful churn start call. - * - * @param cls a ChurnContext - * @param id the peer identity of the started peer - * @param cfg the handle to the configuration of the peer - * @param d handle to the daemon for the peer - * @param emsg NULL on success, non-NULL on failure - * - */ -void -churn_start_callback (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - struct ChurnRestartContext *startup_ctx = cls; - struct ChurnContext *churn_ctx = startup_ctx->churn_ctx; - - unsigned int total_left; - char *error_message; - - error_message = NULL; - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Churn stop callback failed with error `%s'\n", emsg); - churn_ctx->num_failed_start++; - } - else - { - churn_ctx->num_to_start--; - } - - total_left = - (churn_ctx->num_to_stop - churn_ctx->num_failed_stop) + - (churn_ctx->num_to_start - churn_ctx->num_failed_start); - - if (total_left == 0) - { - if ((churn_ctx->num_failed_stop > 0) || (churn_ctx->num_failed_start > 0)) - GNUNET_asprintf (&error_message, - "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!", - churn_ctx->num_failed_start, churn_ctx->num_failed_stop); - churn_ctx->cb (churn_ctx->cb_cls, error_message); - GNUNET_free_non_null (error_message); - GNUNET_free (churn_ctx); - GNUNET_free (startup_ctx); - } -} - -static void -schedule_churn_restart (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct PeerRestartContext *peer_restart_ctx = cls; - struct ChurnRestartContext *startup_ctx = peer_restart_ctx->churn_restart_ctx; - - if (startup_ctx->outstanding > startup_ctx->pg->max_concurrent_ssh) - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, 100), - &schedule_churn_restart, peer_restart_ctx); - else - { - if (startup_ctx->churn_ctx->service != NULL) - GNUNET_TESTING_daemon_start_stopped_service (peer_restart_ctx->daemon, - startup_ctx-> - churn_ctx->service, - startup_ctx->timeout, - &churn_start_callback, - startup_ctx); - else - GNUNET_TESTING_daemon_start_stopped (peer_restart_ctx->daemon, - startup_ctx->timeout, - &churn_start_callback, startup_ctx); - GNUNET_free (peer_restart_ctx); - } -} - -/** - * Callback for informing us about a successful - * or unsuccessful churn start call. - * - * @param cls a struct ServiceStartContext *startup_ctx - * @param id the peer identity of the started peer - * @param cfg the handle to the configuration of the peer - * @param d handle to the daemon for the peer - * @param emsg NULL on success, non-NULL on failure - * - */ -void -service_start_callback (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - struct ServiceStartContext *startup_ctx = (struct ServiceStartContext *) cls; - - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Service start failed with error `%s'\n", emsg); - } - - startup_ctx->outstanding--; - startup_ctx->remaining--; - - if (startup_ctx->remaining == 0) - { - startup_ctx->cb (startup_ctx->cb_cls, NULL); - GNUNET_free (startup_ctx->service); - GNUNET_free (startup_ctx); - } -} - -static void -schedule_service_start (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct PeerServiceStartContext *peer_ctx = cls; - struct ServiceStartContext *startup_ctx = peer_ctx->start_ctx; - - if (startup_ctx->outstanding > startup_ctx->pg->max_concurrent_ssh) - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, 100), - &schedule_service_start, peer_ctx); - else - { - - GNUNET_TESTING_daemon_start_service (peer_ctx->daemon, startup_ctx->service, - startup_ctx->timeout, - &service_start_callback, startup_ctx); - GNUNET_free (peer_ctx); - } -} - - -static void -internal_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct InternalStartContext *internal_context = cls; - - if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - { - return; - } - - if ((internal_context->peer->pg->starting < - internal_context->peer->pg->max_concurrent_ssh) || - ((internal_context->hostname != NULL) && - (count_outstanding_at_host - (internal_context->hostname, - internal_context->peer->pg) < - internal_context->peer->pg->max_concurrent_ssh))) - { - if (internal_context->hostname != NULL) - increment_outstanding_at_host (internal_context->hostname, - internal_context->peer->pg); - internal_context->peer->pg->starting++; - internal_context->peer->daemon = - GNUNET_TESTING_daemon_start (internal_context->peer->cfg, - internal_context->timeout, GNUNET_NO, - internal_context->hostname, - internal_context->username, - internal_context->sshport, - internal_context->hostkey, - &internal_hostkey_callback, - internal_context, - &internal_startup_callback, - internal_context); - } - else - { - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, 100), - &internal_start, internal_context); - } -} - -#if USE_START_HELPER - -struct PeerStartHelperContext -{ - struct GNUNET_TESTING_PeerGroup *pg; - - struct HostData *host; - - struct GNUNET_OS_Process *proc; -}; - -static void -check_peers_started (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct PeerStartHelperContext *helper = cls; - enum GNUNET_OS_ProcessStatusType type; - unsigned long code; - unsigned int i; - GNUNET_TESTING_NotifyDaemonRunning cb; - - if (GNUNET_NO == GNUNET_OS_process_status (helper->proc, &type, &code)) /* Still running, wait some more! */ - { - GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, - &check_peers_started, helper); - return; - } - - helper->pg->starting--; - if (helper->pg->starting == 0) /* All peers have finished starting! */ - { - /* Call the peer started callback for each peer, set proper FSM state (?) */ - for (i = 0; i < helper->pg->total; i++) - { - cb = helper->pg->peers[i].daemon->cb; - helper->pg->peers[i].daemon->cb = NULL; - helper->pg->peers[i].daemon->running = GNUNET_YES; - helper->pg->peers[i].daemon->phase = SP_START_DONE; - if (NULL != cb) - { - if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0)) - cb (helper->pg->peers[i].daemon->cb_cls, - &helper->pg->peers[i].daemon->id, - helper->pg->peers[i].daemon->cfg, helper->pg->peers[i].daemon, - "Failed to execute peerStartHelper.pl, or return code bad!"); - else - cb (helper->pg->peers[i].daemon->cb_cls, - &helper->pg->peers[i].daemon->id, - helper->pg->peers[i].daemon->cfg, helper->pg->peers[i].daemon, - NULL); - - } - - } - } - GNUNET_OS_process_destroy (helper->proc); -} - -static void -start_peer_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct PeerStartHelperContext *helper = cls; - char *baseservicehome; - char *tempdir; - char *arg; - - /* ssh user@host peerStartHelper /path/to/basedirectory */ - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (helper->pg->cfg, - "PATHS", "SERVICEHOME", - &baseservicehome)); - GNUNET_asprintf (&tempdir, "%s/%s/", baseservicehome, helper->host->hostname); - if (NULL != helper->host->username) - GNUNET_asprintf (&arg, "%s@%s", helper->host->username, - helper->host->hostname); - else - GNUNET_asprintf (&arg, "%s", helper->host->hostname); - - /* FIXME: Doesn't support ssh_port option! */ - helper->proc = - GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", arg, - "peerStartHelper.pl", tempdir, NULL); - GNUNET_assert (helper->proc != NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting peers with cmd ssh %s %s %s\n", - arg, "peerStartHelper.pl", tempdir); - GNUNET_SCHEDULER_add_now (&check_peers_started, helper); - GNUNET_free (tempdir); - GNUNET_free (baseservicehome); - GNUNET_free (arg); -} -#endif - -/** - * Function which continues a peer group starting up - * after successfully generating hostkeys for each peer. - * - * @param pg the peer group to continue starting - * - */ -void -GNUNET_TESTING_daemons_continue_startup (struct GNUNET_TESTING_PeerGroup *pg) -{ - unsigned int i; - -#if USE_START_HELPER - if ((pg->num_hosts > 0) && (pg->hostkey_data != NULL)) - { - struct PeerStartHelperContext *helper; - - pg->starting = pg->num_hosts; - for (i = 0; i < pg->num_hosts; i++) - { - helper = GNUNET_malloc (sizeof (struct PeerStartHelperContext)); - helper->pg = pg; - helper->host = &pg->hosts[i]; - GNUNET_SCHEDULER_add_now (&start_peer_helper, helper); - } - } - else - { - pg->starting = 0; - for (i = 0; i < pg->total; i++) - { - pg->peers[i].startup_task = - GNUNET_SCHEDULER_add_now (&internal_continue_startup, - &pg->peers[i].internal_context); - } - } -#else - pg->starting = 0; - for (i = 0; i < pg->total; i++) - { - pg->peers[i].startup_task = - GNUNET_SCHEDULER_add_now (&internal_continue_startup, - &pg->peers[i].internal_context); - } -#endif -} - -#if USE_START_HELPER -static void -call_hostkey_callbacks (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_TESTING_PeerGroup *pg = cls; - unsigned int i; - - for (i = 0; i < pg->total; i++) - { - if (pg->peers[i].internal_context.hostkey_callback != NULL) - pg->peers[i].internal_context.hostkey_callback (pg->peers[i]. - internal_context.hostkey_cls, - &pg->peers[i].daemon->id, - pg->peers[i].daemon, - NULL); - } - - if (pg->peers[0].internal_context.hostkey_callback == NULL) - GNUNET_TESTING_daemons_continue_startup (pg); -} -#endif - -/** - * Start count gnunet instances with the same set of transports and - * applications. The port numbers (any option called "PORT") will be - * adjusted to ensure that no two peers running on the same system - * have the same port(s) in their respective configurations. - * - * @param cfg configuration template to use - * @param total number of daemons to start - * @param max_concurrent_connections for testing, how many peers can - * we connect to simultaneously - * @param max_concurrent_ssh when starting with ssh, how many ssh - * connections will we allow at once (based on remote hosts allowed!) - * @param timeout total time allowed for peers to start - * @param hostkey_callback function to call on each peers hostkey generation - * if NULL, peers will be started by this call, if non-null, - * GNUNET_TESTING_daemons_continue_startup must be called after - * successful hostkey generation - * @param hostkey_cls closure for hostkey callback - * @param cb function to call on each daemon that was started - * @param cb_cls closure for cb - * @param connect_callback function to call each time two hosts are connected - * @param connect_callback_cls closure for connect_callback - * @param hostnames linked list of host structs to use to start peers on - * (NULL to run on localhost only) - * - * @return NULL on error, otherwise handle to control peer group - */ -struct GNUNET_TESTING_PeerGroup * -GNUNET_TESTING_daemons_start (const struct GNUNET_CONFIGURATION_Handle *cfg, - unsigned int total, - unsigned int max_concurrent_connections, - unsigned int max_concurrent_ssh, - struct GNUNET_TIME_Relative timeout, - GNUNET_TESTING_NotifyHostkeyCreated - hostkey_callback, void *hostkey_cls, - GNUNET_TESTING_NotifyDaemonRunning cb, - void *cb_cls, - GNUNET_TESTING_NotifyConnection connect_callback, - void *connect_callback_cls, - const struct GNUNET_TESTING_Host *hostnames) -{ - struct GNUNET_TESTING_PeerGroup *pg; - const struct GNUNET_TESTING_Host *hostpos; - const char *hostname; - const char *username; - char *baseservicehome; - char *newservicehome; - char *tmpdir; - char *hostkeys_file; - char *arg; - char *ssh_port_str; - struct GNUNET_DISK_FileHandle *fd; - struct GNUNET_CONFIGURATION_Handle *pcfg; - unsigned int off; - struct OutstandingSSH *ssh_entry; - unsigned int hostcnt; - unsigned int i; - uint16_t minport; - uint16_t sshport; - uint32_t upnum; - uint32_t fdnum; - uint64_t fs; - uint64_t total_hostkeys; - struct GNUNET_OS_Process *proc; - - username = NULL; - if (0 == total) - { - GNUNET_break (0); - return NULL; - } - - upnum = 0; - fdnum = 0; - pg = GNUNET_malloc (sizeof (struct GNUNET_TESTING_PeerGroup)); - pg->cfg = cfg; - pg->notify_connection = connect_callback; - pg->notify_connection_cls = connect_callback_cls; - pg->total = total; - pg->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); - pg->peers = GNUNET_malloc (total * sizeof (struct PeerData)); - pg->max_outstanding_connections = max_concurrent_connections; - pg->max_concurrent_ssh = max_concurrent_ssh; - if (NULL != hostnames) - { - off = 0; - hostpos = hostnames; - while (hostpos != NULL) - { - hostpos = hostpos->next; - off++; - } - pg->hosts = GNUNET_malloc (off * sizeof (struct HostData)); - off = 0; - - hostpos = hostnames; - while (hostpos != NULL) - { - pg->hosts[off].minport = LOW_PORT; - pg->hosts[off].hostname = GNUNET_strdup (hostpos->hostname); - if (hostpos->username != NULL) - pg->hosts[off].username = GNUNET_strdup (hostpos->username); - pg->hosts[off].sshport = hostpos->port; - hostpos = hostpos->next; - off++; - } - - if (off == 0) - { - pg->hosts = NULL; - } - hostcnt = off; - minport = 0; - pg->num_hosts = off; - } - else - { - hostcnt = 0; - minport = LOW_PORT; - } - - /* Create the servicehome directory for each remote peer */ - GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", - "SERVICEHOME", - &baseservicehome)); - for (i = 0; i < pg->num_hosts; i++) - { - ssh_entry = GNUNET_malloc (sizeof (struct OutstandingSSH)); - ssh_entry->hostname = pg->hosts[i].hostname; /* Don't free! */ - GNUNET_CONTAINER_DLL_insert (pg->ssh_head, pg->ssh_tail, ssh_entry); - GNUNET_asprintf (&tmpdir, "%s/%s", baseservicehome, pg->hosts[i].hostname); - if (NULL != pg->hosts[i].username) - GNUNET_asprintf (&arg, "%s@%s", pg->hosts[i].username, - pg->hosts[i].hostname); - else - GNUNET_asprintf (&arg, "%s", pg->hosts[i].hostname); - if (pg->hosts[i].sshport != 0) - { - GNUNET_asprintf (&ssh_port_str, "%d", pg->hosts[i].sshport); - proc = - GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", "-P", ssh_port_str, - "-q", - arg, "mkdir -p", tmpdir, NULL); - } - else - proc = - GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", arg, "mkdir -p", - tmpdir, NULL); - GNUNET_assert (proc != NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating remote dir with command ssh %s %s %s\n", arg, - " mkdir -p ", tmpdir); - GNUNET_free (tmpdir); - GNUNET_free (arg); - GNUNET_OS_process_wait (proc); - GNUNET_OS_process_destroy (proc); - } - GNUNET_free (baseservicehome); - baseservicehome = NULL; - - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "TESTING", "HOSTKEYSFILE", - &hostkeys_file)) - { - if (GNUNET_YES != GNUNET_DISK_file_test (hostkeys_file)) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Could not read hostkeys file!\n")); - else - { - /* Check hostkey file size, read entire thing into memory */ - fd = GNUNET_DISK_file_open (hostkeys_file, GNUNET_DISK_OPEN_READ, - GNUNET_DISK_PERM_NONE); - if (NULL == fd) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", - hostkeys_file); - GNUNET_free (hostkeys_file); - for (i = 0; i < pg->num_hosts; i++) - { - GNUNET_free (pg->hosts[i].hostname); - GNUNET_free_non_null (pg->hosts[i].username); - } - GNUNET_free (pg->peers); - GNUNET_free (pg->hosts); - GNUNET_free (pg); - return NULL; - } - - if (GNUNET_OK != GNUNET_DISK_file_size (hostkeys_file, &fs, GNUNET_YES, GNUNET_YES)) - fs = 0; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Found file size %llu for hostkeys\n", fs); - if (0 != (fs % HOSTKEYFILESIZE)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "File size %llu seems incorrect for hostkeys...\n", fs); - } - else - { - total_hostkeys = fs / HOSTKEYFILESIZE; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Will read %llu hostkeys from file\n", total_hostkeys); - pg->hostkey_data = GNUNET_malloc_large (fs); - GNUNET_assert (fs == GNUNET_DISK_file_read (fd, pg->hostkey_data, fs)); - } - GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd)); - } - GNUNET_free (hostkeys_file); - } - - for (off = 0; off < total; off++) - { - if (hostcnt > 0) - { - hostname = pg->hosts[off % hostcnt].hostname; - username = pg->hosts[off % hostcnt].username; - sshport = pg->hosts[off % hostcnt].sshport; - pcfg = - GNUNET_TESTING_create_cfg (cfg, off, &pg->hosts[off % hostcnt].minport, &upnum, - hostname, &fdnum); - } - else - { - hostname = NULL; - username = NULL; - sshport = 0; - pcfg = GNUNET_TESTING_create_cfg (cfg, off, &minport, &upnum, hostname, &fdnum); - } - - if (NULL == pcfg) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Could not create configuration for peer number %u on `%s'!\n"), - off, hostname == NULL ? "localhost" : hostname); - continue; - } - - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (pcfg, "PATHS", "SERVICEHOME", - &baseservicehome)) - { - if (hostname != NULL) - GNUNET_asprintf (&newservicehome, "%s/%s/%d/", baseservicehome, - hostname, off); - else - GNUNET_asprintf (&newservicehome, "%s/%d/", baseservicehome, off); - GNUNET_free (baseservicehome); - baseservicehome = NULL; - } - else - { - tmpdir = getenv ("TMPDIR"); - tmpdir = tmpdir ? tmpdir : "/tmp"; - if (hostname != NULL) - GNUNET_asprintf (&newservicehome, "%s/%s/%s/%d/", tmpdir, hostname, - "gnunet-testing-test-test", off); - else - GNUNET_asprintf (&newservicehome, "%s/%s/%d/", tmpdir, - "gnunet-testing-test-test", off); - } - GNUNET_CONFIGURATION_set_value_string (pcfg, "PATHS", "SERVICEHOME", - newservicehome); - GNUNET_free (newservicehome); - pg->peers[off].cfg = pcfg; - pg->peers[off].pg = pg; - pg->peers[off].internal_context.peer = &pg->peers[off]; - pg->peers[off].internal_context.timeout = timeout; - pg->peers[off].internal_context.hostname = hostname; - pg->peers[off].internal_context.username = username; - pg->peers[off].internal_context.sshport = sshport; - if (pg->hostkey_data != NULL) - pg->peers[off].internal_context.hostkey = - &pg->hostkey_data[off * HOSTKEYFILESIZE]; - pg->peers[off].internal_context.hostkey_callback = hostkey_callback; - pg->peers[off].internal_context.hostkey_cls = hostkey_cls; - pg->peers[off].internal_context.start_cb = cb; - pg->peers[off].internal_context.start_cb_cls = cb_cls; -#if !USE_START_HELPER - GNUNET_SCHEDULER_add_now (&internal_start, - &pg->peers[off].internal_context); -#else - if ((pg->hostkey_data != NULL) && (hostcnt > 0)) - { - pg->peers[off].daemon = - GNUNET_TESTING_daemon_start (pcfg, timeout, GNUNET_YES, hostname, - username, sshport, - pg->peers[off].internal_context.hostkey, - &internal_hostkey_callback, - &pg->peers[off].internal_context, - &internal_startup_callback, - &pg->peers[off].internal_context); - /** - * At this point, given that we had a hostkeyfile, - * we can call the hostkey callback! - * But first, we should copy (rsync) all of the configs - * and hostkeys to the remote peers. Then let topology - * creation happen, then call the peer start helper processes, - * then set pg->whatever_phase for each peer and let them - * enter the fsm to get the HELLO's for peers and start connecting. - */ - } - else - { - GNUNET_SCHEDULER_add_now (&internal_start, - &pg->peers[off].internal_context); - } - -#endif - } - -#if USE_START_HELPER /* Now the peergroup has been set up, hostkeys and configs written to files. */ - if ((pg->hostkey_data != NULL) && (hostcnt > 0)) - { - for (off = 0; off < hostcnt; off++) - { - - if (hostcnt > 0) - { - hostname = pg->hosts[off % hostcnt].hostname; - username = pg->hosts[off % hostcnt].username; - sshport = pg->hosts[off % hostcnt].sshport; - } - else - { - hostname = NULL; - username = NULL; - sshport = 0; - } - - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "SERVICEHOME", - &baseservicehome)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "baseservice home is %s\n", - baseservicehome); - if (hostname != NULL) - GNUNET_asprintf (&newservicehome, "%s/%s/", baseservicehome, - hostname); - else - GNUNET_asprintf (&newservicehome, "%s/", baseservicehome); - GNUNET_free (baseservicehome); - baseservicehome = NULL; - } - else - { - tmpdir = getenv ("TMPDIR"); - tmpdir = tmpdir ? tmpdir : "/tmp"; - if (hostname != NULL) - GNUNET_asprintf (&newservicehome, "%s/%s/%s/", tmpdir, hostname, - "gnunet-testing-test-test"); - else - GNUNET_asprintf (&newservicehome, "%s/%s/", tmpdir, - "gnunet-testing-test-test", off); - } - - if (NULL != username) - GNUNET_asprintf (&arg, "%s@%s:%s", username, pg->hosts[off].hostname, - newservicehome); - else - GNUNET_asprintf (&arg, "%s:%s", pg->hosts[off].hostname, - newservicehome); - - /* FIXME: Doesn't support ssh_port option! */ - proc = - GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "rsync", "rsync", "-r", - newservicehome, arg, NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "copying directory with command rsync -r %s %s\n", - newservicehome, arg); - GNUNET_free (newservicehome); - GNUNET_free (arg); - if (NULL == proc) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("Could not start `%s' process to copy configuration directory.\n"), - "scp"); - GNUNET_assert (0); - } - GNUNET_OS_process_wait (proc); - GNUNET_OS_process_destroy (proc); - } - /* Now all the configuration files and hostkeys are copied to the remote host. Call the hostkey callback for each peer! */ - GNUNET_SCHEDULER_add_now (&call_hostkey_callbacks, pg); - } -#endif - return pg; -} - -/* - * Get a daemon by number, so callers don't have to do nasty - * offsetting operation. - */ -struct GNUNET_TESTING_Daemon * -GNUNET_TESTING_daemon_get (struct GNUNET_TESTING_PeerGroup *pg, - unsigned int position) -{ - if (position < pg->total) - return pg->peers[position].daemon; - return NULL; -} - -/* - * Get a daemon by peer identity, so callers can - * retrieve the daemon without knowing it's offset. - * - * @param pg the peer group to retrieve the daemon from - * @param peer_id the peer identity of the daemon to retrieve - * - * @return the daemon on success, or NULL if no such peer identity is found - */ -struct GNUNET_TESTING_Daemon * -GNUNET_TESTING_daemon_get_by_id (struct GNUNET_TESTING_PeerGroup *pg, - const struct GNUNET_PeerIdentity *peer_id) -{ - unsigned int i; - - for (i = 0; i < pg->total; i++) - { - if (0 == - memcmp (&pg->peers[i].daemon->id, peer_id, - sizeof (struct GNUNET_PeerIdentity))) - return pg->peers[i].daemon; - } - return NULL; -} - -/** - * Prototype of a function that will be called when a - * particular operation was completed the testing library. - * - * @param cls closure (a struct RestartContext) - * @param id id of the peer that was restarted - * @param cfg handle to the configuration of the peer - * @param d handle to the daemon that was restarted - * @param emsg NULL on success - */ -static void -restart_callback (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - struct RestartContext *restart_context = cls; - - if (emsg == NULL) - { - restart_context->peers_restarted++; - } - else - { - restart_context->peers_restart_failed++; - } - - if (restart_context->peers_restarted == restart_context->peer_group->total) - { - restart_context->callback (restart_context->callback_cls, NULL); - GNUNET_free (restart_context); - } - else if (restart_context->peers_restart_failed + - restart_context->peers_restarted == - restart_context->peer_group->total) - { - restart_context->callback (restart_context->callback_cls, - "Failed to restart peers!"); - GNUNET_free (restart_context); - } - -} - -/** - * Callback for informing us about a successful - * or unsuccessful churn stop call. - * - * @param cls a ChurnContext - * @param emsg NULL on success, non-NULL on failure - * - */ -static void -churn_stop_callback (void *cls, const char *emsg) -{ - struct ShutdownContext *shutdown_ctx = cls; - struct ChurnContext *churn_ctx = shutdown_ctx->cb_cls; - unsigned int total_left; - char *error_message; - - error_message = NULL; - shutdown_ctx->outstanding--; - - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Churn stop callback failed with error `%s'\n", emsg); - churn_ctx->num_failed_stop++; - } - else - { - churn_ctx->num_to_stop--; - } - - total_left = - (churn_ctx->num_to_stop - churn_ctx->num_failed_stop) + - (churn_ctx->num_to_start - churn_ctx->num_failed_start); - - if (total_left == 0) - { - if ((churn_ctx->num_failed_stop > 0) || (churn_ctx->num_failed_start > 0)) - { - GNUNET_asprintf (&error_message, - "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!", - churn_ctx->num_failed_start, churn_ctx->num_failed_stop); - } - churn_ctx->cb (churn_ctx->cb_cls, error_message); - GNUNET_free_non_null (error_message); - GNUNET_free (churn_ctx); - GNUNET_free (shutdown_ctx); - } -} - -/** - * Count the number of running peers. - * - * @param pg handle for the peer group - * - * @return the number of currently running peers in the peer group - */ -unsigned int -GNUNET_TESTING_daemons_running (struct GNUNET_TESTING_PeerGroup *pg) -{ - unsigned int i; - unsigned int running = 0; - - for (i = 0; i < pg->total; i++) - { - if (pg->peers[i].daemon->running == GNUNET_YES) - { - GNUNET_assert (running != -1); - running++; - } - } - return running; -} - -/** - * Task to rate limit the number of outstanding peer shutdown - * requests. This is necessary for making sure we don't do - * too many ssh connections at once, but is generally nicer - * to any system as well (graduated task starts, as opposed - * to calling gnunet-arm N times all at once). - */ -static void -schedule_churn_shutdown_task (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct PeerShutdownContext *peer_shutdown_ctx = cls; - struct ShutdownContext *shutdown_ctx; - struct ChurnContext *churn_ctx; - - GNUNET_assert (peer_shutdown_ctx != NULL); - shutdown_ctx = peer_shutdown_ctx->shutdown_ctx; - GNUNET_assert (shutdown_ctx != NULL); - churn_ctx = (struct ChurnContext *) shutdown_ctx->cb_cls; - if (shutdown_ctx->outstanding > churn_ctx->pg->max_concurrent_ssh) - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, 100), - &schedule_churn_shutdown_task, - peer_shutdown_ctx); - else - { - shutdown_ctx->outstanding++; - if (churn_ctx->service != NULL) - GNUNET_TESTING_daemon_stop_service (peer_shutdown_ctx->daemon, - churn_ctx->service, - shutdown_ctx->timeout, - shutdown_ctx->cb, shutdown_ctx); - else - GNUNET_TESTING_daemon_stop (peer_shutdown_ctx->daemon, - shutdown_ctx->timeout, shutdown_ctx->cb, - shutdown_ctx, GNUNET_NO, GNUNET_YES); - GNUNET_free (peer_shutdown_ctx); - } -} - - -/** - * Simulate churn by stopping some peers (and possibly - * re-starting others if churn is called multiple times). This - * function can only be used to create leave-join churn (peers "never" - * leave for good). First "voff" random peers that are currently - * online will be taken offline; then "von" random peers that are then - * offline will be put back online. No notifications will be - * generated for any of these operations except for the callback upon - * completion. - * - * @param pg handle for the peer group - * @param service the service to churn off/on, NULL to churn peer - * @param voff number of peers that should go offline - * @param von number of peers that should come back online; - * must be zero on first call (since "testbed_start" - * always starts all of the peers) - * @param timeout how long to wait for operations to finish before - * giving up - * @param cb function to call at the end - * @param cb_cls closure for cb - */ -void -GNUNET_TESTING_daemons_churn (struct GNUNET_TESTING_PeerGroup *pg, - char *service, unsigned int voff, - unsigned int von, - struct GNUNET_TIME_Relative timeout, - GNUNET_TESTING_NotifyCompletion cb, void *cb_cls) -{ - struct ChurnContext *churn_ctx; - struct ShutdownContext *shutdown_ctx; - struct PeerShutdownContext *peer_shutdown_ctx; - struct PeerRestartContext *peer_restart_ctx; - struct ChurnRestartContext *churn_startup_ctx; - - unsigned int running; - unsigned int stopped; - unsigned int total_running; - unsigned int total_stopped; - unsigned int i; - unsigned int *running_arr; - unsigned int *stopped_arr; - unsigned int *running_permute; - unsigned int *stopped_permute; - char *pos; - - shutdown_ctx = NULL; - peer_shutdown_ctx = NULL; - peer_restart_ctx = NULL; - churn_startup_ctx = NULL; - - running = 0; - stopped = 0; - - if ((von == 0) && (voff == 0)) /* No peers at all? */ - { - cb (cb_cls, NULL); - return; - } - - for (i = 0; i < pg->total; i++) - { - if (service == NULL) - { - if (pg->peers[i].daemon->running == GNUNET_YES) - { - GNUNET_assert (running != -1); - running++; - } - else - { - GNUNET_assert (stopped != -1); - stopped++; - } - } - else - { - /* FIXME: make churned services a list! */ - pos = pg->peers[i].daemon->churned_services; - /* FIXME: while (pos != NULL) */ - if (pos != NULL) - { -#if FIXME - if (0 == strcasecmp (pos, service)) - { - - break; - } -#endif - GNUNET_assert (stopped != -1); - stopped++; - /* FIXME: pos = pos->next; */ - } - if (pos == NULL) - { - GNUNET_assert (running != -1); - running++; - } - } - } - - if (voff > running) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Trying to stop more peers (%d) than are currently running (%d)!\n", - voff, running); - cb (cb_cls, "Trying to stop more peers than are currently running!"); - return; - } - - if (von > stopped) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Trying to start more peers (%d) than are currently stopped (%d)!\n", - von, stopped); - cb (cb_cls, "Trying to start more peers than are currently stopped!"); - return; - } - - churn_ctx = GNUNET_malloc (sizeof (struct ChurnContext)); - - if (service != NULL) - churn_ctx->service = GNUNET_strdup (service); - running_arr = NULL; - if (running > 0) - running_arr = GNUNET_malloc (running * sizeof (unsigned int)); - - stopped_arr = NULL; - if (stopped > 0) - stopped_arr = GNUNET_malloc (stopped * sizeof (unsigned int)); - - running_permute = NULL; - stopped_permute = NULL; - - if (running > 0) - running_permute = - GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, running); - if (stopped > 0) - stopped_permute = - GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, stopped); - - total_running = running; - total_stopped = stopped; - running = 0; - stopped = 0; - - churn_ctx->num_to_start = von; - churn_ctx->num_to_stop = voff; - churn_ctx->cb = cb; - churn_ctx->cb_cls = cb_cls; - churn_ctx->pg = pg; - - for (i = 0; i < pg->total; i++) - { - if (service == NULL) - { - if (pg->peers[i].daemon->running == GNUNET_YES) - { - GNUNET_assert ((running_arr != NULL) && (total_running > running)); - running_arr[running] = i; - running++; - } - else - { - GNUNET_assert ((stopped_arr != NULL) && (total_stopped > stopped)); - stopped_arr[stopped] = i; - stopped++; - } - } - else - { - /* FIXME: make churned services a list! */ - pos = pg->peers[i].daemon->churned_services; - /* FIXME: while (pos != NULL) */ - if (pos != NULL) - { - GNUNET_assert ((stopped_arr != NULL) && (total_stopped > stopped)); - stopped_arr[stopped] = i; - stopped++; - /* FIXME: pos = pos->next; */ - } - if (pos == NULL) - { - GNUNET_assert ((running_arr != NULL) && (total_running > running)); - running_arr[running] = i; - running++; - } - } - } - - GNUNET_assert (running >= voff); - if (voff > 0) - { - shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext)); - shutdown_ctx->cb = &churn_stop_callback; - shutdown_ctx->cb_cls = churn_ctx; - shutdown_ctx->total_peers = voff; - shutdown_ctx->timeout = timeout; - } - - for (i = 0; i < voff; i++) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peer %d!\n", - running_arr[running_permute[i]]); - GNUNET_assert (running_arr != NULL); - peer_shutdown_ctx = GNUNET_malloc (sizeof (struct PeerShutdownContext)); - peer_shutdown_ctx->daemon = - pg->peers[running_arr[running_permute[i]]].daemon; - peer_shutdown_ctx->shutdown_ctx = shutdown_ctx; - GNUNET_SCHEDULER_add_now (&schedule_churn_shutdown_task, peer_shutdown_ctx); - } - - GNUNET_assert (stopped >= von); - if (von > 0) - { - churn_startup_ctx = GNUNET_malloc (sizeof (struct ChurnRestartContext)); - churn_startup_ctx->churn_ctx = churn_ctx; - churn_startup_ctx->timeout = timeout; - churn_startup_ctx->pg = pg; - } - for (i = 0; i < von; i++) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting up peer %d!\n", - stopped_arr[stopped_permute[i]]); - GNUNET_assert (stopped_arr != NULL); - peer_restart_ctx = GNUNET_malloc (sizeof (struct PeerRestartContext)); - peer_restart_ctx->churn_restart_ctx = churn_startup_ctx; - peer_restart_ctx->daemon = - pg->peers[stopped_arr[stopped_permute[i]]].daemon; - GNUNET_SCHEDULER_add_now (&schedule_churn_restart, peer_restart_ctx); - } - - GNUNET_free_non_null (running_arr); - GNUNET_free_non_null (stopped_arr); - GNUNET_free_non_null (running_permute); - GNUNET_free_non_null (stopped_permute); -} - -/* - * Start a given service for each of the peers in the peer group. - * - * @param pg handle for the peer group - * @param service the service to start - * @param timeout how long to wait for operations to finish before - * giving up - * @param cb function to call once finished - * @param cb_cls closure for cb - * - */ -void -GNUNET_TESTING_daemons_start_service (struct GNUNET_TESTING_PeerGroup *pg, - char *service, - struct GNUNET_TIME_Relative timeout, - GNUNET_TESTING_NotifyCompletion cb, - void *cb_cls) -{ - struct ServiceStartContext *start_ctx; - struct PeerServiceStartContext *peer_start_ctx; - unsigned int i; - - GNUNET_assert (service != NULL); - - start_ctx = GNUNET_malloc (sizeof (struct ServiceStartContext)); - start_ctx->pg = pg; - start_ctx->remaining = pg->total; - start_ctx->cb = cb; - start_ctx->cb_cls = cb_cls; - start_ctx->service = GNUNET_strdup (service); - start_ctx->timeout = timeout; - - for (i = 0; i < pg->total; i++) - { - peer_start_ctx = GNUNET_malloc (sizeof (struct PeerServiceStartContext)); - peer_start_ctx->start_ctx = start_ctx; - peer_start_ctx->daemon = pg->peers[i].daemon; - GNUNET_SCHEDULER_add_now (&schedule_service_start, peer_start_ctx); - } -} - -/** - * Restart all peers in the given group. - * - * @param pg the handle to the peer group - * @param callback function to call on completion (or failure) - * @param callback_cls closure for the callback function - */ -void -GNUNET_TESTING_daemons_restart (struct GNUNET_TESTING_PeerGroup *pg, - GNUNET_TESTING_NotifyCompletion callback, - void *callback_cls) -{ - struct RestartContext *restart_context; - unsigned int off; - - if (pg->total > 0) - { - restart_context = GNUNET_malloc (sizeof (struct RestartContext)); - restart_context->peer_group = pg; - restart_context->peers_restarted = 0; - restart_context->callback = callback; - restart_context->callback_cls = callback_cls; - - for (off = 0; off < pg->total; off++) - { - GNUNET_TESTING_daemon_restart (pg->peers[off].daemon, &restart_callback, - restart_context); - } - } -} - - -/** - * Start or stop an individual peer from the given group. - * - * @param pg handle to the peer group - * @param offset which peer to start or stop - * @param desired_status GNUNET_YES to have it running, GNUNET_NO to stop it - * @param timeout how long to wait for shutdown - * @param cb function to call at the end - * @param cb_cls closure for cb - */ -void -GNUNET_TESTING_daemons_vary (struct GNUNET_TESTING_PeerGroup *pg, - unsigned int offset, int desired_status, - struct GNUNET_TIME_Relative timeout, - GNUNET_TESTING_NotifyCompletion cb, void *cb_cls) -{ - struct ShutdownContext *shutdown_ctx; - struct ChurnRestartContext *startup_ctx; - struct ChurnContext *churn_ctx; - - if (GNUNET_NO == desired_status) - { - if (NULL != pg->peers[offset].daemon) - { - shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext)); - churn_ctx = GNUNET_malloc (sizeof (struct ChurnContext)); - churn_ctx->num_to_start = 0; - churn_ctx->num_to_stop = 1; - churn_ctx->cb = cb; - churn_ctx->cb_cls = cb_cls; - shutdown_ctx->cb_cls = churn_ctx; - GNUNET_TESTING_daemon_stop (pg->peers[offset].daemon, timeout, - &churn_stop_callback, shutdown_ctx, GNUNET_NO, - GNUNET_YES); - } - } - else if (GNUNET_YES == desired_status) - { - if (NULL == pg->peers[offset].daemon) - { - startup_ctx = GNUNET_malloc (sizeof (struct ChurnRestartContext)); - churn_ctx = GNUNET_malloc (sizeof (struct ChurnContext)); - churn_ctx->num_to_start = 1; - churn_ctx->num_to_stop = 0; - churn_ctx->cb = cb; - churn_ctx->cb_cls = cb_cls; - startup_ctx->churn_ctx = churn_ctx; - GNUNET_TESTING_daemon_start_stopped (pg->peers[offset].daemon, timeout, - &churn_start_callback, startup_ctx); - } - } - else - GNUNET_break (0); -} - - -/** - * Callback for shutting down peers in a peer group. - * - * @param cls closure (struct ShutdownContext) - * @param emsg NULL on success - */ -static void -internal_shutdown_callback (void *cls, const char *emsg) -{ - struct PeerShutdownContext *peer_shutdown_ctx = cls; - struct ShutdownContext *shutdown_ctx = peer_shutdown_ctx->shutdown_ctx; - unsigned int off; - int i; - struct OutstandingSSH *ssh_pos; - - shutdown_ctx->outstanding--; - if (peer_shutdown_ctx->daemon->hostname != NULL) - decrement_outstanding_at_host (peer_shutdown_ctx->daemon->hostname, - shutdown_ctx->pg); - - if (emsg == NULL) - { - shutdown_ctx->peers_down++; - } - else - { - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "internal_shutdown_callback", - "Failed to stop a peer: %s\n", emsg); - shutdown_ctx->peers_failed++; - } - - if ((shutdown_ctx->cb != NULL) && - (shutdown_ctx->peers_down + shutdown_ctx->peers_failed == - shutdown_ctx->total_peers)) - { - if (shutdown_ctx->peers_failed > 0) - shutdown_ctx->cb (shutdown_ctx->cb_cls, - "Not all peers successfully shut down!"); - else - shutdown_ctx->cb (shutdown_ctx->cb_cls, NULL); - - for (i = 0; i < shutdown_ctx->pg->total; i++) - { - if (shutdown_ctx->pg->peers[i].startup_task != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (shutdown_ctx->pg->peers[i].startup_task); - } - GNUNET_free (shutdown_ctx->pg->peers); - GNUNET_free_non_null (shutdown_ctx->pg->hostkey_data); - for (off = 0; off < shutdown_ctx->pg->num_hosts; off++) - { - GNUNET_free (shutdown_ctx->pg->hosts[off].hostname); - GNUNET_free_non_null (shutdown_ctx->pg->hosts[off].username); - } - GNUNET_free_non_null (shutdown_ctx->pg->hosts); - while (NULL != (ssh_pos = shutdown_ctx->pg->ssh_head)) - { - GNUNET_CONTAINER_DLL_remove (shutdown_ctx->pg->ssh_head, - shutdown_ctx->pg->ssh_tail, ssh_pos); - GNUNET_free (ssh_pos); - } - GNUNET_free (shutdown_ctx->pg); - GNUNET_free (shutdown_ctx); - } - GNUNET_free (peer_shutdown_ctx); -} - - -/** - * Task to rate limit the number of outstanding peer shutdown - * requests. This is necessary for making sure we don't do - * too many ssh connections at once, but is generally nicer - * to any system as well (graduated task starts, as opposed - * to calling gnunet-arm N times all at once). - */ -static void -schedule_shutdown_task (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct PeerShutdownContext *peer_shutdown_ctx = cls; - struct ShutdownContext *shutdown_ctx; - struct GNUNET_TESTING_Daemon *d; - - GNUNET_assert (peer_shutdown_ctx != NULL); - d = peer_shutdown_ctx->daemon; - shutdown_ctx = peer_shutdown_ctx->shutdown_ctx; - GNUNET_assert (shutdown_ctx != NULL); - - if ((shutdown_ctx->outstanding < shutdown_ctx->pg->max_concurrent_ssh) || - ((d->hostname != NULL) && - (count_outstanding_at_host - (d->hostname, - shutdown_ctx->pg) < shutdown_ctx->pg->max_concurrent_ssh))) - { - if (d->hostname != NULL) - increment_outstanding_at_host (d->hostname, - shutdown_ctx->pg); - shutdown_ctx->outstanding++; - GNUNET_TESTING_daemon_stop (d, - shutdown_ctx->timeout, - &internal_shutdown_callback, peer_shutdown_ctx, - shutdown_ctx->delete_files, GNUNET_NO); - } - else - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, 100), - &schedule_shutdown_task, peer_shutdown_ctx); - -} - -/** - * Read a testing hosts file based on a configuration. - * Returns a DLL of hosts (caller must free!) on success - * or NULL on failure. - * - * @param cfg a configuration with a testing section - * - * @return DLL of hosts on success, NULL on failure - */ -struct GNUNET_TESTING_Host * -GNUNET_TESTING_hosts_load (const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_TESTING_Host *hosts; - struct GNUNET_TESTING_Host *temphost; - char *data; - char *buf; - char *hostfile; - struct stat frstat; - int count; - int ret; - - /* Check for a hostfile containing user@host:port triples */ - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "hostfile", - &hostfile)) - return NULL; - - hosts = NULL; - temphost = NULL; - data = NULL; - if (hostfile != NULL) - { - if (GNUNET_OK != GNUNET_DISK_file_test (hostfile)) - GNUNET_DISK_fn_write (hostfile, NULL, 0, - GNUNET_DISK_PERM_USER_READ | - GNUNET_DISK_PERM_USER_WRITE); - if ((0 != STAT (hostfile, &frstat)) || (frstat.st_size == 0)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not open file specified for host list, ending test!"); - GNUNET_free (hostfile); - return NULL; - } - - data = GNUNET_malloc_large (frstat.st_size); - GNUNET_assert (data != NULL); - if (frstat.st_size != GNUNET_DISK_fn_read (hostfile, data, frstat.st_size)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not read file %s specified for host list, ending test!", - hostfile); - GNUNET_free (hostfile); - GNUNET_free (data); - return NULL; - } - - GNUNET_free_non_null (hostfile); - - buf = data; - count = 0; - while (count < frstat.st_size - 1) - { - count++; - if (((data[count] == '\n')) && (buf != &data[count])) - { - data[count] = '\0'; - temphost = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Host)); - ret = - SSCANF (buf, "%a[a-zA-Z0-9_]@%a[a-zA-Z0-9.]:%hd", - &temphost->username, &temphost->hostname, &temphost->port); - if (3 == ret) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Successfully read host %s, port %d and user %s from file\n", - temphost->hostname, temphost->port, temphost->username); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Error reading line `%s' in hostfile\n", buf); - GNUNET_free (temphost); - buf = &data[count + 1]; - continue; - } - temphost->next = hosts; - hosts = temphost; - buf = &data[count + 1]; - } - else if ((data[count] == '\n') || (data[count] == '\0')) - buf = &data[count + 1]; - } - } - GNUNET_free_non_null (data); - - return hosts; -} - -/** - * Shutdown all peers started in the given group. - * - * @param pg handle to the peer group - * @param timeout how long to wait for shutdown - * @param cb callback to notify upon success or failure - * @param cb_cls closure for cb - */ -void -GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg, - struct GNUNET_TIME_Relative timeout, - GNUNET_TESTING_NotifyCompletion cb, void *cb_cls) -{ - unsigned int off; - struct ShutdownContext *shutdown_ctx; - struct PeerShutdownContext *peer_shutdown_ctx; - -#if OLD - struct PeerConnection *conn_iter; - struct PeerConnection *temp_conn; -#endif - struct ConnectContext *cc; - - GNUNET_assert (pg->total > 0); - while (NULL != (cc = pg->cc_head)) - { - GNUNET_CONTAINER_DLL_remove (pg->cc_head, pg->cc_tail, cc); - if (GNUNET_SCHEDULER_NO_TASK != cc->task) - GNUNET_SCHEDULER_cancel (cc->task); - if (NULL != cc->cc) - GNUNET_TESTING_daemons_connect_cancel (cc->cc); - GNUNET_free (cc); - } - - shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext)); - shutdown_ctx->delete_files = - GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING", "DELETE_FILES"); - shutdown_ctx->cb = cb; - shutdown_ctx->cb_cls = cb_cls; - shutdown_ctx->total_peers = pg->total; - shutdown_ctx->timeout = timeout; - shutdown_ctx->pg = pg; - - for (off = 0; off < pg->total; off++) - { - GNUNET_assert (NULL != pg->peers[off].daemon); - peer_shutdown_ctx = GNUNET_malloc (sizeof (struct PeerShutdownContext)); - peer_shutdown_ctx->daemon = pg->peers[off].daemon; - peer_shutdown_ctx->shutdown_ctx = shutdown_ctx; - GNUNET_SCHEDULER_add_now (&schedule_shutdown_task, peer_shutdown_ctx); - - if (NULL != pg->peers[off].cfg) - { - GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg); - pg->peers[off].cfg = NULL; - } -#if OLD -// FIXME Do DLL remove for all pg->peers[off].LIST - conn_iter = pg->peers[off].allowed_peers_head; - while (conn_iter != NULL) - { - temp_conn = conn_iter->next; - GNUNET_free (conn_iter); - conn_iter = temp_conn; - } - pg->peers[off].allowed_peers_head = NULL; - - conn_iter = pg->peers[off].connect_peers_head; - while (conn_iter != NULL) - { - temp_conn = conn_iter->next; - GNUNET_free (conn_iter); - conn_iter = temp_conn; - } - pg->peers[off].connect_peers_head = NULL; - - conn_iter = pg->peers[off].blacklisted_peers_head; - while (conn_iter != NULL) - { - temp_conn = conn_iter->next; - GNUNET_free (conn_iter); - conn_iter = temp_conn; - } - pg->peers[off].blacklisted_peers_head = NULL; - - conn_iter = pg->peers[off].connect_peers_working_set_head; - while (conn_iter != NULL) - { - temp_conn = conn_iter->next; - GNUNET_free (conn_iter); - conn_iter = temp_conn; - } - pg->peers[off].connect_peers_working_set_head = NULL; -#else - if (pg->peers[off].allowed_peers != NULL) - GNUNET_CONTAINER_multihashmap_destroy (pg->peers[off].allowed_peers); - if (pg->peers[off].connect_peers != NULL) - GNUNET_CONTAINER_multihashmap_destroy (pg->peers[off].connect_peers); - if (pg->peers[off].blacklisted_peers != NULL) - GNUNET_CONTAINER_multihashmap_destroy (pg->peers[off].blacklisted_peers); -#endif - } -} - -/* end of testing_group.c */ diff --git a/src/testing/testing_peergroup.c b/src/testing/testing_peergroup.c deleted file mode 100644 index 87504ed6d..000000000 --- a/src/testing/testing_peergroup.c +++ /dev/null @@ -1,1017 +0,0 @@ -/* - This file is part of GNUnet - (C) 2008-2011 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 testing/testing_peergroup.c - * @brief API implementation for easy peer group creation - * @author Nathan Evans - * @author Christian Grothoff - * - */ -#include "platform.h" -#include "gnunet_constants.h" -#include "gnunet_arm_service.h" -#include "gnunet_testing_lib.h" -#include "gnunet_core_service.h" -#include "gnunet_disk_lib.h" - -/** Globals **/ -#define DEFAULT_CONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) - -#define DEFAULT_CONNECT_ATTEMPTS 2 - -/** Struct definitions **/ - -struct PeerGroupStartupContext -{ - struct GNUNET_TESTING_PeerGroup *pg; - const struct GNUNET_CONFIGURATION_Handle *cfg; - unsigned int total; - unsigned int peers_left; - unsigned long long max_concurrent_connections; - - /** - * Maximum attemps to connect two daemons. - */ - unsigned long long connect_attempts; - - /** - * How long to spend trying to establish all the connections? - */ - struct GNUNET_TIME_Relative connect_timeout; - - unsigned long long max_concurrent_ssh; - struct GNUNET_TIME_Absolute timeout; - GNUNET_TESTING_NotifyConnection connect_cb; - GNUNET_TESTING_NotifyCompletion peergroup_cb; - - /** - * Closure for all peergroup callbacks. - */ - void *cls; - - const struct GNUNET_TESTING_Host *hostnames; - - /** - * FIXME document - */ - enum GNUNET_TESTING_Topology topology; - - float topology_percentage; - - float topology_probability; - - /** - * FIXME document - */ - enum GNUNET_TESTING_Topology restrict_topology; - - /** - * FIXME document - */ - char *restrict_transports; - - /** - * Initial connections - */ - enum GNUNET_TESTING_Topology connect_topology; - enum GNUNET_TESTING_TopologyOption connect_topology_option; - double connect_topology_option_modifier; - int verbose; - - struct ProgressMeter *hostkey_meter; - struct ProgressMeter *peer_start_meter; - struct ProgressMeter *connect_meter; - - /** - * Task used to kill the peergroup. - */ - GNUNET_SCHEDULER_TaskIdentifier die_task; - - char *fail_reason; - - /** - * Variable used to store the number of connections we should wait for. - */ - unsigned int expected_connections; - - /** - * Time when the connecting peers was started. - */ - struct GNUNET_TIME_Absolute connect_start_time; - - /** - * The total number of connections that have been created so far. - */ - unsigned int total_connections; - - /** - * The total number of connections that have failed so far. - */ - unsigned int failed_connections; - - /** - * File handle to write out topology in dot format. - */ - struct GNUNET_DISK_FileHandle *topology_output_file; -}; - -struct TopologyOutputContext -{ - struct GNUNET_DISK_FileHandle *file; - GNUNET_TESTING_NotifyCompletion notify_cb; - void *notify_cb_cls; -}; - -/** - * Simple struct to keep track of progress, and print a - * percentage meter for long running tasks. - */ -struct ProgressMeter -{ - /** - * Total number of tasks to complete. - */ - unsigned int total; - - /** - * Print percentage done after modnum tasks. - */ - unsigned int modnum; - - /** - * Print a . each dotnum tasks. - */ - unsigned int dotnum; - - /** - * Total number completed thus far. - */ - unsigned int completed; - - /** - * Whether or not to print. - */ - int print; - - /** - * Startup string for progress meter. - */ - char *startup_string; -}; - - -/** Utility functions **/ - -/** - * Create a meter to keep track of the progress of some task. - * - * @param total the total number of items to complete - * @param start_string a string to prefix the meter with (if printing) - * @param print GNUNET_YES to print the meter, GNUNET_NO to count - * internally only - * - * @return the progress meter - */ -static struct ProgressMeter * -create_meter (unsigned int total, char *start_string, int print) -{ - struct ProgressMeter *ret; - - ret = GNUNET_malloc (sizeof (struct ProgressMeter)); - ret->print = print; - ret->total = total; - ret->modnum = (total / 4 == 0) ? 1 : (total / 4); - ret->dotnum = (total / 50) + 1; - if (start_string != NULL) - ret->startup_string = GNUNET_strdup (start_string); - else - ret->startup_string = GNUNET_strdup (""); - - return ret; -} - -/** - * Update progress meter (increment by one). - * - * @param meter the meter to update and print info for - * - * @return GNUNET_YES if called the total requested, - * GNUNET_NO if more items expected - */ -static int -update_meter (struct ProgressMeter *meter) -{ - if (meter->print == GNUNET_YES) - { - if (meter->completed % meter->modnum == 0) - { - if (meter->completed == 0) - { - FPRINTF (stdout, "%sProgress: [0%%", meter->startup_string); - } - else - FPRINTF (stdout, "%d%%", - (int) (((float) meter->completed / meter->total) * 100)); - } - else if (meter->completed % meter->dotnum == 0) - FPRINTF (stdout, "%s", "."); - - if (meter->completed + 1 == meter->total) - FPRINTF (stdout, "%d%%]\n", 100); - fflush (stdout); - } - meter->completed++; - - if (meter->completed == meter->total) - return GNUNET_YES; - return GNUNET_NO; -} - -/** - * Reset progress meter. - * - * @param meter the meter to reset - * - * @return GNUNET_YES if meter reset, - * GNUNET_SYSERR on error - */ -static int -reset_meter (struct ProgressMeter *meter) -{ - if (meter == NULL) - return GNUNET_SYSERR; - - meter->completed = 0; - return GNUNET_YES; -} - -/** - * Release resources for meter - * - * @param meter the meter to free - */ -static void -free_meter (struct ProgressMeter *meter) -{ - GNUNET_free_non_null (meter->startup_string); - GNUNET_free (meter); -} - - -/** Functions for creating, starting and connecting the peergroup **/ - -/** - * Check whether peers successfully shut down. - */ -static void -internal_shutdown_callback (void *cls, const char *emsg) -{ - struct PeerGroupStartupContext *pg_start_ctx = cls; - - if (emsg != NULL) - pg_start_ctx->peergroup_cb (pg_start_ctx->cls, emsg); - else - pg_start_ctx->peergroup_cb (pg_start_ctx->cls, pg_start_ctx->fail_reason); -} - -/** - * Check if the get_handle is being used, if so stop the request. Either - * way, schedule the end_badly_cont function which actually shuts down the - * test. - */ -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct PeerGroupStartupContext *pg_start_ctx = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failing peer group startup with error: `%s'!\n", - pg_start_ctx->fail_reason); - - GNUNET_TESTING_daemons_stop (pg_start_ctx->pg, - GNUNET_TIME_absolute_get_remaining - (pg_start_ctx->timeout), - &internal_shutdown_callback, pg_start_ctx); - - if (pg_start_ctx->hostkey_meter != NULL) - { - free_meter (pg_start_ctx->hostkey_meter); - pg_start_ctx->hostkey_meter = NULL; - } - if (pg_start_ctx->peer_start_meter != NULL) - { - free_meter (pg_start_ctx->peer_start_meter); - pg_start_ctx->peer_start_meter = NULL; - } - if (pg_start_ctx->connect_meter != NULL) - { - free_meter (pg_start_ctx->connect_meter); - pg_start_ctx->connect_meter = NULL; - } -} - -/** - * This function is called whenever a connection attempt is finished between two of - * the started peers (started with GNUNET_TESTING_daemons_start). The total - * number of times this function is called should equal the number returned - * from the GNUNET_TESTING_connect_topology call. - * - * The emsg variable is NULL on success (peers connected), and non-NULL on - * failure (peers failed to connect). - */ -static void -internal_topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, - uint32_t distance, - const struct GNUNET_CONFIGURATION_Handle *first_cfg, - const struct GNUNET_CONFIGURATION_Handle - *second_cfg, - struct GNUNET_TESTING_Daemon *first_daemon, - struct GNUNET_TESTING_Daemon *second_daemon, - const char *emsg) -{ - struct PeerGroupStartupContext *pg_start_ctx = cls; - char *temp_str; - char *second_str; - int temp; - -#if TIMING - unsigned long long duration; - unsigned long long total_duration; - unsigned int new_connections; - unsigned int new_failed_connections; - double conns_per_sec_recent; - double conns_per_sec_total; - double failed_conns_per_sec_recent; - double failed_conns_per_sec_total; -#endif - -#if TIMING - if (GNUNET_TIME_absolute_get_difference - (connect_last_time, - GNUNET_TIME_absolute_get ()).rel_value > - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, - CONN_UPDATE_DURATION).rel_value) - { - /* Get number of new connections */ - new_connections = total_connections - previous_connections; - - /* Get number of new FAILED connections */ - new_failed_connections = failed_connections - previous_failed_connections; - - /* Get duration in seconds */ - duration = - GNUNET_TIME_absolute_get_difference (connect_last_time, - GNUNET_TIME_absolute_get - ()).rel_value / 1000; - total_duration = - GNUNET_TIME_absolute_get_difference (connect_start_time, - GNUNET_TIME_absolute_get - ()).rel_value / 1000; - - failed_conns_per_sec_recent = (double) new_failed_connections / duration; - failed_conns_per_sec_total = (double) failed_connections / total_duration; - conns_per_sec_recent = (double) new_connections / duration; - conns_per_sec_total = (double) total_connections / total_duration; - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Recent: %.2f/s, Total: %.2f/s, Recent failed: %.2f/s, total failed %.2f/s\n", - conns_per_sec_recent, CONN_UPDATE_DURATION, conns_per_sec_total, - failed_conns_per_sec_recent, failed_conns_per_sec_total); - connect_last_time = GNUNET_TIME_absolute_get (); - previous_connections = total_connections; - previous_failed_connections = failed_connections; - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "have %u total_connections, %u failed\n", total_connections, - failed_connections); - } -#endif - - - if (emsg == NULL) - { - pg_start_ctx->total_connections++; -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "connected peer %s to peer %s, distance %u\n", - first_daemon->shortname, second_daemon->shortname, distance); -#endif - if (pg_start_ctx->topology_output_file != NULL) - { - second_str = GNUNET_strdup (GNUNET_i2s (second)); - temp = - GNUNET_asprintf (&temp_str, "\t\"%s\" -- \"%s\"\n", - GNUNET_i2s (first), second_str); - GNUNET_free (second_str); - if (temp > 0) - GNUNET_DISK_file_write (pg_start_ctx->topology_output_file, temp_str, - temp); - GNUNET_free (temp_str); - } - } - else - { - pg_start_ctx->failed_connections++; -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to connect peer %s to peer %s with error :\n%s\n", - first_daemon->shortname, second_daemon->shortname, emsg); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Failed to connect peer %s to peer %s with error :\n%s\n", - first_daemon->shortname, second_daemon->shortname, emsg); -#endif - } - - GNUNET_assert (pg_start_ctx->connect_meter != NULL); - if (pg_start_ctx->connect_cb != NULL) - pg_start_ctx->connect_cb (pg_start_ctx->cls, first, second, distance, - first_cfg, second_cfg, first_daemon, - second_daemon, emsg); - if (GNUNET_YES != update_meter (pg_start_ctx->connect_meter)) - { - /* No finished yet */ - return; - } -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Created %d total connections, which is our target number! Starting next phase of testing.\n", - pg_start_ctx->total_connections); -#endif - -#if TIMING - total_duration = - GNUNET_TIME_absolute_get_difference (connect_start_time, - GNUNET_TIME_absolute_get - ()).rel_value / 1000; - failed_conns_per_sec_total = (double) failed_connections / total_duration; - conns_per_sec_total = (double) total_connections / total_duration; - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Overall connection info --- Total: %u, Total Failed %u/s\n", - total_connections, failed_connections); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Overall connection info --- Total: %.2f/s, Total Failed %.2f/s\n", - conns_per_sec_total, failed_conns_per_sec_total); -#endif - - GNUNET_assert (pg_start_ctx->die_task != GNUNET_SCHEDULER_NO_TASK); - GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task); - - /* Call final callback, signifying that the peer group has been started and connected */ - if (pg_start_ctx->peergroup_cb != NULL) - pg_start_ctx->peergroup_cb (pg_start_ctx->cls, NULL); - - if (pg_start_ctx->topology_output_file != NULL) - { - temp = GNUNET_asprintf (&temp_str, "}\n"); - if (temp > 0) - GNUNET_DISK_file_write (pg_start_ctx->topology_output_file, temp_str, - temp); - GNUNET_free (temp_str); - GNUNET_DISK_file_close (pg_start_ctx->topology_output_file); - } - GNUNET_free_non_null (pg_start_ctx->fail_reason); - if (NULL != pg_start_ctx->hostkey_meter) - free_meter(pg_start_ctx->hostkey_meter); - if (NULL != pg_start_ctx->peer_start_meter) - free_meter(pg_start_ctx->peer_start_meter); - if (NULL != pg_start_ctx->connect_meter) - free_meter(pg_start_ctx->connect_meter); - GNUNET_free (pg_start_ctx); -} - - -/** - * Callback called for each started daemon. - * - * @param cls Clause (PG Context). - * @param id PeerIdentidy of started daemon. - * @param cfg Configuration used by the daemon. - * @param d Handle for the daemon. - * @param emsg Error message, NULL on success. - */ -static void -internal_peers_started_callback (void *cls, - const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, - const char *emsg) -{ - struct PeerGroupStartupContext *pg_start_ctx = cls; - - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Failed to start daemon with error: `%s'\n", emsg); - return; - } - GNUNET_assert (id != NULL); - -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n", - (pg_start_ctx->total - pg_start_ctx->peers_left) + 1, - pg_start_ctx->total); -#endif - - pg_start_ctx->peers_left--; - - if (NULL == pg_start_ctx->peer_start_meter) - { - /* Cancelled Ctrl-C or error */ - return; - } - if (GNUNET_YES == update_meter (pg_start_ctx->peer_start_meter)) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "All %d daemons started, now connecting peers!\n", - pg_start_ctx->total); -#endif - GNUNET_assert (pg_start_ctx->die_task != GNUNET_SCHEDULER_NO_TASK); - GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task); - - pg_start_ctx->expected_connections = UINT_MAX; - // FIXME: why whould peers_left be != 0?? Or pg NULL? - if ((pg_start_ctx->pg != NULL) && (pg_start_ctx->peers_left == 0)) - { - pg_start_ctx->connect_start_time = GNUNET_TIME_absolute_get (); - pg_start_ctx->expected_connections = - GNUNET_TESTING_connect_topology (pg_start_ctx->pg, - pg_start_ctx->connect_topology, - pg_start_ctx->connect_topology_option, - pg_start_ctx->connect_topology_option_modifier, - pg_start_ctx->connect_timeout, - pg_start_ctx->connect_attempts, NULL, - NULL); - - pg_start_ctx->connect_meter = - create_meter (pg_start_ctx->expected_connections, "Peer connection ", - pg_start_ctx->verbose); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n", - pg_start_ctx->expected_connections); - } - - if (pg_start_ctx->expected_connections == 0) - { - GNUNET_free_non_null (pg_start_ctx->fail_reason); - pg_start_ctx->fail_reason = - GNUNET_strdup ("from connect topology (bad return)"); - pg_start_ctx->die_task = - GNUNET_SCHEDULER_add_now (&end_badly, pg_start_ctx); - return; - } - - GNUNET_free_non_null (pg_start_ctx->fail_reason); - pg_start_ctx->fail_reason = - GNUNET_strdup ("from connect topology (timeout)"); - pg_start_ctx->die_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining - (pg_start_ctx->timeout), &end_badly, - pg_start_ctx); - } -} - -/** - * Callback indicating that the hostkey was created for a peer. - * - * @param cls NULL - * @param id the peer identity - * @param d the daemon handle (pretty useless at this point, remove?) - * @param emsg non-null on failure - */ -static void -internal_hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - struct PeerGroupStartupContext *pg_start_ctx = cls; - unsigned int create_expected_connections; - - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Hostkey callback received error: %s\n", emsg); - } - -#if VERBOSE > 1 - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Hostkey (%d/%d) created for peer `%s'\n", - pg_start_ctx->total - pg_start_ctx->peers_left + 1, - pg_start_ctx->total, GNUNET_i2s (id)); -#endif - - pg_start_ctx->peers_left--; - if (GNUNET_YES == update_meter (pg_start_ctx->hostkey_meter)) - { - GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task); - GNUNET_free_non_null (pg_start_ctx->fail_reason); - /* Set up task in case topology creation doesn't finish - * within a reasonable amount of time */ - pg_start_ctx->fail_reason = GNUNET_strdup ("from create_topology"); - pg_start_ctx->die_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining - (pg_start_ctx->timeout), &end_badly, - pg_start_ctx); - pg_start_ctx->peers_left = pg_start_ctx->total; /* Reset counter */ - create_expected_connections = - GNUNET_TESTING_create_topology (pg_start_ctx->pg, - pg_start_ctx->topology, - pg_start_ctx->restrict_topology, - pg_start_ctx->restrict_transports); - if (create_expected_connections > 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Topology set up, have %u expected connections, now starting peers!\n", - create_expected_connections); - GNUNET_TESTING_daemons_continue_startup (pg_start_ctx->pg); - } - else - { - GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task); - GNUNET_free_non_null (pg_start_ctx->fail_reason); - pg_start_ctx->fail_reason = - GNUNET_strdup ("from create topology (bad return)"); - pg_start_ctx->die_task = - GNUNET_SCHEDULER_add_now (&end_badly, pg_start_ctx); - return; - } - - GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task); - GNUNET_free_non_null (pg_start_ctx->fail_reason); - pg_start_ctx->fail_reason = - GNUNET_strdup ("from continue startup (timeout)"); - pg_start_ctx->die_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining - (pg_start_ctx->timeout), &end_badly, - pg_start_ctx); - } -} - - -/** - * Prototype of a callback function indicating that two peers - * are currently connected. - * - * @param cls closure - * @param first peer id for first daemon - * @param second peer id for the second daemon - * @param emsg error message (NULL on success) - */ -void -write_topology_cb (void *cls, const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, const char *emsg) -{ - struct TopologyOutputContext *topo_ctx; - int temp; - char *temp_str; - char *temp_pid2; - - topo_ctx = (struct TopologyOutputContext *) cls; - GNUNET_assert (topo_ctx->file != NULL); - if ((emsg == NULL) && (first != NULL) && (second != NULL)) - { - GNUNET_assert (first != NULL); - GNUNET_assert (second != NULL); - temp_pid2 = GNUNET_strdup (GNUNET_i2s (second)); - temp = - GNUNET_asprintf (&temp_str, "\t\"%s\" -- \"%s\"\n", GNUNET_i2s (first), - temp_pid2); - GNUNET_free (temp_pid2); - GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp); - } - else if ((emsg == NULL) && (first == NULL) && (second == NULL)) - { - temp = GNUNET_asprintf (&temp_str, "}\n"); - GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp); - GNUNET_DISK_file_close (topo_ctx->file); - topo_ctx->notify_cb (topo_ctx->notify_cb_cls, NULL); - GNUNET_free (topo_ctx); - } - else - { - temp = GNUNET_asprintf (&temp_str, "}\n"); - GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp); - GNUNET_DISK_file_close (topo_ctx->file); - topo_ctx->notify_cb (topo_ctx->notify_cb_cls, emsg); - GNUNET_free (topo_ctx); - } -} - -/** - * Print current topology to a graphviz readable file. - * - * @param pg a currently running peergroup to print to file - * @param output_filename the file to write the topology to - * @param notify_cb callback to call upon completion or failure - * @param notify_cb_cls closure for notify_cb - * - */ -void -GNUNET_TESTING_peergroup_topology_to_file (struct GNUNET_TESTING_PeerGroup *pg, - const char *output_filename, - GNUNET_TESTING_NotifyCompletion - notify_cb, void *notify_cb_cls) -{ - struct TopologyOutputContext *topo_ctx; - int temp; - char *temp_str; - - topo_ctx = GNUNET_malloc (sizeof (struct TopologyOutputContext)); - - topo_ctx->notify_cb = notify_cb; - topo_ctx->notify_cb_cls = notify_cb_cls; - topo_ctx->file = - GNUNET_DISK_file_open (output_filename, - GNUNET_DISK_OPEN_READWRITE | - GNUNET_DISK_OPEN_CREATE, - GNUNET_DISK_PERM_USER_READ | - GNUNET_DISK_PERM_USER_WRITE); - if (topo_ctx->file == NULL) - { - notify_cb (notify_cb_cls, "Failed to open output file!"); - GNUNET_free (topo_ctx); - return; - } - - temp = GNUNET_asprintf (&temp_str, "strict graph G {\n"); - if (temp > 0) - GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp); - GNUNET_free_non_null (temp_str); - GNUNET_TESTING_get_topology (pg, &write_topology_cb, topo_ctx); -} - -/** - * Start a peer group with a given number of peers. Notify - * on completion of peer startup and connection based on given - * topological constraints. Optionally notify on each - * established connection. - * - * @param cfg configuration template to use - * @param total number of daemons to start - * @param timeout total time allowed for peers to start - * @param connect_cb function to call each time two daemons are connected - * @param peergroup_cb function to call once all peers are up and connected - * @param peergroup_cls closure for peergroup callbacks - * @param hostnames linked list of host structs to use to start peers on - * (NULL to run on localhost only) - * - * @return NULL on error, otherwise handle to control peer group - */ -struct GNUNET_TESTING_PeerGroup * -GNUNET_TESTING_peergroup_start (const struct GNUNET_CONFIGURATION_Handle *cfg, - unsigned int total, - struct GNUNET_TIME_Relative timeout, - GNUNET_TESTING_NotifyConnection connect_cb, - GNUNET_TESTING_NotifyCompletion peergroup_cb, - void *peergroup_cls, - const struct GNUNET_TESTING_Host *hostnames) -{ - struct PeerGroupStartupContext *pg_start_ctx; - char *temp_str; - int temp; - struct GNUNET_TIME_Relative rtimeout; - - GNUNET_assert (total > 0); - GNUNET_assert (cfg != NULL); - - pg_start_ctx = GNUNET_malloc (sizeof (struct PeerGroupStartupContext)); - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts", - &pg_start_ctx->connect_attempts)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "connect_attempts"); - GNUNET_free (pg_start_ctx); - return NULL; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "CONNECT_TIMEOUT", - &pg_start_ctx->connect_timeout)) - { - pg_start_ctx->connect_timeout = DEFAULT_CONNECT_TIMEOUT; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", - "max_outstanding_connections", - &pg_start_ctx->max_concurrent_connections)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "max_outstanding_connections"); - GNUNET_free (pg_start_ctx); - return NULL; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", - "max_concurrent_ssh", - &pg_start_ctx->max_concurrent_ssh)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "max_concurrent_ssh"); - GNUNET_free (pg_start_ctx); - return NULL; - } - - if (GNUNET_SYSERR == - (pg_start_ctx->verbose = - GNUNET_CONFIGURATION_get_value_yesno (cfg, "testing", - "use_progressbars"))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "use_progressbars"); - GNUNET_free (pg_start_ctx); - return NULL; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "PEERGROUP_TIMEOUT", - &rtimeout)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", - "testing", "PEERGROUP_TIMEOUT"); - GNUNET_free (pg_start_ctx); - return NULL; - } - pg_start_ctx->timeout = GNUNET_TIME_relative_to_absolute (rtimeout); - - - /* Read topology related options from the configuration file */ - temp_str = NULL; - if ((GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "topology", - &temp_str)) && - (GNUNET_NO == - GNUNET_TESTING_topology_get (&pg_start_ctx->topology, temp_str))) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid topology `%s' given for section %s option %s\n", - temp_str, "TESTING", "TOPOLOGY"); - pg_start_ctx->topology = GNUNET_TESTING_TOPOLOGY_CLIQUE; /* Defaults to NONE, so set better default here */ - } - GNUNET_free_non_null (temp_str); - - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "topology_output_file", &temp_str)) - { - pg_start_ctx->topology_output_file = - GNUNET_DISK_file_open (temp_str, - GNUNET_DISK_OPEN_READWRITE | - GNUNET_DISK_OPEN_CREATE, - GNUNET_DISK_PERM_USER_READ | - GNUNET_DISK_PERM_USER_WRITE); - if (pg_start_ctx->topology_output_file != NULL) - { - GNUNET_free (temp_str); - temp = GNUNET_asprintf (&temp_str, "strict graph G {\n"); - if (temp > 0) - GNUNET_DISK_file_write (pg_start_ctx->topology_output_file, temp_str, - temp); - } - GNUNET_free (temp_str); - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "percentage", - &temp_str)) - pg_start_ctx->topology_percentage = 0.5; - else - { - pg_start_ctx->topology_percentage = atof (temp_str); - GNUNET_free (temp_str); - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "probability", - &temp_str)) - pg_start_ctx->topology_probability = 0.5; - else - { - pg_start_ctx->topology_probability = atof (temp_str); - GNUNET_free (temp_str); - } - - if ((GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "connect_topology", &temp_str)) && - (GNUNET_NO == - GNUNET_TESTING_topology_get (&pg_start_ctx->connect_topology, temp_str))) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid connect topology `%s' given for section %s option %s\n", - temp_str, "TESTING", "CONNECT_TOPOLOGY"); - } - GNUNET_free_non_null (temp_str); - - if ((GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "connect_topology_option", - &temp_str)) && - (GNUNET_NO == - GNUNET_TESTING_topology_option_get - (&pg_start_ctx->connect_topology_option, temp_str))) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid connect topology option `%s' given for section %s option %s\n", - temp_str, "TESTING", "CONNECT_TOPOLOGY_OPTION"); - pg_start_ctx->connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Defaults to NONE, set to ALL */ - } - GNUNET_free_non_null (temp_str); - - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "connect_topology_option_modifier", - &temp_str)) - { - if (SSCANF - (temp_str, "%lf", &pg_start_ctx->connect_topology_option_modifier) != 1) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), - temp_str, "connect_topology_option_modifier", "TESTING"); - GNUNET_free (temp_str); - GNUNET_free (pg_start_ctx); - return NULL; - } - GNUNET_free (temp_str); - } - - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "blacklist_transports", - &pg_start_ctx->restrict_transports)) - pg_start_ctx->restrict_transports = NULL; - - pg_start_ctx->restrict_topology = GNUNET_TESTING_TOPOLOGY_NONE; - if ((GNUNET_YES == - GNUNET_CONFIGURATION_get_value_string (cfg, "testing", - "blacklist_topology", &temp_str)) - && (GNUNET_NO == - GNUNET_TESTING_topology_get (&pg_start_ctx->restrict_topology, - temp_str))) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid topology `%s' given for section %s option %s\n", - temp_str, "TESTING", "BLACKLIST_TOPOLOGY"); - } - - GNUNET_free_non_null (temp_str); - - pg_start_ctx->cfg = cfg; - pg_start_ctx->total = total; - pg_start_ctx->peers_left = total; - pg_start_ctx->connect_cb = connect_cb; - pg_start_ctx->peergroup_cb = peergroup_cb; - pg_start_ctx->cls = peergroup_cls; - pg_start_ctx->hostnames = hostnames; - pg_start_ctx->hostkey_meter = - create_meter (pg_start_ctx->peers_left, "Hostkeys created ", - pg_start_ctx->verbose); - pg_start_ctx->peer_start_meter = - create_meter (pg_start_ctx->peers_left, "Peers started ", - pg_start_ctx->verbose); - /* Make compilers happy */ - reset_meter (pg_start_ctx->peer_start_meter); - pg_start_ctx->fail_reason = - GNUNET_strdup - ("didn't generate all hostkeys within allowed startup time!"); - pg_start_ctx->die_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining - (pg_start_ctx->timeout), &end_badly, - pg_start_ctx); - - pg_start_ctx->pg = - GNUNET_TESTING_daemons_start (pg_start_ctx->cfg, pg_start_ctx->peers_left, - pg_start_ctx->max_concurrent_connections, - pg_start_ctx->max_concurrent_ssh, - GNUNET_TIME_absolute_get_remaining - (pg_start_ctx->timeout), - &internal_hostkey_callback, pg_start_ctx, - &internal_peers_started_callback, - pg_start_ctx, &internal_topology_callback, - pg_start_ctx, pg_start_ctx->hostnames); - - return pg_start_ctx->pg; -} - -/* end of testing_peergroup.c */ -- cgit v1.2.3