diff options
author | Bart Polot <bart@net.in.tum.de> | 2012-12-20 14:01:15 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2012-12-20 14:01:15 +0000 |
commit | 12f8c88861a06e58df7f33a807dc27403bf88dfb (patch) | |
tree | 088f7e395979b6b80ae62bcff202b730e62d3863 | |
parent | da2650da002c5cdb38b9fca08b8ef0984629694a (diff) | |
download | gnunet-12f8c88861a06e58df7f33a807dc27403bf88dfb.tar.gz gnunet-12f8c88861a06e58df7f33a807dc27403bf88dfb.zip |
Remove testing_old
43 files changed, 1 insertions, 16025 deletions
diff --git a/configure.ac b/configure.ac index 86b070e96..369941f02 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -1282,7 +1282,6 @@ src/template/Makefile | |||
1282 | src/testbed/Makefile | 1282 | src/testbed/Makefile |
1283 | src/testbed/testbed.conf | 1283 | src/testbed/testbed.conf |
1284 | src/testing/Makefile | 1284 | src/testing/Makefile |
1285 | src/testing_old/Makefile | ||
1286 | src/topology/Makefile | 1285 | src/topology/Makefile |
1287 | src/transport/Makefile | 1286 | src/transport/Makefile |
1288 | src/transport/transport.conf | 1287 | src/transport/transport.conf |
diff --git a/po/POTFILES.in b/po/POTFILES.in index 462f96d25..da8e2e90c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in | |||
@@ -18,6 +18,7 @@ src/block/plugin_block_template.c | |||
18 | src/block/plugin_block_test.c | 18 | src/block/plugin_block_test.c |
19 | src/consensus/consensus_api.c | 19 | src/consensus/consensus_api.c |
20 | src/consensus/gnunet-consensus.c | 20 | src/consensus/gnunet-consensus.c |
21 | src/consensus/gnunet-consensus-ibf.c | ||
21 | src/consensus/gnunet-consensus-start-peers.c | 22 | src/consensus/gnunet-consensus-start-peers.c |
22 | src/consensus/gnunet-service-consensus.c | 23 | src/consensus/gnunet-service-consensus.c |
23 | src/consensus/ibf.c | 24 | src/consensus/ibf.c |
diff --git a/src/Makefile.am b/src/Makefile.am index 4440f63ec..f10630d63 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
@@ -47,7 +47,6 @@ SUBDIRS = \ | |||
47 | peerinfo-tool \ | 47 | peerinfo-tool \ |
48 | core \ | 48 | core \ |
49 | testbed \ | 49 | testbed \ |
50 | testing_old \ | ||
51 | nse \ | 50 | nse \ |
52 | dht \ | 51 | dht \ |
53 | hostlist \ | 52 | hostlist \ |
diff --git a/src/testing_old/Makefile.am b/src/testing_old/Makefile.am deleted file mode 100644 index 2e5eb4bf7..000000000 --- a/src/testing_old/Makefile.am +++ /dev/null | |||
@@ -1,270 +0,0 @@ | |||
1 | INCLUDES = -I$(top_srcdir)/src/include | ||
2 | |||
3 | if MINGW | ||
4 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
5 | endif | ||
6 | |||
7 | if USE_COVERAGE | ||
8 | AM_CFLAGS = --coverage -O0 | ||
9 | XLIB = -lgcov | ||
10 | endif | ||
11 | |||
12 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
13 | |||
14 | dist_pkgcfg_DATA = \ | ||
15 | testing_old.conf | ||
16 | |||
17 | if HAVE_EXPENSIVE_TESTS | ||
18 | EXPENSIVE_TESTS = \ | ||
19 | test_testing_topology_stability \ | ||
20 | test_testing_topology_clique_random \ | ||
21 | test_testing_topology_clique_minimum \ | ||
22 | test_testing_topology_clique_dfs \ | ||
23 | test_testing_topology_churn \ | ||
24 | test_testing_topology_line \ | ||
25 | test_testing_topology_blacklist \ | ||
26 | test_testing_group_remote \ | ||
27 | test_testing_topology_ring \ | ||
28 | test_testing_topology_2d_torus \ | ||
29 | test_testing_topology_small_world_ring \ | ||
30 | test_testing_topology_small_world_torus \ | ||
31 | test_testing_topology_erdos_renyi \ | ||
32 | test_testing_topology_internat \ | ||
33 | test_testing_topology_scale_free | ||
34 | endif | ||
35 | |||
36 | lib_LTLIBRARIES = \ | ||
37 | libgnunettesting_old.la | ||
38 | |||
39 | libgnunettesting_old_la_SOURCES = \ | ||
40 | helper.c \ | ||
41 | testing.c \ | ||
42 | testing_group.c \ | ||
43 | testing_peergroup.c | ||
44 | libgnunettesting_old_la_LIBADD = $(XLIB) \ | ||
45 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
46 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
47 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
48 | $(top_builddir)/src/hello/libgnunethello.la \ | ||
49 | -lm \ | ||
50 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
51 | $(LTLIBINTL) | ||
52 | libgnunettesting_old_la_LDFLAGS = \ | ||
53 | $(GN_LIB_LDFLAGS) \ | ||
54 | -version-info 0:1:0 | ||
55 | |||
56 | |||
57 | check_PROGRAMS = \ | ||
58 | test_testing \ | ||
59 | test_testing_connect \ | ||
60 | test_testing_reconnect \ | ||
61 | test_testing_group \ | ||
62 | test_testing_peergroup \ | ||
63 | test_testing_topology_stability \ | ||
64 | test_testing_topology_clique \ | ||
65 | test_testing_topology_clique_random \ | ||
66 | test_testing_topology_clique_minimum \ | ||
67 | test_testing_topology_clique_dfs \ | ||
68 | test_testing_topology_churn \ | ||
69 | test_testing_topology_line \ | ||
70 | test_testing_topology_blacklist \ | ||
71 | test_testing_group_remote \ | ||
72 | test_testing_2dtorus \ | ||
73 | test_testing_topology_ring \ | ||
74 | test_testing_topology_2d_torus \ | ||
75 | test_testing_topology_small_world_ring \ | ||
76 | test_testing_topology_small_world_torus \ | ||
77 | test_testing_topology_erdos_renyi \ | ||
78 | test_testing_topology_internat \ | ||
79 | test_testing_topology_none \ | ||
80 | test_testing_topology_scale_free | ||
81 | |||
82 | if ENABLE_TEST_RUN | ||
83 | # Don't bother to test old-testing at this point | ||
84 | #TESTS = \ | ||
85 | # test_testing \ | ||
86 | # test_testing_connect \ | ||
87 | # test_testing_reconnect \ | ||
88 | # test_testing_group \ | ||
89 | # test_testing_peergroup | ||
90 | endif | ||
91 | |||
92 | |||
93 | |||
94 | test_testing_SOURCES = \ | ||
95 | test_testing.c | ||
96 | test_testing_LDADD = \ | ||
97 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
98 | $(top_builddir)/src/util/libgnunetutil.la | ||
99 | |||
100 | test_testing_connect_SOURCES = \ | ||
101 | test_testing_connect.c | ||
102 | test_testing_connect_LDADD = \ | ||
103 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
104 | $(top_builddir)/src/util/libgnunetutil.la | ||
105 | |||
106 | test_testing_reconnect_SOURCES = \ | ||
107 | test_testing_reconnect.c | ||
108 | test_testing_reconnect_LDADD = \ | ||
109 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
110 | $(top_builddir)/src/util/libgnunetutil.la | ||
111 | |||
112 | test_testing_group_SOURCES = \ | ||
113 | test_testing_group.c | ||
114 | test_testing_group_LDADD = \ | ||
115 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
116 | $(top_builddir)/src/util/libgnunetutil.la | ||
117 | |||
118 | test_testing_peergroup_SOURCES = \ | ||
119 | test_testing_peergroup.c | ||
120 | test_testing_peergroup_LDADD = \ | ||
121 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
122 | $(top_builddir)/src/util/libgnunetutil.la | ||
123 | |||
124 | test_testing_topology_clique_SOURCES = \ | ||
125 | test_testing_topology.c | ||
126 | test_testing_topology_clique_LDADD = \ | ||
127 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
128 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
129 | $(top_builddir)/src/util/libgnunetutil.la | ||
130 | |||
131 | test_testing_topology_stability_SOURCES = \ | ||
132 | test_testing_topology.c | ||
133 | test_testing_topology_stability_LDADD = \ | ||
134 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
135 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
136 | $(top_builddir)/src/util/libgnunetutil.la | ||
137 | |||
138 | test_testing_topology_blacklist_SOURCES = \ | ||
139 | test_testing_topology_blacklist.c | ||
140 | test_testing_topology_blacklist_LDADD = \ | ||
141 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
142 | $(top_builddir)/src/util/libgnunetutil.la | ||
143 | |||
144 | test_testing_topology_churn_SOURCES = \ | ||
145 | test_testing_topology_churn.c | ||
146 | test_testing_topology_churn_LDADD = \ | ||
147 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
148 | $(top_builddir)/src/util/libgnunetutil.la | ||
149 | |||
150 | test_testing_topology_clique_random_SOURCES = \ | ||
151 | test_testing_topology.c | ||
152 | test_testing_topology_clique_random_LDADD = \ | ||
153 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
154 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
155 | $(top_builddir)/src/util/libgnunetutil.la | ||
156 | |||
157 | test_testing_topology_clique_minimum_SOURCES = \ | ||
158 | test_testing_topology.c | ||
159 | test_testing_topology_clique_minimum_LDADD = \ | ||
160 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
161 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
162 | $(top_builddir)/src/util/libgnunetutil.la | ||
163 | |||
164 | test_testing_topology_clique_dfs_SOURCES = \ | ||
165 | test_testing_topology.c | ||
166 | test_testing_topology_clique_dfs_LDADD = \ | ||
167 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
168 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
169 | $(top_builddir)/src/util/libgnunetutil.la | ||
170 | |||
171 | test_testing_topology_line_SOURCES = \ | ||
172 | test_testing_topology.c | ||
173 | test_testing_topology_line_LDADD = \ | ||
174 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
175 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
176 | $(top_builddir)/src/util/libgnunetutil.la | ||
177 | |||
178 | |||
179 | test_testing_group_remote_SOURCES = \ | ||
180 | test_testing_group_remote.c | ||
181 | test_testing_group_remote_LDADD = \ | ||
182 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
183 | $(top_builddir)/src/util/libgnunetutil.la | ||
184 | |||
185 | test_testing_2dtorus_SOURCES = \ | ||
186 | test_testing_2dtorus.c | ||
187 | test_testing_2dtorus_LDADD = \ | ||
188 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
189 | $(top_builddir)/src/util/libgnunetutil.la | ||
190 | |||
191 | test_testing_topology_ring_SOURCES = \ | ||
192 | test_testing_topology.c | ||
193 | test_testing_topology_ring_LDADD = \ | ||
194 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
195 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
196 | $(top_builddir)/src/util/libgnunetutil.la | ||
197 | |||
198 | test_testing_topology_2d_torus_SOURCES = \ | ||
199 | test_testing_topology.c | ||
200 | test_testing_topology_2d_torus_LDADD = \ | ||
201 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
202 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
203 | $(top_builddir)/src/util/libgnunetutil.la | ||
204 | |||
205 | test_testing_topology_small_world_ring_SOURCES = \ | ||
206 | test_testing_topology.c | ||
207 | test_testing_topology_small_world_ring_LDADD = \ | ||
208 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
209 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
210 | $(top_builddir)/src/util/libgnunetutil.la | ||
211 | |||
212 | test_testing_topology_small_world_torus_SOURCES = \ | ||
213 | test_testing_topology.c | ||
214 | test_testing_topology_small_world_torus_LDADD = \ | ||
215 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
216 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
217 | $(top_builddir)/src/util/libgnunetutil.la | ||
218 | |||
219 | test_testing_topology_internat_SOURCES = \ | ||
220 | test_testing_topology.c | ||
221 | test_testing_topology_internat_LDADD = \ | ||
222 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
223 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
224 | $(top_builddir)/src/util/libgnunetutil.la | ||
225 | |||
226 | test_testing_topology_erdos_renyi_SOURCES = \ | ||
227 | test_testing_topology.c | ||
228 | test_testing_topology_erdos_renyi_LDADD = \ | ||
229 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
230 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
231 | $(top_builddir)/src/util/libgnunetutil.la | ||
232 | |||
233 | test_testing_topology_scale_free_SOURCES = \ | ||
234 | test_testing_topology.c | ||
235 | test_testing_topology_scale_free_LDADD = \ | ||
236 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
237 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
238 | $(top_builddir)/src/util/libgnunetutil.la | ||
239 | |||
240 | test_testing_topology_none_SOURCES = \ | ||
241 | test_testing_topology.c | ||
242 | test_testing_topology_none_LDADD = \ | ||
243 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
244 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
245 | $(top_builddir)/src/util/libgnunetutil.la | ||
246 | |||
247 | |||
248 | EXTRA_DIST = \ | ||
249 | test_testing_defaults.conf \ | ||
250 | test_testing_data.conf \ | ||
251 | test_testing_connect_peer1.conf \ | ||
252 | test_testing_connect_peer2.conf \ | ||
253 | test_testing_2dtorus.conf \ | ||
254 | test_testing_data_topology_clique.conf \ | ||
255 | test_testing_data_topology_clique_random.conf \ | ||
256 | test_testing_data_topology_clique_minimum.conf \ | ||
257 | test_testing_data_topology_clique_dfs.conf \ | ||
258 | test_testing_data_topology_ring.conf \ | ||
259 | test_testing_data_topology_2d_torus.conf \ | ||
260 | test_testing_data_topology_small_world_ring.conf \ | ||
261 | test_testing_data_topology_small_world_torus.conf \ | ||
262 | test_testing_data_topology_erdos_renyi.conf \ | ||
263 | test_testing_data_topology_internat.conf \ | ||
264 | test_testing_data_topology_scale_free.conf \ | ||
265 | test_testing_data_topology_blacklist.conf \ | ||
266 | test_testing_data_topology_churn.conf \ | ||
267 | test_testing_data_topology_none.conf \ | ||
268 | test_testing_data_remote.conf \ | ||
269 | test_testing_data_topology_stability.conf \ | ||
270 | test_testing_peergroup_data.conf | ||
diff --git a/src/testing_old/gnunet-testing-remote-peer-start.pl b/src/testing_old/gnunet-testing-remote-peer-start.pl deleted file mode 100755 index e4f72e9d0..000000000 --- a/src/testing_old/gnunet-testing-remote-peer-start.pl +++ /dev/null | |||
@@ -1,92 +0,0 @@ | |||
1 | # | ||
2 | # This file is part of GNUnet | ||
3 | # (C) 2008, 2009 Christian Grothoff (and other contributing authors) | ||
4 | # | ||
5 | # GNUnet is free software; you can redistribute it and/or modify | ||
6 | # it under the terms of the GNU General Public License as published | ||
7 | # by the Free Software Foundation; either version 3, or (at your | ||
8 | # option) any later version. | ||
9 | # | ||
10 | # GNUnet is distributed in the hope that it will be useful, but | ||
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | # General Public License for more details. | ||
14 | # | ||
15 | # You should have received a copy of the GNU General Public License | ||
16 | # along with GNUnet; see the file COPYING. If not, write to the | ||
17 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | # Boston, MA 02111-1307, USA. | ||
19 | # | ||
20 | # | ||
21 | # | ||
22 | # @file contrib/peerStartHelper.pl | ||
23 | # @brief Helper process for starting gnunet-testing peers. | ||
24 | # @author Nathan Evans | ||
25 | # | ||
26 | # Finds configuration files (or any files) of the format | ||
27 | # /path/*/gnunet-testing-config* and runs gnunet-arm with | ||
28 | # each as the given configuration. | ||
29 | # | ||
30 | # usage: peerStartHelper.pl /path/to/testing_dir/ | ||
31 | #!/usr/bin/perl | ||
32 | use strict; | ||
33 | |||
34 | my $max_outstanding = 300; | ||
35 | |||
36 | $ARGV[0] || die "No directory provided for peer information, exiting!\n"; | ||
37 | |||
38 | my $directory = $ARGV[0]; | ||
39 | my @config_files = `find $directory -iname gnunet-testing-config*`; | ||
40 | my @child_arr = {}; | ||
41 | my $count = 0; | ||
42 | my $outstanding = 0; | ||
43 | foreach my $file (@config_files) | ||
44 | { | ||
45 | chomp($file); | ||
46 | #print "Starting GNUnet peer with config file $file\n"; | ||
47 | my $pid = fork(); | ||
48 | if ($pid == -1) | ||
49 | { | ||
50 | die; | ||
51 | } | ||
52 | elsif ($pid == 0) | ||
53 | { | ||
54 | exec "gnunet-arm -q -c $file -s" or die; | ||
55 | } | ||
56 | |||
57 | if ($pid != 0) | ||
58 | { | ||
59 | push @child_arr, $pid; | ||
60 | $count++; | ||
61 | $outstanding++; | ||
62 | if ($outstanding > $max_outstanding) | ||
63 | { | ||
64 | for (my $i = 0; $i < $max_outstanding / 5; $i++) | ||
65 | { | ||
66 | #print "Too many outstanding peers, waiting!\n"; | ||
67 | waitpid($child_arr[0], 0); | ||
68 | shift(@child_arr); | ||
69 | $outstanding--; | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | |||
75 | print "All $count peers started (waiting for them to finish!\n"; | ||
76 | |||
77 | while ($outstanding > 0) | ||
78 | { | ||
79 | waitpid($child_arr[0], 0); | ||
80 | shift(@child_arr); | ||
81 | $outstanding--; | ||
82 | if ($outstanding % 50 == 0) | ||
83 | { | ||
84 | print "All $count peers started (waiting for $outstanding to finish!\n"; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | while (wait() != -1) {sleep 1} | ||
89 | |||
90 | print "All $count peers started!\n"; | ||
91 | |||
92 | |||
diff --git a/src/testing_old/helper.c b/src/testing_old/helper.c deleted file mode 100644 index 366162d6e..000000000 --- a/src/testing_old/helper.c +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | (C) 2012 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testing_old/helper.c | ||
23 | * @brief helper functions for testing | ||
24 | * @author Christian Grothoff | ||
25 | * | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_testing_lib.h" | ||
29 | |||
30 | |||
31 | |||
32 | |||
33 | /** | ||
34 | * Obtain the peer identity of the peer with the given configuration | ||
35 | * handle. This function reads the private key of the peer, obtains | ||
36 | * the public key and hashes it. | ||
37 | * | ||
38 | * @param cfg configuration of the peer | ||
39 | * @param pid where to store the peer identity | ||
40 | * @return GNUNET_OK on success, GNUNET_SYSERR on failure | ||
41 | */ | ||
42 | int | ||
43 | GNUNET_TESTING_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
44 | struct GNUNET_PeerIdentity *pid) | ||
45 | { | ||
46 | char *keyfile; | ||
47 | struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key; | ||
48 | struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; | ||
49 | |||
50 | if (GNUNET_OK != | ||
51 | GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY", | ||
52 | &keyfile)) | ||
53 | { | ||
54 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
55 | _ | ||
56 | ("Peer is lacking HOSTKEY configuration setting.\n")); | ||
57 | return GNUNET_SYSERR; | ||
58 | } | ||
59 | my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); | ||
60 | GNUNET_free (keyfile); | ||
61 | if (my_private_key == NULL) | ||
62 | { | ||
63 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
64 | _("Could not access hostkey.\n")); | ||
65 | return GNUNET_SYSERR; | ||
66 | } | ||
67 | GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key); | ||
68 | GNUNET_CRYPTO_rsa_key_free (my_private_key); | ||
69 | GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), | ||
70 | &pid->hashPubKey); | ||
71 | return GNUNET_OK; | ||
72 | } | ||
73 | |||
74 | |||
75 | /* end of helper.c */ | ||
diff --git a/src/testing_old/test_testing.c b/src/testing_old/test_testing.c deleted file mode 100644 index 3e2cd65ee..000000000 --- a/src/testing_old/test_testing.c +++ /dev/null | |||
@@ -1,126 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file testing/test_testing.c | ||
22 | * @brief testcase for testing.c | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_testing_lib.h" | ||
26 | |||
27 | #define VERBOSE GNUNET_YES | ||
28 | |||
29 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) | ||
30 | |||
31 | static int ok; | ||
32 | |||
33 | static void | ||
34 | end_cb (void *cls, const char *emsg) | ||
35 | { | ||
36 | if (emsg != NULL) | ||
37 | { | ||
38 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg); | ||
39 | ok = 1; | ||
40 | } | ||
41 | else | ||
42 | { | ||
43 | #if VERBOSE | ||
44 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon terminated, will now exit.\n"); | ||
45 | #endif | ||
46 | ok = 0; | ||
47 | } | ||
48 | } | ||
49 | |||
50 | |||
51 | |||
52 | void | ||
53 | do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
54 | { | ||
55 | struct GNUNET_TESTING_Daemon *d = cls; | ||
56 | |||
57 | GNUNET_TESTING_daemon_stop (d, TIMEOUT, &end_cb, NULL, GNUNET_YES, GNUNET_NO); | ||
58 | } | ||
59 | |||
60 | |||
61 | static void | ||
62 | my_cb (void *cls, const struct GNUNET_PeerIdentity *id, | ||
63 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
64 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
65 | { | ||
66 | GNUNET_assert (id != NULL); | ||
67 | #if VERBOSE | ||
68 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
69 | "Daemon `%s' started, will now stop it.\n", GNUNET_i2s (id)); | ||
70 | #endif | ||
71 | GNUNET_SCHEDULER_add_now (&do_shutdown, d); | ||
72 | } | ||
73 | |||
74 | |||
75 | static void | ||
76 | run (void *cls, char *const *args, const char *cfgfile, | ||
77 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
78 | { | ||
79 | struct GNUNET_TESTING_Daemon *d; | ||
80 | |||
81 | ok = 1; | ||
82 | #if VERBOSE | ||
83 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n"); | ||
84 | #endif | ||
85 | d = GNUNET_TESTING_daemon_start (cfg, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL, | ||
86 | NULL, NULL, &my_cb, NULL); | ||
87 | GNUNET_assert (d != NULL); | ||
88 | } | ||
89 | |||
90 | static int | ||
91 | check () | ||
92 | { | ||
93 | char *const argv[] = { "test-testing", | ||
94 | "-c", | ||
95 | "test_testing_data.conf", | ||
96 | #if VERBOSE | ||
97 | "-L", "DEBUG", | ||
98 | #endif | ||
99 | NULL | ||
100 | }; | ||
101 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
102 | GNUNET_GETOPT_OPTION_END | ||
103 | }; | ||
104 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
105 | "test-testing", "nohelp", options, &run, &ok); | ||
106 | return ok; | ||
107 | } | ||
108 | |||
109 | int | ||
110 | main (int argc, char *argv[]) | ||
111 | { | ||
112 | int ret; | ||
113 | |||
114 | GNUNET_log_setup ("test-testing", | ||
115 | #if VERBOSE | ||
116 | "DEBUG", | ||
117 | #else | ||
118 | "WARNING", | ||
119 | #endif | ||
120 | NULL); | ||
121 | ret = check (); | ||
122 | |||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | /* end of test_testing.c */ | ||
diff --git a/src/testing_old/test_testing_2dtorus.c b/src/testing_old/test_testing_2dtorus.c deleted file mode 100644 index 00a66d65c..000000000 --- a/src/testing_old/test_testing_2dtorus.c +++ /dev/null | |||
@@ -1,372 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2011 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file testing/test_testing_2dtorus.c | ||
22 | * | ||
23 | * @brief Test for creating a 2dtorus. | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | |||
28 | #define VERBOSE GNUNET_YES | ||
29 | #define REMOVE_DIR GNUNET_YES | ||
30 | |||
31 | /** | ||
32 | * How long until we give up on connecting the peers? | ||
33 | */ | ||
34 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500) | ||
35 | |||
36 | /** | ||
37 | * Time to wait for stuff that should be rather fast | ||
38 | */ | ||
39 | #define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
40 | |||
41 | |||
42 | /** | ||
43 | * How many events have happened | ||
44 | */ | ||
45 | static int ok; | ||
46 | |||
47 | /** | ||
48 | * Be verbose | ||
49 | */ | ||
50 | static int verbose; | ||
51 | |||
52 | /** | ||
53 | * Total number of peers in the test. | ||
54 | */ | ||
55 | static unsigned long long num_peers; | ||
56 | |||
57 | /** | ||
58 | * Global configuration file | ||
59 | */ | ||
60 | static struct GNUNET_CONFIGURATION_Handle *testing_cfg; | ||
61 | |||
62 | /** | ||
63 | * Total number of currently running peers. | ||
64 | */ | ||
65 | static unsigned long long peers_running; | ||
66 | |||
67 | /** | ||
68 | * Total number of successful connections in the whole network. | ||
69 | */ | ||
70 | static unsigned int total_connections; | ||
71 | |||
72 | /** | ||
73 | * Total number of counted topo connections | ||
74 | */ | ||
75 | static unsigned int topo_connections; | ||
76 | |||
77 | /** | ||
78 | * Total number of failed connections in the whole network. | ||
79 | */ | ||
80 | static unsigned int failed_connections; | ||
81 | |||
82 | /** | ||
83 | * The currently running peer group. | ||
84 | */ | ||
85 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
86 | |||
87 | /** | ||
88 | * Task called to disconnect peers | ||
89 | */ | ||
90 | static GNUNET_SCHEDULER_TaskIdentifier disconnect_task; | ||
91 | |||
92 | /** | ||
93 | * Task called to shutdown test. | ||
94 | */ | ||
95 | static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle; | ||
96 | |||
97 | |||
98 | /** | ||
99 | * Check whether peers successfully shut down. | ||
100 | */ | ||
101 | static void | ||
102 | shutdown_callback (void *cls, const char *emsg) | ||
103 | { | ||
104 | if (emsg != NULL) | ||
105 | { | ||
106 | #if VERBOSE | ||
107 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Shutdown of peers failed!\n"); | ||
108 | #endif | ||
109 | ok--; | ||
110 | } | ||
111 | else | ||
112 | { | ||
113 | #if VERBOSE | ||
114 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
115 | "test: All peers successfully shut down!\n"); | ||
116 | #endif | ||
117 | } | ||
118 | } | ||
119 | |||
120 | |||
121 | static void | ||
122 | shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
123 | { | ||
124 | #if VERBOSE | ||
125 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Ending test.\n"); | ||
126 | #endif | ||
127 | |||
128 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
129 | GNUNET_CONFIGURATION_destroy (testing_cfg); | ||
130 | } | ||
131 | |||
132 | |||
133 | static void | ||
134 | disconnect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
135 | { | ||
136 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: disconnecting peers\n"); | ||
137 | |||
138 | if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle) | ||
139 | { | ||
140 | GNUNET_SCHEDULER_cancel (shutdown_handle); | ||
141 | shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | |||
146 | /** | ||
147 | * Prototype of a callback function indicating that two peers | ||
148 | * are currently connected. | ||
149 | * | ||
150 | * @param cls closure | ||
151 | * @param first peer id for first daemon | ||
152 | * @param second peer id for the second daemon | ||
153 | * @param distance distance between the connected peers | ||
154 | * @param emsg error message (NULL on success) | ||
155 | */ | ||
156 | void | ||
157 | topo_cb (void *cls, const struct GNUNET_PeerIdentity *first, | ||
158 | const struct GNUNET_PeerIdentity *second, const char *emsg) | ||
159 | { | ||
160 | topo_connections++; | ||
161 | if (NULL != emsg) | ||
162 | { | ||
163 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: Error by topo %u: %s\n", | ||
164 | topo_connections, emsg); | ||
165 | } | ||
166 | else | ||
167 | { | ||
168 | if (first == NULL || second == NULL) | ||
169 | { | ||
170 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Connection %u NULL\n", | ||
171 | topo_connections); | ||
172 | if (disconnect_task != GNUNET_SCHEDULER_NO_TASK) | ||
173 | { | ||
174 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
175 | GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL); | ||
176 | } | ||
177 | return; | ||
178 | } | ||
179 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Connection %u ok\n", | ||
180 | topo_connections); | ||
181 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: %s\n", GNUNET_i2s (first)); | ||
182 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: %s\n", GNUNET_i2s (second)); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | |||
187 | /** | ||
188 | * peergroup_ready: start test when all peers are connected | ||
189 | * @param cls closure | ||
190 | * @param emsg error message | ||
191 | */ | ||
192 | static void | ||
193 | peergroup_ready (void *cls, const char *emsg) | ||
194 | { | ||
195 | if (emsg != NULL) | ||
196 | { | ||
197 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
198 | "test: Peergroup callback called with error, aborting test!\n"); | ||
199 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Error from testing: `%s'\n", | ||
200 | emsg); | ||
201 | ok--; | ||
202 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
203 | return; | ||
204 | } | ||
205 | #if VERBOSE | ||
206 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
207 | "************************************************************\n"); | ||
208 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
209 | "test: Peer Group started successfully!\n"); | ||
210 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Have %u connections\n", | ||
211 | total_connections); | ||
212 | #endif | ||
213 | |||
214 | peers_running = GNUNET_TESTING_daemons_running (pg); | ||
215 | if (0 < failed_connections) | ||
216 | { | ||
217 | ok = GNUNET_SYSERR; | ||
218 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: %u connections have FAILED!\n", | ||
219 | failed_connections); | ||
220 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL); | ||
221 | |||
222 | } | ||
223 | else | ||
224 | { | ||
225 | GNUNET_TESTING_get_topology (pg, &topo_cb, NULL); | ||
226 | disconnect_task = | ||
227 | GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_peers, NULL); | ||
228 | ok = GNUNET_OK; | ||
229 | } | ||
230 | |||
231 | } | ||
232 | |||
233 | |||
234 | /** | ||
235 | * Function that will be called whenever two daemons are connected by | ||
236 | * the testing library. | ||
237 | * | ||
238 | * @param cls closure | ||
239 | * @param first peer id for first daemon | ||
240 | * @param second peer id for the second daemon | ||
241 | * @param distance distance between the connected peers | ||
242 | * @param first_cfg config for the first daemon | ||
243 | * @param second_cfg config for the second daemon | ||
244 | * @param first_daemon handle for the first daemon | ||
245 | * @param second_daemon handle for the second daemon | ||
246 | * @param emsg error message (NULL on success) | ||
247 | */ | ||
248 | static void | ||
249 | connect_cb (void *cls, const struct GNUNET_PeerIdentity *first, | ||
250 | const struct GNUNET_PeerIdentity *second, uint32_t distance, | ||
251 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
252 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
253 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
254 | struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg) | ||
255 | { | ||
256 | if (emsg == NULL) | ||
257 | { | ||
258 | total_connections++; | ||
259 | } | ||
260 | else | ||
261 | { | ||
262 | failed_connections++; | ||
263 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
264 | "test: Problem with new connection (%s)\n", emsg); | ||
265 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: (%s)\n", GNUNET_i2s (first)); | ||
266 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: (%s)\n", GNUNET_i2s (second)); | ||
267 | } | ||
268 | |||
269 | } | ||
270 | |||
271 | |||
272 | /** | ||
273 | * run: load configuration options and schedule test to run (start peergroup) | ||
274 | * @param cls closure | ||
275 | * @param args argv | ||
276 | * @param cfgfile configuration file name (can be NULL) | ||
277 | * @param cfg configuration handle | ||
278 | */ | ||
279 | static void | ||
280 | run (void *cls, char *const *args, const char *cfgfile, | ||
281 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
282 | { | ||
283 | struct GNUNET_TESTING_Host *hosts; | ||
284 | |||
285 | ok = GNUNET_NO; | ||
286 | total_connections = 0; | ||
287 | failed_connections = 0; | ||
288 | testing_cfg = GNUNET_CONFIGURATION_dup (cfg); | ||
289 | |||
290 | GNUNET_log_setup ("test_testing_2dtorus", | ||
291 | #if VERBOSE | ||
292 | "DEBUG", | ||
293 | #else | ||
294 | "WARNING", | ||
295 | #endif | ||
296 | NULL); | ||
297 | |||
298 | #if VERBOSE | ||
299 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Starting daemons.\n"); | ||
300 | GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing", | ||
301 | "use_progressbars", "YES"); | ||
302 | #endif | ||
303 | |||
304 | if (GNUNET_OK != | ||
305 | GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing", | ||
306 | "num_peers", &num_peers)) | ||
307 | { | ||
308 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
309 | "Option TESTING:NUM_PEERS is required!\n"); | ||
310 | return; | ||
311 | } | ||
312 | |||
313 | hosts = GNUNET_TESTING_hosts_load (testing_cfg); | ||
314 | |||
315 | pg = GNUNET_TESTING_peergroup_start (testing_cfg, num_peers, TIMEOUT, | ||
316 | &connect_cb, &peergroup_ready, NULL, | ||
317 | hosts); | ||
318 | GNUNET_assert (pg != NULL); | ||
319 | shutdown_handle = | ||
320 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | ||
321 | &shutdown_task, NULL); | ||
322 | } | ||
323 | |||
324 | |||
325 | /** | ||
326 | * test_testing_2dtorus command line options | ||
327 | */ | ||
328 | static struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
329 | {'V', "verbose", NULL, | ||
330 | gettext_noop ("be verbose (print progress information)"), | ||
331 | 0, &GNUNET_GETOPT_set_one, &verbose}, | ||
332 | GNUNET_GETOPT_OPTION_END | ||
333 | }; | ||
334 | |||
335 | |||
336 | /** | ||
337 | * Main: start test | ||
338 | */ | ||
339 | int | ||
340 | main (int argc, char *argv[]) | ||
341 | { | ||
342 | char *const argv2[] = { | ||
343 | argv[0], | ||
344 | "-c", | ||
345 | "test_testing_2dtorus.conf", | ||
346 | #if VERBOSE | ||
347 | "-L", | ||
348 | "DEBUG", | ||
349 | #endif | ||
350 | NULL | ||
351 | }; | ||
352 | |||
353 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Start\n"); | ||
354 | |||
355 | |||
356 | GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, | ||
357 | "test_testing_2dtorus", | ||
358 | gettext_noop ("Test testing 2d torus."), options, &run, | ||
359 | NULL); | ||
360 | #if REMOVE_DIR | ||
361 | GNUNET_DISK_directory_remove ("/tmp/test_testing_2dtorus"); | ||
362 | #endif | ||
363 | if (GNUNET_OK != ok) | ||
364 | { | ||
365 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: FAILED!\n"); | ||
366 | return 1; | ||
367 | } | ||
368 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: success\n"); | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | /* end of test_testing_2dtorus.c */ | ||
diff --git a/src/testing_old/test_testing_2dtorus.conf b/src/testing_old/test_testing_2dtorus.conf deleted file mode 100644 index 993ab372d..000000000 --- a/src/testing_old/test_testing_2dtorus.conf +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | SERVICEHOME = /tmp/test_testing_2dtorus/ | ||
4 | |||
5 | [arm] | ||
6 | PORT = 10010 | ||
7 | DEFAULTSERVICES = core | ||
8 | |||
9 | [statistics] | ||
10 | AUTOSTART = YES | ||
11 | PORT = 10000 | ||
12 | |||
13 | [dht] | ||
14 | AUTOSTART = YES | ||
15 | ACCEPT_FROM6 = ::1; | ||
16 | ACCEPT_FROM = 127.0.0.1; | ||
17 | HOSTNAME = localhost | ||
18 | PORT = 10001 | ||
19 | |||
20 | [nse] | ||
21 | WORKBITS = 0 | ||
22 | |||
23 | [dns] | ||
24 | AUTOSTART = NO | ||
25 | PORT = 10011 | ||
26 | |||
27 | [transport] | ||
28 | PORT = 10002 | ||
29 | AUTOSTART = YES | ||
30 | PLUGINS = tcp | ||
31 | |||
32 | [nat] | ||
33 | DISABLEV6 = YES | ||
34 | BINDTO = 127.0.0.1 | ||
35 | ENABLE_UPNP = NO | ||
36 | BEHIND_NAT = NO | ||
37 | ALLOW_NAT = NO | ||
38 | INTERNAL_ADDRESS = 127.0.0.1 | ||
39 | EXTERNAL_ADDRESS = 127.0.0.1 | ||
40 | |||
41 | [ats] | ||
42 | WAN_QUOTA_IN = 1 GB | ||
43 | WAN_QUOTA_OUT = 1 GB | ||
44 | |||
45 | [core] | ||
46 | AUTOSTART = YES | ||
47 | PORT = 10003 | ||
48 | |||
49 | [peerinfo] | ||
50 | AUTOSTART = YES | ||
51 | PORT = 10004 | ||
52 | |||
53 | [testing_old] | ||
54 | NUM_PEERS = 16 | ||
55 | WEAKRANDOM = YES | ||
56 | TOPOLOGY = 2D_TORUS | ||
57 | CONNECT_TOPOLOGY = 2D_TORUS | ||
58 | #TOPOLOGY_FILE = small.dat | ||
59 | CONNECT_TOPOLOGY = 2D_TORUS | ||
60 | #CONNECT_TOPOLOGY_OPTION = CONNECT_MINIMUM | ||
61 | #CONNECT_TOPOLOGY_OPTION_MODIFIER = 25 | ||
62 | #PERCENTAGE = 3 | ||
63 | #PROBABILITY = .1 | ||
64 | F2F = NO | ||
65 | CONNECT_TIMEOUT = 600 s | ||
66 | CONNECT_ATTEMPTS = 2 | ||
67 | HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat | ||
68 | MAX_CONCURRENT_SSH = 10 | ||
69 | USE_PROGRESSBARS = YES | ||
70 | PEERGROUP_TIMEOUT = 2400 s | ||
71 | TOPOLOGY_OUTPUT_FILE = testing_topo_initial | ||
72 | MAX_OUTSTANDING_CONNECTIONS = 75 | ||
73 | #SINGLE_PEERINFO_PER_HOST = YES | ||
74 | #NUM_PEERINFO_PER_HOST = 10 | ||
75 | #SINGLE_STATISTICS_PER_HOST = YES | ||
76 | #NUM_STATISTICS_PER_HOST = 10 | ||
77 | DELETE_FILES = YES | ||
diff --git a/src/testing_old/test_testing_connect.c b/src/testing_old/test_testing_connect.c deleted file mode 100644 index c69c20326..000000000 --- a/src/testing_old/test_testing_connect.c +++ /dev/null | |||
@@ -1,197 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file testing/test_testing_connect.c | ||
22 | * @brief testcase for functions to connect two peers in testing.c | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_testing_lib.h" | ||
26 | |||
27 | #define VERBOSE GNUNET_NO | ||
28 | |||
29 | /** | ||
30 | * How long until we give up on connecting the peers? | ||
31 | */ | ||
32 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) | ||
33 | |||
34 | #define CONNECT_ATTEMPTS 3 | ||
35 | |||
36 | static int ok; | ||
37 | |||
38 | static struct GNUNET_TESTING_Daemon *d1; | ||
39 | |||
40 | static struct GNUNET_TESTING_Daemon *d2; | ||
41 | |||
42 | static struct GNUNET_CONFIGURATION_Handle *c1; | ||
43 | |||
44 | static struct GNUNET_CONFIGURATION_Handle *c2; | ||
45 | |||
46 | static struct GNUNET_TESTING_ConnectContext *cc; | ||
47 | |||
48 | static void | ||
49 | end2_cb (void *cls, const char *emsg) | ||
50 | { | ||
51 | |||
52 | if (emsg != NULL) | ||
53 | { | ||
54 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg); | ||
55 | ok = 1; | ||
56 | } | ||
57 | else | ||
58 | { | ||
59 | #if VERBOSE | ||
60 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
61 | "Both daemons terminated, will now exit.\n"); | ||
62 | #endif | ||
63 | ok = 0; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | static void | ||
68 | end1_cb (void *cls, const char *emsg) | ||
69 | { | ||
70 | if (emsg != NULL) | ||
71 | { | ||
72 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Stopping daemon 1 gave: %s\n", | ||
73 | emsg); | ||
74 | ok = 1; | ||
75 | } | ||
76 | else | ||
77 | { | ||
78 | ok = 0; | ||
79 | } | ||
80 | |||
81 | GNUNET_TESTING_daemon_stop (d2, TIMEOUT, &end2_cb, NULL, GNUNET_YES, | ||
82 | GNUNET_NO); | ||
83 | d2 = NULL; | ||
84 | } | ||
85 | |||
86 | static void | ||
87 | finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
88 | { | ||
89 | GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &end1_cb, NULL, GNUNET_YES, | ||
90 | GNUNET_NO); | ||
91 | d1 = NULL; | ||
92 | } | ||
93 | |||
94 | static void | ||
95 | my_connect_complete (void *cls, const struct GNUNET_PeerIdentity *first, | ||
96 | const struct GNUNET_PeerIdentity *second, | ||
97 | unsigned int distance, | ||
98 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
99 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
100 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
101 | struct GNUNET_TESTING_Daemon *second_daemon, | ||
102 | const char *emsg) | ||
103 | { | ||
104 | cc = NULL; | ||
105 | GNUNET_SCHEDULER_add_now (&finish_testing, NULL); | ||
106 | } | ||
107 | |||
108 | |||
109 | static void | ||
110 | my_cb2 (void *cls, const struct GNUNET_PeerIdentity *id, | ||
111 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
112 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
113 | { | ||
114 | GNUNET_assert (id != NULL); | ||
115 | #if VERBOSE | ||
116 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n", | ||
117 | GNUNET_i2s (id)); | ||
118 | #endif | ||
119 | cc = GNUNET_TESTING_daemons_connect (d1, d2, TIMEOUT, CONNECT_ATTEMPTS, | ||
120 | GNUNET_YES, &my_connect_complete, NULL); | ||
121 | } | ||
122 | |||
123 | |||
124 | static void | ||
125 | my_cb1 (void *cls, const struct GNUNET_PeerIdentity *id, | ||
126 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
127 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
128 | { | ||
129 | GNUNET_assert (id != NULL); | ||
130 | #if VERBOSE | ||
131 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n", | ||
132 | GNUNET_i2s (id)); | ||
133 | #endif | ||
134 | d2 = GNUNET_TESTING_daemon_start (c2, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL, | ||
135 | NULL, NULL, &my_cb2, NULL); | ||
136 | GNUNET_assert (d2 != NULL); | ||
137 | |||
138 | } | ||
139 | |||
140 | |||
141 | static void | ||
142 | run (void *cls, char *const *args, const char *cfgfile, | ||
143 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
144 | { | ||
145 | ok = 1; | ||
146 | #if VERBOSE | ||
147 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n"); | ||
148 | #endif | ||
149 | c1 = GNUNET_CONFIGURATION_create (); | ||
150 | GNUNET_assert (GNUNET_OK == | ||
151 | GNUNET_CONFIGURATION_load (c1, | ||
152 | "test_testing_connect_peer1.conf")); | ||
153 | c2 = GNUNET_CONFIGURATION_create (); | ||
154 | GNUNET_assert (GNUNET_OK == | ||
155 | GNUNET_CONFIGURATION_load (c2, | ||
156 | "test_testing_connect_peer2.conf")); | ||
157 | d1 = GNUNET_TESTING_daemon_start (c1, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL, | ||
158 | NULL, NULL, &my_cb1, NULL); | ||
159 | GNUNET_assert (d1 != NULL); | ||
160 | } | ||
161 | |||
162 | static int | ||
163 | check () | ||
164 | { | ||
165 | char *const argv[] = { "test-testing", | ||
166 | "-c", | ||
167 | "test_testing_data.conf", | ||
168 | #if VERBOSE | ||
169 | "-L", "DEBUG", | ||
170 | #endif | ||
171 | NULL | ||
172 | }; | ||
173 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
174 | GNUNET_GETOPT_OPTION_END | ||
175 | }; | ||
176 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
177 | "test-testing-connect", "nohelp", options, &run, &ok); | ||
178 | return ok; | ||
179 | } | ||
180 | |||
181 | int | ||
182 | main (int argc, char *argv[]) | ||
183 | { | ||
184 | int ret; | ||
185 | |||
186 | GNUNET_log_setup ("test-testing-connect", | ||
187 | #if VERBOSE | ||
188 | "DEBUG", | ||
189 | #else | ||
190 | "WARNING", | ||
191 | #endif | ||
192 | NULL); | ||
193 | ret = check (); | ||
194 | return ret; | ||
195 | } | ||
196 | |||
197 | /* end of test_testing_connect.c */ | ||
diff --git a/src/testing_old/test_testing_connect_peer1.conf b/src/testing_old/test_testing_connect_peer1.conf deleted file mode 100644 index 3349990c5..000000000 --- a/src/testing_old/test_testing_connect_peer1.conf +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | SERVICEHOME = /tmp/test-gnunet-testing-connect-peer1/ | ||
4 | |||
5 | [transport-tcp] | ||
6 | PORT = 12568 | ||
7 | |||
8 | [arm] | ||
9 | PORT = 12566 | ||
10 | DEFAULTSERVICES = core | ||
11 | UNIXPATH = /tmp/gnunet-p1-service-arm.sock | ||
12 | |||
13 | [statistics] | ||
14 | PORT = 12567 | ||
15 | UNIXPATH = /tmp/gnunet-p1-service-statistics.sock | ||
16 | |||
17 | [resolver] | ||
18 | PORT = 12564 | ||
19 | UNIXPATH = /tmp/gnunet-p1-service-resolver.sock | ||
20 | |||
21 | [peerinfo] | ||
22 | PORT = 12569 | ||
23 | UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock | ||
24 | |||
25 | [transport] | ||
26 | PORT = 12565 | ||
27 | UNIXPATH = /tmp/gnunet-p1-service-transport.sock | ||
28 | |||
29 | [core] | ||
30 | PORT = 12570 | ||
31 | UNIXPATH = /tmp/gnunet-p1-service-core.sock | ||
32 | |||
33 | [ats] | ||
34 | PORT = 12571 | ||
35 | UNIXPATH = /tmp/gnunet-p1-service-ats.sock | ||
36 | |||
diff --git a/src/testing_old/test_testing_connect_peer2.conf b/src/testing_old/test_testing_connect_peer2.conf deleted file mode 100644 index fb1f19c8e..000000000 --- a/src/testing_old/test_testing_connect_peer2.conf +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | SERVICEHOME = /tmp/test-gnunet-testing-connect-peer2/ | ||
4 | |||
5 | [transport-tcp] | ||
6 | PORT = 22568 | ||
7 | |||
8 | [arm] | ||
9 | PORT = 22566 | ||
10 | DEFAULTSERVICES = core | ||
11 | UNIXPATH = /tmp/gnunet-p2-service-arm.sock | ||
12 | |||
13 | [statistics] | ||
14 | PORT = 22567 | ||
15 | UNIXPATH = /tmp/gnunet-p2-service-statistics.sock | ||
16 | |||
17 | [resolver] | ||
18 | PORT = 22564 | ||
19 | UNIXPATH = /tmp/gnunet-p2-service-resolver.sock | ||
20 | |||
21 | [peerinfo] | ||
22 | PORT = 22569 | ||
23 | UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock | ||
24 | |||
25 | [transport] | ||
26 | PORT = 22565 | ||
27 | UNIXPATH = /tmp/gnunet-p2-service-transport.sock | ||
28 | |||
29 | [core] | ||
30 | PORT = 22570 | ||
31 | UNIXPATH = /tmp/gnunet-p2-service-core.sock | ||
32 | |||
33 | [ats] | ||
34 | PORT = 22571 | ||
35 | UNIXPATH = /tmp/gnunet-p2-service-ats.sock | ||
36 | |||
diff --git a/src/testing_old/test_testing_data.conf b/src/testing_old/test_testing_data.conf deleted file mode 100644 index 8bccc3e8d..000000000 --- a/src/testing_old/test_testing_data.conf +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [arm] | ||
5 | DEFAULTSERVICES = core | ||
6 | |||
diff --git a/src/testing_old/test_testing_data_remote.conf b/src/testing_old/test_testing_data_remote.conf deleted file mode 100644 index 3c7389afc..000000000 --- a/src/testing_old/test_testing_data_remote.conf +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | CONTROL_HOST = 127.0.0.1 | ||
6 | HOSTFILE = remote_hosts.txt | ||
7 | MAX_OUTSTANDING_SSH = 5 | ||
8 | |||
9 | [statistics] | ||
10 | AUTOSTART = NO | ||
11 | |||
diff --git a/src/testing_old/test_testing_data_topology_2d_torus.conf b/src/testing_old/test_testing_data_topology_2d_torus.conf deleted file mode 100644 index 6a890e95b..000000000 --- a/src/testing_old/test_testing_data_topology_2d_torus.conf +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | NUM_PEERS = 13 | ||
6 | TOPOLOGY = 2D_TORUS | ||
diff --git a/src/testing_old/test_testing_data_topology_blacklist.conf b/src/testing_old/test_testing_data_topology_blacklist.conf deleted file mode 100644 index d60d9d77a..000000000 --- a/src/testing_old/test_testing_data_topology_blacklist.conf +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | NUM_PEERS = 4 | ||
6 | TOPOLOGY = CLIQUE | ||
7 | BLACKLIST_TOPOLOGY = RING | ||
8 | BLACKLIST_TRANSPORTS = tcp udp http | ||
9 | |||
10 | [transport-udp] | ||
11 | PORT = 2568 | ||
12 | |||
diff --git a/src/testing_old/test_testing_data_topology_churn.conf b/src/testing_old/test_testing_data_topology_churn.conf deleted file mode 100644 index 53a261f2b..000000000 --- a/src/testing_old/test_testing_data_topology_churn.conf +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | NUM_PEERS = 12 | ||
6 | |||
7 | [arm] | ||
8 | DEFAULTSERVICES = peerinfo transport core | ||
9 | |||
diff --git a/src/testing_old/test_testing_data_topology_clique.conf b/src/testing_old/test_testing_data_topology_clique.conf deleted file mode 100644 index 8ef25c78e..000000000 --- a/src/testing_old/test_testing_data_topology_clique.conf +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | CONNECT_TIMEOUT = 180 s | ||
6 | CONNECT_ATTEMPTS = 14 | ||
7 | NUM_PEERS = 4 | ||
8 | TOPOLOGY = CLIQUE | ||
9 | SETTLE_TIME = 0 | ||
diff --git a/src/testing_old/test_testing_data_topology_clique_dfs.conf b/src/testing_old/test_testing_data_topology_clique_dfs.conf deleted file mode 100644 index 8fc926320..000000000 --- a/src/testing_old/test_testing_data_topology_clique_dfs.conf +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | NUM_PEERS = 7 | ||
6 | TOPOLOGY = CLIQUE | ||
7 | CONNECT_TOPOLOGY_OPTION = CONNECT_DFS | ||
8 | CONNECT_TOPOLOGY_OPTION_MODIFIER = 2.0 | ||
9 | |||
10 | [arm] | ||
11 | DEFAULTSERVICES = peerinfo transport core | ||
12 | |||
diff --git a/src/testing_old/test_testing_data_topology_clique_minimum.conf b/src/testing_old/test_testing_data_topology_clique_minimum.conf deleted file mode 100644 index 88de2aef1..000000000 --- a/src/testing_old/test_testing_data_topology_clique_minimum.conf +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | NUM_PEERS = 20 | ||
6 | TOPOLOGY = CLIQUE | ||
7 | CONNECT_TOPOLOGY_OPTION = CONNECT_MINIMUM | ||
8 | CONNECT_TOPOLOGY_OPTION_MODIFIER = 2.0 | ||
9 | |||
diff --git a/src/testing_old/test_testing_data_topology_clique_random.conf b/src/testing_old/test_testing_data_topology_clique_random.conf deleted file mode 100644 index a88ddccbc..000000000 --- a/src/testing_old/test_testing_data_topology_clique_random.conf +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | NUM_PEERS = 20 | ||
6 | TOPOLOGY = CLIQUE | ||
7 | CONNECT_TOPOLOGY_OPTION = CONNECT_RANDOM_SUBSET | ||
8 | CONNECT_TOPOLOGY_OPTION_MODIFIER = .15 | ||
9 | |||
10 | [statistics] | ||
11 | AUTOSTART = NO | ||
12 | |||
13 | [resolver] | ||
14 | AUTOSTART = NO | ||
15 | |||
diff --git a/src/testing_old/test_testing_data_topology_erdos_renyi.conf b/src/testing_old/test_testing_data_topology_erdos_renyi.conf deleted file mode 100644 index e8a5883b2..000000000 --- a/src/testing_old/test_testing_data_topology_erdos_renyi.conf +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | TOPOLOGY = ERDOS_RENYI | ||
6 | |||
diff --git a/src/testing_old/test_testing_data_topology_internat.conf b/src/testing_old/test_testing_data_topology_internat.conf deleted file mode 100644 index 2a0da4ac2..000000000 --- a/src/testing_old/test_testing_data_topology_internat.conf +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | TOPOLOGY = INTERNAT | ||
6 | |||
diff --git a/src/testing_old/test_testing_data_topology_none.conf b/src/testing_old/test_testing_data_topology_none.conf deleted file mode 100644 index e0ffe5244..000000000 --- a/src/testing_old/test_testing_data_topology_none.conf +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | NUM_PEERS = 1000 | ||
6 | TOPOLOGY = NONE | ||
7 | F2F = NO | ||
8 | BLACKLIST_TOPOLOGY = NONE | ||
9 | CONNECT_TOPOLOGY = RING | ||
10 | |||
11 | [arm] | ||
12 | PORT = 0 | ||
13 | |||
14 | [statistics] | ||
15 | AUTOSTART = NO | ||
16 | PORT = 0 | ||
17 | |||
18 | [resolver] | ||
19 | AUTOSTART = NO | ||
20 | PORT = 0 | ||
21 | |||
22 | [peerinfo] | ||
23 | PORT = 0 | ||
24 | |||
25 | [transport] | ||
26 | PORT = 0 | ||
27 | |||
28 | [core] | ||
29 | PORT = 0 | ||
30 | |||
31 | [topology] | ||
32 | PORT = 0 | ||
33 | |||
34 | [hostlist] | ||
35 | PORT = 0 | ||
36 | |||
diff --git a/src/testing_old/test_testing_data_topology_ring.conf b/src/testing_old/test_testing_data_topology_ring.conf deleted file mode 100644 index 4720d6ddd..000000000 --- a/src/testing_old/test_testing_data_topology_ring.conf +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | TOPOLOGY = RING | ||
6 | |||
diff --git a/src/testing_old/test_testing_data_topology_scale_free.conf b/src/testing_old/test_testing_data_topology_scale_free.conf deleted file mode 100644 index 06a8095f0..000000000 --- a/src/testing_old/test_testing_data_topology_scale_free.conf +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | NUM_PEERS = 50 | ||
6 | TOPOLOGY = SCALE_FREE | ||
7 | |||
8 | [arm] | ||
9 | DEFAULTSERVICES = peerinfo transport core | ||
10 | |||
diff --git a/src/testing_old/test_testing_data_topology_small_world_ring.conf b/src/testing_old/test_testing_data_topology_small_world_ring.conf deleted file mode 100644 index dc4f0991a..000000000 --- a/src/testing_old/test_testing_data_topology_small_world_ring.conf +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | NUM_PEERS = 25 | ||
6 | TOPOLOGY = SMALL_WORLD_RING | ||
7 | |||
diff --git a/src/testing_old/test_testing_data_topology_small_world_torus.conf b/src/testing_old/test_testing_data_topology_small_world_torus.conf deleted file mode 100644 index cfc2f76d2..000000000 --- a/src/testing_old/test_testing_data_topology_small_world_torus.conf +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | TOPOLOGY = SMALL_WORLD | ||
6 | |||
diff --git a/src/testing_old/test_testing_data_topology_stability.conf b/src/testing_old/test_testing_data_topology_stability.conf deleted file mode 100644 index aa2cf2cfa..000000000 --- a/src/testing_old/test_testing_data_topology_stability.conf +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | SETTLE_TIME = 600 s | ||
6 | NUM_PEERS = 2 | ||
7 | TOPOLOGY = CLIQUE | ||
8 | |||
diff --git a/src/testing_old/test_testing_defaults.conf b/src/testing_old/test_testing_defaults.conf deleted file mode 100644 index dac98aac3..000000000 --- a/src/testing_old/test_testing_defaults.conf +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | [PATHS] | ||
2 | SERVICEHOME = /tmp/test-gnunet-testing/ | ||
3 | |||
4 | [resolver] | ||
5 | PORT = 2564 | ||
6 | |||
7 | [transport] | ||
8 | PORT = 2565 | ||
9 | PLUGINS = tcp | ||
10 | |||
11 | [arm] | ||
12 | PORT = 2566 | ||
13 | DEFAULTSERVICES = | ||
14 | |||
15 | [statistics] | ||
16 | PORT = 2567 | ||
17 | |||
18 | [transport-tcp] | ||
19 | PORT = 2568 | ||
20 | BINDTO = 127.0.0.1 | ||
21 | |||
22 | [peerinfo] | ||
23 | PORT = 2569 | ||
24 | |||
25 | [core] | ||
26 | PORT = 2570 | ||
27 | |||
28 | [testing_old] | ||
29 | NUM_PEERS = 5 | ||
30 | WEAKRANDOM = YES | ||
31 | F2F = YES | ||
32 | HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat | ||
33 | |||
34 | [dht] | ||
35 | AUTOSTART = NO | ||
36 | |||
37 | [nat] | ||
38 | DISABLEV6 = YES | ||
39 | ENABLE_UPNP = NO | ||
40 | BEHIND_NAT = NO | ||
41 | ALLOW_NAT = NO | ||
42 | INTERNAL_ADDRESS = 127.0.0.1 | ||
43 | EXTERNAL_ADDRESS = 127.0.0.1 | ||
44 | USE_LOCALADDR = NO | ||
45 | |||
46 | [dns] | ||
47 | AUTOSTART = NO | ||
48 | |||
49 | [nse] | ||
50 | AUTOSTART = NO | ||
51 | |||
52 | [mesh] | ||
53 | AUTOSTART = NO | ||
54 | |||
55 | [datastore] | ||
56 | AUTOSTART = NO | ||
57 | |||
58 | [fs] | ||
59 | AUTOSTART = NO | ||
60 | |||
61 | [dv] | ||
62 | AUTOSTART = NO | ||
63 | |||
64 | [chat] | ||
65 | AUTOSTART = NO | ||
66 | |||
67 | [vpn] | ||
68 | AUTOSTART = NO | ||
69 | |||
70 | [gns] | ||
71 | AUTOSTART = NO | ||
72 | |||
73 | [namestore] | ||
74 | AUTOSTART = NO | ||
75 | |||
76 | [lockmanager] | ||
77 | AUTOSTART = NO | ||
diff --git a/src/testing_old/test_testing_group.c b/src/testing_old/test_testing_group.c deleted file mode 100644 index f5df45b19..000000000 --- a/src/testing_old/test_testing_group.c +++ /dev/null | |||
@@ -1,166 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file testing/test_testing_group.c | ||
22 | * @brief testcase for functions to connect peers in testing.c | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_testing_lib.h" | ||
26 | |||
27 | #define VERBOSE GNUNET_NO | ||
28 | |||
29 | #define NUM_PEERS 4 | ||
30 | |||
31 | /** | ||
32 | * How long until we give up on connecting the peers? | ||
33 | */ | ||
34 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) | ||
35 | |||
36 | static int ok; | ||
37 | |||
38 | static int peers_left; | ||
39 | |||
40 | static int failed_peers; | ||
41 | |||
42 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
43 | |||
44 | /** | ||
45 | * Check whether peers successfully shut down. | ||
46 | */ | ||
47 | void | ||
48 | shutdown_callback (void *cls, const char *emsg) | ||
49 | { | ||
50 | if (emsg != NULL) | ||
51 | { | ||
52 | #if VERBOSE | ||
53 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n"); | ||
54 | #endif | ||
55 | if (ok == 0) | ||
56 | ok = 666; | ||
57 | } | ||
58 | else | ||
59 | { | ||
60 | #if VERBOSE | ||
61 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); | ||
62 | #endif | ||
63 | } | ||
64 | } | ||
65 | |||
66 | |||
67 | static void | ||
68 | my_cb (void *cls, const struct GNUNET_PeerIdentity *id, | ||
69 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
70 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
71 | { | ||
72 | if (id == NULL) | ||
73 | { | ||
74 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
75 | "Start callback called with error (too long starting peers), aborting test!\n"); | ||
76 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n"); | ||
77 | failed_peers++; | ||
78 | if (failed_peers == peers_left) | ||
79 | { | ||
80 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
81 | "Too many peers failed, ending test!\n"); | ||
82 | ok = 1; | ||
83 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
84 | } | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | peers_left--; | ||
89 | if (peers_left == 0) | ||
90 | { | ||
91 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
92 | "All peers started successfully, ending test!\n"); | ||
93 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
94 | ok = 0; | ||
95 | } | ||
96 | else if (failed_peers == peers_left) | ||
97 | { | ||
98 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
99 | "Too many peers failed, ending test!\n"); | ||
100 | ok = 1; | ||
101 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | |||
106 | static void | ||
107 | run (void *cls, char *const *args, const char *cfgfile, | ||
108 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
109 | { | ||
110 | ok = 1; | ||
111 | #if VERBOSE | ||
112 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n"); | ||
113 | #endif | ||
114 | peers_left = NUM_PEERS; | ||
115 | pg = GNUNET_TESTING_daemons_start (cfg, peers_left, /* Total number of peers */ | ||
116 | peers_left, /* Number of outstanding connections */ | ||
117 | peers_left, /* Number of parallel ssh connections, or peers being started at once */ | ||
118 | TIMEOUT, NULL, NULL, &my_cb, NULL, NULL, | ||
119 | NULL, NULL); | ||
120 | GNUNET_assert (pg != NULL); | ||
121 | } | ||
122 | |||
123 | static int | ||
124 | check () | ||
125 | { | ||
126 | char *const argv[] = { "test-testing", | ||
127 | "-c", | ||
128 | "test_testing_data.conf", | ||
129 | #if VERBOSE | ||
130 | "-L", "DEBUG", | ||
131 | #endif | ||
132 | NULL | ||
133 | }; | ||
134 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
135 | GNUNET_GETOPT_OPTION_END | ||
136 | }; | ||
137 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
138 | "test-testing-group", "nohelp", options, &run, &ok); | ||
139 | return ok; | ||
140 | } | ||
141 | |||
142 | int | ||
143 | main (int argc, char *argv[]) | ||
144 | { | ||
145 | int ret; | ||
146 | |||
147 | GNUNET_log_setup ("test-testing-group", | ||
148 | #if VERBOSE | ||
149 | "DEBUG", | ||
150 | #else | ||
151 | "WARNING", | ||
152 | #endif | ||
153 | NULL); | ||
154 | ret = check (); | ||
155 | /** | ||
156 | * Still need to remove the base testing directory here, | ||
157 | * because group starts will create subdirectories under this | ||
158 | * main dir. However, we no longer need to sleep, as the | ||
159 | * shutdown sequence won't return until everything is cleaned | ||
160 | * up. | ||
161 | */ | ||
162 | GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing"); | ||
163 | return ret; | ||
164 | } | ||
165 | |||
166 | /* end of test_testing_group.c */ | ||
diff --git a/src/testing_old/test_testing_group_remote.c b/src/testing_old/test_testing_group_remote.c deleted file mode 100644 index b06655ca4..000000000 --- a/src/testing_old/test_testing_group_remote.c +++ /dev/null | |||
@@ -1,263 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file testing/test_testing_group_remote.c | ||
22 | * @brief testcase for testing remote and local starting and connecting | ||
23 | * of hosts from the testing library. The test_testing_data_remote.conf | ||
24 | * file should be modified if this testcase is intended to be used. | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_testing_lib.h" | ||
28 | |||
29 | #define VERBOSE GNUNET_YES | ||
30 | |||
31 | |||
32 | /** | ||
33 | * How long until we give up on connecting the peers? | ||
34 | */ | ||
35 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) | ||
36 | |||
37 | #define DEFAULT_NUM_PEERS 8; | ||
38 | |||
39 | static int ok; | ||
40 | |||
41 | static int peers_left; | ||
42 | |||
43 | static int peers_failed; | ||
44 | |||
45 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
46 | |||
47 | static unsigned long long num_peers; | ||
48 | |||
49 | |||
50 | /** | ||
51 | * Check whether peers successfully shut down. | ||
52 | */ | ||
53 | void | ||
54 | shutdown_callback (void *cls, const char *emsg) | ||
55 | { | ||
56 | if (emsg != NULL) | ||
57 | { | ||
58 | #if VERBOSE | ||
59 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
60 | "Shutdown of peers failed (error %s)!\n", emsg); | ||
61 | #endif | ||
62 | if (ok == 0) | ||
63 | ok = 666; | ||
64 | } | ||
65 | else | ||
66 | { | ||
67 | #if VERBOSE | ||
68 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); | ||
69 | #endif | ||
70 | } | ||
71 | } | ||
72 | |||
73 | |||
74 | static void | ||
75 | my_cb (void *cls, const struct GNUNET_PeerIdentity *id, | ||
76 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
77 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
78 | { | ||
79 | if (emsg != NULL) | ||
80 | { | ||
81 | peers_failed++; | ||
82 | } | ||
83 | |||
84 | peers_left--; | ||
85 | if (peers_left == 0) | ||
86 | { | ||
87 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
88 | ok = 0; | ||
89 | } | ||
90 | else if (peers_failed == peers_left) | ||
91 | { | ||
92 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
93 | "Too many peers failed, ending test!\n"); | ||
94 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | |||
99 | static void | ||
100 | run (void *cls, char *const *args, const char *cfgfile, | ||
101 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
102 | { | ||
103 | struct GNUNET_TESTING_Host *hosts; | ||
104 | struct GNUNET_TESTING_Host *hostpos; | ||
105 | struct GNUNET_TESTING_Host *temphost; | ||
106 | char *hostfile; | ||
107 | struct stat frstat; | ||
108 | char *buf; | ||
109 | char *data; | ||
110 | int count; | ||
111 | int ret; | ||
112 | |||
113 | ok = 1; | ||
114 | #if VERBOSE | ||
115 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n"); | ||
116 | #endif | ||
117 | |||
118 | if (GNUNET_SYSERR == | ||
119 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers", | ||
120 | &num_peers)) | ||
121 | num_peers = DEFAULT_NUM_PEERS; | ||
122 | |||
123 | GNUNET_assert (num_peers > 0 && num_peers < (unsigned long long) -1); | ||
124 | if (GNUNET_OK != | ||
125 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "hostfile", | ||
126 | &hostfile)) | ||
127 | hostfile = NULL; | ||
128 | |||
129 | hosts = NULL; | ||
130 | data = NULL; | ||
131 | if (hostfile != NULL) | ||
132 | { | ||
133 | if (GNUNET_OK != GNUNET_DISK_file_test (hostfile)) | ||
134 | GNUNET_DISK_fn_write (hostfile, NULL, 0, | ||
135 | GNUNET_DISK_PERM_USER_READ | | ||
136 | GNUNET_DISK_PERM_USER_WRITE); | ||
137 | if ((0 != STAT (hostfile, &frstat)) || (frstat.st_size == 0)) | ||
138 | { | ||
139 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
140 | "Could not open file specified for host list, ending test!"); | ||
141 | ok = 1119; | ||
142 | GNUNET_free (hostfile); | ||
143 | return; | ||
144 | } | ||
145 | |||
146 | data = GNUNET_malloc_large (frstat.st_size); | ||
147 | GNUNET_assert (data != NULL); | ||
148 | if (frstat.st_size != GNUNET_DISK_fn_read (hostfile, data, frstat.st_size)) | ||
149 | { | ||
150 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
151 | "Could not read file %s specified for host list, ending test!", | ||
152 | hostfile); | ||
153 | GNUNET_free (hostfile); | ||
154 | GNUNET_free (data); | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | GNUNET_free_non_null (hostfile); | ||
159 | |||
160 | buf = data; | ||
161 | count = 0; | ||
162 | while (count < frstat.st_size) | ||
163 | { | ||
164 | count++; | ||
165 | if (count >= frstat.st_size) | ||
166 | break; | ||
167 | |||
168 | /* if (((data[count] == '\n') || (data[count] == '\0')) && (buf != &data[count])) */ | ||
169 | if (((data[count] == '\n')) && (buf != &data[count])) | ||
170 | { | ||
171 | data[count] = '\0'; | ||
172 | temphost = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Host)); | ||
173 | ret = | ||
174 | SSCANF (buf, "%a[a-zA-Z0-9]@%a[a-zA-Z0-9.]:%hd", | ||
175 | &temphost->username, &temphost->hostname, &temphost->port); | ||
176 | if (3 == ret) | ||
177 | { | ||
178 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
179 | "Successfully read host %s, port %d and user %s from file\n", | ||
180 | temphost->hostname, temphost->port, temphost->username); | ||
181 | } | ||
182 | else | ||
183 | { | ||
184 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
185 | "Error reading line `%s' in hostfile\n", buf); | ||
186 | GNUNET_free (temphost); | ||
187 | buf = &data[count + 1]; | ||
188 | continue; | ||
189 | } | ||
190 | /* temphost->hostname = buf; */ | ||
191 | temphost->next = hosts; | ||
192 | hosts = temphost; | ||
193 | buf = &data[count + 1]; | ||
194 | } | ||
195 | else if ((data[count] == '\n') || (data[count] == '\0')) | ||
196 | buf = &data[count + 1]; | ||
197 | } | ||
198 | } | ||
199 | |||
200 | peers_left = num_peers; | ||
201 | pg = GNUNET_TESTING_daemons_start (cfg, peers_left, /* Total number of peers */ | ||
202 | peers_left, /* Number of outstanding connections */ | ||
203 | peers_left, /* Number of parallel ssh connections, or peers being started at once */ | ||
204 | TIMEOUT, NULL, NULL, &my_cb, NULL, NULL, | ||
205 | NULL, hosts); | ||
206 | hostpos = hosts; | ||
207 | while (hostpos != NULL) | ||
208 | { | ||
209 | temphost = hostpos->next; | ||
210 | GNUNET_free (hostpos->hostname); | ||
211 | GNUNET_free (hostpos->username); | ||
212 | GNUNET_free (hostpos); | ||
213 | hostpos = temphost; | ||
214 | } | ||
215 | GNUNET_free_non_null (data); | ||
216 | GNUNET_assert (pg != NULL); | ||
217 | |||
218 | } | ||
219 | |||
220 | static int | ||
221 | check () | ||
222 | { | ||
223 | char *const argv[] = { "test-testing", | ||
224 | "-c", | ||
225 | "test_testing_data_remote.conf", | ||
226 | #if VERBOSE | ||
227 | "-L", "DEBUG", | ||
228 | #endif | ||
229 | NULL | ||
230 | }; | ||
231 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
232 | GNUNET_GETOPT_OPTION_END | ||
233 | }; | ||
234 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
235 | "test-testing-group", "nohelp", options, &run, &ok); | ||
236 | return ok; | ||
237 | } | ||
238 | |||
239 | int | ||
240 | main (int argc, char *argv[]) | ||
241 | { | ||
242 | int ret; | ||
243 | |||
244 | GNUNET_log_setup ("test-testing-group", | ||
245 | #if VERBOSE | ||
246 | "DEBUG", | ||
247 | #else | ||
248 | "WARNING", | ||
249 | #endif | ||
250 | NULL); | ||
251 | ret = check (); | ||
252 | /** | ||
253 | * Still need to remove the base testing directory here, | ||
254 | * because group starts will create subdirectories under this | ||
255 | * main dir. However, we no longer need to sleep, as the | ||
256 | * shutdown sequence won't return until everything is cleaned | ||
257 | * up. | ||
258 | */ | ||
259 | GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing"); | ||
260 | return ret; | ||
261 | } | ||
262 | |||
263 | /* end of test_testing_group.c */ | ||
diff --git a/src/testing_old/test_testing_large_topology.c b/src/testing_old/test_testing_large_topology.c deleted file mode 100644 index a7cab095c..000000000 --- a/src/testing_old/test_testing_large_topology.c +++ /dev/null | |||
@@ -1,1197 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file testing/test_testing_topology.c | ||
22 | * @brief base testcase for testing all the topologies provided | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_testing_lib.h" | ||
26 | #include "gnunet_core_service.h" | ||
27 | #include "gnunet_os_lib.h" | ||
28 | |||
29 | #define VERBOSE GNUNET_YES | ||
30 | |||
31 | #define DELAY_FOR_LOGGING GNUNET_NO | ||
32 | |||
33 | #define SECONDS_PER_PEER_START 120 | ||
34 | |||
35 | #define DEFAULT_NUM_PEERS 4 | ||
36 | |||
37 | #define MAX_OUTSTANDING_CONNECTIONS 100 | ||
38 | |||
39 | static float fail_percentage = 0.05; | ||
40 | |||
41 | static int ok; | ||
42 | |||
43 | struct GNUNET_TIME_Relative connect_timeout; | ||
44 | |||
45 | static unsigned long long connect_attempts; | ||
46 | |||
47 | static unsigned long long num_peers; | ||
48 | |||
49 | static unsigned int topology_connections; | ||
50 | |||
51 | static unsigned int total_connections; | ||
52 | |||
53 | static unsigned int failed_connections; | ||
54 | |||
55 | static unsigned int total_server_connections; | ||
56 | |||
57 | static unsigned int total_messages_received; | ||
58 | |||
59 | static unsigned int expected_messages; | ||
60 | |||
61 | static unsigned int expected_connections; | ||
62 | |||
63 | static unsigned long long peers_left; | ||
64 | |||
65 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
66 | |||
67 | const struct GNUNET_CONFIGURATION_Handle *main_cfg; | ||
68 | |||
69 | GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
70 | |||
71 | static char *dotOutFileName; | ||
72 | |||
73 | static struct GNUNET_TIME_Relative settle_time; | ||
74 | |||
75 | static FILE *dotOutFile; | ||
76 | |||
77 | static char *topology_string; | ||
78 | |||
79 | static char *blacklist_transports; | ||
80 | |||
81 | static int transmit_ready_scheduled; | ||
82 | |||
83 | static int transmit_ready_failed; | ||
84 | |||
85 | static int transmit_ready_called; | ||
86 | |||
87 | struct GNUNET_TIME_Relative test_timeout; | ||
88 | |||
89 | struct GNUNET_TIME_Relative timeout; | ||
90 | |||
91 | static unsigned int modnum; | ||
92 | |||
93 | static unsigned int dotnum; | ||
94 | |||
95 | static enum GNUNET_TESTING_Topology topology; | ||
96 | |||
97 | static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* Don't do any blacklisting */ | ||
98 | |||
99 | static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */ | ||
100 | |||
101 | static enum GNUNET_TESTING_TopologyOption connect_topology_option = | ||
102 | GNUNET_TESTING_TOPOLOGY_OPTION_ALL; | ||
103 | |||
104 | static double connect_topology_option_modifier = 0.0; | ||
105 | |||
106 | static char *test_directory; | ||
107 | |||
108 | #define MTYPE 12345 | ||
109 | |||
110 | GNUNET_NETWORK_STRUCT_BEGIN | ||
111 | |||
112 | struct GNUNET_TestMessage | ||
113 | { | ||
114 | /** | ||
115 | * Header of the message | ||
116 | */ | ||
117 | struct GNUNET_MessageHeader header; | ||
118 | |||
119 | /** | ||
120 | * Unique identifier for this message. | ||
121 | */ | ||
122 | uint32_t uid; | ||
123 | }; | ||
124 | GNUNET_NETWORK_STRUCT_END | ||
125 | |||
126 | struct TestMessageContext | ||
127 | { | ||
128 | /* This is a linked list */ | ||
129 | struct TestMessageContext *next; | ||
130 | |||
131 | /* Handle to the sending peer core */ | ||
132 | struct GNUNET_CORE_Handle *peer1handle; | ||
133 | |||
134 | /* Handle to the receiving peer core */ | ||
135 | struct GNUNET_CORE_Handle *peer2handle; | ||
136 | |||
137 | /* Handle to the sending peer daemon */ | ||
138 | struct GNUNET_TESTING_Daemon *peer1; | ||
139 | |||
140 | /* Handle to the receiving peer daemon */ | ||
141 | struct GNUNET_TESTING_Daemon *peer2; | ||
142 | |||
143 | /* Identifier for this message, so we don't disconnect other peers! */ | ||
144 | uint32_t uid; | ||
145 | |||
146 | /* Has peer1 been notified already of a connection to peer2? */ | ||
147 | int peer1notified; | ||
148 | |||
149 | /* Has the core of peer2 been connected already? */ | ||
150 | int peer2connected; | ||
151 | |||
152 | /* Task for disconnecting cores, allow task to be cancelled on shutdown */ | ||
153 | GNUNET_SCHEDULER_TaskIdentifier disconnect_task; | ||
154 | |||
155 | }; | ||
156 | |||
157 | static struct TestMessageContext *test_messages; | ||
158 | |||
159 | /** | ||
160 | * Check whether peers successfully shut down. | ||
161 | */ | ||
162 | void | ||
163 | shutdown_callback (void *cls, const char *emsg) | ||
164 | { | ||
165 | if (emsg != NULL) | ||
166 | { | ||
167 | #if VERBOSE | ||
168 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n"); | ||
169 | #endif | ||
170 | if (ok == 0) | ||
171 | ok = 666; | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | #if VERBOSE | ||
176 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); | ||
177 | #endif | ||
178 | } | ||
179 | } | ||
180 | |||
181 | #if DELAY_FOR_LOGGING | ||
182 | static void | ||
183 | gather_log_data () | ||
184 | { | ||
185 | char *peer_number; | ||
186 | char *connect_number; | ||
187 | struct GNUNET_OS_Process *mem_process; | ||
188 | |||
189 | GNUNET_asprintf (&peer_number, "%llu", num_peers); | ||
190 | GNUNET_asprintf (&connect_number, "%llu", expected_connections); | ||
191 | mem_process = | ||
192 | GNUNET_OS_start_process (NULL, NULL, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, "./memsize.pl", "memsize.pl", | ||
193 | "totals.txt", peer_number, connect_number, NULL); | ||
194 | GNUNET_OS_process_wait (mem_process); | ||
195 | GNUNET_OS_process_destroy (mem_process); | ||
196 | mem_process = NULL; | ||
197 | } | ||
198 | |||
199 | #endif | ||
200 | |||
201 | static void | ||
202 | finish_testing () | ||
203 | { | ||
204 | GNUNET_assert (pg != NULL); | ||
205 | struct TestMessageContext *pos; | ||
206 | struct TestMessageContext *free_pos; | ||
207 | |||
208 | #if VERBOSE | ||
209 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
210 | "Called finish testing, stopping daemons.\n"); | ||
211 | #endif | ||
212 | |||
213 | pos = test_messages; | ||
214 | while (pos != NULL) | ||
215 | { | ||
216 | if (pos->peer1handle != NULL) | ||
217 | { | ||
218 | GNUNET_CORE_disconnect (pos->peer1handle); | ||
219 | pos->peer1handle = NULL; | ||
220 | } | ||
221 | if (pos->peer2handle != NULL) | ||
222 | { | ||
223 | GNUNET_CORE_disconnect (pos->peer2handle); | ||
224 | pos->peer2handle = NULL; | ||
225 | } | ||
226 | free_pos = pos; | ||
227 | pos = pos->next; | ||
228 | if (free_pos->disconnect_task != GNUNET_SCHEDULER_NO_TASK) | ||
229 | { | ||
230 | GNUNET_SCHEDULER_cancel (free_pos->disconnect_task); | ||
231 | } | ||
232 | GNUNET_free (free_pos); | ||
233 | } | ||
234 | #if VERBOSE | ||
235 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
236 | "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n", | ||
237 | transmit_ready_scheduled, transmit_ready_failed, | ||
238 | transmit_ready_called); | ||
239 | #endif | ||
240 | |||
241 | #if VERBOSE | ||
242 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n"); | ||
243 | #endif | ||
244 | GNUNET_TESTING_daemons_stop (pg, timeout, &shutdown_callback, NULL); | ||
245 | |||
246 | if (dotOutFile != NULL) | ||
247 | { | ||
248 | FPRINTF (dotOutFile, "%s", "}"); | ||
249 | FCLOSE (dotOutFile); | ||
250 | } | ||
251 | |||
252 | ok = 0; | ||
253 | } | ||
254 | |||
255 | |||
256 | static void | ||
257 | disconnect_cores (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
258 | { | ||
259 | struct TestMessageContext *pos = cls; | ||
260 | |||
261 | /* Disconnect from the respective cores */ | ||
262 | #if VERBOSE > 1 | ||
263 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 1 `%4s'\n", | ||
264 | GNUNET_i2s (&pos->peer1->id)); | ||
265 | #endif | ||
266 | if (pos->peer1handle != NULL) | ||
267 | GNUNET_CORE_disconnect (pos->peer1handle); | ||
268 | #if VERBOSE > 1 | ||
269 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 2 `%4s'\n", | ||
270 | GNUNET_i2s (&pos->peer2->id)); | ||
271 | #endif | ||
272 | if (pos->peer2handle != NULL) | ||
273 | GNUNET_CORE_disconnect (pos->peer2handle); | ||
274 | /* Set handles to NULL so test case can be ended properly */ | ||
275 | pos->peer1handle = NULL; | ||
276 | pos->peer2handle = NULL; | ||
277 | pos->disconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
278 | /* Decrement total connections so new can be established */ | ||
279 | total_server_connections -= 2; | ||
280 | } | ||
281 | |||
282 | |||
283 | static void | ||
284 | topology_cb (void *cls, const struct GNUNET_PeerIdentity *first, | ||
285 | const struct GNUNET_PeerIdentity *second, const char *emsg) | ||
286 | { | ||
287 | FILE *outfile = cls; | ||
288 | |||
289 | if (first != NULL) | ||
290 | { | ||
291 | if (outfile != NULL) | ||
292 | { | ||
293 | FPRINTF (outfile, "\t\"%s\" -- ", GNUNET_i2s (first)); | ||
294 | FPRINTF (outfile, "\"%s\";\n", GNUNET_i2s (second)); | ||
295 | } | ||
296 | topology_connections++; | ||
297 | } | ||
298 | else | ||
299 | { | ||
300 | FPRINTF (stderr, | ||
301 | "Finished iterating over topology, %d total connections!\n", | ||
302 | topology_connections); | ||
303 | if (outfile != NULL) | ||
304 | { | ||
305 | FPRINTF (outfile, "%s", "}\n"); | ||
306 | FCLOSE (outfile); | ||
307 | GNUNET_SCHEDULER_add_now (&finish_testing, NULL); | ||
308 | } | ||
309 | } | ||
310 | } | ||
311 | |||
312 | static int | ||
313 | process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
314 | const struct GNUNET_MessageHeader *message, | ||
315 | const struct GNUNET_ATS_Information *atsi) | ||
316 | { | ||
317 | char *dotOutFileNameFinished; | ||
318 | FILE *dotOutFileFinished; | ||
319 | struct TestMessageContext *pos = cls; | ||
320 | struct GNUNET_TestMessage *msg = (struct GNUNET_TestMessage *) message; | ||
321 | |||
322 | if (pos->uid != ntohl (msg->uid)) | ||
323 | return GNUNET_OK; | ||
324 | |||
325 | #if VERBOSE | ||
326 | if ((total_messages_received) % modnum == 0) | ||
327 | { | ||
328 | if (total_messages_received == 0) | ||
329 | FPRINTF (stdout, "%s", "0%%"); | ||
330 | else | ||
331 | FPRINTF (stdout, "%d%%", | ||
332 | (int) (((float) total_messages_received / expected_messages) * | ||
333 | 100)); | ||
334 | |||
335 | } | ||
336 | else if (total_messages_received % dotnum == 0) | ||
337 | { | ||
338 | FPRINTF (stdout, "%s", "."); | ||
339 | } | ||
340 | fflush (stdout); | ||
341 | #endif | ||
342 | |||
343 | total_messages_received++; | ||
344 | |||
345 | #if VERBOSE > 1 | ||
346 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
347 | "Received message from `%4s', type %d.\n", GNUNET_i2s (peer), | ||
348 | ntohs (message->type)); | ||
349 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
350 | "Total messages received %d, expected %d.\n", | ||
351 | total_messages_received, expected_messages); | ||
352 | #endif | ||
353 | |||
354 | if (total_messages_received == expected_messages) | ||
355 | { | ||
356 | #if VERBOSE | ||
357 | FPRINTF (stdout, "%s", "100%%]\n"); | ||
358 | #endif | ||
359 | GNUNET_SCHEDULER_cancel (die_task); | ||
360 | GNUNET_asprintf (&dotOutFileNameFinished, "%s.dot", "final_topology"); | ||
361 | dotOutFileFinished = FOPEN (dotOutFileNameFinished, "w"); | ||
362 | GNUNET_free (dotOutFileNameFinished); | ||
363 | if (dotOutFileFinished != NULL) | ||
364 | { | ||
365 | FPRINTF (dotOutFileFinished, "%s", "strict graph G {\n"); | ||
366 | } | ||
367 | topology_connections = 0; | ||
368 | GNUNET_TESTING_get_topology (pg, &topology_cb, dotOutFileFinished); | ||
369 | //GNUNET_SCHEDULER_add_now (&finish_testing, NULL); | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | pos->disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cores, pos); | ||
374 | } | ||
375 | |||
376 | return GNUNET_OK; | ||
377 | } | ||
378 | |||
379 | static void | ||
380 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
381 | { | ||
382 | char *msg = cls; | ||
383 | |||
384 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
385 | "End badly was called (%s)... stopping daemons.\n", msg); | ||
386 | struct TestMessageContext *pos; | ||
387 | struct TestMessageContext *free_pos; | ||
388 | |||
389 | pos = test_messages; | ||
390 | while (pos != NULL) | ||
391 | { | ||
392 | if (pos->peer1handle != NULL) | ||
393 | { | ||
394 | GNUNET_CORE_disconnect (pos->peer1handle); | ||
395 | pos->peer1handle = NULL; | ||
396 | } | ||
397 | if (pos->peer2handle != NULL) | ||
398 | { | ||
399 | GNUNET_CORE_disconnect (pos->peer2handle); | ||
400 | pos->peer2handle = NULL; | ||
401 | } | ||
402 | free_pos = pos; | ||
403 | pos = pos->next; | ||
404 | GNUNET_free (free_pos); | ||
405 | } | ||
406 | |||
407 | #if VERBOSE | ||
408 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
409 | "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n", | ||
410 | transmit_ready_scheduled, transmit_ready_failed, | ||
411 | transmit_ready_called); | ||
412 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
413 | "Total messages received %d, expected %d.\n", | ||
414 | total_messages_received, expected_messages); | ||
415 | #endif | ||
416 | |||
417 | if (pg != NULL) | ||
418 | { | ||
419 | GNUNET_TESTING_daemons_stop (pg, timeout, &shutdown_callback, NULL); | ||
420 | ok = 7331; /* Opposite of leet */ | ||
421 | } | ||
422 | else | ||
423 | ok = 401; /* Never got peers started */ | ||
424 | |||
425 | if (dotOutFile != NULL) | ||
426 | { | ||
427 | FPRINTF (dotOutFile, "%s", "}"); | ||
428 | FCLOSE (dotOutFile); | ||
429 | } | ||
430 | } | ||
431 | |||
432 | static size_t | ||
433 | transmit_ready (void *cls, size_t size, void *buf) | ||
434 | { | ||
435 | struct GNUNET_TestMessage *m; | ||
436 | struct TestMessageContext *pos = cls; | ||
437 | |||
438 | GNUNET_assert (buf != NULL); | ||
439 | m = (struct GNUNET_TestMessage *) buf; | ||
440 | m->header.type = htons (MTYPE); | ||
441 | m->header.size = htons (sizeof (struct GNUNET_TestMessage)); | ||
442 | m->uid = htonl (pos->uid); | ||
443 | transmit_ready_called++; | ||
444 | #if VERBOSE > 1 | ||
445 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
446 | "transmit ready for peer %s\ntransmit_ready's scheduled %d, transmit_ready's called %d\n", | ||
447 | GNUNET_i2s (&pos->peer1->id), transmit_ready_scheduled, | ||
448 | transmit_ready_called); | ||
449 | #endif | ||
450 | return sizeof (struct GNUNET_TestMessage); | ||
451 | } | ||
452 | |||
453 | |||
454 | static struct GNUNET_CORE_MessageHandler no_handlers[] = { | ||
455 | {NULL, 0, 0} | ||
456 | }; | ||
457 | |||
458 | static struct GNUNET_CORE_MessageHandler handlers[] = { | ||
459 | {&process_mtype, MTYPE, sizeof (struct GNUNET_TestMessage)}, | ||
460 | {NULL, 0, 0} | ||
461 | }; | ||
462 | |||
463 | static void | ||
464 | init_notify_peer2 (void *cls, struct GNUNET_CORE_Handle *server, | ||
465 | const struct GNUNET_PeerIdentity *my_identity) | ||
466 | { | ||
467 | struct TestMessageContext *pos = cls; | ||
468 | |||
469 | total_server_connections++; | ||
470 | |||
471 | pos->peer2connected = GNUNET_YES; | ||
472 | if (pos->peer1notified == GNUNET_YES) /* Peer 1 has been notified of connection to peer 2 */ | ||
473 | { | ||
474 | #if VERBOSE > 1 | ||
475 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
476 | "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n", | ||
477 | GNUNET_i2s (my_identity), | ||
478 | GNUNET_h2s (&pos->peer1->id.hashPubKey)); | ||
479 | #endif | ||
480 | if (NULL == | ||
481 | GNUNET_CORE_notify_transmit_ready (pos->peer1handle, 0, timeout, | ||
482 | &pos->peer2->id, | ||
483 | sizeof (struct GNUNET_TestMessage), | ||
484 | &transmit_ready, pos)) | ||
485 | { | ||
486 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
487 | "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", | ||
488 | GNUNET_i2s (&pos->peer2->id)); | ||
489 | transmit_ready_failed++; | ||
490 | } | ||
491 | else | ||
492 | { | ||
493 | transmit_ready_scheduled++; | ||
494 | } | ||
495 | } | ||
496 | } | ||
497 | |||
498 | /** | ||
499 | * Method called whenever a given peer connects. | ||
500 | * | ||
501 | * @param cls closure | ||
502 | * @param peer peer identity this notification is about | ||
503 | * @param atsi performance data for the connection | ||
504 | */ | ||
505 | static void | ||
506 | connect_notify_peers (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
507 | const struct GNUNET_ATS_Information *atsi) | ||
508 | { | ||
509 | struct TestMessageContext *pos = cls; | ||
510 | |||
511 | if (0 == memcmp (peer, &pos->peer2->id, sizeof (struct GNUNET_PeerIdentity))) | ||
512 | { | ||
513 | pos->peer1notified = GNUNET_YES; | ||
514 | #if VERBOSE > 1 | ||
515 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
516 | "Peer `%s' notified of connection to peer `%s'\n", | ||
517 | GNUNET_i2s (&pos->peer1->id), GNUNET_h2s (&peer->hashPubKey)); | ||
518 | #endif | ||
519 | } | ||
520 | else | ||
521 | return; | ||
522 | |||
523 | if (pos->peer2connected == GNUNET_YES) /* Already connected and notified of connection, send message! */ | ||
524 | { | ||
525 | #if VERBOSE > 1 | ||
526 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
527 | "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n", | ||
528 | GNUNET_i2s (&pos->peer2->id), | ||
529 | GNUNET_h2s (&pos->peer1->id.hashPubKey)); | ||
530 | #endif | ||
531 | if (NULL == | ||
532 | GNUNET_CORE_notify_transmit_ready (pos->peer1handle, 0, timeout, | ||
533 | &pos->peer2->id, | ||
534 | sizeof (struct GNUNET_TestMessage), | ||
535 | &transmit_ready, pos)) | ||
536 | { | ||
537 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
538 | "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", | ||
539 | GNUNET_i2s (&pos->peer2->id)); | ||
540 | transmit_ready_failed++; | ||
541 | } | ||
542 | else | ||
543 | { | ||
544 | transmit_ready_scheduled++; | ||
545 | } | ||
546 | } | ||
547 | } | ||
548 | |||
549 | static void | ||
550 | init_notify_peer1 (void *cls, struct GNUNET_CORE_Handle *server, | ||
551 | const struct GNUNET_PeerIdentity *my_identity) | ||
552 | { | ||
553 | struct TestMessageContext *pos = cls; | ||
554 | |||
555 | total_server_connections++; | ||
556 | |||
557 | #if VERBOSE > 1 | ||
558 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
559 | "Core connection to `%4s' established, setting up handles\n", | ||
560 | GNUNET_i2s (my_identity)); | ||
561 | #endif | ||
562 | |||
563 | /* | ||
564 | * Connect to the receiving peer | ||
565 | */ | ||
566 | pos->peer2handle = | ||
567 | GNUNET_CORE_connect (pos->peer2->cfg, pos, &init_notify_peer2, NULL, | ||
568 | NULL, NULL, NULL, GNUNET_YES, NULL, GNUNET_YES, | ||
569 | handlers); | ||
570 | |||
571 | } | ||
572 | |||
573 | |||
574 | static void | ||
575 | send_test_messages (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
576 | { | ||
577 | struct TestMessageContext *pos = cls; | ||
578 | |||
579 | if ((pos == test_messages) && (settle_time.rel_value > 0)) | ||
580 | { | ||
581 | topology_connections = 0; | ||
582 | GNUNET_TESTING_get_topology (pg, &topology_cb, NULL); | ||
583 | } | ||
584 | if (((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) || (cls == NULL)) | ||
585 | return; | ||
586 | |||
587 | if (die_task == GNUNET_SCHEDULER_NO_TASK) | ||
588 | { | ||
589 | die_task = | ||
590 | GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly, | ||
591 | "from send test messages (timeout)"); | ||
592 | } | ||
593 | |||
594 | if (total_server_connections >= MAX_OUTSTANDING_CONNECTIONS) | ||
595 | { | ||
596 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
597 | (GNUNET_TIME_UNIT_SECONDS, 1), | ||
598 | &send_test_messages, pos); | ||
599 | return; /* Otherwise we'll double schedule messages here! */ | ||
600 | } | ||
601 | |||
602 | /* | ||
603 | * Connect to the sending peer | ||
604 | */ | ||
605 | pos->peer1handle = | ||
606 | GNUNET_CORE_connect (pos->peer1->cfg, pos, &init_notify_peer1, | ||
607 | &connect_notify_peers, NULL, NULL, NULL, GNUNET_NO, | ||
608 | NULL, GNUNET_NO, no_handlers); | ||
609 | |||
610 | GNUNET_assert (pos->peer1handle != NULL); | ||
611 | |||
612 | if (total_server_connections < MAX_OUTSTANDING_CONNECTIONS) | ||
613 | { | ||
614 | GNUNET_SCHEDULER_add_now (&send_test_messages, pos->next); | ||
615 | } | ||
616 | else | ||
617 | { | ||
618 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
619 | (GNUNET_TIME_UNIT_SECONDS, 1), | ||
620 | &send_test_messages, pos->next); | ||
621 | } | ||
622 | } | ||
623 | |||
624 | |||
625 | void | ||
626 | topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, | ||
627 | const struct GNUNET_PeerIdentity *second, uint32_t distance, | ||
628 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
629 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
630 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
631 | struct GNUNET_TESTING_Daemon *second_daemon, | ||
632 | const char *emsg) | ||
633 | { | ||
634 | struct TestMessageContext *temp_context; | ||
635 | |||
636 | if (emsg == NULL) | ||
637 | { | ||
638 | #if VERBOSE | ||
639 | if ((total_connections) % modnum == 0) | ||
640 | { | ||
641 | if (total_connections == 0) | ||
642 | FPRINTF (stdout, "%s", "0%%"); | ||
643 | else | ||
644 | FPRINTF (stdout, "%d%%", | ||
645 | (int) (((float) total_connections / expected_connections) * | ||
646 | 100)); | ||
647 | |||
648 | } | ||
649 | else if (total_connections % dotnum == 0) | ||
650 | { | ||
651 | FPRINTF (stdout, "%s", "."); | ||
652 | } | ||
653 | fflush (stdout); | ||
654 | #endif | ||
655 | total_connections++; | ||
656 | #if VERBOSE > 1 | ||
657 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "connected peer %s to peer %s\n", | ||
658 | first_daemon->shortname, second_daemon->shortname); | ||
659 | #endif | ||
660 | temp_context = GNUNET_malloc (sizeof (struct TestMessageContext)); | ||
661 | temp_context->peer1 = first_daemon; | ||
662 | temp_context->peer2 = second_daemon; | ||
663 | temp_context->next = test_messages; | ||
664 | temp_context->uid = total_connections; | ||
665 | temp_context->disconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
666 | test_messages = temp_context; | ||
667 | |||
668 | expected_messages++; | ||
669 | if (dotOutFile != NULL) | ||
670 | FPRINTF (dotOutFile, "\tn%s -- n%s;\n", first_daemon->shortname, | ||
671 | second_daemon->shortname); | ||
672 | } | ||
673 | #if VERBOSE | ||
674 | else | ||
675 | { | ||
676 | failed_connections++; | ||
677 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
678 | "Failed to connect peer %s to peer %s with error :\n%s\n", | ||
679 | first_daemon->shortname, second_daemon->shortname, emsg); | ||
680 | } | ||
681 | #endif | ||
682 | |||
683 | if (total_connections == expected_connections) | ||
684 | { | ||
685 | #if VERBOSE | ||
686 | FPRINTF (stdout, "%s", "100%%]\n"); | ||
687 | #endif | ||
688 | #if VERBOSE | ||
689 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
690 | "Created %d total connections, which is our target number! Calling send messages.\n", | ||
691 | total_connections); | ||
692 | #endif | ||
693 | modnum = expected_messages / 4; | ||
694 | dotnum = (expected_messages / 50) + 1; | ||
695 | GNUNET_SCHEDULER_cancel (die_task); | ||
696 | die_task = GNUNET_SCHEDULER_NO_TASK; | ||
697 | #if DELAY_FOR_LOGGING | ||
698 | FPRINTF (stdout, "%s", "Sending test messages in 10 seconds.\n"); | ||
699 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
700 | (GNUNET_TIME_UNIT_SECONDS, 10), | ||
701 | &send_test_messages, test_messages); | ||
702 | gather_log_data (); | ||
703 | #else | ||
704 | if (settle_time.rel_value > 0) | ||
705 | { | ||
706 | GNUNET_TESTING_get_topology (pg, &topology_cb, NULL); | ||
707 | } | ||
708 | GNUNET_SCHEDULER_add_delayed (settle_time, &send_test_messages, | ||
709 | test_messages); | ||
710 | #endif | ||
711 | #if VERBOSE | ||
712 | FPRINTF (stdout, "%s", "Test message progress: ["); | ||
713 | #endif | ||
714 | |||
715 | } | ||
716 | else if (total_connections + failed_connections == expected_connections) | ||
717 | { | ||
718 | if (failed_connections < | ||
719 | (unsigned int) (fail_percentage * total_connections)) | ||
720 | { | ||
721 | GNUNET_SCHEDULER_cancel (die_task); | ||
722 | die_task = GNUNET_SCHEDULER_NO_TASK; | ||
723 | GNUNET_SCHEDULER_add_now (&send_test_messages, test_messages); | ||
724 | } | ||
725 | else | ||
726 | { | ||
727 | GNUNET_SCHEDULER_cancel (die_task); | ||
728 | die_task = | ||
729 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
730 | "from topology_callback (too many failed connections)"); | ||
731 | } | ||
732 | } | ||
733 | else | ||
734 | { | ||
735 | #if VERBOSE > 1 | ||
736 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
737 | "Have %d total connections, %d failed connections, Want %d (at least %d)\n", | ||
738 | total_connections, failed_connections, expected_connections, | ||
739 | expected_connections - | ||
740 | (unsigned int) (fail_percentage * expected_connections)); | ||
741 | #endif | ||
742 | } | ||
743 | } | ||
744 | |||
745 | static void | ||
746 | topology_creation_finished (void *cls, const char *emsg) | ||
747 | { | ||
748 | #if VERBOSE | ||
749 | if (emsg == NULL) | ||
750 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
751 | "All topology connections created successfully!\n"); | ||
752 | #endif | ||
753 | } | ||
754 | |||
755 | static void | ||
756 | connect_topology () | ||
757 | { | ||
758 | expected_connections = -1; | ||
759 | if ((pg != NULL) && (peers_left == 0)) | ||
760 | { | ||
761 | expected_connections = | ||
762 | GNUNET_TESTING_connect_topology (pg, connection_topology, | ||
763 | connect_topology_option, | ||
764 | connect_topology_option_modifier, | ||
765 | connect_timeout, connect_attempts, | ||
766 | &topology_creation_finished, NULL); | ||
767 | #if VERBOSE > 1 | ||
768 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n", | ||
769 | expected_connections); | ||
770 | #endif | ||
771 | } | ||
772 | |||
773 | GNUNET_SCHEDULER_cancel (die_task); | ||
774 | if (expected_connections == GNUNET_SYSERR) | ||
775 | { | ||
776 | die_task = | ||
777 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
778 | "from connect topology (bad return)"); | ||
779 | } | ||
780 | |||
781 | die_task = | ||
782 | GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly, | ||
783 | "from connect topology (timeout)"); | ||
784 | modnum = expected_connections / 4; | ||
785 | dotnum = (expected_connections / 50) + 1; | ||
786 | #if VERBOSE | ||
787 | FPRINTF (stdout, "%s", "Peer connection progress: ["); | ||
788 | #endif | ||
789 | } | ||
790 | |||
791 | static void | ||
792 | create_topology () | ||
793 | { | ||
794 | peers_left = num_peers; /* Reset counter */ | ||
795 | if (GNUNET_TESTING_create_topology | ||
796 | (pg, topology, blacklist_topology, blacklist_transports) != GNUNET_SYSERR) | ||
797 | { | ||
798 | #if VERBOSE | ||
799 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
800 | "Topology set up, now starting peers!\n"); | ||
801 | FPRINTF (stdout, "%s", "Daemon start progress ["); | ||
802 | #endif | ||
803 | GNUNET_TESTING_daemons_continue_startup (pg); | ||
804 | } | ||
805 | else | ||
806 | { | ||
807 | GNUNET_SCHEDULER_cancel (die_task); | ||
808 | die_task = | ||
809 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
810 | "from create topology (bad return)"); | ||
811 | } | ||
812 | GNUNET_SCHEDULER_cancel (die_task); | ||
813 | die_task = | ||
814 | GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly, | ||
815 | "from continue startup (timeout)"); | ||
816 | } | ||
817 | |||
818 | |||
819 | static void | ||
820 | peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
821 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
822 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
823 | { | ||
824 | if (emsg != NULL) | ||
825 | { | ||
826 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
827 | "Failed to start daemon with error: `%s'\n", emsg); | ||
828 | return; | ||
829 | } | ||
830 | GNUNET_assert (id != NULL); | ||
831 | #if VERBOSE > 1 | ||
832 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n", | ||
833 | (num_peers - peers_left) + 1, num_peers); | ||
834 | #endif | ||
835 | #if VERBOSE | ||
836 | if ((num_peers - peers_left) % modnum == 0) | ||
837 | { | ||
838 | if (num_peers - peers_left == 0) | ||
839 | FPRINTF (stdout, "%s", "0%%"); | ||
840 | else | ||
841 | FPRINTF (stdout, "%d%%", | ||
842 | (int) (((float) (num_peers - peers_left) / num_peers) * 100)); | ||
843 | |||
844 | } | ||
845 | else if ((num_peers - peers_left) % dotnum == 0) | ||
846 | { | ||
847 | FPRINTF (stdout, "%s", "."); | ||
848 | } | ||
849 | fflush (stdout); | ||
850 | #endif | ||
851 | peers_left--; | ||
852 | if (peers_left == 0) | ||
853 | { | ||
854 | #if VERBOSE | ||
855 | FPRINTF (stdout, "%s", "100%%]\n"); | ||
856 | #endif | ||
857 | #if VERBOSE | ||
858 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
859 | "All %d daemons started, now connecting peers!\n", num_peers); | ||
860 | #endif | ||
861 | GNUNET_SCHEDULER_cancel (die_task); | ||
862 | /* Set up task in case topology creation doesn't finish | ||
863 | * within a reasonable amount of time */ | ||
864 | die_task = | ||
865 | GNUNET_SCHEDULER_add_delayed (timeout, &end_badly, | ||
866 | "from peers_started_callback"); | ||
867 | #if DELAY_FOR_LOGGING | ||
868 | FPRINTF (stdout, "%s", "Connecting topology in 10 seconds\n"); | ||
869 | gather_log_data (); | ||
870 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
871 | (GNUNET_TIME_UNIT_SECONDS, 10), | ||
872 | &connect_topology, NULL); | ||
873 | #else | ||
874 | connect_topology (); | ||
875 | #endif | ||
876 | ok = 0; | ||
877 | } | ||
878 | } | ||
879 | |||
880 | /** | ||
881 | * Callback indicating that the hostkey was created for a peer. | ||
882 | * | ||
883 | * @param cls NULL | ||
884 | * @param id the peer identity | ||
885 | * @param d the daemon handle (pretty useless at this point, remove?) | ||
886 | * @param emsg non-null on failure | ||
887 | */ | ||
888 | void | ||
889 | hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
890 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
891 | { | ||
892 | if (emsg != NULL) | ||
893 | { | ||
894 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
895 | "Hostkey callback received error: %s\n", emsg); | ||
896 | } | ||
897 | |||
898 | #if VERBOSE > 1 | ||
899 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
900 | "Hostkey (%d/%d) created for peer `%s'\n", num_peers - peers_left, | ||
901 | num_peers, GNUNET_i2s (id)); | ||
902 | #endif | ||
903 | |||
904 | #if VERBOSE | ||
905 | if ((num_peers - peers_left) % modnum == 0) | ||
906 | { | ||
907 | if (num_peers - peers_left == 0) | ||
908 | FPRINTF (stdout, "%s", "0%%"); | ||
909 | else | ||
910 | FPRINTF (stdout, "%d%%", | ||
911 | (int) (((float) (num_peers - peers_left) / num_peers) * 100)); | ||
912 | |||
913 | } | ||
914 | else if ((num_peers - peers_left) % dotnum == 0) | ||
915 | { | ||
916 | FPRINTF (stdout, "%s", "."); | ||
917 | } | ||
918 | fflush (stdout); | ||
919 | #endif | ||
920 | peers_left--; | ||
921 | if (peers_left == 0) | ||
922 | { | ||
923 | #if VERBOSE | ||
924 | FPRINTF (stdout, "%s", "100%%]\n"); | ||
925 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
926 | "All %d hostkeys created, now creating topology!\n", num_peers); | ||
927 | #endif | ||
928 | GNUNET_SCHEDULER_cancel (die_task); | ||
929 | /* Set up task in case topology creation doesn't finish | ||
930 | * within a reasonable amount of time */ | ||
931 | die_task = | ||
932 | GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly, | ||
933 | "from create_topology"); | ||
934 | GNUNET_SCHEDULER_add_now (&create_topology, NULL); | ||
935 | ok = 0; | ||
936 | } | ||
937 | } | ||
938 | |||
939 | static void | ||
940 | run (void *cls, char *const *args, const char *cfgfile, | ||
941 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
942 | { | ||
943 | char *topology_str; | ||
944 | char *connect_topology_str; | ||
945 | char *blacklist_topology_str; | ||
946 | char *connect_topology_option_str; | ||
947 | char *connect_topology_option_modifier_string; | ||
948 | unsigned long long temp_settle; | ||
949 | |||
950 | ok = 1; | ||
951 | |||
952 | dotOutFile = FOPEN (dotOutFileName, "w"); | ||
953 | if (dotOutFile != NULL) | ||
954 | { | ||
955 | FPRINTF (dotOutFile, "%s", "strict graph G {\n"); | ||
956 | } | ||
957 | |||
958 | #if VERBOSE | ||
959 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
960 | "Starting daemons based on config file %s\n", cfgfile); | ||
961 | #endif | ||
962 | |||
963 | if (GNUNET_YES != | ||
964 | GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", | ||
965 | &test_directory)) | ||
966 | { | ||
967 | ok = 404; | ||
968 | return; | ||
969 | } | ||
970 | |||
971 | if ((GNUNET_YES == | ||
972 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "topology", | ||
973 | &topology_str)) && | ||
974 | (GNUNET_NO == GNUNET_TESTING_topology_get (&topology, topology_str))) | ||
975 | { | ||
976 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
977 | "Invalid topology `%s' given for section %s option %s\n", | ||
978 | topology_str, "TESTING", "TOPOLOGY"); | ||
979 | topology = GNUNET_TESTING_TOPOLOGY_CLIQUE; /* Defaults to NONE, so set better default here */ | ||
980 | } | ||
981 | |||
982 | if ((GNUNET_YES == | ||
983 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", | ||
984 | "connect_topology", | ||
985 | &connect_topology_str)) && | ||
986 | (GNUNET_NO == | ||
987 | GNUNET_TESTING_topology_get (&connection_topology, | ||
988 | connect_topology_str))) | ||
989 | { | ||
990 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
991 | "Invalid connect topology `%s' given for section %s option %s\n", | ||
992 | connect_topology_str, "TESTING", "CONNECT_TOPOLOGY"); | ||
993 | } | ||
994 | GNUNET_free_non_null (connect_topology_str); | ||
995 | if ((GNUNET_YES == | ||
996 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", | ||
997 | "connect_topology_option", | ||
998 | &connect_topology_option_str)) && | ||
999 | (GNUNET_NO == | ||
1000 | GNUNET_TESTING_topology_option_get (&connect_topology_option, | ||
1001 | connect_topology_option_str))) | ||
1002 | { | ||
1003 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1004 | "Invalid connect topology option `%s' given for section %s option %s\n", | ||
1005 | connect_topology_option_str, "TESTING", | ||
1006 | "CONNECT_TOPOLOGY_OPTION"); | ||
1007 | connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Defaults to NONE, set to ALL */ | ||
1008 | } | ||
1009 | GNUNET_free_non_null (connect_topology_option_str); | ||
1010 | if (GNUNET_YES == | ||
1011 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", | ||
1012 | "connect_topology_option_modifier", | ||
1013 | &connect_topology_option_modifier_string)) | ||
1014 | { | ||
1015 | if (SSCANF | ||
1016 | (connect_topology_option_modifier_string, "%lf", | ||
1017 | &connect_topology_option_modifier) != 1) | ||
1018 | { | ||
1019 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1020 | _ | ||
1021 | ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), | ||
1022 | connect_topology_option_modifier_string, | ||
1023 | "connect_topology_option_modifier", "TESTING"); | ||
1024 | } | ||
1025 | GNUNET_free (connect_topology_option_modifier_string); | ||
1026 | } | ||
1027 | |||
1028 | if (GNUNET_YES != | ||
1029 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", | ||
1030 | "blacklist_transports", | ||
1031 | &blacklist_transports)) | ||
1032 | blacklist_transports = NULL; | ||
1033 | |||
1034 | if ((GNUNET_YES == | ||
1035 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", | ||
1036 | "blacklist_topology", | ||
1037 | &blacklist_topology_str)) && | ||
1038 | (GNUNET_NO == | ||
1039 | GNUNET_TESTING_topology_get (&blacklist_topology, | ||
1040 | blacklist_topology_str))) | ||
1041 | { | ||
1042 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1043 | "Invalid topology `%s' given for section %s option %s\n", | ||
1044 | topology_str, "TESTING", "BLACKLIST_TOPOLOGY"); | ||
1045 | } | ||
1046 | GNUNET_free_non_null (topology_str); | ||
1047 | GNUNET_free_non_null (blacklist_topology_str); | ||
1048 | |||
1049 | if (GNUNET_OK != | ||
1050 | GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "SETTLE_TIME", | ||
1051 | &settle_time)) | ||
1052 | { | ||
1053 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
1054 | "testing", "SETTLE_TIME"); | ||
1055 | return; | ||
1056 | } | ||
1057 | if (GNUNET_SYSERR == | ||
1058 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers", | ||
1059 | &num_peers)) | ||
1060 | num_peers = DEFAULT_NUM_PEERS; | ||
1061 | |||
1062 | if (GNUNET_OK != | ||
1063 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "CONNECT_TIMEOUT", | ||
1064 | &connect_timeout)) | ||
1065 | { | ||
1066 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
1067 | "testing", "CONNECT_TIMEOUT"); | ||
1068 | return; | ||
1069 | } | ||
1070 | |||
1071 | |||
1072 | if (GNUNET_OK != | ||
1073 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts", | ||
1074 | &connect_attempts)) | ||
1075 | { | ||
1076 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
1077 | "testing", "connect_attempts"); | ||
1078 | return; | ||
1079 | } | ||
1080 | |||
1081 | main_cfg = cfg; | ||
1082 | |||
1083 | peers_left = num_peers; | ||
1084 | |||
1085 | /** | ||
1086 | * How long until we fail the whole testcase? | ||
1087 | */ | ||
1088 | test_timeout = | ||
1089 | GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_multiply | ||
1090 | (GNUNET_TIME_UNIT_SECONDS, | ||
1091 | SECONDS_PER_PEER_START), num_peers * 2); | ||
1092 | |||
1093 | /** | ||
1094 | * How long until we give up on starting the peers? | ||
1095 | */ | ||
1096 | timeout = | ||
1097 | GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_multiply | ||
1098 | (GNUNET_TIME_UNIT_SECONDS, | ||
1099 | SECONDS_PER_PEER_START), num_peers); | ||
1100 | |||
1101 | modnum = num_peers / 4; | ||
1102 | dotnum = (num_peers / 50) + 1; | ||
1103 | #if VERBOSE | ||
1104 | FPRINTF (stdout, "%s", "Hostkey generation progress: ["); | ||
1105 | #endif | ||
1106 | /* Set up a task to end testing if peer start fails */ | ||
1107 | die_task = | ||
1108 | GNUNET_SCHEDULER_add_delayed (timeout, &end_badly, | ||
1109 | "didn't generate all hostkeys within a reasonable amount of time!!!"); | ||
1110 | |||
1111 | GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1); | ||
1112 | pg = GNUNET_TESTING_daemons_start (cfg, peers_left, peers_left / 2, | ||
1113 | peers_left, timeout, &hostkey_callback, | ||
1114 | NULL, &peers_started_callback, NULL, | ||
1115 | &topology_callback, NULL, NULL); | ||
1116 | |||
1117 | } | ||
1118 | |||
1119 | static int | ||
1120 | check () | ||
1121 | { | ||
1122 | char *binary_name; | ||
1123 | char *config_file_name; | ||
1124 | |||
1125 | GNUNET_asprintf (&binary_name, "test-testing-topology-%s", topology_string); | ||
1126 | GNUNET_asprintf (&config_file_name, "test_testing_data_topology_%s.conf", | ||
1127 | topology_string); | ||
1128 | int ret; | ||
1129 | |||
1130 | char *const argv[] = { binary_name, | ||
1131 | "-c", | ||
1132 | config_file_name, | ||
1133 | #if VERBOSE | ||
1134 | "-L", "DEBUG", | ||
1135 | #endif | ||
1136 | NULL | ||
1137 | }; | ||
1138 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
1139 | GNUNET_GETOPT_OPTION_END | ||
1140 | }; | ||
1141 | ret = | ||
1142 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
1143 | binary_name, "nohelp", options, &run, &ok); | ||
1144 | if (ret != GNUNET_OK) | ||
1145 | { | ||
1146 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1147 | "`test-testing-topology-%s': Failed with error code %d\n", | ||
1148 | topology_string, ret); | ||
1149 | } | ||
1150 | GNUNET_free (binary_name); | ||
1151 | GNUNET_free (config_file_name); | ||
1152 | return ok; | ||
1153 | } | ||
1154 | |||
1155 | int | ||
1156 | main (int argc, char *argv[]) | ||
1157 | { | ||
1158 | int ret; | ||
1159 | char *binary_start_pos; | ||
1160 | char *our_binary_name; | ||
1161 | |||
1162 | binary_start_pos = strrchr (argv[0], '/'); | ||
1163 | GNUNET_assert (binary_start_pos != NULL); | ||
1164 | topology_string = strstr (binary_start_pos, "_topology"); | ||
1165 | GNUNET_assert (topology_string != NULL); | ||
1166 | topology_string++; | ||
1167 | topology_string = strstr (topology_string, "_"); | ||
1168 | GNUNET_assert (topology_string != NULL); | ||
1169 | topology_string++; | ||
1170 | |||
1171 | GNUNET_asprintf (&our_binary_name, "test-testing-large-topology_%s", | ||
1172 | topology_string); | ||
1173 | GNUNET_asprintf (&dotOutFileName, "large_topology_%s.dot", topology_string); | ||
1174 | |||
1175 | GNUNET_log_setup (our_binary_name, | ||
1176 | #if VERBOSE | ||
1177 | "DEBUG", | ||
1178 | #else | ||
1179 | "WARNING", | ||
1180 | #endif | ||
1181 | NULL); | ||
1182 | ret = check (); | ||
1183 | |||
1184 | /** | ||
1185 | * Need to remove base directory, subdirectories taken care | ||
1186 | * of by the testing framework. | ||
1187 | */ | ||
1188 | if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK) | ||
1189 | { | ||
1190 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1191 | "Failed to remove testing directory %s\n", test_directory); | ||
1192 | } | ||
1193 | GNUNET_free (our_binary_name); | ||
1194 | return ret; | ||
1195 | } | ||
1196 | |||
1197 | /* end of test_testing_topology.c */ | ||
diff --git a/src/testing_old/test_testing_peergroup.c b/src/testing_old/test_testing_peergroup.c deleted file mode 100644 index 061a0ca75..000000000 --- a/src/testing_old/test_testing_peergroup.c +++ /dev/null | |||
@@ -1,157 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file testing/test_testing_peergroup.c | ||
22 | * @brief testcase for functions to connect peers in testing_peergroup.c | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_testing_lib.h" | ||
26 | |||
27 | #define VERBOSE GNUNET_NO | ||
28 | |||
29 | #define NUM_PEERS 4 | ||
30 | |||
31 | /** | ||
32 | * How long until we give up on connecting the peers? | ||
33 | */ | ||
34 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) | ||
35 | |||
36 | static int ok; | ||
37 | |||
38 | static int peers_left; | ||
39 | |||
40 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
41 | |||
42 | /** | ||
43 | * Check whether peers successfully shut down. | ||
44 | */ | ||
45 | void | ||
46 | shutdown_callback (void *cls, const char *emsg) | ||
47 | { | ||
48 | if (emsg != NULL) | ||
49 | { | ||
50 | #if VERBOSE | ||
51 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n"); | ||
52 | #endif | ||
53 | if (ok == 0) | ||
54 | ok = 666; | ||
55 | } | ||
56 | else | ||
57 | { | ||
58 | #if VERBOSE | ||
59 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); | ||
60 | #endif | ||
61 | ok = 0; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | |||
66 | static void | ||
67 | my_cb (void *cls, const char *emsg) | ||
68 | { | ||
69 | if (emsg != NULL) | ||
70 | { | ||
71 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
72 | "Peergroup callback called with error, aborting test!\n"); | ||
73 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n"); | ||
74 | ok = 1; | ||
75 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
76 | return; | ||
77 | } | ||
78 | |||
79 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
80 | "Peer Group started successfully, ending test!\n"); | ||
81 | /** | ||
82 | * If something is to actually be DONE with the testcase, it should | ||
83 | * be put in here. Usually there will be a struct declared (or global | ||
84 | * variables can be used) to keep track of the state, statistics, | ||
85 | * handles to peers, etc. The example here is the opaque "TestCaseData" | ||
86 | * struct that could be passed into a function "additional_code_for_testing" | ||
87 | * which can be used to perform actions on the peers in the peergroup. | ||
88 | * Also, the GNUNET_TESTING_daemons_stop call would need to be removed, | ||
89 | * and only called once all of the testing is complete. | ||
90 | */ | ||
91 | |||
92 | /** | ||
93 | * struct TestcaseData *state_closure; | ||
94 | * GNUNET_SCHEDULER_add_now(&additional_code_for_testing, state_closure); | ||
95 | */ | ||
96 | |||
97 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
98 | } | ||
99 | |||
100 | |||
101 | static void | ||
102 | run (void *cls, char *const *args, const char *cfgfile, | ||
103 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
104 | { | ||
105 | struct GNUNET_CONFIGURATION_Handle *testing_cfg; | ||
106 | |||
107 | ok = 1; | ||
108 | testing_cfg = GNUNET_CONFIGURATION_create (); | ||
109 | GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (testing_cfg, cfgfile)); | ||
110 | #if VERBOSE | ||
111 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n"); | ||
112 | GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing", | ||
113 | "use_progressbars", "YES"); | ||
114 | #endif | ||
115 | peers_left = NUM_PEERS; | ||
116 | pg = GNUNET_TESTING_peergroup_start (testing_cfg, peers_left, TIMEOUT, NULL, | ||
117 | &my_cb, NULL, NULL); | ||
118 | GNUNET_assert (pg != NULL); | ||
119 | } | ||
120 | |||
121 | static int | ||
122 | check () | ||
123 | { | ||
124 | char *const argv[] = { "test-testing-peergroup", | ||
125 | "-c", | ||
126 | "test_testing_peergroup_data.conf", | ||
127 | #if VERBOSE | ||
128 | "-L", "DEBUG", | ||
129 | #endif | ||
130 | NULL | ||
131 | }; | ||
132 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
133 | GNUNET_GETOPT_OPTION_END | ||
134 | }; | ||
135 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
136 | "test-testing-peergroup", "nohelp", options, &run, &ok); | ||
137 | return ok; | ||
138 | } | ||
139 | |||
140 | int | ||
141 | main (int argc, char *argv[]) | ||
142 | { | ||
143 | int ret; | ||
144 | |||
145 | GNUNET_log_setup ("test-testing-peergroup", | ||
146 | #if VERBOSE | ||
147 | "DEBUG", | ||
148 | #else | ||
149 | "WARNING", | ||
150 | #endif | ||
151 | NULL); | ||
152 | ret = check (); | ||
153 | GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing"); | ||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | /* end of test_testing_peergroup.c */ | ||
diff --git a/src/testing_old/test_testing_peergroup_data.conf b/src/testing_old/test_testing_peergroup_data.conf deleted file mode 100644 index f642627a1..000000000 --- a/src/testing_old/test_testing_peergroup_data.conf +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | @INLINE@ test_testing_defaults.conf | ||
2 | [PATHS] | ||
3 | |||
4 | [TESTING_old] | ||
5 | CONNECT_ATTEMPTS = 2 | ||
6 | MAX_OUTSTANDING_CONNECTIONS = 20 | ||
7 | MAX_CONCURRENT_SSH = 1 | ||
8 | PEERGROUP_TIMEOUT = 300 s | ||
9 | TOPOLOGY = CLIQUE | ||
10 | PERCENTAGE = 0.5 | ||
11 | PROBABILITY = 0.5 | ||
12 | CONNECT_TOPOLOGY = CLIQUE | ||
13 | CONNECT_TOPOLOGY_OPTION = CONNECT_NONE | ||
14 | CONNECT_TOPOLOGY_OPTION_MODIFIER = 0.0 | ||
15 | BLACKLIST_TOPOLOGY = NONE | ||
16 | BLACKLIST_TRANSPORTS = tcp udp | ||
17 | USE_PROGRESSBARS = NO | ||
18 | |||
19 | [arm] | ||
20 | DEFAULTSERVICES = core | ||
21 | |||
diff --git a/src/testing_old/test_testing_reconnect.c b/src/testing_old/test_testing_reconnect.c deleted file mode 100644 index bcee38659..000000000 --- a/src/testing_old/test_testing_reconnect.c +++ /dev/null | |||
@@ -1,249 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file testing/test_testing_reconnect.c | ||
22 | * @brief testcase for functions to connect two peers in testing.c | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_testing_lib.h" | ||
26 | |||
27 | #define VERBOSE GNUNET_YES | ||
28 | |||
29 | /** | ||
30 | * How long until we give up on connecting the peers? | ||
31 | */ | ||
32 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) | ||
33 | |||
34 | #define CONNECT_ATTEMPTS 3 | ||
35 | |||
36 | static int ok; | ||
37 | |||
38 | static struct GNUNET_TESTING_Daemon *d1; | ||
39 | |||
40 | static struct GNUNET_TESTING_Daemon *d2; | ||
41 | |||
42 | static struct GNUNET_CONFIGURATION_Handle *c1; | ||
43 | |||
44 | static struct GNUNET_CONFIGURATION_Handle *c2; | ||
45 | |||
46 | static struct GNUNET_TESTING_ConnectContext *cc; | ||
47 | |||
48 | /** | ||
49 | * How many start-connect-stop iterations should we do? | ||
50 | */ | ||
51 | #define NUM_PHASES 2 | ||
52 | |||
53 | static int phase; | ||
54 | |||
55 | /** | ||
56 | * Run the next phase of starting daemons, connecting them and | ||
57 | * stopping them again. | ||
58 | */ | ||
59 | static void | ||
60 | run_phase (void); | ||
61 | |||
62 | static void | ||
63 | end2_cb (void *cls, const char *emsg) | ||
64 | { | ||
65 | |||
66 | if (emsg != NULL) | ||
67 | { | ||
68 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg); | ||
69 | ok = 1; | ||
70 | } | ||
71 | else | ||
72 | { | ||
73 | if (phase < NUM_PHASES) | ||
74 | { | ||
75 | FPRINTF (stderr, "%s", "."); | ||
76 | run_phase (); | ||
77 | return; | ||
78 | } | ||
79 | FPRINTF (stderr, "%s", ".\n"); | ||
80 | #if VERBOSE | ||
81 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
82 | "Both daemons terminated, will now exit.\n"); | ||
83 | #endif | ||
84 | ok = 0; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static void | ||
89 | end1_cb (void *cls, const char *emsg) | ||
90 | { | ||
91 | if (emsg != NULL) | ||
92 | { | ||
93 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Stopping daemon 1 gave: %s\n", | ||
94 | emsg); | ||
95 | ok = 1; | ||
96 | } | ||
97 | else | ||
98 | { | ||
99 | ok = 0; | ||
100 | } | ||
101 | if (d2 != NULL) | ||
102 | { | ||
103 | GNUNET_TESTING_daemon_stop (d2, TIMEOUT, &end2_cb, NULL, | ||
104 | (phase == NUM_PHASES) ? GNUNET_YES : GNUNET_NO, | ||
105 | GNUNET_NO); | ||
106 | d2 = NULL; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | static void | ||
111 | finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
112 | { | ||
113 | GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &end1_cb, NULL, | ||
114 | (phase == NUM_PHASES) ? GNUNET_YES : GNUNET_NO, | ||
115 | GNUNET_NO); | ||
116 | d1 = NULL; | ||
117 | } | ||
118 | |||
119 | |||
120 | static void | ||
121 | my_connect_complete (void *cls, const struct GNUNET_PeerIdentity *first, | ||
122 | const struct GNUNET_PeerIdentity *second, | ||
123 | unsigned int distance, | ||
124 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
125 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
126 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
127 | struct GNUNET_TESTING_Daemon *second_daemon, | ||
128 | const char *emsg) | ||
129 | { | ||
130 | cc = NULL; | ||
131 | #if VERBOSE | ||
132 | FPRINTF (stderr, "Peer %s ", GNUNET_i2s (first)); | ||
133 | FPRINTF (stderr, "connected to %s\n", GNUNET_i2s (second)); | ||
134 | #endif | ||
135 | GNUNET_SCHEDULER_add_now (&finish_testing, NULL); | ||
136 | } | ||
137 | |||
138 | |||
139 | |||
140 | |||
141 | static void | ||
142 | my_cb2 (void *cls, const struct GNUNET_PeerIdentity *id, | ||
143 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
144 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
145 | { | ||
146 | if (emsg != NULL) | ||
147 | { | ||
148 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Starting daemon 2 gave: %s\n", | ||
149 | emsg); | ||
150 | GNUNET_assert (0); | ||
151 | return; | ||
152 | } | ||
153 | GNUNET_assert (id != NULL); | ||
154 | #if VERBOSE | ||
155 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n", | ||
156 | GNUNET_i2s (id)); | ||
157 | #endif | ||
158 | cc = GNUNET_TESTING_daemons_connect (d1, d2, TIMEOUT, CONNECT_ATTEMPTS, | ||
159 | GNUNET_YES, &my_connect_complete, NULL); | ||
160 | } | ||
161 | |||
162 | |||
163 | static void | ||
164 | my_cb1 (void *cls, const struct GNUNET_PeerIdentity *id, | ||
165 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
166 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
167 | { | ||
168 | if (emsg != NULL) | ||
169 | { | ||
170 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Starting daemon 1 gave: %s\n", | ||
171 | emsg); | ||
172 | GNUNET_assert (0); | ||
173 | return; | ||
174 | } | ||
175 | GNUNET_assert (id != NULL); | ||
176 | #if VERBOSE | ||
177 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n", | ||
178 | GNUNET_i2s (id)); | ||
179 | #endif | ||
180 | d2 = GNUNET_TESTING_daemon_start (c2, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL, | ||
181 | NULL, NULL, &my_cb2, NULL); | ||
182 | GNUNET_assert (d2 != NULL); | ||
183 | } | ||
184 | |||
185 | |||
186 | static void | ||
187 | run (void *cls, char *const *args, const char *cfgfile, | ||
188 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
189 | { | ||
190 | ok = 1; | ||
191 | #if VERBOSE | ||
192 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n"); | ||
193 | #endif | ||
194 | c1 = GNUNET_CONFIGURATION_create (); | ||
195 | GNUNET_assert (GNUNET_OK == | ||
196 | GNUNET_CONFIGURATION_load (c1, | ||
197 | "test_testing_connect_peer1.conf")); | ||
198 | c2 = GNUNET_CONFIGURATION_create (); | ||
199 | GNUNET_assert (GNUNET_OK == | ||
200 | GNUNET_CONFIGURATION_load (c2, | ||
201 | "test_testing_connect_peer2.conf")); | ||
202 | run_phase (); | ||
203 | } | ||
204 | |||
205 | static void | ||
206 | run_phase () | ||
207 | { | ||
208 | phase++; | ||
209 | d1 = GNUNET_TESTING_daemon_start (c1, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL, | ||
210 | NULL, NULL, &my_cb1, NULL); | ||
211 | GNUNET_assert (d1 != NULL); | ||
212 | } | ||
213 | |||
214 | static int | ||
215 | check () | ||
216 | { | ||
217 | char *const argv[] = { "test-testing-reconnect", | ||
218 | "-c", | ||
219 | "test_testing_data.conf", | ||
220 | #if VERBOSE | ||
221 | "-L", "DEBUG", | ||
222 | #endif | ||
223 | NULL | ||
224 | }; | ||
225 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
226 | GNUNET_GETOPT_OPTION_END | ||
227 | }; | ||
228 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
229 | "test-testing-reconnect", "nohelp", options, &run, &ok); | ||
230 | return ok; | ||
231 | } | ||
232 | |||
233 | int | ||
234 | main (int argc, char *argv[]) | ||
235 | { | ||
236 | int ret; | ||
237 | |||
238 | GNUNET_log_setup ("test-testing-reconnect", | ||
239 | #if VERBOSE | ||
240 | "DEBUG", | ||
241 | #else | ||
242 | "WARNING", | ||
243 | #endif | ||
244 | NULL); | ||
245 | ret = check (); | ||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | /* end of test_testing_reconnect.c */ | ||
diff --git a/src/testing_old/test_testing_topology.c b/src/testing_old/test_testing_topology.c deleted file mode 100644 index 62fa89b32..000000000 --- a/src/testing_old/test_testing_topology.c +++ /dev/null | |||
@@ -1,1220 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file testing/test_testing_topology.c | ||
22 | * @brief base testcase for testing all the topologies provided | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_testing_lib.h" | ||
26 | #include "gnunet_core_service.h" | ||
27 | #include "gnunet_os_lib.h" | ||
28 | |||
29 | |||
30 | #define PROGRESS_BARS GNUNET_YES | ||
31 | |||
32 | #define DELAY_FOR_LOGGING GNUNET_NO | ||
33 | |||
34 | /** | ||
35 | * How long until we fail the whole testcase? | ||
36 | */ | ||
37 | #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 240) | ||
38 | |||
39 | /** | ||
40 | * How long until we give up on starting the peers? | ||
41 | */ | ||
42 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 500) | ||
43 | |||
44 | #define SECONDS_PER_PEER_START 120 | ||
45 | |||
46 | #define DEFAULT_NUM_PEERS 4 | ||
47 | |||
48 | #define MAX_OUTSTANDING_CONNECTIONS 100 | ||
49 | |||
50 | static float fail_percentage = 0.05; | ||
51 | |||
52 | static int ok; | ||
53 | |||
54 | static unsigned long long num_peers; | ||
55 | |||
56 | struct GNUNET_TIME_Relative connect_timeout; | ||
57 | |||
58 | static unsigned long long connect_attempts; | ||
59 | |||
60 | static unsigned int topology_connections; | ||
61 | |||
62 | static unsigned int total_connections; | ||
63 | |||
64 | static unsigned int failed_connections; | ||
65 | |||
66 | static unsigned int total_server_connections; | ||
67 | |||
68 | static unsigned int total_messages_received; | ||
69 | |||
70 | static unsigned int expected_messages; | ||
71 | |||
72 | static unsigned int expected_connections; | ||
73 | |||
74 | static unsigned long long peers_left; | ||
75 | |||
76 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
77 | |||
78 | const struct GNUNET_CONFIGURATION_Handle *main_cfg; | ||
79 | |||
80 | GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
81 | |||
82 | static char *dotOutFileName; | ||
83 | |||
84 | static struct GNUNET_TIME_Relative settle_time; | ||
85 | |||
86 | static FILE *dotOutFile; | ||
87 | |||
88 | static char *topology_string; | ||
89 | |||
90 | static char *blacklist_transports; | ||
91 | |||
92 | static int transmit_ready_scheduled; | ||
93 | |||
94 | static int transmit_ready_failed; | ||
95 | |||
96 | static int transmit_ready_called; | ||
97 | |||
98 | static unsigned int modnum; | ||
99 | |||
100 | static unsigned int dotnum; | ||
101 | |||
102 | static enum GNUNET_TESTING_Topology topology; | ||
103 | |||
104 | static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* Don't do any blacklisting */ | ||
105 | |||
106 | static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */ | ||
107 | |||
108 | static enum GNUNET_TESTING_TopologyOption connect_topology_option = | ||
109 | GNUNET_TESTING_TOPOLOGY_OPTION_ALL; | ||
110 | |||
111 | static double connect_topology_option_modifier = 0.0; | ||
112 | |||
113 | static char *test_directory; | ||
114 | |||
115 | #define MTYPE 12345 | ||
116 | |||
117 | GNUNET_NETWORK_STRUCT_BEGIN | ||
118 | |||
119 | struct GNUNET_TestMessage | ||
120 | { | ||
121 | /** | ||
122 | * Header of the message | ||
123 | */ | ||
124 | struct GNUNET_MessageHeader header; | ||
125 | |||
126 | /** | ||
127 | * Unique identifier for this message. | ||
128 | */ | ||
129 | uint32_t uid; | ||
130 | }; | ||
131 | GNUNET_NETWORK_STRUCT_END | ||
132 | |||
133 | struct TestMessageContext | ||
134 | { | ||
135 | /* This is a linked list */ | ||
136 | struct TestMessageContext *next; | ||
137 | |||
138 | /* Handle to the sending peer core */ | ||
139 | struct GNUNET_CORE_Handle *peer1handle; | ||
140 | |||
141 | /* Handle to the receiving peer core */ | ||
142 | struct GNUNET_CORE_Handle *peer2handle; | ||
143 | |||
144 | /* Handle to the sending peer daemon */ | ||
145 | struct GNUNET_TESTING_Daemon *peer1; | ||
146 | |||
147 | /* Handle to the receiving peer daemon */ | ||
148 | struct GNUNET_TESTING_Daemon *peer2; | ||
149 | |||
150 | /* Identifier for this message, so we don't disconnect other peers! */ | ||
151 | uint32_t uid; | ||
152 | |||
153 | /* Has peer1 been notified already of a connection to peer2? */ | ||
154 | int peer1notified; | ||
155 | |||
156 | /* Has the core of peer2 been connected already? */ | ||
157 | int peer2connected; | ||
158 | |||
159 | /* Task for disconnecting cores, allow task to be cancelled on shutdown */ | ||
160 | GNUNET_SCHEDULER_TaskIdentifier disconnect_task; | ||
161 | |||
162 | }; | ||
163 | |||
164 | static struct TestMessageContext *test_messages; | ||
165 | |||
166 | /** | ||
167 | * Check whether peers successfully shut down. | ||
168 | */ | ||
169 | static void | ||
170 | shutdown_callback (void *cls, const char *emsg) | ||
171 | { | ||
172 | if (emsg != NULL) | ||
173 | { | ||
174 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Shutdown of peers failed: %s!\n", | ||
175 | emsg); | ||
176 | if (ok == 0) | ||
177 | ok = 666; | ||
178 | } | ||
179 | else | ||
180 | { | ||
181 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | |||
186 | #if DELAY_FOR_LOGGING | ||
187 | static void | ||
188 | gather_log_data () | ||
189 | { | ||
190 | char *peer_number; | ||
191 | char *connect_number; | ||
192 | struct GNUNET_OS_Process *mem_process; | ||
193 | |||
194 | GNUNET_asprintf (&peer_number, "%llu", num_peers); | ||
195 | GNUNET_asprintf (&connect_number, "%llu", expected_connections); | ||
196 | mem_process = | ||
197 | GNUNET_OS_start_process (NULL, NULL, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, "./memsize.pl", "memsize.pl", | ||
198 | "totals.txt", peer_number, connect_number, NULL); | ||
199 | GNUNET_OS_process_wait (mem_process); | ||
200 | GNUNET_OS_process_destroy (mem_process); | ||
201 | mem_process = NULL; | ||
202 | } | ||
203 | #endif | ||
204 | |||
205 | |||
206 | static void | ||
207 | finish_testing () | ||
208 | { | ||
209 | GNUNET_assert (pg != NULL); | ||
210 | struct TestMessageContext *pos; | ||
211 | struct TestMessageContext *free_pos; | ||
212 | |||
213 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
214 | "Called finish testing, stopping daemons.\n"); | ||
215 | pos = test_messages; | ||
216 | while (pos != NULL) | ||
217 | { | ||
218 | if (pos->peer1handle != NULL) | ||
219 | { | ||
220 | GNUNET_CORE_disconnect (pos->peer1handle); | ||
221 | pos->peer1handle = NULL; | ||
222 | } | ||
223 | if (pos->peer2handle != NULL) | ||
224 | { | ||
225 | GNUNET_CORE_disconnect (pos->peer2handle); | ||
226 | pos->peer2handle = NULL; | ||
227 | } | ||
228 | free_pos = pos; | ||
229 | pos = pos->next; | ||
230 | if (free_pos->disconnect_task != GNUNET_SCHEDULER_NO_TASK) | ||
231 | { | ||
232 | GNUNET_SCHEDULER_cancel (free_pos->disconnect_task); | ||
233 | } | ||
234 | GNUNET_free (free_pos); | ||
235 | } | ||
236 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
237 | "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n", | ||
238 | transmit_ready_scheduled, transmit_ready_failed, | ||
239 | transmit_ready_called); | ||
240 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n"); | ||
241 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
242 | |||
243 | if (dotOutFile != NULL) | ||
244 | { | ||
245 | FPRINTF (dotOutFile, "%s", "}"); | ||
246 | FCLOSE (dotOutFile); | ||
247 | } | ||
248 | ok = 0; | ||
249 | } | ||
250 | |||
251 | |||
252 | static void | ||
253 | disconnect_cores (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
254 | { | ||
255 | struct TestMessageContext *pos = cls; | ||
256 | |||
257 | /* Disconnect from the respective cores */ | ||
258 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 1 `%4s'\n", | ||
259 | GNUNET_i2s (&pos->peer1->id)); | ||
260 | if (pos->peer1handle != NULL) | ||
261 | { | ||
262 | GNUNET_CORE_disconnect (pos->peer1handle); | ||
263 | pos->peer1handle = NULL; | ||
264 | } | ||
265 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 2 `%4s'\n", | ||
266 | GNUNET_i2s (&pos->peer2->id)); | ||
267 | if (pos->peer2handle != NULL) | ||
268 | { | ||
269 | GNUNET_CORE_disconnect (pos->peer2handle); | ||
270 | pos->peer2handle = NULL; | ||
271 | } | ||
272 | pos->disconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
273 | /* Decrement total connections so new can be established */ | ||
274 | total_server_connections -= 2; | ||
275 | } | ||
276 | |||
277 | #if DO_STATS | ||
278 | static void | ||
279 | stats_finished (void *cls, int result) | ||
280 | { | ||
281 | GNUNET_SCHEDULER_add_now (&finish_testing, NULL); | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * Callback function to process statistic values. | ||
286 | * | ||
287 | * @param cls closure | ||
288 | * @param peer the peer the statistics belong to | ||
289 | * @param subsystem name of subsystem that created the statistic | ||
290 | * @param name the name of the datum | ||
291 | * @param value the current value | ||
292 | * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not | ||
293 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | ||
294 | */ | ||
295 | static int | ||
296 | stats_print (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
297 | const char *subsystem, const char *name, uint64_t value, | ||
298 | int is_persistent) | ||
299 | { | ||
300 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s:%s:%s -- %llu\n", GNUNET_i2s (peer), | ||
301 | subsystem, name, value); | ||
302 | return GNUNET_OK; | ||
303 | } | ||
304 | #endif | ||
305 | |||
306 | |||
307 | static void | ||
308 | topology_cb (void *cls, const struct GNUNET_PeerIdentity *first, | ||
309 | const struct GNUNET_PeerIdentity *second, const char *emsg) | ||
310 | { | ||
311 | FILE *outfile = cls; | ||
312 | |||
313 | if (first != NULL) | ||
314 | { | ||
315 | if (outfile != NULL) | ||
316 | { | ||
317 | FPRINTF (outfile, "\t\"%s\" -- ", GNUNET_i2s (first)); | ||
318 | FPRINTF (outfile, "\"%s\";\n", GNUNET_i2s (second)); | ||
319 | } | ||
320 | topology_connections++; | ||
321 | } | ||
322 | else | ||
323 | { | ||
324 | FPRINTF (stderr, | ||
325 | "Finished iterating over topology, %d total connections!\n", | ||
326 | topology_connections); | ||
327 | if (outfile != NULL) | ||
328 | { | ||
329 | FPRINTF (outfile, "%s", "}\n"); | ||
330 | FCLOSE (outfile); | ||
331 | #if DO_STATS | ||
332 | GNUNET_TESTING_get_statistics (pg, &stats_finished, &stats_print, NULL); | ||
333 | #endif | ||
334 | GNUNET_SCHEDULER_add_now (&finish_testing, NULL); | ||
335 | } | ||
336 | } | ||
337 | } | ||
338 | |||
339 | |||
340 | static int | ||
341 | process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
342 | const struct GNUNET_MessageHeader *message, | ||
343 | const struct GNUNET_ATS_Information *atsi, | ||
344 | unsigned int atsi_count) | ||
345 | { | ||
346 | char *dotOutFileNameFinished; | ||
347 | FILE *dotOutFileFinished; | ||
348 | struct TestMessageContext *pos = cls; | ||
349 | struct GNUNET_TestMessage *msg = (struct GNUNET_TestMessage *) message; | ||
350 | |||
351 | if (pos->uid != ntohl (msg->uid)) | ||
352 | return GNUNET_OK; | ||
353 | |||
354 | #if PROGRESS_BARS | ||
355 | if ((total_messages_received) % modnum == 0) | ||
356 | { | ||
357 | if (total_messages_received == 0) | ||
358 | FPRINTF (stdout, "%s", "0%%"); | ||
359 | else | ||
360 | FPRINTF (stdout, "%d%%", | ||
361 | (int) (((float) total_messages_received / expected_messages) * | ||
362 | 100)); | ||
363 | |||
364 | } | ||
365 | else if (total_messages_received % dotnum == 0) | ||
366 | { | ||
367 | FPRINTF (stdout, "%s", "."); | ||
368 | } | ||
369 | fflush (stdout); | ||
370 | #endif | ||
371 | |||
372 | total_messages_received++; | ||
373 | |||
374 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
375 | "Received message from `%4s', type %d.\n", GNUNET_i2s (peer), | ||
376 | ntohs (message->type)); | ||
377 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
378 | "Total messages received %d, expected %d.\n", | ||
379 | total_messages_received, expected_messages); | ||
380 | |||
381 | if (total_messages_received == expected_messages) | ||
382 | { | ||
383 | #if PROGRESS_BARS | ||
384 | FPRINTF (stdout, "%s", "100%%]\n"); | ||
385 | #endif | ||
386 | GNUNET_SCHEDULER_cancel (die_task); | ||
387 | GNUNET_asprintf (&dotOutFileNameFinished, "%s.dot", "final_topology"); | ||
388 | dotOutFileFinished = FOPEN (dotOutFileNameFinished, "w"); | ||
389 | GNUNET_free (dotOutFileNameFinished); | ||
390 | if (dotOutFileFinished != NULL) | ||
391 | { | ||
392 | FPRINTF (dotOutFileFinished, "%s", "strict graph G {\n"); | ||
393 | } | ||
394 | topology_connections = 0; | ||
395 | GNUNET_TESTING_get_topology (pg, &topology_cb, dotOutFileFinished); | ||
396 | //GNUNET_SCHEDULER_add_now (&finish_testing, NULL); | ||
397 | } | ||
398 | else | ||
399 | { | ||
400 | pos->disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cores, pos); | ||
401 | } | ||
402 | |||
403 | return GNUNET_OK; | ||
404 | } | ||
405 | |||
406 | |||
407 | static void | ||
408 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
409 | { | ||
410 | char *msg = cls; | ||
411 | |||
412 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
413 | "Ending with error: %s\n", msg); | ||
414 | struct TestMessageContext *pos; | ||
415 | struct TestMessageContext *free_pos; | ||
416 | |||
417 | pos = test_messages; | ||
418 | while (pos != NULL) | ||
419 | { | ||
420 | if (pos->peer1handle != NULL) | ||
421 | { | ||
422 | GNUNET_CORE_disconnect (pos->peer1handle); | ||
423 | pos->peer1handle = NULL; | ||
424 | } | ||
425 | if (pos->peer2handle != NULL) | ||
426 | { | ||
427 | GNUNET_CORE_disconnect (pos->peer2handle); | ||
428 | pos->peer2handle = NULL; | ||
429 | } | ||
430 | free_pos = pos; | ||
431 | pos = pos->next; | ||
432 | GNUNET_free (free_pos); | ||
433 | } | ||
434 | |||
435 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
436 | "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n", | ||
437 | transmit_ready_scheduled, transmit_ready_failed, | ||
438 | transmit_ready_called); | ||
439 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
440 | "Total messages received %d, expected %d.\n", | ||
441 | total_messages_received, expected_messages); | ||
442 | |||
443 | if (pg != NULL) | ||
444 | { | ||
445 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
446 | ok = 7331; /* Opposite of leet */ | ||
447 | } | ||
448 | else | ||
449 | ok = 401; /* Never got peers started */ | ||
450 | |||
451 | if (dotOutFile != NULL) | ||
452 | { | ||
453 | FPRINTF (dotOutFile, "%s", "}"); | ||
454 | FCLOSE (dotOutFile); | ||
455 | } | ||
456 | } | ||
457 | |||
458 | |||
459 | static size_t | ||
460 | transmit_ready (void *cls, size_t size, void *buf) | ||
461 | { | ||
462 | struct GNUNET_TestMessage *m; | ||
463 | struct TestMessageContext *pos = cls; | ||
464 | |||
465 | GNUNET_assert (buf != NULL); | ||
466 | m = (struct GNUNET_TestMessage *) buf; | ||
467 | m->header.type = htons (MTYPE); | ||
468 | m->header.size = htons (sizeof (struct GNUNET_TestMessage)); | ||
469 | m->uid = htonl (pos->uid); | ||
470 | transmit_ready_called++; | ||
471 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
472 | "transmit ready for peer %s\ntransmit_ready's scheduled %d, transmit_ready's called %d\n", | ||
473 | GNUNET_i2s (&pos->peer1->id), transmit_ready_scheduled, | ||
474 | transmit_ready_called); | ||
475 | return sizeof (struct GNUNET_TestMessage); | ||
476 | } | ||
477 | |||
478 | |||
479 | static struct GNUNET_CORE_MessageHandler no_handlers[] = { | ||
480 | {NULL, 0, 0} | ||
481 | }; | ||
482 | |||
483 | |||
484 | static struct GNUNET_CORE_MessageHandler handlers[] = { | ||
485 | {&process_mtype, MTYPE, sizeof (struct GNUNET_TestMessage)}, | ||
486 | {NULL, 0, 0} | ||
487 | }; | ||
488 | |||
489 | |||
490 | static void | ||
491 | init_notify_peer2 (void *cls, struct GNUNET_CORE_Handle *server, | ||
492 | const struct GNUNET_PeerIdentity *my_identity) | ||
493 | { | ||
494 | struct TestMessageContext *pos = cls; | ||
495 | |||
496 | total_server_connections++; | ||
497 | |||
498 | pos->peer2connected = GNUNET_YES; | ||
499 | if (pos->peer1notified == GNUNET_YES) /* Peer 1 has been notified of connection to peer 2 */ | ||
500 | { | ||
501 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
502 | "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n", | ||
503 | GNUNET_i2s (my_identity), | ||
504 | GNUNET_h2s (&pos->peer1->id.hashPubKey)); | ||
505 | if (NULL == | ||
506 | GNUNET_CORE_notify_transmit_ready (pos->peer1handle, GNUNET_YES, 0, | ||
507 | TIMEOUT, &pos->peer2->id, | ||
508 | sizeof (struct GNUNET_TestMessage), | ||
509 | &transmit_ready, pos)) | ||
510 | { | ||
511 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
512 | "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", | ||
513 | GNUNET_i2s (&pos->peer2->id)); | ||
514 | transmit_ready_failed++; | ||
515 | } | ||
516 | else | ||
517 | { | ||
518 | transmit_ready_scheduled++; | ||
519 | } | ||
520 | } | ||
521 | } | ||
522 | |||
523 | |||
524 | /** | ||
525 | * Method called whenever a given peer connects. | ||
526 | * | ||
527 | * @param cls closure | ||
528 | * @param peer peer identity this notification is about | ||
529 | * @param atsi performance data for the connection | ||
530 | * @param atsi_count number of records in 'atsi' | ||
531 | */ | ||
532 | static void | ||
533 | connect_notify_peers (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
534 | const struct GNUNET_ATS_Information *atsi, | ||
535 | unsigned int atsi_count) | ||
536 | { | ||
537 | struct TestMessageContext *pos = cls; | ||
538 | |||
539 | if (0 == memcmp (peer, &pos->peer2->id, sizeof (struct GNUNET_PeerIdentity))) | ||
540 | { | ||
541 | pos->peer1notified = GNUNET_YES; | ||
542 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
543 | "Peer `%s' notified of connection to peer `%s'\n", | ||
544 | GNUNET_i2s (&pos->peer1->id), GNUNET_h2s (&peer->hashPubKey)); | ||
545 | } | ||
546 | else | ||
547 | return; | ||
548 | |||
549 | if (pos->peer2connected == GNUNET_YES) /* Already connected and notified of connection, send message! */ | ||
550 | { | ||
551 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
552 | "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n", | ||
553 | GNUNET_i2s (&pos->peer2->id), | ||
554 | GNUNET_h2s (&pos->peer1->id.hashPubKey)); | ||
555 | if (NULL == | ||
556 | GNUNET_CORE_notify_transmit_ready (pos->peer1handle, GNUNET_YES, 0, | ||
557 | TIMEOUT, &pos->peer2->id, | ||
558 | sizeof (struct GNUNET_TestMessage), | ||
559 | &transmit_ready, pos)) | ||
560 | { | ||
561 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
562 | "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", | ||
563 | GNUNET_i2s (&pos->peer2->id)); | ||
564 | transmit_ready_failed++; | ||
565 | } | ||
566 | else | ||
567 | { | ||
568 | transmit_ready_scheduled++; | ||
569 | } | ||
570 | } | ||
571 | } | ||
572 | |||
573 | |||
574 | static void | ||
575 | init_notify_peer1 (void *cls, struct GNUNET_CORE_Handle *server, | ||
576 | const struct GNUNET_PeerIdentity *my_identity) | ||
577 | { | ||
578 | struct TestMessageContext *pos = cls; | ||
579 | |||
580 | total_server_connections++; | ||
581 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
582 | "Core connection to `%4s' established, setting up handles\n", | ||
583 | GNUNET_i2s (my_identity)); | ||
584 | /* | ||
585 | * Connect to the receiving peer | ||
586 | */ | ||
587 | pos->peer2handle = | ||
588 | GNUNET_CORE_connect (pos->peer2->cfg, pos, &init_notify_peer2, NULL, | ||
589 | NULL, NULL, GNUNET_YES, NULL, GNUNET_YES, handlers); | ||
590 | |||
591 | } | ||
592 | |||
593 | |||
594 | static void | ||
595 | send_test_messages (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
596 | { | ||
597 | struct TestMessageContext *pos = cls; | ||
598 | |||
599 | if ((pos == test_messages) && (settle_time.rel_value > 0)) | ||
600 | { | ||
601 | topology_connections = 0; | ||
602 | GNUNET_TESTING_get_topology (pg, &topology_cb, NULL); | ||
603 | } | ||
604 | if (((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) || (cls == NULL)) | ||
605 | return; | ||
606 | |||
607 | if (die_task == GNUNET_SCHEDULER_NO_TASK) | ||
608 | { | ||
609 | die_task = | ||
610 | GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &end_badly, | ||
611 | "from send test messages (timeout)"); | ||
612 | } | ||
613 | |||
614 | if (total_server_connections >= MAX_OUTSTANDING_CONNECTIONS) | ||
615 | { | ||
616 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
617 | (GNUNET_TIME_UNIT_SECONDS, 1), | ||
618 | &send_test_messages, pos); | ||
619 | return; /* Otherwise we'll double schedule messages here! */ | ||
620 | } | ||
621 | |||
622 | /* | ||
623 | * Connect to the sending peer | ||
624 | */ | ||
625 | pos->peer1handle = | ||
626 | GNUNET_CORE_connect (pos->peer1->cfg, pos, &init_notify_peer1, | ||
627 | &connect_notify_peers, NULL, NULL, GNUNET_NO, NULL, | ||
628 | GNUNET_NO, no_handlers); | ||
629 | |||
630 | GNUNET_assert (pos->peer1handle != NULL); | ||
631 | |||
632 | if (total_server_connections < MAX_OUTSTANDING_CONNECTIONS) | ||
633 | { | ||
634 | GNUNET_SCHEDULER_add_now (&send_test_messages, pos->next); | ||
635 | } | ||
636 | else | ||
637 | { | ||
638 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
639 | (GNUNET_TIME_UNIT_SECONDS, 1), | ||
640 | &send_test_messages, pos->next); | ||
641 | } | ||
642 | } | ||
643 | |||
644 | |||
645 | static void | ||
646 | topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, | ||
647 | const struct GNUNET_PeerIdentity *second, uint32_t distance, | ||
648 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
649 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
650 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
651 | struct GNUNET_TESTING_Daemon *second_daemon, | ||
652 | const char *emsg) | ||
653 | { | ||
654 | struct TestMessageContext *temp_context; | ||
655 | |||
656 | if (emsg == NULL) | ||
657 | { | ||
658 | #if PROGRESS_BARS | ||
659 | if ((total_connections) % modnum == 0) | ||
660 | { | ||
661 | if (total_connections == 0) | ||
662 | FPRINTF (stdout, "%s", "0%%"); | ||
663 | else | ||
664 | FPRINTF (stdout, "%d%%", | ||
665 | (int) (((float) total_connections / expected_connections) * | ||
666 | 100)); | ||
667 | |||
668 | } | ||
669 | else if (total_connections % dotnum == 0) | ||
670 | { | ||
671 | FPRINTF (stdout, "%s", "."); | ||
672 | } | ||
673 | fflush (stdout); | ||
674 | #endif | ||
675 | total_connections++; | ||
676 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "connected peer %s to peer %s\n", | ||
677 | first_daemon->shortname, second_daemon->shortname); | ||
678 | temp_context = GNUNET_malloc (sizeof (struct TestMessageContext)); | ||
679 | temp_context->peer1 = first_daemon; | ||
680 | temp_context->peer2 = second_daemon; | ||
681 | temp_context->next = test_messages; | ||
682 | temp_context->uid = total_connections; | ||
683 | temp_context->disconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
684 | test_messages = temp_context; | ||
685 | |||
686 | expected_messages++; | ||
687 | if (dotOutFile != NULL) | ||
688 | FPRINTF (dotOutFile, "\tn%s -- n%s;\n", first_daemon->shortname, | ||
689 | second_daemon->shortname); | ||
690 | } | ||
691 | else | ||
692 | { | ||
693 | failed_connections++; | ||
694 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
695 | "Failed to connect peer %s to peer %s with error :\n%s\n", | ||
696 | first_daemon->shortname, second_daemon->shortname, emsg); | ||
697 | } | ||
698 | |||
699 | if (total_connections == expected_connections) | ||
700 | { | ||
701 | #if PROGRESS_BARS | ||
702 | FPRINTF (stdout, "%s", "100%%]\n"); | ||
703 | #endif | ||
704 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
705 | "Created %d total connections, which is our target number! Calling send messages.\n", | ||
706 | total_connections); | ||
707 | modnum = expected_messages / 4; | ||
708 | dotnum = (expected_messages / 50) + 1; | ||
709 | if (modnum == 0) | ||
710 | modnum = 1; | ||
711 | if (dotnum == 0) | ||
712 | dotnum = 1; | ||
713 | GNUNET_SCHEDULER_cancel (die_task); | ||
714 | die_task = GNUNET_SCHEDULER_NO_TASK; | ||
715 | #if DELAY_FOR_LOGGING | ||
716 | FPRINTF (stdout, "%s", "Sending test messages in 10 seconds.\n"); | ||
717 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
718 | (GNUNET_TIME_UNIT_SECONDS, 10), | ||
719 | &send_test_messages, test_messages); | ||
720 | gather_log_data (); | ||
721 | #else | ||
722 | if (settle_time.rel_value > 0) | ||
723 | { | ||
724 | GNUNET_TESTING_get_topology (pg, &topology_cb, NULL); | ||
725 | } | ||
726 | GNUNET_SCHEDULER_add_delayed (settle_time, &send_test_messages, | ||
727 | test_messages); | ||
728 | #endif | ||
729 | #if PROGRESS_BARS | ||
730 | FPRINTF (stdout, "%s", "Test message progress: ["); | ||
731 | #endif | ||
732 | |||
733 | } | ||
734 | else if (total_connections + failed_connections == expected_connections) | ||
735 | { | ||
736 | if (failed_connections < | ||
737 | (unsigned int) (fail_percentage * total_connections)) | ||
738 | { | ||
739 | GNUNET_SCHEDULER_cancel (die_task); | ||
740 | die_task = GNUNET_SCHEDULER_NO_TASK; | ||
741 | GNUNET_SCHEDULER_add_now (&send_test_messages, test_messages); | ||
742 | } | ||
743 | else | ||
744 | { | ||
745 | GNUNET_SCHEDULER_cancel (die_task); | ||
746 | die_task = | ||
747 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
748 | "from topology_callback (too many failed connections)"); | ||
749 | } | ||
750 | } | ||
751 | else | ||
752 | { | ||
753 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
754 | "Have %d total connections, %d failed connections, Want %d (at least %d)\n", | ||
755 | total_connections, failed_connections, expected_connections, | ||
756 | expected_connections - | ||
757 | (unsigned int) (fail_percentage * expected_connections)); | ||
758 | } | ||
759 | } | ||
760 | |||
761 | |||
762 | static void | ||
763 | topology_creation_finished (void *cls, const char *emsg) | ||
764 | { | ||
765 | if (emsg == NULL) | ||
766 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
767 | "All topology connections created successfully!\n"); | ||
768 | } | ||
769 | |||
770 | |||
771 | static void | ||
772 | connect_topology () | ||
773 | { | ||
774 | expected_connections = -1; | ||
775 | if ((pg != NULL) && (peers_left == 0)) | ||
776 | { | ||
777 | expected_connections = | ||
778 | GNUNET_TESTING_connect_topology (pg, connection_topology, | ||
779 | connect_topology_option, | ||
780 | connect_topology_option_modifier, | ||
781 | connect_timeout, connect_attempts, | ||
782 | &topology_creation_finished, NULL); | ||
783 | #if PROGRESS_BARS | ||
784 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n", | ||
785 | expected_connections); | ||
786 | #endif | ||
787 | } | ||
788 | |||
789 | GNUNET_SCHEDULER_cancel (die_task); | ||
790 | if (expected_connections < 1) | ||
791 | { | ||
792 | die_task = | ||
793 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
794 | "from connect topology (bad return)"); | ||
795 | return; | ||
796 | } | ||
797 | |||
798 | die_task = | ||
799 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
800 | (GNUNET_TIME_UNIT_SECONDS, | ||
801 | SECONDS_PER_PEER_START * num_peers), | ||
802 | &end_badly, | ||
803 | "from connect topology (timeout)"); | ||
804 | modnum = expected_connections / 4; | ||
805 | dotnum = (expected_connections / 50) + 1; | ||
806 | if (modnum == 0) | ||
807 | modnum = 1; | ||
808 | if (dotnum == 0) | ||
809 | dotnum = 1; | ||
810 | #if PROGRESS_BARS | ||
811 | FPRINTF (stdout, "%s", "Peer connection progress: ["); | ||
812 | #endif | ||
813 | } | ||
814 | |||
815 | static void | ||
816 | create_topology () | ||
817 | { | ||
818 | peers_left = num_peers; /* Reset counter */ | ||
819 | if (GNUNET_TESTING_create_topology | ||
820 | (pg, topology, blacklist_topology, blacklist_transports) != GNUNET_SYSERR) | ||
821 | { | ||
822 | #if PROGRESS_BARS | ||
823 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
824 | "Topology set up, now starting peers!\n"); | ||
825 | FPRINTF (stdout, "%s", "Daemon start progress ["); | ||
826 | #endif | ||
827 | GNUNET_TESTING_daemons_continue_startup (pg); | ||
828 | } | ||
829 | else | ||
830 | { | ||
831 | GNUNET_SCHEDULER_cancel (die_task); | ||
832 | die_task = | ||
833 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
834 | "from create topology (bad return)"); | ||
835 | } | ||
836 | GNUNET_SCHEDULER_cancel (die_task); | ||
837 | die_task = | ||
838 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
839 | (GNUNET_TIME_UNIT_SECONDS, | ||
840 | SECONDS_PER_PEER_START * num_peers), | ||
841 | &end_badly, | ||
842 | "from continue startup (timeout)"); | ||
843 | } | ||
844 | |||
845 | |||
846 | static void | ||
847 | peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
848 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
849 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
850 | { | ||
851 | if (emsg != NULL) | ||
852 | { | ||
853 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
854 | "Failed to start daemon with error: `%s'\n", emsg); | ||
855 | return; | ||
856 | } | ||
857 | GNUNET_assert (id != NULL); | ||
858 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n", | ||
859 | (num_peers - peers_left) + 1, num_peers); | ||
860 | #if PROGRESS_BARS | ||
861 | if ((num_peers - peers_left) % modnum == 0) | ||
862 | { | ||
863 | if (num_peers - peers_left == 0) | ||
864 | FPRINTF (stdout, "%s", "0%%"); | ||
865 | else | ||
866 | FPRINTF (stdout, "%d%%", | ||
867 | (int) (((float) (num_peers - peers_left) / num_peers) * 100)); | ||
868 | |||
869 | } | ||
870 | else if ((num_peers - peers_left) % dotnum == 0) | ||
871 | { | ||
872 | FPRINTF (stdout, "%s", "."); | ||
873 | } | ||
874 | fflush (stdout); | ||
875 | #endif | ||
876 | peers_left--; | ||
877 | if (peers_left == 0) | ||
878 | { | ||
879 | #if PROGRESS_BARS | ||
880 | FPRINTF (stdout, "%s", "100%%]\n"); | ||
881 | #endif | ||
882 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
883 | "All %d daemons started, now connecting peers!\n", num_peers); | ||
884 | GNUNET_SCHEDULER_cancel (die_task); | ||
885 | /* Set up task in case topology creation doesn't finish | ||
886 | * within a reasonable amount of time */ | ||
887 | die_task = | ||
888 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
889 | (GNUNET_TIME_UNIT_MINUTES, 8), &end_badly, | ||
890 | "from peers_started_callback"); | ||
891 | #if DELAY_FOR_LOGGING | ||
892 | FPRINTF (stdout, "%s", "Connecting topology in 10 seconds\n"); | ||
893 | gather_log_data (); | ||
894 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
895 | (GNUNET_TIME_UNIT_SECONDS, 10), | ||
896 | &connect_topology, NULL); | ||
897 | #else | ||
898 | connect_topology (); | ||
899 | #endif | ||
900 | ok = 0; | ||
901 | } | ||
902 | } | ||
903 | |||
904 | /** | ||
905 | * Callback indicating that the hostkey was created for a peer. | ||
906 | * | ||
907 | * @param cls NULL | ||
908 | * @param id the peer identity | ||
909 | * @param d the daemon handle (pretty useless at this point, remove?) | ||
910 | * @param emsg non-null on failure | ||
911 | */ | ||
912 | void | ||
913 | hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
914 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
915 | { | ||
916 | if (emsg != NULL) | ||
917 | { | ||
918 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
919 | "Hostkey callback received error: %s\n", emsg); | ||
920 | } | ||
921 | |||
922 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
923 | "Hostkey (%d/%d) created for peer `%s'\n", num_peers - peers_left, | ||
924 | num_peers, GNUNET_i2s (id)); | ||
925 | #if PROGRESS_BARS | ||
926 | if ((num_peers - peers_left) % modnum == 0) | ||
927 | { | ||
928 | if (num_peers - peers_left == 0) | ||
929 | FPRINTF (stdout, "%s", "0%%"); | ||
930 | else | ||
931 | FPRINTF (stdout, "%d%%", | ||
932 | (int) (((float) (num_peers - peers_left) / num_peers) * 100)); | ||
933 | |||
934 | } | ||
935 | else if ((num_peers - peers_left) % dotnum == 0) | ||
936 | { | ||
937 | FPRINTF (stdout, "%s", "."); | ||
938 | } | ||
939 | fflush (stdout); | ||
940 | #endif | ||
941 | peers_left--; | ||
942 | if (peers_left == 0) | ||
943 | { | ||
944 | #if PROGRESS_BARS | ||
945 | FPRINTF (stdout, "%s", "100%%]\n"); | ||
946 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
947 | "All %d hostkeys created, now creating topology!\n", num_peers); | ||
948 | #endif | ||
949 | GNUNET_SCHEDULER_cancel (die_task); | ||
950 | /* Set up task in case topology creation doesn't finish | ||
951 | * within a reasonable amount of time */ | ||
952 | die_task = | ||
953 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, | ||
954 | "from create_topology"); | ||
955 | GNUNET_SCHEDULER_add_now (&create_topology, NULL); | ||
956 | ok = 0; | ||
957 | } | ||
958 | } | ||
959 | |||
960 | |||
961 | static void | ||
962 | run (void *cls, char *const *args, const char *cfgfile, | ||
963 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
964 | { | ||
965 | char *topology_str; | ||
966 | char *connect_topology_str; | ||
967 | char *blacklist_topology_str; | ||
968 | char *connect_topology_option_str; | ||
969 | char *connect_topology_option_modifier_string; | ||
970 | unsigned long long max_outstanding_connections; | ||
971 | |||
972 | ok = 1; | ||
973 | |||
974 | dotOutFile = FOPEN (dotOutFileName, "w"); | ||
975 | if (dotOutFile != NULL) | ||
976 | { | ||
977 | FPRINTF (dotOutFile, "%s", "strict graph G {\n"); | ||
978 | } | ||
979 | |||
980 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
981 | "Starting daemons based on config file %s\n", cfgfile); | ||
982 | if (GNUNET_YES != | ||
983 | GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", | ||
984 | &test_directory)) | ||
985 | { | ||
986 | ok = 404; | ||
987 | return; | ||
988 | } | ||
989 | |||
990 | if ((GNUNET_YES == | ||
991 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "topology", | ||
992 | &topology_str)) && | ||
993 | (GNUNET_NO == GNUNET_TESTING_topology_get (&topology, topology_str))) | ||
994 | { | ||
995 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
996 | "Invalid topology `%s' given for section %s option %s\n", | ||
997 | topology_str, "TESTING", "TOPOLOGY"); | ||
998 | topology = GNUNET_TESTING_TOPOLOGY_CLIQUE; /* Defaults to NONE, so set better default here */ | ||
999 | } | ||
1000 | |||
1001 | if ((GNUNET_YES == | ||
1002 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", | ||
1003 | "connect_topology", | ||
1004 | &connect_topology_str)) && | ||
1005 | (GNUNET_NO == | ||
1006 | GNUNET_TESTING_topology_get (&connection_topology, | ||
1007 | connect_topology_str))) | ||
1008 | { | ||
1009 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1010 | "Invalid connect topology `%s' given for section %s option %s\n", | ||
1011 | connect_topology_str, "TESTING", "CONNECT_TOPOLOGY"); | ||
1012 | } | ||
1013 | GNUNET_free_non_null (connect_topology_str); | ||
1014 | if ((GNUNET_YES == | ||
1015 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", | ||
1016 | "connect_topology_option", | ||
1017 | &connect_topology_option_str)) && | ||
1018 | (GNUNET_NO == | ||
1019 | GNUNET_TESTING_topology_option_get (&connect_topology_option, | ||
1020 | connect_topology_option_str))) | ||
1021 | { | ||
1022 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1023 | "Invalid connect topology option `%s' given for section %s option %s\n", | ||
1024 | connect_topology_option_str, "TESTING", | ||
1025 | "CONNECT_TOPOLOGY_OPTION"); | ||
1026 | connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Defaults to NONE, set to ALL */ | ||
1027 | } | ||
1028 | GNUNET_free_non_null (connect_topology_option_str); | ||
1029 | if (GNUNET_YES == | ||
1030 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", | ||
1031 | "connect_topology_option_modifier", | ||
1032 | &connect_topology_option_modifier_string)) | ||
1033 | { | ||
1034 | if (SSCANF | ||
1035 | (connect_topology_option_modifier_string, "%lf", | ||
1036 | &connect_topology_option_modifier) != 1) | ||
1037 | { | ||
1038 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1039 | _ | ||
1040 | ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), | ||
1041 | connect_topology_option_modifier_string, | ||
1042 | "connect_topology_option_modifier", "TESTING"); | ||
1043 | } | ||
1044 | GNUNET_free (connect_topology_option_modifier_string); | ||
1045 | } | ||
1046 | |||
1047 | if (GNUNET_YES != | ||
1048 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", | ||
1049 | "blacklist_transports", | ||
1050 | &blacklist_transports)) | ||
1051 | blacklist_transports = NULL; | ||
1052 | |||
1053 | if ((GNUNET_YES == | ||
1054 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", | ||
1055 | "blacklist_topology", | ||
1056 | &blacklist_topology_str)) && | ||
1057 | (GNUNET_NO == | ||
1058 | GNUNET_TESTING_topology_get (&blacklist_topology, | ||
1059 | blacklist_topology_str))) | ||
1060 | { | ||
1061 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1062 | "Invalid topology `%s' given for section %s option %s\n", | ||
1063 | topology_str, "TESTING", "BLACKLIST_TOPOLOGY"); | ||
1064 | } | ||
1065 | GNUNET_free_non_null (topology_str); | ||
1066 | GNUNET_free_non_null (blacklist_topology_str); | ||
1067 | |||
1068 | if (GNUNET_OK != | ||
1069 | GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "SETTLE_TIME", | ||
1070 | &settle_time)) | ||
1071 | { | ||
1072 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
1073 | "testing", "SETTLE_TIME"); | ||
1074 | return; | ||
1075 | } | ||
1076 | |||
1077 | if (GNUNET_OK != | ||
1078 | GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "CONNECT_TIMEOUT", | ||
1079 | &connect_timeout)) | ||
1080 | { | ||
1081 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
1082 | "testing", "CONNECT_TIMEOUT"); | ||
1083 | return; | ||
1084 | } | ||
1085 | |||
1086 | |||
1087 | if (GNUNET_OK != | ||
1088 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts", | ||
1089 | &connect_attempts)) | ||
1090 | { | ||
1091 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
1092 | "testing", "connect_attempts"); | ||
1093 | return; | ||
1094 | } | ||
1095 | |||
1096 | if (GNUNET_OK != | ||
1097 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", | ||
1098 | "max_outstanding_connections", | ||
1099 | &max_outstanding_connections)) | ||
1100 | { | ||
1101 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
1102 | "testing", "max_outstanding_connections"); | ||
1103 | return; | ||
1104 | } | ||
1105 | |||
1106 | if (GNUNET_SYSERR == | ||
1107 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers", | ||
1108 | &num_peers)) | ||
1109 | num_peers = DEFAULT_NUM_PEERS; | ||
1110 | |||
1111 | main_cfg = cfg; | ||
1112 | |||
1113 | peers_left = num_peers; | ||
1114 | modnum = num_peers / 4; | ||
1115 | dotnum = (num_peers / 50) + 1; | ||
1116 | if (modnum == 0) | ||
1117 | modnum = 1; | ||
1118 | if (dotnum == 0) | ||
1119 | dotnum = 1; | ||
1120 | #if PROGRESS_BARS | ||
1121 | FPRINTF (stdout, "%s", "Hostkey generation progress: ["); | ||
1122 | #endif | ||
1123 | /* Set up a task to end testing if peer start fails */ | ||
1124 | die_task = | ||
1125 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
1126 | (GNUNET_TIME_UNIT_SECONDS, | ||
1127 | SECONDS_PER_PEER_START * num_peers), | ||
1128 | &end_badly, | ||
1129 | "didn't generate all hostkeys within a reasonable amount of time!!!"); | ||
1130 | |||
1131 | GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1); | ||
1132 | pg = GNUNET_TESTING_daemons_start (cfg, peers_left, | ||
1133 | max_outstanding_connections, peers_left, | ||
1134 | GNUNET_TIME_relative_multiply | ||
1135 | (GNUNET_TIME_UNIT_SECONDS, | ||
1136 | SECONDS_PER_PEER_START * num_peers), | ||
1137 | &hostkey_callback, NULL, | ||
1138 | &peers_started_callback, NULL, | ||
1139 | &topology_callback, NULL, NULL); | ||
1140 | |||
1141 | } | ||
1142 | |||
1143 | |||
1144 | static int | ||
1145 | check () | ||
1146 | { | ||
1147 | char *binary_name; | ||
1148 | char *config_file_name; | ||
1149 | |||
1150 | GNUNET_asprintf (&binary_name, "test-testing-topology-%s", topology_string); | ||
1151 | GNUNET_asprintf (&config_file_name, "test_testing_data_topology_%s.conf", | ||
1152 | topology_string); | ||
1153 | int ret; | ||
1154 | |||
1155 | char *const argv[] = { binary_name, | ||
1156 | "-c", | ||
1157 | config_file_name, | ||
1158 | NULL | ||
1159 | }; | ||
1160 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
1161 | GNUNET_GETOPT_OPTION_END | ||
1162 | }; | ||
1163 | ret = | ||
1164 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
1165 | binary_name, "nohelp", options, &run, &ok); | ||
1166 | if (ret != GNUNET_OK) | ||
1167 | { | ||
1168 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1169 | "`test-testing-topology-%s': Failed with error code %d\n", | ||
1170 | topology_string, ret); | ||
1171 | } | ||
1172 | GNUNET_free (binary_name); | ||
1173 | GNUNET_free (config_file_name); | ||
1174 | return ok; | ||
1175 | } | ||
1176 | |||
1177 | |||
1178 | int | ||
1179 | main (int argc, char *argv[]) | ||
1180 | { | ||
1181 | int ret; | ||
1182 | char *binary_start_pos; | ||
1183 | char *our_binary_name; | ||
1184 | char *dotexe; | ||
1185 | |||
1186 | binary_start_pos = strchr (argv[0], '/'); | ||
1187 | GNUNET_assert (binary_start_pos != NULL); | ||
1188 | topology_string = strstr (binary_start_pos, "_topology"); | ||
1189 | GNUNET_assert (topology_string != NULL); | ||
1190 | topology_string++; | ||
1191 | topology_string = strstr (topology_string, "_"); | ||
1192 | GNUNET_assert (topology_string != NULL); | ||
1193 | topology_string++; | ||
1194 | topology_string = GNUNET_strdup (topology_string); | ||
1195 | if (NULL != (dotexe = strstr (topology_string, ".exe"))) | ||
1196 | dotexe[0] = '\0'; | ||
1197 | GNUNET_asprintf (&our_binary_name, "test-testing-topology_%s", | ||
1198 | topology_string); | ||
1199 | GNUNET_asprintf (&dotOutFileName, "topology_%s.dot", topology_string); | ||
1200 | |||
1201 | GNUNET_log_setup (our_binary_name, | ||
1202 | "WARNING", | ||
1203 | NULL); | ||
1204 | ret = check (); | ||
1205 | GNUNET_free (topology_string); | ||
1206 | |||
1207 | /** | ||
1208 | * Need to remove base directory, subdirectories taken care | ||
1209 | * of by the testing framework. | ||
1210 | */ | ||
1211 | if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK) | ||
1212 | { | ||
1213 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1214 | "Failed to remove testing directory %s\n", test_directory); | ||
1215 | } | ||
1216 | GNUNET_free (our_binary_name); | ||
1217 | return ret; | ||
1218 | } | ||
1219 | |||
1220 | /* end of test_testing_topology.c */ | ||
diff --git a/src/testing_old/test_testing_topology_blacklist.c b/src/testing_old/test_testing_topology_blacklist.c deleted file mode 100644 index c90f48d9b..000000000 --- a/src/testing_old/test_testing_topology_blacklist.c +++ /dev/null | |||
@@ -1,595 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file testing/test_testing_topology_blacklist.c | ||
22 | * @brief base testcase for testing transport level blacklisting | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_testing_lib.h" | ||
26 | #include "gnunet_core_service.h" | ||
27 | |||
28 | #define VERBOSE GNUNET_NO | ||
29 | |||
30 | /** | ||
31 | * How long until we fail the whole testcase? | ||
32 | */ | ||
33 | #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600) | ||
34 | |||
35 | /** | ||
36 | * How long until we give up on starting the peers? (Must be longer than the connect timeout!) | ||
37 | */ | ||
38 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) | ||
39 | |||
40 | #define DEFAULT_NUM_PEERS 4 | ||
41 | |||
42 | #define MAX_OUTSTANDING_CONNECTIONS 300 | ||
43 | |||
44 | static int ok; | ||
45 | |||
46 | struct GNUNET_TIME_Relative connect_timeout; | ||
47 | |||
48 | static unsigned long long connect_attempts; | ||
49 | |||
50 | static unsigned long long num_peers; | ||
51 | |||
52 | static unsigned int total_connections; | ||
53 | |||
54 | static unsigned int failed_connections; | ||
55 | |||
56 | static unsigned int expected_connections; | ||
57 | |||
58 | static unsigned int expected_failed_connections; | ||
59 | |||
60 | static unsigned long long peers_left; | ||
61 | |||
62 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
63 | |||
64 | const struct GNUNET_CONFIGURATION_Handle *main_cfg; | ||
65 | |||
66 | GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
67 | |||
68 | static char *dotOutFileName; | ||
69 | |||
70 | static FILE *dotOutFile; | ||
71 | |||
72 | static char *blacklist_transports; | ||
73 | |||
74 | static enum GNUNET_TESTING_Topology topology = GNUNET_TESTING_TOPOLOGY_CLIQUE; /* Overlay should allow all connections */ | ||
75 | |||
76 | static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_RING; /* Blacklist underlay into a ring */ | ||
77 | |||
78 | static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */ | ||
79 | |||
80 | static enum GNUNET_TESTING_TopologyOption connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Try to connect all possible OVERLAY connections */ | ||
81 | |||
82 | static double connect_topology_option_modifier = 0.0; | ||
83 | |||
84 | static char *test_directory; | ||
85 | |||
86 | #define MTYPE 12345 | ||
87 | |||
88 | GNUNET_NETWORK_STRUCT_BEGIN | ||
89 | |||
90 | struct GNUNET_TestMessage | ||
91 | { | ||
92 | /** | ||
93 | * Header of the message | ||
94 | */ | ||
95 | struct GNUNET_MessageHeader header; | ||
96 | |||
97 | /** | ||
98 | * Unique identifier for this message. | ||
99 | */ | ||
100 | uint32_t uid; | ||
101 | }; | ||
102 | GNUNET_NETWORK_STRUCT_END | ||
103 | |||
104 | /** | ||
105 | * Check whether peers successfully shut down. | ||
106 | */ | ||
107 | void | ||
108 | shutdown_callback (void *cls, const char *emsg) | ||
109 | { | ||
110 | if (emsg != NULL) | ||
111 | { | ||
112 | #if VERBOSE | ||
113 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n"); | ||
114 | #endif | ||
115 | if (ok == 0) | ||
116 | ok = 666; | ||
117 | } | ||
118 | else | ||
119 | { | ||
120 | #if VERBOSE | ||
121 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); | ||
122 | #endif | ||
123 | } | ||
124 | } | ||
125 | |||
126 | static void | ||
127 | finish_testing () | ||
128 | { | ||
129 | GNUNET_assert (pg != NULL); | ||
130 | |||
131 | #if VERBOSE | ||
132 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
133 | "Called finish testing, stopping daemons.\n"); | ||
134 | #endif | ||
135 | sleep (1); | ||
136 | #if VERBOSE | ||
137 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n"); | ||
138 | #endif | ||
139 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
140 | #if VERBOSE | ||
141 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "daemons_stop finished\n"); | ||
142 | #endif | ||
143 | if (dotOutFile != NULL) | ||
144 | { | ||
145 | FPRINTF (dotOutFile, "%s", "}"); | ||
146 | FCLOSE (dotOutFile); | ||
147 | } | ||
148 | |||
149 | ok = 0; | ||
150 | } | ||
151 | |||
152 | static void | ||
153 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
154 | { | ||
155 | char *msg = cls; | ||
156 | |||
157 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
158 | "End badly was called (%s)... stopping daemons.\n", msg); | ||
159 | |||
160 | if (pg != NULL) | ||
161 | { | ||
162 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
163 | ok = 7331; /* Opposite of leet */ | ||
164 | } | ||
165 | else | ||
166 | ok = 401; /* Never got peers started */ | ||
167 | |||
168 | if (dotOutFile != NULL) | ||
169 | { | ||
170 | FPRINTF (dotOutFile, "%s", "}"); | ||
171 | FCLOSE (dotOutFile); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | |||
176 | |||
177 | void | ||
178 | topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, | ||
179 | const struct GNUNET_PeerIdentity *second, uint32_t distance, | ||
180 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
181 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
182 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
183 | struct GNUNET_TESTING_Daemon *second_daemon, | ||
184 | const char *emsg) | ||
185 | { | ||
186 | if (emsg == NULL) | ||
187 | { | ||
188 | total_connections++; | ||
189 | #if VERBOSE | ||
190 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected peer %s to peer %s\n", | ||
191 | first_daemon->shortname, second_daemon->shortname); | ||
192 | #endif | ||
193 | if (dotOutFile != NULL) | ||
194 | FPRINTF (dotOutFile, "\tn%s -- n%s;\n", first_daemon->shortname, | ||
195 | second_daemon->shortname); | ||
196 | } | ||
197 | |||
198 | else | ||
199 | { | ||
200 | failed_connections++; | ||
201 | #if VERBOSE | ||
202 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
203 | "Failed to connect peer %s to peer %s with error :\n%s\n", | ||
204 | first_daemon->shortname, second_daemon->shortname, emsg); | ||
205 | #endif | ||
206 | } | ||
207 | |||
208 | |||
209 | if (total_connections == expected_connections) | ||
210 | { | ||
211 | #if VERBOSE | ||
212 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
213 | "Created %d total connections, which is our target number (that's bad)!\n", | ||
214 | total_connections); | ||
215 | #endif | ||
216 | |||
217 | GNUNET_SCHEDULER_cancel (die_task); | ||
218 | die_task = GNUNET_SCHEDULER_NO_TASK; | ||
219 | die_task = | ||
220 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
221 | "from topology_callback (too many successful connections)"); | ||
222 | } | ||
223 | else if (total_connections + failed_connections == expected_connections) | ||
224 | { | ||
225 | if ((failed_connections == expected_failed_connections) && | ||
226 | (total_connections == | ||
227 | expected_connections - expected_failed_connections)) | ||
228 | { | ||
229 | GNUNET_SCHEDULER_cancel (die_task); | ||
230 | die_task = GNUNET_SCHEDULER_NO_TASK; | ||
231 | die_task = GNUNET_SCHEDULER_add_now (&finish_testing, NULL); | ||
232 | } | ||
233 | else | ||
234 | { | ||
235 | GNUNET_SCHEDULER_cancel (die_task); | ||
236 | die_task = | ||
237 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
238 | "from topology_callback (wrong number of failed connections)"); | ||
239 | } | ||
240 | } | ||
241 | else | ||
242 | { | ||
243 | #if VERBOSE | ||
244 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
245 | "Have %d total connections, %d failed connections, Want %d (failed) and %d (successful)\n", | ||
246 | total_connections, failed_connections, | ||
247 | expected_failed_connections, | ||
248 | expected_connections - expected_failed_connections); | ||
249 | #endif | ||
250 | } | ||
251 | } | ||
252 | |||
253 | static void | ||
254 | connect_topology () | ||
255 | { | ||
256 | expected_connections = -1; | ||
257 | if ((pg != NULL) && (peers_left == 0)) | ||
258 | { | ||
259 | expected_connections = | ||
260 | GNUNET_TESTING_connect_topology (pg, connection_topology, | ||
261 | connect_topology_option, | ||
262 | connect_topology_option_modifier, | ||
263 | connect_timeout, connect_attempts, | ||
264 | NULL, NULL); | ||
265 | #if VERBOSE | ||
266 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n", | ||
267 | expected_connections); | ||
268 | #endif | ||
269 | } | ||
270 | |||
271 | GNUNET_SCHEDULER_cancel (die_task); | ||
272 | if (expected_connections == GNUNET_SYSERR) | ||
273 | { | ||
274 | die_task = | ||
275 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
276 | "from connect topology (bad return)"); | ||
277 | } | ||
278 | |||
279 | die_task = | ||
280 | GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &end_badly, | ||
281 | "from connect topology (timeout)"); | ||
282 | } | ||
283 | |||
284 | static void | ||
285 | create_topology () | ||
286 | { | ||
287 | peers_left = num_peers; /* Reset counter */ | ||
288 | if (GNUNET_TESTING_create_topology | ||
289 | (pg, topology, blacklist_topology, blacklist_transports) != GNUNET_SYSERR) | ||
290 | { | ||
291 | #if VERBOSE | ||
292 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
293 | "Topology set up, now starting peers!\n"); | ||
294 | #endif | ||
295 | GNUNET_TESTING_daemons_continue_startup (pg); | ||
296 | } | ||
297 | else | ||
298 | { | ||
299 | GNUNET_SCHEDULER_cancel (die_task); | ||
300 | die_task = | ||
301 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
302 | "from create topology (bad return)"); | ||
303 | } | ||
304 | GNUNET_SCHEDULER_cancel (die_task); | ||
305 | die_task = | ||
306 | GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &end_badly, | ||
307 | "from continue startup (timeout)"); | ||
308 | } | ||
309 | |||
310 | |||
311 | static void | ||
312 | peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
313 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
314 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
315 | { | ||
316 | if (emsg != NULL) | ||
317 | { | ||
318 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
319 | "Failed to start daemon with error: `%s'\n", emsg); | ||
320 | return; | ||
321 | } | ||
322 | GNUNET_assert (id != NULL); | ||
323 | #if VERBOSE | ||
324 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n", | ||
325 | (num_peers - peers_left) + 1, num_peers); | ||
326 | #endif | ||
327 | peers_left--; | ||
328 | if (peers_left == 0) | ||
329 | { | ||
330 | #if VERBOSE | ||
331 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
332 | "All %d daemons started, now creating topology!\n", num_peers); | ||
333 | #endif | ||
334 | GNUNET_SCHEDULER_cancel (die_task); | ||
335 | /* Set up task in case topology creation doesn't finish | ||
336 | * within a reasonable amount of time */ | ||
337 | die_task = | ||
338 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
339 | (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly, | ||
340 | "from peers_started_callback"); | ||
341 | connect_topology (); | ||
342 | ok = 0; | ||
343 | } | ||
344 | } | ||
345 | |||
346 | /** | ||
347 | * Callback indicating that the hostkey was created for a peer. | ||
348 | * | ||
349 | * @param cls NULL | ||
350 | * @param id the peer identity | ||
351 | * @param d the daemon handle (pretty useless at this point, remove?) | ||
352 | * @param emsg non-null on failure | ||
353 | */ | ||
354 | void | ||
355 | hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
356 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
357 | { | ||
358 | if (emsg != NULL) | ||
359 | { | ||
360 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
361 | "Hostkey callback received error: %s\n", emsg); | ||
362 | } | ||
363 | |||
364 | #if VERBOSE | ||
365 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostkey created for peer `%s'\n", | ||
366 | GNUNET_i2s (id)); | ||
367 | #endif | ||
368 | peers_left--; | ||
369 | if (peers_left == 0) | ||
370 | { | ||
371 | #if VERBOSE | ||
372 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
373 | "All %d hostkeys created, now creating topology!\n", num_peers); | ||
374 | #endif | ||
375 | GNUNET_SCHEDULER_cancel (die_task); | ||
376 | /* Set up task in case topology creation doesn't finish | ||
377 | * within a reasonable amount of time */ | ||
378 | die_task = | ||
379 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
380 | (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly, | ||
381 | "from hostkey_callback"); | ||
382 | GNUNET_SCHEDULER_add_now (&create_topology, NULL); | ||
383 | ok = 0; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | static void | ||
388 | run (void *cls, char *const *args, const char *cfgfile, | ||
389 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
390 | { | ||
391 | unsigned long long topology_num; | ||
392 | unsigned long long connect_topology_num; | ||
393 | unsigned long long blacklist_topology_num; | ||
394 | unsigned long long connect_topology_option_num; | ||
395 | char *connect_topology_option_modifier_string; | ||
396 | |||
397 | ok = 1; | ||
398 | |||
399 | dotOutFile = FOPEN (dotOutFileName, "w"); | ||
400 | if (dotOutFile != NULL) | ||
401 | { | ||
402 | FPRINTF (dotOutFile, "%s", "strict graph G {\n"); | ||
403 | } | ||
404 | |||
405 | #if VERBOSE | ||
406 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
407 | "Starting daemons based on config file %s\n", cfgfile); | ||
408 | #endif | ||
409 | |||
410 | if (GNUNET_YES != | ||
411 | GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", | ||
412 | &test_directory)) | ||
413 | { | ||
414 | ok = 404; | ||
415 | if (dotOutFile != NULL) | ||
416 | { | ||
417 | FCLOSE (dotOutFile); | ||
418 | } | ||
419 | return; | ||
420 | } | ||
421 | |||
422 | if (GNUNET_YES == | ||
423 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "topology", | ||
424 | &topology_num)) | ||
425 | topology = topology_num; | ||
426 | |||
427 | if (GNUNET_YES == | ||
428 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_topology", | ||
429 | &connect_topology_num)) | ||
430 | connection_topology = connect_topology_num; | ||
431 | |||
432 | if (GNUNET_YES == | ||
433 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", | ||
434 | "connect_topology_option", | ||
435 | &connect_topology_option_num)) | ||
436 | connect_topology_option = connect_topology_option_num; | ||
437 | |||
438 | if (GNUNET_YES == | ||
439 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", | ||
440 | "connect_topology_option_modifier", | ||
441 | &connect_topology_option_modifier_string)) | ||
442 | { | ||
443 | if (SSCANF | ||
444 | (connect_topology_option_modifier_string, "%lf", | ||
445 | &connect_topology_option_modifier) != 1) | ||
446 | { | ||
447 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
448 | _ | ||
449 | ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), | ||
450 | connect_topology_option_modifier_string, | ||
451 | "connect_topology_option_modifier", "TESTING"); | ||
452 | GNUNET_free (connect_topology_option_modifier_string); | ||
453 | ok = 707; | ||
454 | if (dotOutFile != NULL) | ||
455 | { | ||
456 | FCLOSE (dotOutFile); | ||
457 | } | ||
458 | return; | ||
459 | } | ||
460 | GNUNET_free (connect_topology_option_modifier_string); | ||
461 | } | ||
462 | |||
463 | if (GNUNET_OK != | ||
464 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing", | ||
465 | "blacklist_transports", | ||
466 | &blacklist_transports)) | ||
467 | { | ||
468 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
469 | "No transports specified for blacklisting in blacklist testcase (this shouldn't happen!)\n"); | ||
470 | ok = 808; | ||
471 | if (dotOutFile != NULL) | ||
472 | { | ||
473 | FCLOSE (dotOutFile); | ||
474 | } | ||
475 | return; | ||
476 | } | ||
477 | |||
478 | if (GNUNET_YES == | ||
479 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", | ||
480 | "blacklist_topology", | ||
481 | &blacklist_topology_num)) | ||
482 | blacklist_topology = blacklist_topology_num; | ||
483 | |||
484 | if (GNUNET_SYSERR == | ||
485 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers", | ||
486 | &num_peers)) | ||
487 | num_peers = DEFAULT_NUM_PEERS; | ||
488 | |||
489 | if (GNUNET_OK != | ||
490 | GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "CONNECT_TIMEOUT", | ||
491 | &connect_timeout)) | ||
492 | { | ||
493 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
494 | "testing", "CONNECT_TIMEOUT"); | ||
495 | return; | ||
496 | } | ||
497 | |||
498 | |||
499 | if (GNUNET_OK != | ||
500 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts", | ||
501 | &connect_attempts)) | ||
502 | { | ||
503 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
504 | "testing", "connect_attempts"); | ||
505 | return; | ||
506 | } | ||
507 | |||
508 | main_cfg = cfg; | ||
509 | |||
510 | GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1); | ||
511 | peers_left = num_peers; | ||
512 | |||
513 | /* For this specific test we only really want a CLIQUE topology as the | ||
514 | * overlay allowed topology, and a RING topology as the underlying connection | ||
515 | * allowed topology. So we will expect only num_peers * 2 connections to | ||
516 | * work, and (num_peers * (num_peers - 1)) - (num_peers * 2) to fail. | ||
517 | */ | ||
518 | expected_connections = num_peers * (num_peers - 1); | ||
519 | expected_failed_connections = expected_connections - (num_peers * 2); | ||
520 | |||
521 | |||
522 | /* Set up a task to end testing if peer start fails */ | ||
523 | die_task = | ||
524 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
525 | (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly, | ||
526 | "didn't start all daemons in reasonable amount of time!!!"); | ||
527 | |||
528 | pg = GNUNET_TESTING_daemons_start (cfg, peers_left, peers_left, peers_left, | ||
529 | TIMEOUT, &hostkey_callback, NULL, | ||
530 | &peers_started_callback, NULL, | ||
531 | &topology_callback, NULL, NULL); | ||
532 | |||
533 | } | ||
534 | |||
535 | static int | ||
536 | check () | ||
537 | { | ||
538 | int ret; | ||
539 | |||
540 | char *const argv[] = { "test-testing-topology-blacklist", | ||
541 | "-c", | ||
542 | "test_testing_data_topology_blacklist.conf", | ||
543 | #if VERBOSE | ||
544 | "-L", "DEBUG", | ||
545 | #endif | ||
546 | NULL | ||
547 | }; | ||
548 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
549 | GNUNET_GETOPT_OPTION_END | ||
550 | }; | ||
551 | ret = | ||
552 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
553 | "test-testing-topology-blacklist", "nohelp", options, | ||
554 | &run, &ok); | ||
555 | if (ret != GNUNET_OK) | ||
556 | { | ||
557 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
558 | "`test-testing-topology-blacklist': Failed with error code %d\n", | ||
559 | ret); | ||
560 | } | ||
561 | |||
562 | return ok; | ||
563 | } | ||
564 | |||
565 | int | ||
566 | main (int argc, char *argv[]) | ||
567 | { | ||
568 | int ret; | ||
569 | |||
570 | GNUNET_log_setup ("test_testing_topology_blacklist", | ||
571 | #if VERBOSE | ||
572 | "DEBUG", | ||
573 | #else | ||
574 | "WARNING", | ||
575 | #endif | ||
576 | NULL); | ||
577 | ret = check (); | ||
578 | |||
579 | /** | ||
580 | * Need to remove base directory, subdirectories taken care | ||
581 | * of by the testing framework. | ||
582 | */ | ||
583 | if (test_directory != NULL) | ||
584 | { | ||
585 | if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK) | ||
586 | { | ||
587 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
588 | "Failed to remove testing directory %s\n", test_directory); | ||
589 | } | ||
590 | } | ||
591 | |||
592 | return ret; | ||
593 | } | ||
594 | |||
595 | /* end of test_testing_topology_blacklist.c */ | ||
diff --git a/src/testing_old/test_testing_topology_churn.c b/src/testing_old/test_testing_topology_churn.c deleted file mode 100644 index 9c0bbf27d..000000000 --- a/src/testing_old/test_testing_topology_churn.c +++ /dev/null | |||
@@ -1,322 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file testing/test_testing_topology_churn.c | ||
22 | * @brief base testcase for testing simple churn functionality | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_testing_lib.h" | ||
26 | #include "gnunet_core_service.h" | ||
27 | |||
28 | |||
29 | /** | ||
30 | * How long until we fail the whole testcase? | ||
31 | */ | ||
32 | #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600) | ||
33 | |||
34 | /** | ||
35 | * How long until we give up on starting the peers? (Must be longer than the connect timeout!) | ||
36 | */ | ||
37 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) | ||
38 | |||
39 | #define DEFAULT_NUM_PEERS 4 | ||
40 | |||
41 | static int ok; | ||
42 | |||
43 | static unsigned long long num_peers; | ||
44 | |||
45 | static unsigned int expected_connections; | ||
46 | |||
47 | static unsigned int expected_failed_connections; | ||
48 | |||
49 | static unsigned long long peers_left; | ||
50 | |||
51 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
52 | |||
53 | const struct GNUNET_CONFIGURATION_Handle *main_cfg; | ||
54 | |||
55 | GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
56 | |||
57 | static char *test_directory; | ||
58 | |||
59 | #define MTYPE 12345 | ||
60 | |||
61 | GNUNET_NETWORK_STRUCT_BEGIN | ||
62 | |||
63 | struct GNUNET_TestMessage | ||
64 | { | ||
65 | /** | ||
66 | * Header of the message | ||
67 | */ | ||
68 | struct GNUNET_MessageHeader header; | ||
69 | |||
70 | /** | ||
71 | * Unique identifier for this message. | ||
72 | */ | ||
73 | uint32_t uid; | ||
74 | }; | ||
75 | GNUNET_NETWORK_STRUCT_END | ||
76 | |||
77 | /** | ||
78 | * Check whether peers successfully shut down. | ||
79 | */ | ||
80 | void | ||
81 | shutdown_callback (void *cls, const char *emsg) | ||
82 | { | ||
83 | if (emsg != NULL) | ||
84 | { | ||
85 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n"); | ||
86 | if (ok == 0) | ||
87 | ok = 666; | ||
88 | } | ||
89 | else | ||
90 | { | ||
91 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | static void | ||
96 | finish_testing () | ||
97 | { | ||
98 | GNUNET_assert (pg != NULL); | ||
99 | |||
100 | if (die_task != GNUNET_SCHEDULER_NO_TASK) | ||
101 | GNUNET_SCHEDULER_cancel (die_task); | ||
102 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
103 | "Called finish testing, stopping daemons.\n"); | ||
104 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n"); | ||
105 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
106 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "daemons_stop finished\n"); | ||
107 | ok = 0; | ||
108 | } | ||
109 | |||
110 | static void | ||
111 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
112 | { | ||
113 | char *msg = cls; | ||
114 | |||
115 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
116 | "End badly was called (%s)... stopping daemons.\n", msg); | ||
117 | |||
118 | if (pg != NULL) | ||
119 | { | ||
120 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
121 | ok = 7331; /* Opposite of leet */ | ||
122 | } | ||
123 | else | ||
124 | ok = 401; /* Never got peers started */ | ||
125 | |||
126 | } | ||
127 | |||
128 | struct ChurnTestContext | ||
129 | { | ||
130 | GNUNET_SCHEDULER_Task next_task; | ||
131 | |||
132 | }; | ||
133 | |||
134 | static struct ChurnTestContext churn_ctx; | ||
135 | |||
136 | /** | ||
137 | * Churn callback, report on success or failure of churn operation. | ||
138 | * | ||
139 | * @param cls closure | ||
140 | * @param emsg NULL on success | ||
141 | */ | ||
142 | void | ||
143 | churn_callback (void *cls, const char *emsg) | ||
144 | { | ||
145 | if (emsg == NULL) | ||
146 | { | ||
147 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Successfully churned peers!\n", | ||
148 | emsg); | ||
149 | GNUNET_SCHEDULER_add_now (churn_ctx.next_task, NULL); | ||
150 | } | ||
151 | else | ||
152 | { | ||
153 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
154 | "Failed to churn peers with error `%s'\n", emsg); | ||
155 | GNUNET_SCHEDULER_cancel (die_task); | ||
156 | die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | |||
161 | static void | ||
162 | churn_peers_both () | ||
163 | { | ||
164 | churn_ctx.next_task = &finish_testing; | ||
165 | GNUNET_TESTING_daemons_churn (pg, NULL, 1, 1, TIMEOUT, &churn_callback, NULL); | ||
166 | } | ||
167 | |||
168 | static void | ||
169 | churn_peers_off_again () | ||
170 | { | ||
171 | churn_ctx.next_task = &churn_peers_both; | ||
172 | GNUNET_TESTING_daemons_churn (pg, NULL, 2, 0, TIMEOUT, &churn_callback, NULL); | ||
173 | } | ||
174 | |||
175 | static void | ||
176 | churn_peers_on () | ||
177 | { | ||
178 | churn_ctx.next_task = &churn_peers_off_again; | ||
179 | GNUNET_TESTING_daemons_churn (pg, NULL, 0, 2, TIMEOUT, &churn_callback, NULL); | ||
180 | } | ||
181 | |||
182 | static void | ||
183 | churn_peers_off () | ||
184 | { | ||
185 | churn_ctx.next_task = &churn_peers_on; | ||
186 | GNUNET_TESTING_daemons_churn (pg, NULL, 2, 0, TIMEOUT, &churn_callback, NULL); | ||
187 | } | ||
188 | |||
189 | static void | ||
190 | peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
191 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
192 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
193 | { | ||
194 | if (emsg != NULL) | ||
195 | { | ||
196 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
197 | "Failed to start daemon with error: `%s'\n", emsg); | ||
198 | return; | ||
199 | } | ||
200 | GNUNET_assert (id != NULL); | ||
201 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n", | ||
202 | (num_peers - peers_left) + 1, num_peers); | ||
203 | peers_left--; | ||
204 | if (peers_left == 0) | ||
205 | { | ||
206 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
207 | "All %d daemons started, now testing churn!\n", num_peers); | ||
208 | GNUNET_SCHEDULER_cancel (die_task); | ||
209 | /* Set up task in case topology creation doesn't finish | ||
210 | * within a reasonable amount of time */ | ||
211 | die_task = | ||
212 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
213 | (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly, | ||
214 | "from peers_started_callback"); | ||
215 | churn_peers_off (); | ||
216 | ok = 0; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | |||
221 | static void | ||
222 | run (void *cls, char *const *args, const char *cfgfile, | ||
223 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
224 | { | ||
225 | ok = 1; | ||
226 | |||
227 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
228 | "Starting daemons based on config file %s\n", cfgfile); | ||
229 | if (GNUNET_YES != | ||
230 | GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", | ||
231 | &test_directory)) | ||
232 | { | ||
233 | ok = 404; | ||
234 | return; | ||
235 | } | ||
236 | |||
237 | if (GNUNET_SYSERR == | ||
238 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers", | ||
239 | &num_peers)) | ||
240 | num_peers = DEFAULT_NUM_PEERS; | ||
241 | |||
242 | main_cfg = cfg; | ||
243 | |||
244 | peers_left = num_peers; | ||
245 | GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1); | ||
246 | |||
247 | /* For this specific test we only really want a CLIQUE topology as the | ||
248 | * overlay allowed topology, and a RING topology as the underlying connection | ||
249 | * allowed topology. So we will expect only num_peers * 2 connections to | ||
250 | * work, and (num_peers * (num_peers - 1)) - (num_peers * 2) to fail. | ||
251 | */ | ||
252 | expected_connections = num_peers * (num_peers - 1); | ||
253 | expected_failed_connections = expected_connections - (num_peers * 2); | ||
254 | |||
255 | |||
256 | /* Set up a task to end testing if peer start fails */ | ||
257 | die_task = | ||
258 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
259 | (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly, | ||
260 | "didn't start all daemons in reasonable amount of time!!!"); | ||
261 | |||
262 | pg = GNUNET_TESTING_daemons_start (cfg, peers_left, peers_left, peers_left, | ||
263 | TIMEOUT, NULL, NULL, | ||
264 | &peers_started_callback, NULL, NULL, NULL, | ||
265 | NULL); | ||
266 | |||
267 | } | ||
268 | |||
269 | static int | ||
270 | check () | ||
271 | { | ||
272 | int ret; | ||
273 | |||
274 | char *const argv[] = { "test-testing-topology-churn", | ||
275 | "-c", | ||
276 | "test_testing_data_topology_churn.conf", | ||
277 | NULL | ||
278 | }; | ||
279 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
280 | GNUNET_GETOPT_OPTION_END | ||
281 | }; | ||
282 | ret = | ||
283 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
284 | "test-testing-topology-churn", "nohelp", options, | ||
285 | &run, &ok); | ||
286 | if (ret != GNUNET_OK) | ||
287 | { | ||
288 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
289 | "`test-testing-topology-churn': Failed with error code %d\n", | ||
290 | ret); | ||
291 | } | ||
292 | |||
293 | return ok; | ||
294 | } | ||
295 | |||
296 | int | ||
297 | main (int argc, char *argv[]) | ||
298 | { | ||
299 | int ret; | ||
300 | |||
301 | GNUNET_log_setup ("test_testing_topology_churn", | ||
302 | "WARNING", | ||
303 | NULL); | ||
304 | ret = check (); | ||
305 | |||
306 | /** | ||
307 | * Need to remove base directory, subdirectories taken care | ||
308 | * of by the testing framework. | ||
309 | */ | ||
310 | if (test_directory != NULL) | ||
311 | { | ||
312 | if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK) | ||
313 | { | ||
314 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
315 | "Failed to remove testing directory %s\n", test_directory); | ||
316 | } | ||
317 | } | ||
318 | |||
319 | return ret; | ||
320 | } | ||
321 | |||
322 | /* end of test_testing_topology_churn.c */ | ||
diff --git a/src/testing_old/testing.c b/src/testing_old/testing.c deleted file mode 100644 index 8084a8d59..000000000 --- a/src/testing_old/testing.c +++ /dev/null | |||
@@ -1,2211 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | (C) 2008, 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testing/testing.c | ||
23 | * @brief convenience API for writing testcases for GNUnet | ||
24 | * Many testcases need to start and stop gnunetd, | ||
25 | * and this library is supposed to make that easier | ||
26 | * for TESTCASES. Normal programs should always | ||
27 | * use functions from gnunet_{util,arm}_lib.h. This API is | ||
28 | * ONLY for writing testcases! | ||
29 | * @author Christian Grothoff | ||
30 | * | ||
31 | */ | ||
32 | #include "platform.h" | ||
33 | #include "gnunet_arm_service.h" | ||
34 | #include "gnunet_core_service.h" | ||
35 | #include "gnunet_constants.h" | ||
36 | #include "gnunet_testing_lib.h" | ||
37 | #include "gnunet_transport_service.h" | ||
38 | #include "gnunet_hello_lib.h" | ||
39 | |||
40 | /** | ||
41 | * Hack to deal with initial HELLO's being often devoid of addresses. | ||
42 | * This hack causes 'process_hello' to ignore HELLOs without addresses. | ||
43 | * The correct implementation would continue with 'process_hello' until | ||
44 | * the connection could be established... | ||
45 | */ | ||
46 | #define EMPTY_HACK GNUNET_YES | ||
47 | |||
48 | |||
49 | /** | ||
50 | * After how long do we retry a service connection that was | ||
51 | * unavailable? Used in cases where an exponential back-off | ||
52 | * seems inappropriate. | ||
53 | */ | ||
54 | #define GNUNET_CONSTANTS_SERVICE_RETRY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500) | ||
55 | |||
56 | /** | ||
57 | * How long do we wait after a FORK+EXEC before testing for the | ||
58 | * resulting process to be up (port open, waitpid, etc.)? | ||
59 | */ | ||
60 | #define GNUNET_CONSTANTS_EXEC_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 200) | ||
61 | |||
62 | /** | ||
63 | * How long do we wait after starting gnunet-service-arm | ||
64 | * for the core service to be alive? | ||
65 | */ | ||
66 | #define ARM_START_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) | ||
67 | |||
68 | /** | ||
69 | * How many times are we willing to try to wait for "scp" or | ||
70 | * "gnunet-service-arm" to complete (waitpid) before giving up? | ||
71 | */ | ||
72 | #define MAX_EXEC_WAIT_RUNS 250 | ||
73 | |||
74 | static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} }; | ||
75 | |||
76 | #if EMPTY_HACK | ||
77 | static int | ||
78 | test_address (void *cls, const struct GNUNET_HELLO_Address *address, | ||
79 | struct GNUNET_TIME_Absolute expiration) | ||
80 | { | ||
81 | int *empty = cls; | ||
82 | |||
83 | *empty = GNUNET_NO; | ||
84 | return GNUNET_OK; | ||
85 | } | ||
86 | #endif | ||
87 | |||
88 | /** | ||
89 | * Receive the HELLO from one peer, give it to the other | ||
90 | * and ask them to connect. | ||
91 | * | ||
92 | * @param cls Closure (daemon whose hello is this). | ||
93 | * @param message HELLO message of peer | ||
94 | */ | ||
95 | static void | ||
96 | process_hello (void *cls, const struct GNUNET_MessageHeader *message) | ||
97 | { | ||
98 | struct GNUNET_TESTING_Daemon *daemon = cls; | ||
99 | int msize; | ||
100 | |||
101 | #if EMPTY_HACK | ||
102 | int empty; | ||
103 | |||
104 | empty = GNUNET_YES; | ||
105 | GNUNET_assert (message != NULL); | ||
106 | GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *) message, | ||
107 | GNUNET_NO, &test_address, &empty); | ||
108 | if (GNUNET_YES == empty) | ||
109 | { | ||
110 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
111 | "Skipping empty HELLO address of peer %s\n", | ||
112 | GNUNET_i2s (&daemon->id)); | ||
113 | return; | ||
114 | } | ||
115 | #endif | ||
116 | GNUNET_assert (daemon->phase == SP_GET_HELLO || | ||
117 | daemon->phase == SP_START_DONE); | ||
118 | daemon->cb = NULL; // FIXME: why??? (see fsm:SP_START_CORE, notify_daemon_started) | ||
119 | if (daemon->task != GNUNET_SCHEDULER_NO_TASK) /* Assertion here instead? */ | ||
120 | GNUNET_SCHEDULER_cancel (daemon->task); | ||
121 | |||
122 | if (daemon->server != NULL) | ||
123 | { | ||
124 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
125 | "Received `%s' from transport service of `%4s', disconnecting core!\n", | ||
126 | "HELLO", GNUNET_i2s (&daemon->id)); | ||
127 | GNUNET_CORE_disconnect (daemon->server); | ||
128 | daemon->server = NULL; | ||
129 | } | ||
130 | |||
131 | msize = ntohs (message->size); | ||
132 | if (msize < 1) | ||
133 | { | ||
134 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
135 | "HELLO message of peer %s is of size 0\n", | ||
136 | GNUNET_i2s (&daemon->id)); | ||
137 | return; | ||
138 | } | ||
139 | if (daemon->ghh != NULL) | ||
140 | { | ||
141 | GNUNET_TRANSPORT_get_hello_cancel (daemon->ghh); | ||
142 | daemon->ghh = NULL; | ||
143 | } | ||
144 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
145 | "Received `%s' from transport service of `%4s'\n", "HELLO", | ||
146 | GNUNET_i2s (&daemon->id)); | ||
147 | GNUNET_free_non_null (daemon->hello); | ||
148 | daemon->hello = GNUNET_malloc (msize); | ||
149 | memcpy (daemon->hello, message, msize); | ||
150 | |||
151 | if (daemon->th != NULL) | ||
152 | { | ||
153 | GNUNET_TRANSPORT_disconnect (daemon->th); | ||
154 | daemon->th = NULL; | ||
155 | } | ||
156 | daemon->phase = SP_START_DONE; | ||
157 | } | ||
158 | |||
159 | |||
160 | /** | ||
161 | * Notify of a peer being up and running. Scheduled as a task | ||
162 | * so that variables which may need to be set are set before | ||
163 | * the connect callback can set up new operations. | ||
164 | * FIXME: what variables?????? where from???? | ||
165 | * | ||
166 | * @param cls the testing daemon | ||
167 | * @param tc task scheduler context | ||
168 | */ | ||
169 | static void | ||
170 | notify_daemon_started (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
171 | { | ||
172 | struct GNUNET_TESTING_Daemon *d = cls; | ||
173 | GNUNET_TESTING_NotifyDaemonRunning cb; | ||
174 | |||
175 | cb = d->cb; | ||
176 | d->cb = NULL; | ||
177 | if (NULL != cb) | ||
178 | cb (d->cb_cls, &d->id, d->cfg, d, NULL); | ||
179 | } | ||
180 | |||
181 | |||
182 | /** | ||
183 | * Finite-state machine for starting GNUnet. | ||
184 | * | ||
185 | * @param cls our "struct GNUNET_TESTING_Daemon" | ||
186 | * @param tc unused | ||
187 | */ | ||
188 | static void | ||
189 | start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
190 | { | ||
191 | struct GNUNET_TESTING_Daemon *d = cls; | ||
192 | GNUNET_TESTING_NotifyDaemonRunning cb; | ||
193 | enum GNUNET_OS_ProcessStatusType type; | ||
194 | unsigned long code; | ||
195 | char *dst; | ||
196 | int bytes_read; | ||
197 | |||
198 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %s FSM is in phase %u.\n", | ||
199 | GNUNET_i2s (&d->id), d->phase); | ||
200 | d->task = GNUNET_SCHEDULER_NO_TASK; | ||
201 | switch (d->phase) | ||
202 | { | ||
203 | case SP_COPYING: | ||
204 | /* confirm copying complete */ | ||
205 | if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_copying, &type, &code)) | ||
206 | { | ||
207 | if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) | ||
208 | { | ||
209 | cb = d->cb; | ||
210 | d->cb = NULL; | ||
211 | if (NULL != cb) | ||
212 | cb (d->cb_cls, NULL, d->cfg, d, | ||
213 | _ | ||
214 | ("`scp' does not seem to terminate (timeout copying config).\n")); | ||
215 | return; | ||
216 | } | ||
217 | /* wait some more */ | ||
218 | d->task = | ||
219 | GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, | ||
220 | d); | ||
221 | return; | ||
222 | } | ||
223 | if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0)) | ||
224 | { | ||
225 | cb = d->cb; | ||
226 | d->cb = NULL; | ||
227 | if (NULL != cb) | ||
228 | cb (d->cb_cls, NULL, d->cfg, d, _("`scp' did not complete cleanly.\n")); | ||
229 | return; | ||
230 | } | ||
231 | GNUNET_OS_process_destroy (d->proc_arm_copying); | ||
232 | d->proc_arm_copying = NULL; | ||
233 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
234 | "Successfully copied configuration file.\n"); | ||
235 | d->phase = SP_COPIED; | ||
236 | /* fall-through */ | ||
237 | case SP_COPIED: | ||
238 | /* Start create hostkey process if we don't already know the peer identity! */ | ||
239 | if (GNUNET_NO == d->have_hostkey) | ||
240 | { | ||
241 | GNUNET_assert (NULL == d->proc_arm_peerinfo); | ||
242 | d->pipe_stdout = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_YES); | ||
243 | if (d->pipe_stdout == NULL) | ||
244 | { | ||
245 | cb = d->cb; | ||
246 | d->cb = NULL; | ||
247 | if (NULL != cb) | ||
248 | cb (d->cb_cls, NULL, d->cfg, d, | ||
249 | (NULL == | ||
250 | d->hostname) ? | ||
251 | _("Failed to create pipe for `gnunet-peerinfo' process.\n") : | ||
252 | _("Failed to create pipe for `ssh' process.\n")); | ||
253 | return; | ||
254 | } | ||
255 | if (NULL == d->hostname) | ||
256 | { | ||
257 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
258 | "Starting local `%s', with command `%s %s %s %s'.\n", | ||
259 | "gnunet-peerinfo", "gnunet-peerinfo", "-c", d->cfgfile, | ||
260 | "-sq"); | ||
261 | d->proc_arm_peerinfo = | ||
262 | GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, d->pipe_stdout, "gnunet-peerinfo", | ||
263 | "gnunet-peerinfo", "-c", d->cfgfile, "-sq", | ||
264 | NULL); | ||
265 | GNUNET_DISK_pipe_close_end (d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE); | ||
266 | } | ||
267 | else | ||
268 | { | ||
269 | if (d->username != NULL) | ||
270 | GNUNET_asprintf (&dst, "%s@%s", d->username, d->hostname); | ||
271 | else | ||
272 | dst = GNUNET_strdup (d->hostname); | ||
273 | |||
274 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
275 | "Starting remove `%s', with command `%s %s %s %s %s %s'.\n", | ||
276 | "gnunet-peerinfo", "ssh", dst, "gnunet-peerinfo", "-c", | ||
277 | d->cfgfile, "-sq"); | ||
278 | if (d->ssh_port_str == NULL) | ||
279 | { | ||
280 | d->proc_arm_peerinfo = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, d->pipe_stdout, "ssh", "ssh", | ||
281 | "-q", | ||
282 | dst, "gnunet-peerinfo", "-c", | ||
283 | d->cfgfile, "-sq", NULL); | ||
284 | } | ||
285 | else | ||
286 | { | ||
287 | d->proc_arm_peerinfo = | ||
288 | GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, d->pipe_stdout, "ssh", "ssh", "-p", | ||
289 | d->ssh_port_str, | ||
290 | "-q", | ||
291 | dst, "gnunet-peerinfo", "-c", d->cfgfile, | ||
292 | "-sq", NULL); | ||
293 | } | ||
294 | GNUNET_DISK_pipe_close_end (d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE); | ||
295 | GNUNET_free (dst); | ||
296 | } | ||
297 | if (NULL == d->proc_arm_peerinfo) | ||
298 | { | ||
299 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
300 | _("Could not start `%s' process to create hostkey.\n"), | ||
301 | (NULL == d->hostname) ? "gnunet-peerinfo" : "ssh"); | ||
302 | cb = d->cb; | ||
303 | d->cb = NULL; | ||
304 | if (NULL != cb) | ||
305 | cb (d->cb_cls, NULL, d->cfg, d, | ||
306 | (NULL == | ||
307 | d->hostname) ? _("Failed to start `gnunet-peerinfo' process.\n") | ||
308 | : _("Failed to start `ssh' process.\n")); | ||
309 | GNUNET_DISK_pipe_close (d->pipe_stdout); | ||
310 | return; | ||
311 | } | ||
312 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
313 | "Started `%s', waiting for hostkey.\n", "gnunet-peerinfo"); | ||
314 | d->phase = SP_HOSTKEY_CREATE; | ||
315 | d->task = | ||
316 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining | ||
317 | (d->max_timeout), | ||
318 | GNUNET_DISK_pipe_handle | ||
319 | (d->pipe_stdout, | ||
320 | GNUNET_DISK_PIPE_END_READ), | ||
321 | &start_fsm, d); | ||
322 | } | ||
323 | else /* Already have a hostkey! */ | ||
324 | { | ||
325 | if (d->hostkey_callback != NULL) | ||
326 | { | ||
327 | d->hostkey_callback (d->hostkey_cls, &d->id, d, NULL); | ||
328 | d->hostkey_callback = NULL; | ||
329 | d->phase = SP_HOSTKEY_CREATED; | ||
330 | } | ||
331 | else | ||
332 | d->phase = SP_TOPOLOGY_SETUP; | ||
333 | |||
334 | /* wait some more */ | ||
335 | d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d); | ||
336 | } | ||
337 | break; | ||
338 | case SP_HOSTKEY_CREATE: | ||
339 | bytes_read = | ||
340 | GNUNET_DISK_file_read (GNUNET_DISK_pipe_handle | ||
341 | (d->pipe_stdout, GNUNET_DISK_PIPE_END_READ), | ||
342 | &d->hostkeybuf[d->hostkeybufpos], | ||
343 | sizeof (d->hostkeybuf) - d->hostkeybufpos); | ||
344 | if (bytes_read > 0) | ||
345 | d->hostkeybufpos += bytes_read; | ||
346 | |||
347 | if ((d->hostkeybufpos < 104) && (bytes_read > 0)) | ||
348 | { | ||
349 | /* keep reading */ | ||
350 | d->task = | ||
351 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining | ||
352 | (d->max_timeout), | ||
353 | GNUNET_DISK_pipe_handle | ||
354 | (d->pipe_stdout, | ||
355 | GNUNET_DISK_PIPE_END_READ), | ||
356 | &start_fsm, d); | ||
357 | return; | ||
358 | } | ||
359 | d->hostkeybuf[103] = '\0'; | ||
360 | |||
361 | if ((bytes_read < 0) || | ||
362 | (GNUNET_OK != | ||
363 | GNUNET_CRYPTO_hash_from_string (d->hostkeybuf, &d->id.hashPubKey))) | ||
364 | { | ||
365 | /* error */ | ||
366 | if (bytes_read < 0) | ||
367 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
368 | _("Error reading from gnunet-peerinfo: %s\n"), | ||
369 | STRERROR (errno)); | ||
370 | else | ||
371 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
372 | _("Malformed output from gnunet-peerinfo!\n")); | ||
373 | cb = d->cb; | ||
374 | d->cb = NULL; | ||
375 | GNUNET_DISK_pipe_close (d->pipe_stdout); | ||
376 | d->pipe_stdout = NULL; | ||
377 | (void) GNUNET_OS_process_kill (d->proc_arm_peerinfo, SIGKILL); | ||
378 | GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (d->proc_arm_peerinfo)); | ||
379 | GNUNET_OS_process_destroy (d->proc_arm_peerinfo); | ||
380 | d->proc_arm_peerinfo = NULL; | ||
381 | if (NULL != cb) | ||
382 | cb (d->cb_cls, NULL, d->cfg, d, _("Failed to get hostkey!\n")); | ||
383 | return; | ||
384 | } | ||
385 | d->shortname = GNUNET_strdup (GNUNET_i2s (&d->id)); | ||
386 | GNUNET_DISK_pipe_close (d->pipe_stdout); | ||
387 | d->pipe_stdout = NULL; | ||
388 | (void) GNUNET_OS_process_kill (d->proc_arm_peerinfo, SIGKILL); | ||
389 | GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (d->proc_arm_peerinfo)); | ||
390 | GNUNET_OS_process_destroy (d->proc_arm_peerinfo); | ||
391 | d->proc_arm_peerinfo = NULL; | ||
392 | d->have_hostkey = GNUNET_YES; | ||
393 | if (d->hostkey_callback != NULL) | ||
394 | { | ||
395 | d->hostkey_callback (d->hostkey_cls, &d->id, d, NULL); | ||
396 | d->hostkey_callback = NULL; | ||
397 | d->phase = SP_HOSTKEY_CREATED; | ||
398 | } | ||
399 | else | ||
400 | { | ||
401 | d->phase = SP_TOPOLOGY_SETUP; | ||
402 | } | ||
403 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully got hostkey!\n"); | ||
404 | /* Fall through */ | ||
405 | case SP_HOSTKEY_CREATED: | ||
406 | /* wait for topology finished */ | ||
407 | if ((GNUNET_YES == d->dead) || | ||
408 | (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)) | ||
409 | { | ||
410 | cb = d->cb; | ||
411 | d->cb = NULL; | ||
412 | if (NULL != cb) | ||
413 | cb (d->cb_cls, NULL, d->cfg, d, | ||
414 | _("`Failed while waiting for topology setup!\n")); | ||
415 | return; | ||
416 | } | ||
417 | |||
418 | d->task = | ||
419 | GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, | ||
420 | d); | ||
421 | break; | ||
422 | case SP_TOPOLOGY_SETUP: /* Indicates topology setup has completed! */ | ||
423 | /* start GNUnet on remote host */ | ||
424 | if (NULL == d->hostname) | ||
425 | { | ||
426 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
427 | "Starting local `%s', with command `%s %s %s %s'.\n", | ||
428 | "gnunet-arm", "gnunet-arm", "-c", d->cfgfile, | ||
429 | "-s"); | ||
430 | d->proc_arm_start = | ||
431 | GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "gnunet-arm", "gnunet-arm", "-c", | ||
432 | d->cfgfile, | ||
433 | "-s", "-q", "-T", "5 s", NULL); | ||
434 | } | ||
435 | else | ||
436 | { | ||
437 | if (d->username != NULL) | ||
438 | GNUNET_asprintf (&dst, "%s@%s", d->username, d->hostname); | ||
439 | else | ||
440 | dst = GNUNET_strdup (d->hostname); | ||
441 | |||
442 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
443 | "Starting remote `%s', with command `%s %s %s %s %s %s %s'.\n", | ||
444 | "gnunet-arm", "ssh", dst, "gnunet-arm", "-c", d->cfgfile, | ||
445 | "-s", "-q"); | ||
446 | if (d->ssh_port_str == NULL) | ||
447 | { | ||
448 | d->proc_arm_start = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "ssh", "ssh", | ||
449 | "-q", | ||
450 | dst, "gnunet-arm", | ||
451 | "-c", d->cfgfile, "-s", "-q", "-T", | ||
452 | GNUNET_STRINGS_relative_time_to_string | ||
453 | (GNUNET_TIME_absolute_get_remaining | ||
454 | (d->max_timeout), GNUNET_NO), NULL); | ||
455 | } | ||
456 | else | ||
457 | { | ||
458 | |||
459 | d->proc_arm_start = | ||
460 | GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "ssh", "ssh", "-p", | ||
461 | d->ssh_port_str, | ||
462 | "-q", | ||
463 | dst, "gnunet-arm", | ||
464 | "-c", d->cfgfile, "-s", "-q", "-T", | ||
465 | GNUNET_STRINGS_relative_time_to_string | ||
466 | (GNUNET_TIME_absolute_get_remaining | ||
467 | (d->max_timeout), GNUNET_NO), NULL); | ||
468 | } | ||
469 | GNUNET_free (dst); | ||
470 | } | ||
471 | if (NULL == d->proc_arm_start) | ||
472 | { | ||
473 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
474 | _("Could not start `%s' process to start GNUnet.\n"), | ||
475 | (NULL == d->hostname) ? "gnunet-arm" : "ssh"); | ||
476 | cb = d->cb; | ||
477 | d->cb = NULL; | ||
478 | if (NULL != cb) | ||
479 | cb (d->cb_cls, NULL, d->cfg, d, | ||
480 | (NULL == | ||
481 | d->hostname) ? _("Failed to start `gnunet-arm' process.\n") : | ||
482 | _("Failed to start `ssh' process.\n")); | ||
483 | return; | ||
484 | } | ||
485 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
486 | "Started `%s', waiting for `%s' to be up.\n", "gnunet-arm", | ||
487 | "gnunet-service-core"); | ||
488 | d->phase = SP_START_ARMING; | ||
489 | d->task = | ||
490 | GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, | ||
491 | d); | ||
492 | // FIXME: busy wait? | ||
493 | break; | ||
494 | case SP_START_ARMING: | ||
495 | if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_start, &type, &code)) | ||
496 | { | ||
497 | if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) | ||
498 | { | ||
499 | cb = d->cb; | ||
500 | d->cb = NULL; | ||
501 | if (NULL != cb) | ||
502 | cb (d->cb_cls, NULL, d->cfg, d, | ||
503 | (NULL == | ||
504 | d->hostname) ? _("`gnunet-arm' does not seem to terminate.\n") : | ||
505 | _("`ssh' does not seem to terminate.\n")); | ||
506 | if (d->cfg != NULL) | ||
507 | { | ||
508 | GNUNET_CONFIGURATION_destroy (d->cfg); | ||
509 | d->cfg = NULL; | ||
510 | } | ||
511 | if (d->cfgfile != NULL) | ||
512 | { | ||
513 | GNUNET_free (d->cfgfile); | ||
514 | d->cfgfile = NULL; | ||
515 | } | ||
516 | GNUNET_free_non_null (d->hostname); | ||
517 | GNUNET_free_non_null (d->username); | ||
518 | GNUNET_OS_process_destroy (d->proc_arm_start); | ||
519 | d->proc_arm_start = NULL; | ||
520 | d->username = NULL; | ||
521 | d->hostname = NULL; // Quick hack to avoid crashing (testing need to be | ||
522 | d->cfg = NULL; // overhauled anyway, and the error managing is | ||
523 | // GNUNET_free (d); // FIXME (could this leak) | ||
524 | // pretty broken anyway. | ||
525 | return; | ||
526 | } | ||
527 | /* wait some more */ | ||
528 | d->task = | ||
529 | GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, | ||
530 | d); | ||
531 | // FIXME: busy wait? | ||
532 | return; | ||
533 | } | ||
534 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully started `%s'.\n", | ||
535 | "gnunet-arm"); | ||
536 | GNUNET_OS_process_destroy (d->proc_arm_start); | ||
537 | d->proc_arm_start = NULL; | ||
538 | d->phase = SP_START_CORE; | ||
539 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling CORE_connect\n"); | ||
540 | /* Fall through */ | ||
541 | case SP_START_CORE: | ||
542 | if (d->server != NULL) | ||
543 | GNUNET_CORE_disconnect (d->server); | ||
544 | |||
545 | d->th = GNUNET_TRANSPORT_connect (d->cfg, &d->id, d, NULL, NULL, NULL); | ||
546 | if (d->th == NULL) | ||
547 | { | ||
548 | if (GNUNET_YES == d->dead) | ||
549 | GNUNET_TESTING_daemon_stop (d, | ||
550 | GNUNET_TIME_absolute_get_remaining | ||
551 | (d->max_timeout), d->dead_cb, | ||
552 | d->dead_cb_cls, GNUNET_YES, GNUNET_NO); | ||
553 | else if (NULL != d->cb) | ||
554 | d->cb (d->cb_cls, &d->id, d->cfg, d, | ||
555 | _("Failed to connect to transport service!\n")); | ||
556 | return; | ||
557 | } | ||
558 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
559 | "Connected to transport service `%s', getting HELLO\n", | ||
560 | GNUNET_i2s (&d->id)); | ||
561 | d->ghh = GNUNET_TRANSPORT_get_hello (d->th, &process_hello, d); | ||
562 | /* FIXME: store task ID somewhere! */ | ||
563 | GNUNET_SCHEDULER_add_now (¬ify_daemon_started, d); | ||
564 | /*cb = d->cb; | ||
565 | * d->cb = NULL; | ||
566 | * if (NULL != cb) | ||
567 | * cb (d->cb_cls, &d->id, d->cfg, d, NULL); */ | ||
568 | d->running = GNUNET_YES; | ||
569 | d->phase = SP_GET_HELLO; | ||
570 | break; | ||
571 | case SP_GET_HELLO: | ||
572 | if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) | ||
573 | { | ||
574 | if (d->server != NULL) | ||
575 | GNUNET_CORE_disconnect (d->server); | ||
576 | if (d->th != NULL) | ||
577 | GNUNET_TRANSPORT_disconnect (d->th); | ||
578 | cb = d->cb; | ||
579 | d->cb = NULL; | ||
580 | if (NULL != cb) | ||
581 | cb (d->cb_cls, NULL, d->cfg, d, _("Unable to get HELLO for peer!\n")); | ||
582 | GNUNET_CONFIGURATION_destroy (d->cfg); | ||
583 | GNUNET_free (d->cfgfile); | ||
584 | GNUNET_free_non_null (d->hostname); | ||
585 | GNUNET_free_non_null (d->username); | ||
586 | GNUNET_free (d); | ||
587 | return; | ||
588 | } | ||
589 | if (d->hello != NULL) | ||
590 | return; | ||
591 | GNUNET_assert (d->task == GNUNET_SCHEDULER_NO_TASK); | ||
592 | d->task = | ||
593 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
594 | (GNUNET_CONSTANTS_SERVICE_RETRY, 2), | ||
595 | &start_fsm, d); | ||
596 | break; | ||
597 | case SP_START_DONE: | ||
598 | GNUNET_break (0); | ||
599 | break; | ||
600 | case SP_SERVICE_START: | ||
601 | /* confirm gnunet-arm exited */ | ||
602 | if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_srv_start, &type, &code)) | ||
603 | { | ||
604 | if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) | ||
605 | { | ||
606 | cb = d->cb; | ||
607 | d->cb = NULL; | ||
608 | if (NULL != cb) | ||
609 | cb (d->cb_cls, NULL, d->cfg, d, | ||
610 | (NULL == | ||
611 | d->hostname) ? _("`gnunet-arm' does not seem to terminate.\n") : | ||
612 | _("`ssh' does not seem to terminate.\n")); | ||
613 | return; | ||
614 | } | ||
615 | /* wait some more */ | ||
616 | d->task = | ||
617 | GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, | ||
618 | d); | ||
619 | return; | ||
620 | } | ||
621 | #if EXTRA_CHECKS | ||
622 | if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0)) | ||
623 | { | ||
624 | cb = d->cb; | ||
625 | d->cb = NULL; | ||
626 | if (NULL != cb) | ||
627 | cb (d->cb_cls, NULL, d->cfg, d, | ||
628 | (NULL == | ||
629 | d->hostname) ? | ||
630 | _ | ||
631 | ("`gnunet-arm' terminated with non-zero exit status (or timed out)!\n") | ||
632 | : _("`ssh' does not seem to terminate.\n")); | ||
633 | return; | ||
634 | } | ||
635 | #endif | ||
636 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service startup complete!\n"); | ||
637 | cb = d->cb; | ||
638 | d->cb = NULL; | ||
639 | d->phase = SP_START_DONE; | ||
640 | if (NULL != cb) | ||
641 | cb (d->cb_cls, &d->id, d->cfg, d, NULL); | ||
642 | GNUNET_OS_process_destroy (d->proc_arm_srv_start); | ||
643 | d->proc_arm_srv_start = NULL; | ||
644 | break; | ||
645 | case SP_SERVICE_SHUTDOWN_START: | ||
646 | /* confirm copying complete */ | ||
647 | if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_srv_stop, &type, &code)) | ||
648 | { | ||
649 | if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) | ||
650 | { | ||
651 | if (NULL != d->dead_cb) | ||
652 | d->dead_cb (d->dead_cb_cls, | ||
653 | _ | ||
654 | ("either `gnunet-arm' or `ssh' does not seem to terminate.\n")); | ||
655 | return; | ||
656 | } | ||
657 | /* wait some more */ | ||
658 | d->task = | ||
659 | GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, | ||
660 | d); | ||
661 | return; | ||
662 | } | ||
663 | #if EXTRA_CHECKS | ||
664 | if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0)) | ||
665 | { | ||
666 | if (NULL != d->dead_cb) | ||
667 | d->dead_cb (d->dead_cb_cls, | ||
668 | _ | ||
669 | ("shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n")); | ||
670 | return; | ||
671 | } | ||
672 | #endif | ||
673 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service shutdown complete.\n"); | ||
674 | if (NULL != d->dead_cb) | ||
675 | d->dead_cb (d->dead_cb_cls, NULL); | ||
676 | break; | ||
677 | case SP_SHUTDOWN_START: | ||
678 | /* confirm copying complete !??? */ | ||
679 | if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_stop, &type, &code)) | ||
680 | { | ||
681 | if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) | ||
682 | { | ||
683 | if (NULL != d->dead_cb) | ||
684 | d->dead_cb (d->dead_cb_cls, | ||
685 | _ | ||
686 | ("either `gnunet-arm' or `ssh' does not seem to terminate.\n")); | ||
687 | if (d->th != NULL) | ||
688 | { | ||
689 | GNUNET_TRANSPORT_get_hello_cancel (d->ghh); | ||
690 | d->ghh = NULL; | ||
691 | GNUNET_TRANSPORT_disconnect (d->th); | ||
692 | d->th = NULL; | ||
693 | } | ||
694 | if (d->cfg != NULL) | ||
695 | { | ||
696 | GNUNET_CONFIGURATION_destroy (d->cfg); | ||
697 | d->cfg = NULL; | ||
698 | } | ||
699 | if (d->cfgfile != NULL) | ||
700 | { | ||
701 | GNUNET_free (d->cfgfile); | ||
702 | d->cfgfile = NULL; | ||
703 | } | ||
704 | GNUNET_free_non_null (d->hello); | ||
705 | GNUNET_free_non_null (d->hostname); | ||
706 | GNUNET_free_non_null (d->username); | ||
707 | GNUNET_free_non_null (d->shortname); | ||
708 | GNUNET_OS_process_destroy (d->proc_arm_stop); | ||
709 | d->proc_arm_stop = NULL; | ||
710 | GNUNET_free (d); | ||
711 | return; | ||
712 | } | ||
713 | /* wait some more */ | ||
714 | d->task = | ||
715 | GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, | ||
716 | d); | ||
717 | return; | ||
718 | } | ||
719 | if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0)) | ||
720 | { | ||
721 | if (NULL != d->dead_cb) | ||
722 | d->dead_cb (d->dead_cb_cls, | ||
723 | _ | ||
724 | ("shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n")); | ||
725 | if (d->th != NULL) | ||
726 | { | ||
727 | GNUNET_TRANSPORT_get_hello_cancel (d->ghh); | ||
728 | d->ghh = NULL; | ||
729 | GNUNET_TRANSPORT_disconnect (d->th); | ||
730 | d->th = NULL; | ||
731 | } | ||
732 | if (d->server != NULL) | ||
733 | { | ||
734 | GNUNET_CORE_disconnect (d->server); | ||
735 | d->server = NULL; | ||
736 | } | ||
737 | GNUNET_CONFIGURATION_destroy (d->cfg); | ||
738 | d->cfg = NULL; | ||
739 | GNUNET_free (d->cfgfile); | ||
740 | GNUNET_free_non_null (d->hello); | ||
741 | GNUNET_free_non_null (d->hostname); | ||
742 | GNUNET_free_non_null (d->username); | ||
743 | GNUNET_free_non_null (d->shortname); | ||
744 | GNUNET_OS_process_destroy (d->proc_arm_stop); | ||
745 | d->proc_arm_stop = NULL; | ||
746 | GNUNET_free (d); | ||
747 | return; | ||
748 | } | ||
749 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer shutdown complete.\n"); | ||
750 | if (d->server != NULL) | ||
751 | { | ||
752 | GNUNET_CORE_disconnect (d->server); | ||
753 | d->server = NULL; | ||
754 | } | ||
755 | |||
756 | if (d->th != NULL) | ||
757 | { | ||
758 | GNUNET_TRANSPORT_get_hello_cancel (d->ghh); | ||
759 | d->ghh = NULL; | ||
760 | GNUNET_TRANSPORT_disconnect (d->th); | ||
761 | d->th = NULL; | ||
762 | } | ||
763 | |||
764 | if (NULL != d->dead_cb) | ||
765 | d->dead_cb (d->dead_cb_cls, NULL); | ||
766 | |||
767 | /* state clean up and notifications */ | ||
768 | if (d->churn == GNUNET_NO) | ||
769 | { | ||
770 | GNUNET_CONFIGURATION_destroy (d->cfg); | ||
771 | d->cfg = NULL; | ||
772 | GNUNET_free (d->cfgfile); | ||
773 | GNUNET_free_non_null (d->hostname); | ||
774 | GNUNET_free_non_null (d->username); | ||
775 | } | ||
776 | |||
777 | GNUNET_free_non_null (d->hello); | ||
778 | d->hello = NULL; | ||
779 | GNUNET_free_non_null (d->shortname); | ||
780 | GNUNET_OS_process_destroy (d->proc_arm_stop); | ||
781 | d->proc_arm_stop = NULL; | ||
782 | d->shortname = NULL; | ||
783 | if (d->churn == GNUNET_NO) | ||
784 | GNUNET_free (d); | ||
785 | |||
786 | break; | ||
787 | case SP_CONFIG_UPDATE: | ||
788 | /* confirm copying complete */ | ||
789 | if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_copying, &type, &code)) | ||
790 | { | ||
791 | if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) /* FIXME: config update should take timeout parameter! */ | ||
792 | { | ||
793 | cb = d->cb; | ||
794 | d->cb = NULL; | ||
795 | if (NULL != cb) | ||
796 | cb (d->cb_cls, NULL, d->cfg, d, | ||
797 | _("`scp' does not seem to terminate.\n")); | ||
798 | return; | ||
799 | } | ||
800 | /* wait some more */ | ||
801 | d->task = | ||
802 | GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, | ||
803 | d); | ||
804 | return; | ||
805 | } | ||
806 | if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0)) | ||
807 | { | ||
808 | if (NULL != d->update_cb) | ||
809 | d->update_cb (d->update_cb_cls, _("`scp' did not complete cleanly.\n")); | ||
810 | return; | ||
811 | } | ||
812 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
813 | "Successfully copied configuration file.\n"); | ||
814 | if (NULL != d->update_cb) | ||
815 | d->update_cb (d->update_cb_cls, NULL); | ||
816 | d->phase = SP_START_DONE; | ||
817 | break; | ||
818 | } | ||
819 | } | ||
820 | |||
821 | /** | ||
822 | * Continues GNUnet daemon startup when user wanted to be notified | ||
823 | * once a hostkey was generated (for creating friends files, blacklists, | ||
824 | * etc.). | ||
825 | * | ||
826 | * @param daemon the daemon to finish starting | ||
827 | */ | ||
828 | void | ||
829 | GNUNET_TESTING_daemon_continue_startup (struct GNUNET_TESTING_Daemon *daemon) | ||
830 | { | ||
831 | GNUNET_assert (daemon->phase == SP_HOSTKEY_CREATED); | ||
832 | daemon->phase = SP_TOPOLOGY_SETUP; | ||
833 | } | ||
834 | |||
835 | /** | ||
836 | * Check whether the given daemon is running. | ||
837 | * | ||
838 | * @param daemon the daemon to check | ||
839 | * | ||
840 | * @return GNUNET_YES if the daemon is up, GNUNET_NO if the | ||
841 | * daemon is down, GNUNET_SYSERR on error. | ||
842 | */ | ||
843 | int | ||
844 | GNUNET_TESTING_test_daemon_running (struct GNUNET_TESTING_Daemon *daemon) | ||
845 | { | ||
846 | if (daemon == NULL) | ||
847 | return GNUNET_SYSERR; | ||
848 | |||
849 | if (daemon->running == GNUNET_YES) | ||
850 | return GNUNET_YES; | ||
851 | return GNUNET_NO; | ||
852 | } | ||
853 | |||
854 | |||
855 | /** | ||
856 | * Starts a GNUnet daemon service which has been previously stopped. | ||
857 | * | ||
858 | * @param d the daemon for which the service should be started | ||
859 | * @param service the name of the service to start | ||
860 | * @param timeout how long to wait for process for shutdown to complete | ||
861 | * @param cb function called once the service starts | ||
862 | * @param cb_cls closure for cb | ||
863 | */ | ||
864 | void | ||
865 | GNUNET_TESTING_daemon_start_stopped_service (struct GNUNET_TESTING_Daemon *d, | ||
866 | char *service, | ||
867 | struct GNUNET_TIME_Relative | ||
868 | timeout, | ||
869 | GNUNET_TESTING_NotifyDaemonRunning | ||
870 | cb, void *cb_cls) | ||
871 | { | ||
872 | char *arg; | ||
873 | |||
874 | d->cb = cb; | ||
875 | d->cb_cls = cb_cls; | ||
876 | |||
877 | GNUNET_assert (d->running == GNUNET_YES); | ||
878 | |||
879 | if (d->phase == SP_CONFIG_UPDATE) | ||
880 | { | ||
881 | GNUNET_SCHEDULER_cancel (d->task); | ||
882 | d->phase = SP_START_DONE; | ||
883 | } | ||
884 | |||
885 | if (d->churned_services == NULL) | ||
886 | { | ||
887 | d->cb (d->cb_cls, &d->id, d->cfg, d, | ||
888 | "No service has been churned off yet!!"); | ||
889 | return; | ||
890 | } | ||
891 | d->phase = SP_SERVICE_START; | ||
892 | GNUNET_free (d->churned_services); | ||
893 | d->churned_services = NULL; | ||
894 | d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
895 | /* Check if this is a local or remote process */ | ||
896 | if (NULL != d->hostname) | ||
897 | { | ||
898 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
899 | "Starting gnunet-arm with config `%s' on host `%s'.\n", | ||
900 | d->cfgfile, d->hostname); | ||
901 | if (d->username != NULL) | ||
902 | GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname); | ||
903 | else | ||
904 | arg = GNUNET_strdup (d->hostname); | ||
905 | |||
906 | d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "ssh", "ssh", | ||
907 | "-q", | ||
908 | arg, "gnunet-arm", | ||
909 | "-c", d->cfgfile, "-i", service, "-q", | ||
910 | "-T", | ||
911 | GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_NO), | ||
912 | NULL); | ||
913 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
914 | "Starting gnunet-arm with command ssh %s gnunet-arm -c %s -i %s -q\n", | ||
915 | arg, "gnunet-arm", d->cfgfile, service); | ||
916 | GNUNET_free (arg); | ||
917 | } | ||
918 | else | ||
919 | { | ||
920 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
921 | "Starting gnunet-arm with config `%s' locally.\n", d->cfgfile); | ||
922 | d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "gnunet-arm", "gnunet-arm", | ||
923 | "-c", d->cfgfile, "-i", service, "-q", | ||
924 | "-T", "5 s", | ||
925 | NULL); | ||
926 | } | ||
927 | |||
928 | d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
929 | d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d); | ||
930 | } | ||
931 | |||
932 | /** | ||
933 | * Starts a GNUnet daemon's service. | ||
934 | * | ||
935 | * @param d the daemon for which the service should be started | ||
936 | * @param service the name of the service to start | ||
937 | * @param timeout how long to wait for process for startup | ||
938 | * @param cb function called once gnunet-arm returns | ||
939 | * @param cb_cls closure for cb | ||
940 | */ | ||
941 | void | ||
942 | GNUNET_TESTING_daemon_start_service (struct GNUNET_TESTING_Daemon *d, | ||
943 | const char *service, | ||
944 | struct GNUNET_TIME_Relative timeout, | ||
945 | GNUNET_TESTING_NotifyDaemonRunning cb, | ||
946 | void *cb_cls) | ||
947 | { | ||
948 | char *arg; | ||
949 | |||
950 | d->cb = cb; | ||
951 | d->cb_cls = cb_cls; | ||
952 | |||
953 | GNUNET_assert (service != NULL); | ||
954 | GNUNET_assert (d->running == GNUNET_YES); | ||
955 | GNUNET_assert (d->phase == SP_START_DONE); | ||
956 | |||
957 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
958 | _("Starting service %s for peer `%4s'\n"), service, | ||
959 | GNUNET_i2s (&d->id)); | ||
960 | d->phase = SP_SERVICE_START; | ||
961 | d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
962 | /* Check if this is a local or remote process */ | ||
963 | if (NULL != d->hostname) | ||
964 | { | ||
965 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
966 | "Starting gnunet-arm with config `%s' on host `%s'.\n", | ||
967 | d->cfgfile, d->hostname); | ||
968 | if (d->username != NULL) | ||
969 | GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname); | ||
970 | else | ||
971 | arg = GNUNET_strdup (d->hostname); | ||
972 | |||
973 | d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "ssh", "ssh", | ||
974 | "-q", | ||
975 | arg, "gnunet-arm", | ||
976 | "-c", d->cfgfile, "-i", service, "-q", | ||
977 | "-T", | ||
978 | GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_NO), | ||
979 | NULL); | ||
980 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
981 | "Starting gnunet-arm with command ssh %s gnunet-arm -c %s -i %s -q -T %s\n", | ||
982 | arg, "gnunet-arm", d->cfgfile, service, | ||
983 | GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_NO)); | ||
984 | GNUNET_free (arg); | ||
985 | } | ||
986 | else | ||
987 | { | ||
988 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
989 | "Starting gnunet-arm with config `%s' locally.\n", d->cfgfile); | ||
990 | d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "gnunet-arm", "gnunet-arm", | ||
991 | "-c", d->cfgfile, "-i", service, "-q", | ||
992 | "-T", "5 s", NULL); | ||
993 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
994 | "Starting gnunet-arm with command %s -c %s -i %s -q -T \"5 s\"\n", | ||
995 | "gnunet-arm", d->cfgfile, service); | ||
996 | } | ||
997 | |||
998 | d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
999 | d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d); | ||
1000 | } | ||
1001 | |||
1002 | /** | ||
1003 | * Start a peer that has previously been stopped using the daemon_stop | ||
1004 | * call (and files weren't deleted and the allow restart flag) | ||
1005 | * | ||
1006 | * @param daemon the daemon to start (has been previously stopped) | ||
1007 | * @param timeout how long to wait for restart | ||
1008 | * @param cb the callback for notification when the peer is running | ||
1009 | * @param cb_cls closure for the callback | ||
1010 | */ | ||
1011 | void | ||
1012 | GNUNET_TESTING_daemon_start_stopped (struct GNUNET_TESTING_Daemon *daemon, | ||
1013 | struct GNUNET_TIME_Relative timeout, | ||
1014 | GNUNET_TESTING_NotifyDaemonRunning cb, | ||
1015 | void *cb_cls) | ||
1016 | { | ||
1017 | if (daemon->running == GNUNET_YES) | ||
1018 | { | ||
1019 | cb (cb_cls, &daemon->id, daemon->cfg, daemon, | ||
1020 | "Daemon already running, can't restart!"); | ||
1021 | return; | ||
1022 | } | ||
1023 | |||
1024 | daemon->cb = cb; | ||
1025 | daemon->cb_cls = cb_cls; | ||
1026 | daemon->phase = SP_TOPOLOGY_SETUP; | ||
1027 | daemon->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
1028 | /* FIXME: why add_continuation? */ | ||
1029 | GNUNET_SCHEDULER_add_continuation (&start_fsm, daemon, | ||
1030 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
1031 | } | ||
1032 | |||
1033 | /** | ||
1034 | * Starts a GNUnet daemon. GNUnet must be installed on the target | ||
1035 | * system and available in the PATH. The machine must furthermore be | ||
1036 | * reachable via "ssh" (unless the hostname is "NULL") without the | ||
1037 | * need to enter a password. | ||
1038 | * | ||
1039 | * @param cfg configuration to use | ||
1040 | * @param timeout how long to wait starting up peers | ||
1041 | * @param pretend GNUNET_YES to set up files but not start peer GNUNET_NO | ||
1042 | * to really start the peer (default) | ||
1043 | * @param hostname name of the machine where to run GNUnet | ||
1044 | * (use NULL for localhost). | ||
1045 | * @param ssh_username ssh username to use when connecting to hostname | ||
1046 | * @param sshport port to pass to ssh process when connecting to hostname | ||
1047 | * @param hostkey pointer to a hostkey to be written to disk (instead of being generated) | ||
1048 | * @param hostkey_callback function to call once the hostkey has been | ||
1049 | * generated for this peer, but it hasn't yet been started | ||
1050 | * (NULL to start immediately, otherwise waits on GNUNET_TESTING_daemon_continue_start) | ||
1051 | * @param hostkey_cls closure for hostkey callback | ||
1052 | * @param cb function to call once peer is up, or failed to start | ||
1053 | * @param cb_cls closure for cb | ||
1054 | * @return handle to the daemon (actual start will be completed asynchronously) | ||
1055 | */ | ||
1056 | struct GNUNET_TESTING_Daemon * | ||
1057 | GNUNET_TESTING_daemon_start (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
1058 | struct GNUNET_TIME_Relative timeout, int pretend, | ||
1059 | const char *hostname, const char *ssh_username, | ||
1060 | uint16_t sshport, const char *hostkey, | ||
1061 | GNUNET_TESTING_NotifyHostkeyCreated | ||
1062 | hostkey_callback, void *hostkey_cls, | ||
1063 | GNUNET_TESTING_NotifyDaemonRunning cb, | ||
1064 | void *cb_cls) | ||
1065 | { | ||
1066 | struct GNUNET_TESTING_Daemon *ret; | ||
1067 | char *arg; | ||
1068 | char *username; | ||
1069 | char *servicehome; | ||
1070 | char *baseservicehome; | ||
1071 | char *slash; | ||
1072 | char *hostkeyfile; | ||
1073 | char *temp_file_name; | ||
1074 | struct GNUNET_DISK_FileHandle *fn; | ||
1075 | struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded public_key; | ||
1076 | struct GNUNET_CRYPTO_RsaPrivateKey *private_key; | ||
1077 | |||
1078 | ret = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Daemon)); | ||
1079 | ret->hostname = (hostname == NULL) ? NULL : GNUNET_strdup (hostname); | ||
1080 | if (sshport != 0) | ||
1081 | { | ||
1082 | GNUNET_asprintf (&ret->ssh_port_str, "%d", sshport); | ||
1083 | } | ||
1084 | else | ||
1085 | ret->ssh_port_str = NULL; | ||
1086 | |||
1087 | /* Find service home and base service home directories, create it if it doesn't exist */ | ||
1088 | GNUNET_assert (GNUNET_OK == | ||
1089 | GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", | ||
1090 | "SERVICEHOME", | ||
1091 | &servicehome)); | ||
1092 | |||
1093 | GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_create (servicehome)); | ||
1094 | GNUNET_asprintf (&temp_file_name, "%s/gnunet-testing-config", servicehome); | ||
1095 | ret->cfgfile = GNUNET_DISK_mktemp (temp_file_name); | ||
1096 | GNUNET_free (temp_file_name); | ||
1097 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1098 | "Setting up peer with configuration file `%s'.\n", ret->cfgfile); | ||
1099 | if (NULL == ret->cfgfile) | ||
1100 | { | ||
1101 | GNUNET_free_non_null (ret->ssh_port_str); | ||
1102 | GNUNET_free_non_null (ret->hostname); | ||
1103 | GNUNET_free (ret); | ||
1104 | return NULL; | ||
1105 | } | ||
1106 | ret->hostkey_callback = hostkey_callback; | ||
1107 | ret->hostkey_cls = hostkey_cls; | ||
1108 | ret->cb = cb; | ||
1109 | ret->cb_cls = cb_cls; | ||
1110 | ret->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
1111 | ret->cfg = GNUNET_CONFIGURATION_dup (cfg); | ||
1112 | GNUNET_CONFIGURATION_set_value_string (ret->cfg, "PATHS", "DEFAULTCONFIG", | ||
1113 | ret->cfgfile); | ||
1114 | |||
1115 | if (hostkey != NULL) /* Get the peer identity from the hostkey */ | ||
1116 | { | ||
1117 | private_key = GNUNET_CRYPTO_rsa_decode_key (hostkey, HOSTKEYFILESIZE); | ||
1118 | GNUNET_assert (private_key != NULL); | ||
1119 | GNUNET_CRYPTO_rsa_key_get_public (private_key, &public_key); | ||
1120 | GNUNET_CRYPTO_hash (&public_key, | ||
1121 | sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), | ||
1122 | &ret->id.hashPubKey); | ||
1123 | ret->shortname = GNUNET_strdup (GNUNET_i2s (&ret->id)); | ||
1124 | ret->have_hostkey = GNUNET_YES; | ||
1125 | GNUNET_CRYPTO_rsa_key_free (private_key); | ||
1126 | } | ||
1127 | |||
1128 | /* Write hostkey to file, if we were given one */ | ||
1129 | hostkeyfile = NULL; | ||
1130 | if (hostkey != NULL) | ||
1131 | { | ||
1132 | GNUNET_asprintf (&hostkeyfile, "%s/.hostkey", servicehome); | ||
1133 | fn = GNUNET_DISK_file_open (hostkeyfile, | ||
1134 | GNUNET_DISK_OPEN_READWRITE | | ||
1135 | GNUNET_DISK_OPEN_CREATE, | ||
1136 | GNUNET_DISK_PERM_USER_READ | | ||
1137 | GNUNET_DISK_PERM_USER_WRITE); | ||
1138 | GNUNET_assert (fn != NULL); | ||
1139 | GNUNET_assert (HOSTKEYFILESIZE == | ||
1140 | GNUNET_DISK_file_write (fn, hostkey, HOSTKEYFILESIZE)); | ||
1141 | GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fn)); | ||
1142 | } | ||
1143 | |||
1144 | /* write configuration to temporary file */ | ||
1145 | if (GNUNET_OK != GNUNET_CONFIGURATION_write (ret->cfg, ret->cfgfile)) | ||
1146 | { | ||
1147 | if (0 != UNLINK (ret->cfgfile)) | ||
1148 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", | ||
1149 | ret->cfgfile); | ||
1150 | GNUNET_CONFIGURATION_destroy (ret->cfg); | ||
1151 | GNUNET_free_non_null (ret->hostname); | ||
1152 | GNUNET_free (ret->cfgfile); | ||
1153 | GNUNET_free (ret); | ||
1154 | return NULL; | ||
1155 | } | ||
1156 | if (ssh_username != NULL) | ||
1157 | username = GNUNET_strdup (ssh_username); | ||
1158 | if ((ssh_username == NULL) && | ||
1159 | (GNUNET_OK != | ||
1160 | GNUNET_CONFIGURATION_get_value_string (cfg, "TESTING_OLD", "USERNAME", | ||
1161 | &username))) | ||
1162 | { | ||
1163 | if (NULL != getenv ("USER")) | ||
1164 | username = GNUNET_strdup (getenv ("USER")); | ||
1165 | else | ||
1166 | username = NULL; | ||
1167 | } | ||
1168 | ret->username = username; | ||
1169 | |||
1170 | if (GNUNET_NO == pretend) /* Copy files, enter finite state machine */ | ||
1171 | { | ||
1172 | /* copy directory to remote host */ | ||
1173 | if (NULL != hostname) | ||
1174 | { | ||
1175 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1176 | "Copying configuration directory to host `%s'.\n", hostname); | ||
1177 | baseservicehome = GNUNET_strdup (servicehome); | ||
1178 | /* Remove trailing /'s */ | ||
1179 | while (baseservicehome[strlen (baseservicehome) - 1] == '/') | ||
1180 | baseservicehome[strlen (baseservicehome) - 1] = '\0'; | ||
1181 | /* Find next directory /, jump one ahead */ | ||
1182 | slash = strrchr (baseservicehome, '/'); | ||
1183 | if (slash != NULL) | ||
1184 | *(++slash) = '\0'; | ||
1185 | |||
1186 | ret->phase = SP_COPYING; | ||
1187 | if (NULL != username) | ||
1188 | GNUNET_asprintf (&arg, "%s@%s:%s", username, hostname, baseservicehome); | ||
1189 | else | ||
1190 | GNUNET_asprintf (&arg, "%s:%s", hostname, baseservicehome); | ||
1191 | GNUNET_free (baseservicehome); | ||
1192 | if (ret->ssh_port_str == NULL) | ||
1193 | { | ||
1194 | ret->proc_arm_copying = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "scp", "scp", "-r", | ||
1195 | "-q", | ||
1196 | servicehome, arg, NULL); | ||
1197 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1198 | "copying directory with command scp -r %s %s\n", | ||
1199 | servicehome, arg); | ||
1200 | } | ||
1201 | else | ||
1202 | { | ||
1203 | ret->proc_arm_copying = | ||
1204 | GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "scp", "scp", "-r", "-P", | ||
1205 | ret->ssh_port_str, | ||
1206 | "-q", | ||
1207 | servicehome, arg, NULL); | ||
1208 | } | ||
1209 | GNUNET_free (arg); | ||
1210 | if (NULL == ret->proc_arm_copying) | ||
1211 | { | ||
1212 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1213 | _ | ||
1214 | ("Could not start `%s' process to copy configuration directory.\n"), | ||
1215 | "scp"); | ||
1216 | if (0 != UNLINK (ret->cfgfile)) | ||
1217 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", | ||
1218 | ret->cfgfile); | ||
1219 | GNUNET_CONFIGURATION_destroy (ret->cfg); | ||
1220 | GNUNET_free_non_null (ret->hostname); | ||
1221 | GNUNET_free_non_null (ret->username); | ||
1222 | GNUNET_free (ret->cfgfile); | ||
1223 | GNUNET_free (ret); | ||
1224 | if ((hostkey != NULL) && (0 != UNLINK (hostkeyfile))) | ||
1225 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", | ||
1226 | hostkeyfile); | ||
1227 | GNUNET_free_non_null (hostkeyfile); | ||
1228 | GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (servicehome)); | ||
1229 | GNUNET_free (servicehome); | ||
1230 | return NULL; | ||
1231 | } | ||
1232 | |||
1233 | ret->task = | ||
1234 | GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, | ||
1235 | ret); | ||
1236 | GNUNET_free_non_null (hostkeyfile); | ||
1237 | GNUNET_free (servicehome); | ||
1238 | return ret; | ||
1239 | } | ||
1240 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1241 | "No need to copy configuration file since we are running locally.\n"); | ||
1242 | ret->phase = SP_COPIED; | ||
1243 | /* FIXME: why add_cont? */ | ||
1244 | GNUNET_SCHEDULER_add_continuation (&start_fsm, ret, | ||
1245 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
1246 | } | ||
1247 | GNUNET_free_non_null (hostkeyfile); | ||
1248 | GNUNET_free (servicehome); | ||
1249 | return ret; | ||
1250 | } | ||
1251 | |||
1252 | |||
1253 | /** | ||
1254 | * Restart (stop and start) a GNUnet daemon. | ||
1255 | * | ||
1256 | * @param d the daemon that should be restarted | ||
1257 | * @param cb function called once the daemon is (re)started | ||
1258 | * @param cb_cls closure for cb | ||
1259 | */ | ||
1260 | void | ||
1261 | GNUNET_TESTING_daemon_restart (struct GNUNET_TESTING_Daemon *d, | ||
1262 | GNUNET_TESTING_NotifyDaemonRunning cb, | ||
1263 | void *cb_cls) | ||
1264 | { | ||
1265 | char *arg; | ||
1266 | char *del_arg; | ||
1267 | |||
1268 | del_arg = NULL; | ||
1269 | if (NULL != d->cb) | ||
1270 | { | ||
1271 | d->dead = GNUNET_YES; | ||
1272 | return; | ||
1273 | } | ||
1274 | |||
1275 | d->cb = cb; | ||
1276 | d->cb_cls = cb_cls; | ||
1277 | |||
1278 | if (d->phase == SP_CONFIG_UPDATE) | ||
1279 | { | ||
1280 | GNUNET_SCHEDULER_cancel (d->task); | ||
1281 | d->phase = SP_START_DONE; | ||
1282 | } | ||
1283 | if (d->server != NULL) | ||
1284 | { | ||
1285 | GNUNET_CORE_disconnect (d->server); | ||
1286 | d->server = NULL; | ||
1287 | } | ||
1288 | |||
1289 | if (d->th != NULL) | ||
1290 | { | ||
1291 | GNUNET_TRANSPORT_get_hello_cancel (d->ghh); | ||
1292 | d->ghh = NULL; | ||
1293 | GNUNET_TRANSPORT_disconnect (d->th); | ||
1294 | d->th = NULL; | ||
1295 | } | ||
1296 | /* state clean up and notifications */ | ||
1297 | GNUNET_free_non_null (d->hello); | ||
1298 | |||
1299 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Terminating peer `%4s'\n"), | ||
1300 | GNUNET_i2s (&d->id)); | ||
1301 | d->phase = SP_START_ARMING; | ||
1302 | |||
1303 | /* Check if this is a local or remote process */ | ||
1304 | if (NULL != d->hostname) | ||
1305 | { | ||
1306 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1307 | "Stopping gnunet-arm with config `%s' on host `%s'.\n", | ||
1308 | d->cfgfile, d->hostname); | ||
1309 | if (d->username != NULL) | ||
1310 | GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname); | ||
1311 | else | ||
1312 | arg = GNUNET_strdup (d->hostname); | ||
1313 | |||
1314 | d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "ssh", "ssh", | ||
1315 | "-q", | ||
1316 | arg, "gnunet-arm", | ||
1317 | "-c", d->cfgfile, "-e", "-r", NULL); | ||
1318 | /* Use -r to restart arm and all services */ | ||
1319 | |||
1320 | GNUNET_free (arg); | ||
1321 | } | ||
1322 | else | ||
1323 | { | ||
1324 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1325 | "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile); | ||
1326 | d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "gnunet-arm", "gnunet-arm", | ||
1327 | "-c", d->cfgfile, "-e", "-r", NULL); | ||
1328 | } | ||
1329 | |||
1330 | GNUNET_free_non_null (del_arg); | ||
1331 | d->task = | ||
1332 | GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, d); | ||
1333 | |||
1334 | } | ||
1335 | |||
1336 | |||
1337 | /** | ||
1338 | * Stops a GNUnet daemon. | ||
1339 | * | ||
1340 | * @param d the daemon that should be stopped | ||
1341 | * @param service the name of the service to stop | ||
1342 | * @param timeout how long to wait for process for shutdown to complete | ||
1343 | * @param cb function called once the daemon was stopped | ||
1344 | * @param cb_cls closure for cb | ||
1345 | */ | ||
1346 | void | ||
1347 | GNUNET_TESTING_daemon_stop_service (struct GNUNET_TESTING_Daemon *d, | ||
1348 | const char *service, | ||
1349 | struct GNUNET_TIME_Relative timeout, | ||
1350 | GNUNET_TESTING_NotifyCompletion cb, | ||
1351 | void *cb_cls) | ||
1352 | { | ||
1353 | char *arg; | ||
1354 | |||
1355 | d->dead_cb = cb; | ||
1356 | d->dead_cb_cls = cb_cls; | ||
1357 | |||
1358 | GNUNET_assert (d->running == GNUNET_YES); | ||
1359 | |||
1360 | if (d->phase == SP_CONFIG_UPDATE) | ||
1361 | { | ||
1362 | GNUNET_SCHEDULER_cancel (d->task); | ||
1363 | d->phase = SP_START_DONE; | ||
1364 | } | ||
1365 | |||
1366 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Terminating peer `%4s'\n"), | ||
1367 | GNUNET_i2s (&d->id)); | ||
1368 | if (d->churned_services != NULL) | ||
1369 | { | ||
1370 | d->dead_cb (d->dead_cb_cls, "A service has already been turned off!!"); | ||
1371 | return; | ||
1372 | } | ||
1373 | d->phase = SP_SERVICE_SHUTDOWN_START; | ||
1374 | d->churned_services = GNUNET_strdup (service); | ||
1375 | d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
1376 | /* Check if this is a local or remote process */ | ||
1377 | if (NULL != d->hostname) | ||
1378 | { | ||
1379 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1380 | "Stopping gnunet-arm with config `%s' on host `%s'.\n", | ||
1381 | d->cfgfile, d->hostname); | ||
1382 | if (d->username != NULL) | ||
1383 | GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname); | ||
1384 | else | ||
1385 | arg = GNUNET_strdup (d->hostname); | ||
1386 | |||
1387 | d->proc_arm_srv_stop = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "ssh", "ssh", | ||
1388 | "-q", | ||
1389 | arg, "gnunet-arm", | ||
1390 | "-c", d->cfgfile, "-k", service, "-q", | ||
1391 | "-T", | ||
1392 | GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_NO), | ||
1393 | NULL); | ||
1394 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1395 | "Stopping gnunet-arm with command ssh %s gnunet-arm -c %s -k %s -q\n", | ||
1396 | arg, "gnunet-arm", d->cfgfile, service); | ||
1397 | GNUNET_free (arg); | ||
1398 | } | ||
1399 | else | ||
1400 | { | ||
1401 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1402 | "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile); | ||
1403 | d->proc_arm_srv_stop = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "gnunet-arm", "gnunet-arm", | ||
1404 | "-c", d->cfgfile, "-k", service, "-q", | ||
1405 | "-T", | ||
1406 | GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_NO), | ||
1407 | NULL); | ||
1408 | } | ||
1409 | |||
1410 | d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
1411 | d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d); | ||
1412 | } | ||
1413 | |||
1414 | |||
1415 | /** | ||
1416 | * Forcefully terminate a process and clean up the child. | ||
1417 | * | ||
1418 | * @param proc handle to process to kill | ||
1419 | */ | ||
1420 | static void | ||
1421 | kill_and_close_process (struct GNUNET_OS_Process *proc) | ||
1422 | { | ||
1423 | (void) GNUNET_OS_process_kill (proc, SIGKILL); | ||
1424 | GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (proc)); | ||
1425 | GNUNET_OS_process_destroy (proc); | ||
1426 | } | ||
1427 | |||
1428 | |||
1429 | /** | ||
1430 | * Stops a GNUnet daemon. | ||
1431 | * | ||
1432 | * @param d the daemon that should be stopped | ||
1433 | * @param timeout how long to wait for process for shutdown to complete | ||
1434 | * @param cb function called once the daemon was stopped | ||
1435 | * @param cb_cls closure for cb | ||
1436 | * @param delete_files GNUNET_YES to remove files, GNUNET_NO | ||
1437 | * to leave them | ||
1438 | * @param allow_restart GNUNET_YES to restart peer later (using this API) | ||
1439 | * GNUNET_NO to kill off and clean up for good | ||
1440 | */ | ||
1441 | void | ||
1442 | GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d, | ||
1443 | struct GNUNET_TIME_Relative timeout, | ||
1444 | GNUNET_TESTING_NotifyCompletion cb, void *cb_cls, | ||
1445 | int delete_files, int allow_restart) | ||
1446 | { | ||
1447 | char *arg; | ||
1448 | char *del_arg; | ||
1449 | |||
1450 | d->dead_cb = cb; | ||
1451 | d->dead_cb_cls = cb_cls; | ||
1452 | |||
1453 | if (NULL != d->cb) | ||
1454 | { | ||
1455 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Setting d->dead on peer `%4s'\n"), | ||
1456 | GNUNET_i2s (&d->id)); | ||
1457 | d->dead = GNUNET_YES; | ||
1458 | return; | ||
1459 | } | ||
1460 | if (NULL != d->proc_arm_start) | ||
1461 | { | ||
1462 | kill_and_close_process (d->proc_arm_start); | ||
1463 | d->proc_arm_start = NULL; | ||
1464 | } | ||
1465 | if (NULL != d->proc_arm_srv_start) | ||
1466 | { | ||
1467 | kill_and_close_process (d->proc_arm_srv_start); | ||
1468 | d->proc_arm_srv_start = NULL; | ||
1469 | } | ||
1470 | if (NULL != d->proc_arm_srv_stop) | ||
1471 | { | ||
1472 | kill_and_close_process (d->proc_arm_srv_stop); | ||
1473 | d->proc_arm_srv_stop = NULL; | ||
1474 | } | ||
1475 | if (NULL != d->proc_arm_copying) | ||
1476 | { | ||
1477 | kill_and_close_process (d->proc_arm_copying); | ||
1478 | d->proc_arm_copying = NULL; | ||
1479 | } | ||
1480 | if (NULL != d->proc_arm_peerinfo) | ||
1481 | { | ||
1482 | kill_and_close_process (d->proc_arm_peerinfo); | ||
1483 | d->proc_arm_peerinfo = NULL; | ||
1484 | } | ||
1485 | if ((d->running == GNUNET_NO) && (d->churn == GNUNET_YES)) | ||
1486 | { | ||
1487 | /* Peer has already been stopped in churn context! | ||
1488 | * Free what was left from churning! */ | ||
1489 | GNUNET_assert (d->cfg != NULL); | ||
1490 | GNUNET_CONFIGURATION_destroy (d->cfg); | ||
1491 | if (delete_files == GNUNET_YES) | ||
1492 | { | ||
1493 | if (0 != UNLINK (d->cfgfile)) | ||
1494 | { | ||
1495 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "unlink"); | ||
1496 | } | ||
1497 | } | ||
1498 | GNUNET_free (d->cfgfile); | ||
1499 | GNUNET_free_non_null (d->hostname); | ||
1500 | GNUNET_free_non_null (d->username); | ||
1501 | if (NULL != d->dead_cb) | ||
1502 | d->dead_cb (d->dead_cb_cls, NULL); | ||
1503 | /* FIXME: this should be an assert and the test below | ||
1504 | should not be required, but testing is broken... */ | ||
1505 | GNUNET_break (NULL == d->proc_arm_stop); | ||
1506 | if (NULL == d->proc_arm_stop) | ||
1507 | GNUNET_free (d); | ||
1508 | return; | ||
1509 | } | ||
1510 | |||
1511 | del_arg = NULL; | ||
1512 | if (delete_files == GNUNET_YES) | ||
1513 | { | ||
1514 | GNUNET_asprintf (&del_arg, "-d"); | ||
1515 | } | ||
1516 | |||
1517 | if (d->phase == SP_CONFIG_UPDATE) | ||
1518 | { | ||
1519 | GNUNET_SCHEDULER_cancel (d->task); | ||
1520 | d->phase = SP_START_DONE; | ||
1521 | } | ||
1522 | /** Move this call to scheduled shutdown as fix for CORE_connect calling daemon_stop? | ||
1523 | if (d->server != NULL) | ||
1524 | { | ||
1525 | GNUNET_CORE_disconnect (d->server); | ||
1526 | d->server = NULL; | ||
1527 | } | ||
1528 | */ | ||
1529 | /* shutdown ARM process (will terminate others) */ | ||
1530 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Terminating peer `%4s'\n" , | ||
1531 | GNUNET_i2s (&d->id)); | ||
1532 | d->phase = SP_SHUTDOWN_START; | ||
1533 | d->running = GNUNET_NO; | ||
1534 | if (allow_restart == GNUNET_YES) | ||
1535 | d->churn = GNUNET_YES; | ||
1536 | if (d->th != NULL) | ||
1537 | { | ||
1538 | GNUNET_TRANSPORT_get_hello_cancel (d->ghh); | ||
1539 | d->ghh = NULL; | ||
1540 | GNUNET_TRANSPORT_disconnect (d->th); | ||
1541 | d->th = NULL; | ||
1542 | } | ||
1543 | /* Check if this is a local or remote process */ | ||
1544 | |||
1545 | |||
1546 | if (NULL != d->hostname) | ||
1547 | { | ||
1548 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1549 | "Stopping gnunet-arm with config `%s' on host `%s'.\n", | ||
1550 | d->cfgfile, d->hostname); | ||
1551 | if (d->username != NULL) | ||
1552 | GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname); | ||
1553 | else | ||
1554 | arg = GNUNET_strdup (d->hostname); | ||
1555 | |||
1556 | d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "ssh", "ssh", | ||
1557 | "-q", | ||
1558 | arg, "gnunet-arm", | ||
1559 | "-c", d->cfgfile, "-e", "-q", "-T", | ||
1560 | GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_NO), | ||
1561 | del_arg, NULL); | ||
1562 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1563 | "Stopping gnunet-arm with command ssh %s gnunet-arm -c %s -e -q %s\n", | ||
1564 | arg, "gnunet-arm", d->cfgfile, del_arg); | ||
1565 | /* Use -e to end arm, and -d to remove temp files */ | ||
1566 | GNUNET_free (arg); | ||
1567 | } | ||
1568 | else | ||
1569 | { | ||
1570 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1571 | "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile); | ||
1572 | d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "gnunet-arm", "gnunet-arm", | ||
1573 | "-c", d->cfgfile, "-e", "-q", "-T", | ||
1574 | GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_NO), | ||
1575 | del_arg, NULL); | ||
1576 | GNUNET_assert (NULL != d->proc_arm_stop); | ||
1577 | } | ||
1578 | |||
1579 | GNUNET_free_non_null (del_arg); | ||
1580 | d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
1581 | if (GNUNET_SCHEDULER_NO_TASK != d->task) | ||
1582 | GNUNET_SCHEDULER_cancel(d->task); | ||
1583 | d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d); | ||
1584 | } | ||
1585 | |||
1586 | |||
1587 | /** | ||
1588 | * Changes the configuration of a GNUnet daemon. | ||
1589 | * | ||
1590 | * @param d the daemon that should be modified | ||
1591 | * @param cfg the new configuration for the daemon | ||
1592 | * @param cb function called once the configuration was changed | ||
1593 | * @param cb_cls closure for cb | ||
1594 | */ | ||
1595 | void | ||
1596 | GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d, | ||
1597 | struct GNUNET_CONFIGURATION_Handle *cfg, | ||
1598 | GNUNET_TESTING_NotifyCompletion cb, | ||
1599 | void *cb_cls) | ||
1600 | { | ||
1601 | char *arg; | ||
1602 | |||
1603 | if (d->phase != SP_START_DONE) | ||
1604 | { | ||
1605 | if (NULL != cb) | ||
1606 | cb (cb_cls, | ||
1607 | _ | ||
1608 | ("Peer not yet running, can not change configuration at this point.")); | ||
1609 | return; | ||
1610 | } | ||
1611 | |||
1612 | /* 1) write configuration to temporary file */ | ||
1613 | if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, d->cfgfile)) | ||
1614 | { | ||
1615 | if (NULL != cb) | ||
1616 | cb (cb_cls, _("Failed to write new configuration to disk.")); | ||
1617 | return; | ||
1618 | } | ||
1619 | |||
1620 | /* 2) copy file to remote host (if necessary) */ | ||
1621 | if (NULL == d->hostname) | ||
1622 | { | ||
1623 | /* signal success */ | ||
1624 | if (NULL != cb) | ||
1625 | cb (cb_cls, NULL); | ||
1626 | return; | ||
1627 | } | ||
1628 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1629 | "Copying updated configuration file to remote host `%s'.\n", | ||
1630 | d->hostname); | ||
1631 | d->phase = SP_CONFIG_UPDATE; | ||
1632 | if (NULL != d->username) | ||
1633 | GNUNET_asprintf (&arg, "%s@%s:%s", d->username, d->hostname, d->cfgfile); | ||
1634 | else | ||
1635 | GNUNET_asprintf (&arg, "%s:%s", d->hostname, d->cfgfile); | ||
1636 | d->proc_arm_copying = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "scp", "scp", | ||
1637 | "-q", | ||
1638 | d->cfgfile, arg, NULL); | ||
1639 | GNUNET_free (arg); | ||
1640 | if (NULL == d->proc_arm_copying) | ||
1641 | { | ||
1642 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1643 | _("Could not start `%s' process to copy configuration file.\n"), | ||
1644 | "scp"); | ||
1645 | if (NULL != cb) | ||
1646 | cb (cb_cls, _("Failed to copy new configuration to remote machine.")); | ||
1647 | d->phase = SP_START_DONE; | ||
1648 | return; | ||
1649 | } | ||
1650 | d->update_cb = cb; | ||
1651 | d->update_cb_cls = cb_cls; | ||
1652 | d->task = | ||
1653 | GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, d); | ||
1654 | } | ||
1655 | |||
1656 | |||
1657 | /** | ||
1658 | * Data kept for each pair of peers that we try | ||
1659 | * to connect. | ||
1660 | */ | ||
1661 | struct GNUNET_TESTING_ConnectContext | ||
1662 | { | ||
1663 | /** | ||
1664 | * Testing handle to the first daemon. | ||
1665 | */ | ||
1666 | struct GNUNET_TESTING_Daemon *d1; | ||
1667 | |||
1668 | /** | ||
1669 | * Handle to core of first daemon (to check connect) | ||
1670 | */ | ||
1671 | struct GNUNET_CORE_Handle *d1core; | ||
1672 | |||
1673 | /** | ||
1674 | * Have we actually connected to the core of the first daemon yet? | ||
1675 | */ | ||
1676 | int d1core_ready; | ||
1677 | |||
1678 | /** | ||
1679 | * Testing handle to the second daemon. | ||
1680 | */ | ||
1681 | struct GNUNET_TESTING_Daemon *d2; | ||
1682 | |||
1683 | /** | ||
1684 | * Transport handle to the first daemon (to offer the HELLO of the second daemon to). | ||
1685 | */ | ||
1686 | struct GNUNET_TRANSPORT_Handle *d1th; | ||
1687 | |||
1688 | /** | ||
1689 | * Function to call once we are done (or have timed out). | ||
1690 | */ | ||
1691 | GNUNET_TESTING_NotifyConnection cb; | ||
1692 | |||
1693 | /** | ||
1694 | * Closure for "nb". | ||
1695 | */ | ||
1696 | void *cb_cls; | ||
1697 | |||
1698 | /** | ||
1699 | * The relative timeout from whence this connect attempt was | ||
1700 | * started. Allows for reconnect attempts. | ||
1701 | */ | ||
1702 | struct GNUNET_TIME_Relative relative_timeout; | ||
1703 | |||
1704 | /** | ||
1705 | * Maximum number of connect attempts, will retry connection | ||
1706 | * this number of times on failures. | ||
1707 | */ | ||
1708 | unsigned int connect_attempts; | ||
1709 | |||
1710 | /** | ||
1711 | * Hello timeout task | ||
1712 | */ | ||
1713 | GNUNET_SCHEDULER_TaskIdentifier hello_send_task; | ||
1714 | |||
1715 | /** | ||
1716 | * Connect timeout task | ||
1717 | */ | ||
1718 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; | ||
1719 | |||
1720 | /** | ||
1721 | * When should this operation be complete (or we must trigger | ||
1722 | * a timeout). | ||
1723 | */ | ||
1724 | struct GNUNET_TIME_Relative timeout_hello; | ||
1725 | |||
1726 | /** | ||
1727 | * Was the connection attempt successful? | ||
1728 | */ | ||
1729 | int connected; | ||
1730 | |||
1731 | /** | ||
1732 | * When connecting, do we need to send the HELLO? | ||
1733 | */ | ||
1734 | int send_hello; | ||
1735 | |||
1736 | /** | ||
1737 | * The distance between the two connected peers | ||
1738 | */ | ||
1739 | uint32_t distance; | ||
1740 | }; | ||
1741 | |||
1742 | |||
1743 | /** Forward declaration **/ | ||
1744 | static void | ||
1745 | reattempt_daemons_connect (void *cls, | ||
1746 | const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
1747 | |||
1748 | |||
1749 | /** | ||
1750 | * Notify callback about success or failure of the attempt | ||
1751 | * to connect the two peers | ||
1752 | * | ||
1753 | * @param cls our "struct GNUNET_TESTING_ConnectContext" (freed) | ||
1754 | * @param tc reason tells us if we succeeded or failed | ||
1755 | */ | ||
1756 | static void | ||
1757 | notify_connect_result (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1758 | { | ||
1759 | struct GNUNET_TESTING_ConnectContext *ctx = cls; | ||
1760 | |||
1761 | ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
1762 | if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK) | ||
1763 | { | ||
1764 | GNUNET_SCHEDULER_cancel (ctx->hello_send_task); | ||
1765 | ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK; | ||
1766 | } | ||
1767 | |||
1768 | if (ctx->d1th != NULL) | ||
1769 | GNUNET_TRANSPORT_disconnect (ctx->d1th); | ||
1770 | ctx->d1th = NULL; | ||
1771 | if (ctx->d1core != NULL) | ||
1772 | GNUNET_CORE_disconnect (ctx->d1core); | ||
1773 | ctx->d1core = NULL; | ||
1774 | |||
1775 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
1776 | { | ||
1777 | GNUNET_free (ctx); | ||
1778 | return; | ||
1779 | } | ||
1780 | |||
1781 | if (ctx->connected == GNUNET_YES) | ||
1782 | { | ||
1783 | if (ctx->cb != NULL) | ||
1784 | { | ||
1785 | ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->distance, | ||
1786 | ctx->d1->cfg, ctx->d2->cfg, ctx->d1, ctx->d2, NULL); | ||
1787 | } | ||
1788 | } | ||
1789 | else if (ctx->connect_attempts > 0) | ||
1790 | { | ||
1791 | ctx->d1core_ready = GNUNET_NO; | ||
1792 | ctx->timeout_task = | ||
1793 | GNUNET_SCHEDULER_add_now (&reattempt_daemons_connect, ctx); | ||
1794 | return; | ||
1795 | } | ||
1796 | else | ||
1797 | { | ||
1798 | if (ctx->cb != NULL) | ||
1799 | { | ||
1800 | ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, | ||
1801 | ctx->d2->cfg, ctx->d1, ctx->d2, _("Peers failed to connect")); | ||
1802 | } | ||
1803 | } | ||
1804 | GNUNET_free (ctx); | ||
1805 | } | ||
1806 | |||
1807 | |||
1808 | /** | ||
1809 | * Success, connection is up. Signal client our success. | ||
1810 | * | ||
1811 | * @param cls our "struct GNUNET_TESTING_ConnectContext" | ||
1812 | * @param peer identity of the peer that has connected | ||
1813 | * @param atsi performance information | ||
1814 | * @param atsi_count number of records in 'atsi' | ||
1815 | * | ||
1816 | */ | ||
1817 | static void | ||
1818 | connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
1819 | const struct GNUNET_ATS_Information *atsi, | ||
1820 | unsigned int atsi_count) | ||
1821 | { | ||
1822 | struct GNUNET_TESTING_ConnectContext *ctx = cls; | ||
1823 | |||
1824 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected peer %s to peer %s\n", | ||
1825 | ctx->d1->shortname, GNUNET_i2s (peer)); | ||
1826 | if (0 != memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity))) | ||
1827 | return; | ||
1828 | ctx->connected = GNUNET_YES; | ||
1829 | ctx->distance = 0; /* FIXME: distance */ | ||
1830 | if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK) | ||
1831 | { | ||
1832 | GNUNET_SCHEDULER_cancel (ctx->hello_send_task); | ||
1833 | ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK; | ||
1834 | } | ||
1835 | GNUNET_SCHEDULER_cancel (ctx->timeout_task); | ||
1836 | ctx->timeout_task = GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); | ||
1837 | } | ||
1838 | |||
1839 | |||
1840 | static void | ||
1841 | send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1842 | { | ||
1843 | struct GNUNET_TESTING_ConnectContext *ctx = cls; | ||
1844 | struct GNUNET_MessageHeader *hello; | ||
1845 | |||
1846 | ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK; | ||
1847 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
1848 | return; | ||
1849 | if ((ctx->d1core_ready == GNUNET_YES) && (ctx->d2->hello != NULL) && | ||
1850 | (NULL != GNUNET_HELLO_get_header (ctx->d2->hello)) && | ||
1851 | (ctx->d1->phase == SP_START_DONE) && (ctx->d2->phase == SP_START_DONE)) | ||
1852 | { | ||
1853 | hello = GNUNET_HELLO_get_header (ctx->d2->hello); | ||
1854 | GNUNET_assert (hello != NULL); | ||
1855 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Offering hello of %s to %s\n", | ||
1856 | ctx->d2->shortname, ctx->d1->shortname); | ||
1857 | GNUNET_TRANSPORT_offer_hello (ctx->d1th, hello, NULL, NULL); | ||
1858 | GNUNET_assert (ctx->d1core != NULL); | ||
1859 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1860 | "Sending connect request to TRANSPORT of %s for peer %s\n", | ||
1861 | GNUNET_i2s (&ctx->d1->id), | ||
1862 | GNUNET_h2s (&ctx->d2->id.hashPubKey)); | ||
1863 | GNUNET_TRANSPORT_try_connect (ctx->d1th, &ctx->d2->id, NULL, NULL); /*FIXME TRY_CONNECT change */ | ||
1864 | ctx->timeout_hello = | ||
1865 | GNUNET_TIME_relative_add (ctx->timeout_hello, | ||
1866 | GNUNET_TIME_relative_multiply | ||
1867 | (GNUNET_TIME_UNIT_MILLISECONDS, 500)); | ||
1868 | } | ||
1869 | ctx->hello_send_task = | ||
1870 | GNUNET_SCHEDULER_add_delayed (ctx->timeout_hello, &send_hello, ctx); | ||
1871 | } | ||
1872 | |||
1873 | /** | ||
1874 | * Notify of a successful connection to the core service. | ||
1875 | * | ||
1876 | * @param cls a ConnectContext | ||
1877 | * @param server handle to the core service | ||
1878 | * @param my_identity the peer identity of this peer | ||
1879 | */ | ||
1880 | void | ||
1881 | core_init_notify (void *cls, struct GNUNET_CORE_Handle *server, | ||
1882 | const struct GNUNET_PeerIdentity *my_identity) | ||
1883 | { | ||
1884 | struct GNUNET_TESTING_ConnectContext *connect_ctx = cls; | ||
1885 | |||
1886 | connect_ctx->d1core_ready = GNUNET_YES; | ||
1887 | |||
1888 | if (connect_ctx->send_hello == GNUNET_NO) | ||
1889 | { | ||
1890 | GNUNET_TRANSPORT_try_connect (connect_ctx->d1th, &connect_ctx->d2->id, NULL, NULL); /*FIXME TRY_CONNECT change */ | ||
1891 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1892 | "Sending connect request to TRANSPORT of %s for peer %s\n", | ||
1893 | connect_ctx->d1->shortname, connect_ctx->d2->shortname); | ||
1894 | } | ||
1895 | } | ||
1896 | |||
1897 | |||
1898 | /** | ||
1899 | * Try to connect again some peers that failed in an earlier attempt. This will | ||
1900 | * be tried as many times as connection_attempts in the configuration file. | ||
1901 | * | ||
1902 | * @param cls Closure (connection context between the two peers). | ||
1903 | * @param tc TaskContext. | ||
1904 | */ | ||
1905 | static void | ||
1906 | reattempt_daemons_connect (void *cls, | ||
1907 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1908 | { | ||
1909 | struct GNUNET_TESTING_ConnectContext *ctx = cls; | ||
1910 | |||
1911 | ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
1912 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
1913 | return; | ||
1914 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1915 | "re-attempting connect of peer %s to peer %s\n", | ||
1916 | ctx->d1->shortname, ctx->d2->shortname); | ||
1917 | ctx->connect_attempts--; | ||
1918 | GNUNET_assert (ctx->d1core == NULL); | ||
1919 | ctx->d1core_ready = GNUNET_NO; | ||
1920 | ctx->d1core = | ||
1921 | GNUNET_CORE_connect (ctx->d1->cfg, ctx, &core_init_notify, | ||
1922 | &connect_notify, NULL, NULL, GNUNET_NO, NULL, | ||
1923 | GNUNET_NO, no_handlers); | ||
1924 | if (ctx->d1core == NULL) | ||
1925 | { | ||
1926 | if (NULL != ctx->cb) | ||
1927 | ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, | ||
1928 | ctx->d2->cfg, ctx->d1, ctx->d2, | ||
1929 | _("Failed to connect to core service of first peer!\n")); | ||
1930 | GNUNET_free (ctx); | ||
1931 | return; | ||
1932 | } | ||
1933 | |||
1934 | /* Don't know reason for initial connect failure, update the HELLO for the second peer */ | ||
1935 | if (NULL != ctx->d2->hello) | ||
1936 | { | ||
1937 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "updating %s's HELLO\n", | ||
1938 | ctx->d2->shortname); | ||
1939 | GNUNET_free (ctx->d2->hello); | ||
1940 | ctx->d2->hello = NULL; | ||
1941 | if (NULL != ctx->d2->th) | ||
1942 | { | ||
1943 | GNUNET_TRANSPORT_get_hello_cancel (ctx->d2->ghh); | ||
1944 | ctx->d2->ghh = NULL; | ||
1945 | GNUNET_TRANSPORT_disconnect (ctx->d2->th); | ||
1946 | } | ||
1947 | ctx->d2->th = | ||
1948 | GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL, | ||
1949 | NULL); | ||
1950 | GNUNET_assert (ctx->d2->th != NULL); | ||
1951 | ctx->d2->ghh = | ||
1952 | GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2); | ||
1953 | } | ||
1954 | else | ||
1955 | { | ||
1956 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "didn't have %s's HELLO\n", | ||
1957 | ctx->d2->shortname); | ||
1958 | } | ||
1959 | |||
1960 | if ((NULL == ctx->d2->hello) && (ctx->d2->th == NULL)) | ||
1961 | { | ||
1962 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1963 | "didn't have %s's HELLO, trying to get it now\n", | ||
1964 | ctx->d2->shortname); | ||
1965 | ctx->d2->th = | ||
1966 | GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL, | ||
1967 | NULL); | ||
1968 | if (NULL == ctx->d2->th) | ||
1969 | { | ||
1970 | GNUNET_CORE_disconnect (ctx->d1core); | ||
1971 | if (NULL != ctx->cb) | ||
1972 | ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, | ||
1973 | ctx->d2->cfg, ctx->d1, ctx->d2, | ||
1974 | _("Failed to connect to transport service!\n")); | ||
1975 | GNUNET_free (ctx); | ||
1976 | return; | ||
1977 | } | ||
1978 | ctx->d2->ghh = | ||
1979 | GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2); | ||
1980 | } | ||
1981 | else | ||
1982 | { | ||
1983 | if (NULL == ctx->d2->hello) | ||
1984 | { | ||
1985 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1986 | "didn't have %s's HELLO but th wasn't NULL, not trying!!\n", | ||
1987 | ctx->d2->shortname); | ||
1988 | } | ||
1989 | } | ||
1990 | |||
1991 | if (ctx->send_hello == GNUNET_YES) | ||
1992 | { | ||
1993 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %s's HELLO to %s\n", | ||
1994 | ctx->d1->shortname, ctx->d2->shortname); | ||
1995 | ctx->d1th = | ||
1996 | GNUNET_TRANSPORT_connect (ctx->d1->cfg, &ctx->d1->id, ctx->d1, NULL, | ||
1997 | NULL, NULL); | ||
1998 | if (ctx->d1th == NULL) | ||
1999 | { | ||
2000 | GNUNET_CORE_disconnect (ctx->d1core); | ||
2001 | if (NULL != ctx->cb) | ||
2002 | ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, | ||
2003 | ctx->d2->cfg, ctx->d1, ctx->d2, | ||
2004 | _("Failed to connect to transport service!\n")); | ||
2005 | GNUNET_free (ctx); | ||
2006 | return; | ||
2007 | } | ||
2008 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->hello_send_task); | ||
2009 | ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx); | ||
2010 | } | ||
2011 | else | ||
2012 | { | ||
2013 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to reconnect %s to %s\n", | ||
2014 | ctx->d1->shortname, ctx->d2->shortname); | ||
2015 | GNUNET_TRANSPORT_try_connect (ctx->d1th, &ctx->d2->id, NULL, NULL); /*FIXME TRY_CONNECT change */ | ||
2016 | } | ||
2017 | ctx->timeout_task = | ||
2018 | GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout, | ||
2019 | ¬ify_connect_result, ctx); | ||
2020 | } | ||
2021 | |||
2022 | /** | ||
2023 | * Iterator for currently known peers, to ensure | ||
2024 | * that we don't try to send duplicate connect | ||
2025 | * requests to core. | ||
2026 | * | ||
2027 | * @param cls our "struct GNUNET_TESTING_ConnectContext" | ||
2028 | * @param peer identity of the peer that has connected, | ||
2029 | * NULL when iteration has finished | ||
2030 | * @param atsi performance information | ||
2031 | * @param atsi_count number of records in 'atsi' | ||
2032 | * | ||
2033 | */ | ||
2034 | static void | ||
2035 | core_initial_iteration (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
2036 | const struct GNUNET_ATS_Information *atsi, | ||
2037 | unsigned int atsi_count) | ||
2038 | { | ||
2039 | struct GNUNET_TESTING_ConnectContext *ctx = cls; | ||
2040 | |||
2041 | if ((peer != NULL) && | ||
2042 | (0 == memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity)))) | ||
2043 | { | ||
2044 | ctx->connected = GNUNET_YES; | ||
2045 | ctx->distance = 0; /* FIXME: distance */ | ||
2046 | return; | ||
2047 | } | ||
2048 | if (peer != NULL) | ||
2049 | return; /* ignore other peers */ | ||
2050 | /* peer == NULL: End of iteration over peers */ | ||
2051 | |||
2052 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->timeout_task); | ||
2053 | if (ctx->connected == GNUNET_YES) | ||
2054 | { | ||
2055 | ctx->timeout_task = GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); | ||
2056 | return; | ||
2057 | } | ||
2058 | |||
2059 | /* Peer not already connected, need to schedule connect request! */ | ||
2060 | if (ctx->d1core == NULL) | ||
2061 | { | ||
2062 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2063 | "Peers are NOT connected, connecting to core!\n"); | ||
2064 | ctx->d1core = | ||
2065 | GNUNET_CORE_connect (ctx->d1->cfg, ctx, &core_init_notify, | ||
2066 | &connect_notify, NULL, NULL, GNUNET_NO, NULL, | ||
2067 | GNUNET_NO, no_handlers); | ||
2068 | } | ||
2069 | |||
2070 | if (ctx->d1core == NULL) | ||
2071 | { | ||
2072 | ctx->timeout_task = GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); | ||
2073 | return; | ||
2074 | } | ||
2075 | |||
2076 | 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 */ | ||
2077 | { | ||
2078 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2079 | "Don't have d2's HELLO, trying to get it!\n"); | ||
2080 | ctx->d2->th = | ||
2081 | GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL, | ||
2082 | NULL); | ||
2083 | if (ctx->d2->th == NULL) | ||
2084 | { | ||
2085 | GNUNET_CORE_disconnect (ctx->d1core); | ||
2086 | ctx->d1core = NULL; | ||
2087 | ctx->timeout_task = | ||
2088 | GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); | ||
2089 | return; | ||
2090 | } | ||
2091 | ctx->d2->ghh = | ||
2092 | GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2); | ||
2093 | } | ||
2094 | |||
2095 | if (ctx->send_hello == GNUNET_YES) | ||
2096 | { | ||
2097 | ctx->d1th = | ||
2098 | GNUNET_TRANSPORT_connect (ctx->d1->cfg, &ctx->d1->id, ctx->d1, NULL, | ||
2099 | NULL, NULL); | ||
2100 | if (ctx->d1th == NULL) | ||
2101 | { | ||
2102 | GNUNET_CORE_disconnect (ctx->d1core); | ||
2103 | ctx->d1core = NULL; | ||
2104 | ctx->timeout_task = | ||
2105 | GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); | ||
2106 | return; | ||
2107 | } | ||
2108 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->hello_send_task); | ||
2109 | ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx); | ||
2110 | } | ||
2111 | |||
2112 | ctx->timeout_task = | ||
2113 | GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout, | ||
2114 | ¬ify_connect_result, ctx); | ||
2115 | |||
2116 | } | ||
2117 | |||
2118 | |||
2119 | /** | ||
2120 | * Establish a connection between two GNUnet daemons. The daemons | ||
2121 | * must both be running and not be stopped until either the | ||
2122 | * 'cb' callback is called OR the connection request has been | ||
2123 | * explicitly cancelled. | ||
2124 | * | ||
2125 | * @param d1 handle for the first daemon | ||
2126 | * @param d2 handle for the second daemon | ||
2127 | * @param timeout how long is the connection attempt | ||
2128 | * allowed to take? | ||
2129 | * @param max_connect_attempts how many times should we try to reconnect | ||
2130 | * (within timeout) | ||
2131 | * @param send_hello GNUNET_YES to send the HELLO, GNUNET_NO to assume | ||
2132 | * the HELLO has already been exchanged | ||
2133 | * @param cb function to call at the end | ||
2134 | * @param cb_cls closure for cb | ||
2135 | * @return handle to cancel the request | ||
2136 | */ | ||
2137 | struct GNUNET_TESTING_ConnectContext * | ||
2138 | GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, | ||
2139 | struct GNUNET_TESTING_Daemon *d2, | ||
2140 | struct GNUNET_TIME_Relative timeout, | ||
2141 | unsigned int max_connect_attempts, | ||
2142 | int send_hello, | ||
2143 | GNUNET_TESTING_NotifyConnection cb, | ||
2144 | void *cb_cls) | ||
2145 | { | ||
2146 | struct GNUNET_TESTING_ConnectContext *ctx; | ||
2147 | |||
2148 | if ((d1->running == GNUNET_NO) || (d2->running == GNUNET_NO)) | ||
2149 | { | ||
2150 | if (NULL != cb) | ||
2151 | cb (cb_cls, &d1->id, &d2->id, 0, d1->cfg, d2->cfg, d1, d2, | ||
2152 | _("Peers are not fully running yet, can not connect!\n")); | ||
2153 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Peers are not up!\n"); | ||
2154 | return NULL; | ||
2155 | } | ||
2156 | |||
2157 | ctx = GNUNET_malloc (sizeof (struct GNUNET_TESTING_ConnectContext)); | ||
2158 | ctx->d1 = d1; | ||
2159 | ctx->d2 = d2; | ||
2160 | ctx->timeout_hello = | ||
2161 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500); | ||
2162 | ctx->relative_timeout = | ||
2163 | GNUNET_TIME_relative_divide (timeout, max_connect_attempts); | ||
2164 | ctx->cb = cb; | ||
2165 | ctx->cb_cls = cb_cls; | ||
2166 | ctx->connect_attempts = max_connect_attempts; | ||
2167 | ctx->connected = GNUNET_NO; | ||
2168 | ctx->send_hello = send_hello; | ||
2169 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asked to connect peer %s to peer %s\n", | ||
2170 | d1->shortname, d2->shortname); | ||
2171 | /* Core is up! Iterate over all _known_ peers first to check if we are already connected to the peer! */ | ||
2172 | GNUNET_assert (NULL != | ||
2173 | GNUNET_CORE_is_peer_connected (ctx->d1->cfg, &ctx->d2->id, | ||
2174 | &core_initial_iteration, ctx)); | ||
2175 | return ctx; | ||
2176 | } | ||
2177 | |||
2178 | |||
2179 | /** | ||
2180 | * Cancel an attempt to connect two daemons. | ||
2181 | * | ||
2182 | * @param cc connect context | ||
2183 | */ | ||
2184 | void | ||
2185 | GNUNET_TESTING_daemons_connect_cancel (struct GNUNET_TESTING_ConnectContext *cc) | ||
2186 | { | ||
2187 | if (GNUNET_SCHEDULER_NO_TASK != cc->timeout_task) | ||
2188 | { | ||
2189 | GNUNET_SCHEDULER_cancel (cc->timeout_task); | ||
2190 | cc->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
2191 | } | ||
2192 | if (GNUNET_SCHEDULER_NO_TASK != cc->hello_send_task) | ||
2193 | { | ||
2194 | GNUNET_SCHEDULER_cancel (cc->hello_send_task); | ||
2195 | cc->hello_send_task = GNUNET_SCHEDULER_NO_TASK; | ||
2196 | } | ||
2197 | if (NULL != cc->d1core) | ||
2198 | { | ||
2199 | GNUNET_CORE_disconnect (cc->d1core); | ||
2200 | cc->d1core = NULL; | ||
2201 | } | ||
2202 | if (NULL != cc->d1th) | ||
2203 | { | ||
2204 | GNUNET_TRANSPORT_disconnect (cc->d1th); | ||
2205 | cc->d1th = NULL; | ||
2206 | } | ||
2207 | GNUNET_free (cc); | ||
2208 | } | ||
2209 | |||
2210 | |||
2211 | /* end of testing.c */ | ||
diff --git a/src/testing_old/testing_group.c b/src/testing_old/testing_group.c deleted file mode 100644 index 66c498256..000000000 --- a/src/testing_old/testing_group.c +++ /dev/null | |||
@@ -1,7062 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | (C) 2008, 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testing_old/testing_group.c | ||
23 | * @brief convenience API for writing testcases for GNUnet | ||
24 | * @author Nathan Evans | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_constants.h" | ||
29 | #include "gnunet_arm_service.h" | ||
30 | #include "gnunet_testing_lib.h" | ||
31 | #include "gnunet_core_service.h" | ||
32 | |||
33 | #define USE_START_HELPER GNUNET_YES | ||
34 | |||
35 | #define OLD 1 | ||
36 | |||
37 | /* Before connecting peers, send all of the HELLOs */ | ||
38 | #define USE_SEND_HELLOS GNUNET_NO | ||
39 | |||
40 | #define TOPOLOGY_HACK GNUNET_YES | ||
41 | |||
42 | |||
43 | /** | ||
44 | * How long do we wait after a FORK+EXEC before testing for the | ||
45 | * resulting process to be up (port open, waitpid, etc.)? | ||
46 | */ | ||
47 | #define GNUNET_CONSTANTS_EXEC_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 200) | ||
48 | |||
49 | /** | ||
50 | * Lowest port used for GNUnet testing. Should be high enough to not | ||
51 | * conflict with other applications running on the hosts but be low | ||
52 | * enough to not conflict with client-ports (typically starting around | ||
53 | * 32k). | ||
54 | */ | ||
55 | #define LOW_PORT 12000 | ||
56 | |||
57 | /** | ||
58 | * Highest port used for GNUnet testing. Should be low enough to not | ||
59 | * conflict with the port range for "local" ports (client apps; see | ||
60 | * /proc/sys/net/ipv4/ip_local_port_range on Linux for example). | ||
61 | */ | ||
62 | #define HIGH_PORT 56000 | ||
63 | |||
64 | /* Maximum time to delay connect attempt */ | ||
65 | #define MAX_CONNECT_DELAY 300 | ||
66 | |||
67 | /** | ||
68 | * Which list of peers do we need to modify? | ||
69 | */ | ||
70 | enum PeerLists | ||
71 | { | ||
72 | /** Modify allowed peers */ | ||
73 | ALLOWED, | ||
74 | |||
75 | /** Modify connect peers */ | ||
76 | CONNECT, | ||
77 | |||
78 | /** Modify blacklist peers */ | ||
79 | BLACKLIST, | ||
80 | |||
81 | /** Modify workingset peers */ | ||
82 | WORKING_SET | ||
83 | }; | ||
84 | |||
85 | /** | ||
86 | * Prototype of a function called whenever two peers would be connected | ||
87 | * in a certain topology. | ||
88 | */ | ||
89 | typedef unsigned int (*GNUNET_TESTING_ConnectionProcessor) (struct | ||
90 | GNUNET_TESTING_PeerGroup | ||
91 | * pg, | ||
92 | unsigned int first, | ||
93 | unsigned int second, | ||
94 | enum PeerLists list, | ||
95 | unsigned int check); | ||
96 | |||
97 | /** | ||
98 | * Context for handling churning a peer group | ||
99 | */ | ||
100 | struct ChurnContext | ||
101 | { | ||
102 | /** | ||
103 | * The peergroup we are dealing with. | ||
104 | */ | ||
105 | struct GNUNET_TESTING_PeerGroup *pg; | ||
106 | |||
107 | /** | ||
108 | * Name of the service to churn on/off, NULL | ||
109 | * to churn entire peer. | ||
110 | */ | ||
111 | char *service; | ||
112 | |||
113 | /** | ||
114 | * Callback used to notify of churning finished | ||
115 | */ | ||
116 | GNUNET_TESTING_NotifyCompletion cb; | ||
117 | |||
118 | /** | ||
119 | * Closure for callback | ||
120 | */ | ||
121 | void *cb_cls; | ||
122 | |||
123 | /** | ||
124 | * Number of peers that still need to be started | ||
125 | */ | ||
126 | unsigned int num_to_start; | ||
127 | |||
128 | /** | ||
129 | * Number of peers that still need to be stopped | ||
130 | */ | ||
131 | unsigned int num_to_stop; | ||
132 | |||
133 | /** | ||
134 | * Number of peers that failed to start | ||
135 | */ | ||
136 | unsigned int num_failed_start; | ||
137 | |||
138 | /** | ||
139 | * Number of peers that failed to stop | ||
140 | */ | ||
141 | unsigned int num_failed_stop; | ||
142 | }; | ||
143 | |||
144 | struct RestartContext | ||
145 | { | ||
146 | /** | ||
147 | * The group of peers being restarted | ||
148 | */ | ||
149 | struct GNUNET_TESTING_PeerGroup *peer_group; | ||
150 | |||
151 | /** | ||
152 | * How many peers have been restarted thus far | ||
153 | */ | ||
154 | unsigned int peers_restarted; | ||
155 | |||
156 | /** | ||
157 | * How many peers got an error when restarting | ||
158 | */ | ||
159 | unsigned int peers_restart_failed; | ||
160 | |||
161 | /** | ||
162 | * The function to call once all peers have been restarted | ||
163 | */ | ||
164 | GNUNET_TESTING_NotifyCompletion callback; | ||
165 | |||
166 | /** | ||
167 | * Closure for callback function | ||
168 | */ | ||
169 | void *callback_cls; | ||
170 | |||
171 | }; | ||
172 | |||
173 | struct SendHelloContext | ||
174 | { | ||
175 | /** | ||
176 | * Global handle to the peer group. | ||
177 | */ | ||
178 | struct GNUNET_TESTING_PeerGroup *pg; | ||
179 | |||
180 | /** | ||
181 | * The data about this specific peer. | ||
182 | */ | ||
183 | struct PeerData *peer; | ||
184 | |||
185 | /** | ||
186 | * The next HELLO that needs sent to this peer. | ||
187 | */ | ||
188 | struct PeerConnection *peer_pos; | ||
189 | |||
190 | /** | ||
191 | * Are we connected to CORE yet? | ||
192 | */ | ||
193 | unsigned int core_ready; | ||
194 | |||
195 | /** | ||
196 | * How many attempts should we make for failed connections? | ||
197 | */ | ||
198 | unsigned int connect_attempts; | ||
199 | |||
200 | /** | ||
201 | * Task for scheduling core connect requests to be sent. | ||
202 | */ | ||
203 | GNUNET_SCHEDULER_TaskIdentifier core_connect_task; | ||
204 | }; | ||
205 | |||
206 | struct ShutdownContext | ||
207 | { | ||
208 | struct GNUNET_TESTING_PeerGroup *pg; | ||
209 | /** | ||
210 | * Total peers to wait for | ||
211 | */ | ||
212 | unsigned int total_peers; | ||
213 | |||
214 | /** | ||
215 | * Number of peers successfully shut down | ||
216 | */ | ||
217 | unsigned int peers_down; | ||
218 | |||
219 | /** | ||
220 | * Number of peers failed to shut down | ||
221 | */ | ||
222 | unsigned int peers_failed; | ||
223 | |||
224 | /** | ||
225 | * Number of peers we have started shutting | ||
226 | * down. If too many, wait on them. | ||
227 | */ | ||
228 | unsigned int outstanding; | ||
229 | |||
230 | /** | ||
231 | * Timeout for shutdown. | ||
232 | */ | ||
233 | struct GNUNET_TIME_Relative timeout; | ||
234 | |||
235 | /** | ||
236 | * Callback to call when all peers either | ||
237 | * shutdown or failed to shutdown | ||
238 | */ | ||
239 | GNUNET_TESTING_NotifyCompletion cb; | ||
240 | |||
241 | /** | ||
242 | * Closure for cb | ||
243 | */ | ||
244 | void *cb_cls; | ||
245 | |||
246 | /** | ||
247 | * Should we delete all of the files from the peers? | ||
248 | */ | ||
249 | int delete_files; | ||
250 | }; | ||
251 | |||
252 | /** | ||
253 | * Individual shutdown context for a particular peer. | ||
254 | */ | ||
255 | struct PeerShutdownContext | ||
256 | { | ||
257 | /** | ||
258 | * Pointer to the high level shutdown context. | ||
259 | */ | ||
260 | struct ShutdownContext *shutdown_ctx; | ||
261 | |||
262 | /** | ||
263 | * The daemon handle for the peer to shut down. | ||
264 | */ | ||
265 | struct GNUNET_TESTING_Daemon *daemon; | ||
266 | }; | ||
267 | |||
268 | /** | ||
269 | * Individual shutdown context for a particular peer. | ||
270 | */ | ||
271 | struct PeerRestartContext | ||
272 | { | ||
273 | /** | ||
274 | * Pointer to the high level restart context. | ||
275 | */ | ||
276 | struct ChurnRestartContext *churn_restart_ctx; | ||
277 | |||
278 | /** | ||
279 | * The daemon handle for the peer to shut down. | ||
280 | */ | ||
281 | struct GNUNET_TESTING_Daemon *daemon; | ||
282 | }; | ||
283 | |||
284 | struct ServiceStartContext | ||
285 | { | ||
286 | struct GNUNET_TESTING_PeerGroup *pg; | ||
287 | unsigned int remaining; | ||
288 | GNUNET_TESTING_NotifyCompletion cb; | ||
289 | unsigned int outstanding; | ||
290 | char *service; | ||
291 | struct GNUNET_TIME_Relative timeout; | ||
292 | void *cb_cls; | ||
293 | }; | ||
294 | |||
295 | /** | ||
296 | * Individual shutdown context for a particular peer. | ||
297 | */ | ||
298 | struct PeerServiceStartContext | ||
299 | { | ||
300 | /** | ||
301 | * Pointer to the high level start context. | ||
302 | */ | ||
303 | struct ServiceStartContext *start_ctx; | ||
304 | |||
305 | /** | ||
306 | * The daemon handle for the peer to start the service on. | ||
307 | */ | ||
308 | struct GNUNET_TESTING_Daemon *daemon; | ||
309 | }; | ||
310 | |||
311 | struct CreateTopologyContext | ||
312 | { | ||
313 | |||
314 | /** | ||
315 | * Function to call with number of connections | ||
316 | */ | ||
317 | GNUNET_TESTING_NotifyConnections cont; | ||
318 | |||
319 | /** | ||
320 | * Closure for connection notification | ||
321 | */ | ||
322 | void *cls; | ||
323 | }; | ||
324 | |||
325 | enum States | ||
326 | { | ||
327 | /** Waiting to read number of peers */ | ||
328 | NUM_PEERS, | ||
329 | |||
330 | /** Should find next peer index */ | ||
331 | PEER_INDEX, | ||
332 | |||
333 | /** Should find colon */ | ||
334 | COLON, | ||
335 | |||
336 | /** Should read other peer index, space, or endline */ | ||
337 | OTHER_PEER_INDEX | ||
338 | }; | ||
339 | |||
340 | #if OLD | ||
341 | struct PeerConnection | ||
342 | { | ||
343 | /** | ||
344 | * Doubly Linked list | ||
345 | */ | ||
346 | struct PeerConnection *prev; | ||
347 | |||
348 | /* | ||
349 | * Doubly Linked list | ||
350 | */ | ||
351 | struct PeerConnection *next; | ||
352 | |||
353 | /* | ||
354 | * Index of daemon in pg->peers | ||
355 | */ | ||
356 | uint32_t index; | ||
357 | |||
358 | }; | ||
359 | #endif | ||
360 | |||
361 | struct InternalStartContext | ||
362 | { | ||
363 | /** | ||
364 | * Pointer to peerdata | ||
365 | */ | ||
366 | struct PeerData *peer; | ||
367 | |||
368 | /** | ||
369 | * Timeout for peer startup | ||
370 | */ | ||
371 | struct GNUNET_TIME_Relative timeout; | ||
372 | |||
373 | /** | ||
374 | * Client callback for hostkey notification | ||
375 | */ | ||
376 | GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback; | ||
377 | |||
378 | /** | ||
379 | * Closure for hostkey_callback | ||
380 | */ | ||
381 | void *hostkey_cls; | ||
382 | |||
383 | /** | ||
384 | * Client callback for peer start notification | ||
385 | */ | ||
386 | GNUNET_TESTING_NotifyDaemonRunning start_cb; | ||
387 | |||
388 | /** | ||
389 | * Closure for cb | ||
390 | */ | ||
391 | void *start_cb_cls; | ||
392 | |||
393 | /** | ||
394 | * Hostname, where to start the peer | ||
395 | */ | ||
396 | const char *hostname; | ||
397 | |||
398 | /** | ||
399 | * Username to use when connecting to the | ||
400 | * host via ssh. | ||
401 | */ | ||
402 | const char *username; | ||
403 | |||
404 | /** | ||
405 | * Pointer to starting memory location of a hostkey | ||
406 | */ | ||
407 | const char *hostkey; | ||
408 | |||
409 | /** | ||
410 | * Port to use for ssh. | ||
411 | */ | ||
412 | uint16_t sshport; | ||
413 | |||
414 | }; | ||
415 | |||
416 | struct ChurnRestartContext | ||
417 | { | ||
418 | /** | ||
419 | * PeerGroup that we are working with. | ||
420 | */ | ||
421 | struct GNUNET_TESTING_PeerGroup *pg; | ||
422 | |||
423 | /** | ||
424 | * Number of restarts currently in flight. | ||
425 | */ | ||
426 | unsigned int outstanding; | ||
427 | |||
428 | /** | ||
429 | * Handle to the underlying churn context. | ||
430 | */ | ||
431 | struct ChurnContext *churn_ctx; | ||
432 | |||
433 | /** | ||
434 | * How long to allow the operation to take. | ||
435 | */ | ||
436 | struct GNUNET_TIME_Relative timeout; | ||
437 | }; | ||
438 | |||
439 | struct OutstandingSSH | ||
440 | { | ||
441 | struct OutstandingSSH *next; | ||
442 | |||
443 | struct OutstandingSSH *prev; | ||
444 | |||
445 | /** | ||
446 | * Number of current ssh connections. | ||
447 | */ | ||
448 | uint32_t outstanding; | ||
449 | |||
450 | /** | ||
451 | * The hostname of this peer. | ||
452 | */ | ||
453 | const char *hostname; | ||
454 | }; | ||
455 | |||
456 | /** | ||
457 | * Data we keep per peer. | ||
458 | */ | ||
459 | struct PeerData | ||
460 | { | ||
461 | /** | ||
462 | * (Initial) configuration of the host. | ||
463 | * (initial because clients could change | ||
464 | * it and we would not know about those | ||
465 | * updates). | ||
466 | */ | ||
467 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
468 | |||
469 | /** | ||
470 | * Handle for controlling the daemon. | ||
471 | */ | ||
472 | struct GNUNET_TESTING_Daemon *daemon; | ||
473 | |||
474 | /** | ||
475 | * The peergroup this peer belongs to. | ||
476 | */ | ||
477 | struct GNUNET_TESTING_PeerGroup *pg; | ||
478 | |||
479 | #if OLD | ||
480 | /** | ||
481 | * Linked list of allowed peer connections. | ||
482 | */ | ||
483 | struct PeerConnection *allowed_peers_head; | ||
484 | |||
485 | /** | ||
486 | * Linked list of allowed peer connections. | ||
487 | */ | ||
488 | struct PeerConnection *allowed_peers_tail; | ||
489 | |||
490 | /** | ||
491 | * Linked list of blacklisted peer connections. | ||
492 | */ | ||
493 | struct PeerConnection *blacklisted_peers_head; | ||
494 | |||
495 | /** | ||
496 | * Linked list of blacklisted peer connections. | ||
497 | */ | ||
498 | struct PeerConnection *blacklisted_peers_tail; | ||
499 | |||
500 | /** | ||
501 | * Linked list of connect peer connections. | ||
502 | */ | ||
503 | struct PeerConnection *connect_peers_head; | ||
504 | |||
505 | /** | ||
506 | * Linked list of connect peer connections. | ||
507 | */ | ||
508 | struct PeerConnection *connect_peers_tail; | ||
509 | |||
510 | /** | ||
511 | * Linked list of connect peer connections. | ||
512 | */ | ||
513 | struct PeerConnection *connect_peers_working_set_head; | ||
514 | |||
515 | /** | ||
516 | * Linked list of connect peer connections. | ||
517 | */ | ||
518 | struct PeerConnection *connect_peers_working_set_tail; | ||
519 | |||
520 | #else | ||
521 | /** | ||
522 | * Hash map of allowed peer connections (F2F created topology) | ||
523 | */ | ||
524 | struct GNUNET_CONTAINER_MultiHashMap *allowed_peers; | ||
525 | |||
526 | /** | ||
527 | * Hash map of blacklisted peers | ||
528 | */ | ||
529 | struct GNUNET_CONTAINER_MultiHashMap *blacklisted_peers; | ||
530 | |||
531 | /** | ||
532 | * Hash map of peer connections | ||
533 | */ | ||
534 | struct GNUNET_CONTAINER_MultiHashMap *connect_peers; | ||
535 | |||
536 | /** | ||
537 | * Temporary hash map of peer connections | ||
538 | */ | ||
539 | struct GNUNET_CONTAINER_MultiHashMap *connect_peers_working_set; | ||
540 | #endif | ||
541 | |||
542 | /** | ||
543 | * Temporary variable for topology creation, should be reset before | ||
544 | * creating any topology so the count is valid once finished. | ||
545 | */ | ||
546 | int num_connections; | ||
547 | |||
548 | /** | ||
549 | * Context to keep track of peers being started, to | ||
550 | * stagger hostkey generation and peer startup. | ||
551 | */ | ||
552 | struct InternalStartContext internal_context; | ||
553 | |||
554 | /** | ||
555 | * Task ID for the queued internal_continue_startup task | ||
556 | */ | ||
557 | GNUNET_SCHEDULER_TaskIdentifier startup_task; | ||
558 | |||
559 | }; | ||
560 | |||
561 | /** | ||
562 | * Linked list of per-host data. | ||
563 | */ | ||
564 | struct HostData | ||
565 | { | ||
566 | /** | ||
567 | * Name of the host. | ||
568 | */ | ||
569 | char *hostname; | ||
570 | |||
571 | /** | ||
572 | * SSH username to use when connecting to this host. | ||
573 | */ | ||
574 | char *username; | ||
575 | |||
576 | /** | ||
577 | * SSH port to use when connecting to this host. | ||
578 | */ | ||
579 | uint16_t sshport; | ||
580 | |||
581 | /** | ||
582 | * Lowest port that we have not yet used | ||
583 | * for GNUnet. | ||
584 | */ | ||
585 | uint16_t minport; | ||
586 | }; | ||
587 | |||
588 | struct TopologyIterateContext | ||
589 | { | ||
590 | /** | ||
591 | * The peergroup we are working with. | ||
592 | */ | ||
593 | struct GNUNET_TESTING_PeerGroup *pg; | ||
594 | |||
595 | /** | ||
596 | * Callback for notifying of two connected peers. | ||
597 | */ | ||
598 | GNUNET_TESTING_NotifyTopology topology_cb; | ||
599 | |||
600 | /** | ||
601 | * Closure for topology_cb | ||
602 | */ | ||
603 | void *cls; | ||
604 | |||
605 | /** | ||
606 | * Number of peers currently connected to. | ||
607 | */ | ||
608 | unsigned int connected; | ||
609 | |||
610 | /** | ||
611 | * Number of peers we have finished iterating. | ||
612 | */ | ||
613 | unsigned int completed; | ||
614 | |||
615 | /** | ||
616 | * Number of peers total. | ||
617 | */ | ||
618 | unsigned int total; | ||
619 | }; | ||
620 | |||
621 | struct StatsIterateContext | ||
622 | { | ||
623 | /** | ||
624 | * The peergroup that we are dealing with. | ||
625 | */ | ||
626 | struct GNUNET_TESTING_PeerGroup *pg; | ||
627 | |||
628 | /** | ||
629 | * Continuation to call once all stats information has been retrieved. | ||
630 | */ | ||
631 | GNUNET_STATISTICS_Callback cont; | ||
632 | |||
633 | /** | ||
634 | * Proc function to call on each value received. | ||
635 | */ | ||
636 | GNUNET_TESTING_STATISTICS_Iterator proc; | ||
637 | |||
638 | /** | ||
639 | * Closure for topology_cb | ||
640 | */ | ||
641 | void *cls; | ||
642 | |||
643 | /** | ||
644 | * Number of peers currently connected to. | ||
645 | */ | ||
646 | unsigned int connected; | ||
647 | |||
648 | /** | ||
649 | * Number of peers we have finished iterating. | ||
650 | */ | ||
651 | unsigned int completed; | ||
652 | |||
653 | /** | ||
654 | * Number of peers total. | ||
655 | */ | ||
656 | unsigned int total; | ||
657 | }; | ||
658 | |||
659 | struct CoreContext | ||
660 | { | ||
661 | void *iter_context; | ||
662 | struct GNUNET_TESTING_Daemon *daemon; | ||
663 | }; | ||
664 | |||
665 | struct StatsCoreContext | ||
666 | { | ||
667 | void *iter_context; | ||
668 | struct GNUNET_TESTING_Daemon *daemon; | ||
669 | /** | ||
670 | * Handle to the statistics service. | ||
671 | */ | ||
672 | struct GNUNET_STATISTICS_Handle *stats_handle; | ||
673 | |||
674 | /** | ||
675 | * Handle for getting statistics. | ||
676 | */ | ||
677 | struct GNUNET_STATISTICS_GetHandle *stats_get_handle; | ||
678 | }; | ||
679 | |||
680 | struct ConnectTopologyContext | ||
681 | { | ||
682 | /** | ||
683 | * How many connections are left to create. | ||
684 | */ | ||
685 | unsigned int remaining_connections; | ||
686 | |||
687 | /** | ||
688 | * Handle to group of peers. | ||
689 | */ | ||
690 | struct GNUNET_TESTING_PeerGroup *pg; | ||
691 | |||
692 | /** | ||
693 | * How long to try this connection before timing out. | ||
694 | */ | ||
695 | struct GNUNET_TIME_Relative connect_timeout; | ||
696 | |||
697 | /** | ||
698 | * How many times to retry connecting the two peers. | ||
699 | */ | ||
700 | unsigned int connect_attempts; | ||
701 | |||
702 | /** | ||
703 | * Temp value set for each iteration. | ||
704 | */ | ||
705 | //struct PeerData *first; | ||
706 | |||
707 | /** | ||
708 | * Notification that all peers are connected. | ||
709 | */ | ||
710 | GNUNET_TESTING_NotifyCompletion notify_connections_done; | ||
711 | |||
712 | /** | ||
713 | * Closure for notify. | ||
714 | */ | ||
715 | void *notify_cls; | ||
716 | }; | ||
717 | |||
718 | struct ConnectContext; | ||
719 | |||
720 | /** | ||
721 | * Handle to a group of GNUnet peers. | ||
722 | */ | ||
723 | struct GNUNET_TESTING_PeerGroup | ||
724 | { | ||
725 | /** | ||
726 | * Configuration template. | ||
727 | */ | ||
728 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
729 | |||
730 | struct ConnectContext *cc_head; | ||
731 | |||
732 | struct ConnectContext *cc_tail; | ||
733 | |||
734 | /** | ||
735 | * Function to call on each started daemon. | ||
736 | */ | ||
737 | //GNUNET_TESTING_NotifyDaemonRunning cb; | ||
738 | |||
739 | /** | ||
740 | * Closure for cb. | ||
741 | */ | ||
742 | //void *cb_cls; | ||
743 | |||
744 | /* | ||
745 | * Function to call on each topology connection created | ||
746 | */ | ||
747 | GNUNET_TESTING_NotifyConnection notify_connection; | ||
748 | |||
749 | /* | ||
750 | * Callback for notify_connection | ||
751 | */ | ||
752 | void *notify_connection_cls; | ||
753 | |||
754 | /** | ||
755 | * Array of information about hosts. | ||
756 | */ | ||
757 | struct HostData *hosts; | ||
758 | |||
759 | /** | ||
760 | * Number of hosts (size of HostData) | ||
761 | */ | ||
762 | unsigned int num_hosts; | ||
763 | |||
764 | /** | ||
765 | * Array of "total" peers. | ||
766 | */ | ||
767 | struct PeerData *peers; | ||
768 | |||
769 | /** | ||
770 | * Number of peers in this group. | ||
771 | */ | ||
772 | unsigned int total; | ||
773 | |||
774 | /** | ||
775 | * At what time should we fail the peer startup process? | ||
776 | */ | ||
777 | struct GNUNET_TIME_Absolute max_timeout; | ||
778 | |||
779 | /** | ||
780 | * How many peers are being started right now? | ||
781 | */ | ||
782 | unsigned int starting; | ||
783 | |||
784 | /** | ||
785 | * How many peers have already been started? | ||
786 | */ | ||
787 | unsigned int started; | ||
788 | |||
789 | /** | ||
790 | * Number of possible connections to peers | ||
791 | * at a time. | ||
792 | */ | ||
793 | unsigned int max_outstanding_connections; | ||
794 | |||
795 | /** | ||
796 | * Number of ssh connections to peers (max). | ||
797 | */ | ||
798 | unsigned int max_concurrent_ssh; | ||
799 | |||
800 | /** | ||
801 | * Number of connects we are waiting on, allows us to rate limit | ||
802 | * connect attempts. | ||
803 | */ | ||
804 | unsigned int outstanding_connects; | ||
805 | |||
806 | /** | ||
807 | * Number of HELLOs we have yet to send. | ||
808 | */ | ||
809 | unsigned int remaining_hellos; | ||
810 | |||
811 | /** | ||
812 | * How many connects have already been scheduled? | ||
813 | */ | ||
814 | unsigned int total_connects_scheduled; | ||
815 | |||
816 | /** | ||
817 | * Hostkeys loaded from a file. | ||
818 | */ | ||
819 | char *hostkey_data; | ||
820 | |||
821 | /** | ||
822 | * Head of DLL to keep track of the number of outstanding | ||
823 | * ssh connections per peer. | ||
824 | */ | ||
825 | struct OutstandingSSH *ssh_head; | ||
826 | |||
827 | /** | ||
828 | * Tail of DLL to keep track of the number of outstanding | ||
829 | * ssh connections per peer. | ||
830 | */ | ||
831 | struct OutstandingSSH *ssh_tail; | ||
832 | |||
833 | /** | ||
834 | * Stop scheduling peers connecting. | ||
835 | */ | ||
836 | unsigned int stop_connects; | ||
837 | |||
838 | /** | ||
839 | * Connection context for peer group. | ||
840 | */ | ||
841 | struct ConnectTopologyContext ct_ctx; | ||
842 | }; | ||
843 | |||
844 | struct UpdateContext | ||
845 | { | ||
846 | /** | ||
847 | * The altered configuration. | ||
848 | */ | ||
849 | struct GNUNET_CONFIGURATION_Handle *ret; | ||
850 | |||
851 | /** | ||
852 | * The original configuration to alter. | ||
853 | */ | ||
854 | const struct GNUNET_CONFIGURATION_Handle *orig; | ||
855 | |||
856 | /** | ||
857 | * The hostname that this peer will run on. | ||
858 | */ | ||
859 | const char *hostname; | ||
860 | |||
861 | /** | ||
862 | * The next possible port to assign. | ||
863 | */ | ||
864 | unsigned int nport; | ||
865 | |||
866 | /** | ||
867 | * Unique number for unix domain sockets. | ||
868 | */ | ||
869 | unsigned int upnum; | ||
870 | |||
871 | /** | ||
872 | * Unique number for this peer/host to offset | ||
873 | * things that are grouped by host. | ||
874 | */ | ||
875 | unsigned int fdnum; | ||
876 | }; | ||
877 | |||
878 | struct ConnectContext | ||
879 | { | ||
880 | |||
881 | struct ConnectContext *next; | ||
882 | |||
883 | struct ConnectContext *prev; | ||
884 | |||
885 | /** | ||
886 | * Index of peer to connect second to. | ||
887 | */ | ||
888 | uint32_t first_index; | ||
889 | |||
890 | /** | ||
891 | * Index of peer to connect first to. | ||
892 | */ | ||
893 | uint32_t second_index; | ||
894 | |||
895 | /** | ||
896 | * Task associated with the attempt to connect. | ||
897 | */ | ||
898 | GNUNET_SCHEDULER_TaskIdentifier task; | ||
899 | |||
900 | /** | ||
901 | * Context in 'testing.c', to cancel connection attempt. | ||
902 | */ | ||
903 | struct GNUNET_TESTING_ConnectContext *cc; | ||
904 | |||
905 | /** | ||
906 | * Higher level topology connection context. | ||
907 | */ | ||
908 | struct ConnectTopologyContext *ct_ctx; | ||
909 | |||
910 | /** | ||
911 | * Whether this connection has been accounted for in the schedule_connect call. | ||
912 | */ | ||
913 | int counted; | ||
914 | }; | ||
915 | |||
916 | struct UnblacklistContext | ||
917 | { | ||
918 | /** | ||
919 | * The peergroup | ||
920 | */ | ||
921 | struct GNUNET_TESTING_PeerGroup *pg; | ||
922 | |||
923 | /** | ||
924 | * uid of the first peer | ||
925 | */ | ||
926 | uint32_t first_uid; | ||
927 | }; | ||
928 | |||
929 | struct RandomContext | ||
930 | { | ||
931 | /** | ||
932 | * The peergroup | ||
933 | */ | ||
934 | struct GNUNET_TESTING_PeerGroup *pg; | ||
935 | |||
936 | /** | ||
937 | * uid of the first peer | ||
938 | */ | ||
939 | uint32_t first_uid; | ||
940 | |||
941 | /** | ||
942 | * Peer data for first peer. | ||
943 | */ | ||
944 | struct PeerData *first; | ||
945 | |||
946 | /** | ||
947 | * Random percentage to use | ||
948 | */ | ||
949 | double percentage; | ||
950 | }; | ||
951 | |||
952 | struct MinimumContext | ||
953 | { | ||
954 | /** | ||
955 | * The peergroup | ||
956 | */ | ||
957 | struct GNUNET_TESTING_PeerGroup *pg; | ||
958 | |||
959 | /** | ||
960 | * uid of the first peer | ||
961 | */ | ||
962 | uint32_t first_uid; | ||
963 | |||
964 | /** | ||
965 | * Peer data for first peer. | ||
966 | */ | ||
967 | struct PeerData *first; | ||
968 | |||
969 | /** | ||
970 | * Number of conns per peer | ||
971 | */ | ||
972 | unsigned int num_to_add; | ||
973 | |||
974 | /** | ||
975 | * Permuted array of all possible connections. Only add the Nth | ||
976 | * peer if it's in the Nth position. | ||
977 | */ | ||
978 | unsigned int *pg_array; | ||
979 | |||
980 | /** | ||
981 | * What number is the current element we are iterating over? | ||
982 | */ | ||
983 | unsigned int current; | ||
984 | }; | ||
985 | |||
986 | struct DFSContext | ||
987 | { | ||
988 | /** | ||
989 | * The peergroup | ||
990 | */ | ||
991 | struct GNUNET_TESTING_PeerGroup *pg; | ||
992 | |||
993 | /** | ||
994 | * uid of the first peer | ||
995 | */ | ||
996 | uint32_t first_uid; | ||
997 | |||
998 | /** | ||
999 | * uid of the second peer | ||
1000 | */ | ||
1001 | uint32_t second_uid; | ||
1002 | |||
1003 | /** | ||
1004 | * Peer data for first peer. | ||
1005 | */ | ||
1006 | struct PeerData *first; | ||
1007 | |||
1008 | /** | ||
1009 | * Which peer has been chosen as the one to add? | ||
1010 | */ | ||
1011 | unsigned int chosen; | ||
1012 | |||
1013 | /** | ||
1014 | * What number is the current element we are iterating over? | ||
1015 | */ | ||
1016 | unsigned int current; | ||
1017 | }; | ||
1018 | |||
1019 | /** | ||
1020 | * Simple struct to keep track of progress, and print a | ||
1021 | * nice little percentage meter for long running tasks. | ||
1022 | */ | ||
1023 | struct ProgressMeter | ||
1024 | { | ||
1025 | unsigned int total; | ||
1026 | |||
1027 | unsigned int modnum; | ||
1028 | |||
1029 | unsigned int dotnum; | ||
1030 | |||
1031 | unsigned int completed; | ||
1032 | |||
1033 | int print; | ||
1034 | |||
1035 | char *startup_string; | ||
1036 | }; | ||
1037 | |||
1038 | #if !OLD | ||
1039 | /** | ||
1040 | * Convert unique ID to hash code. | ||
1041 | * | ||
1042 | * @param uid unique ID to convert | ||
1043 | * @param hash set to uid (extended with zeros) | ||
1044 | */ | ||
1045 | static void | ||
1046 | hash_from_uid (uint32_t uid, struct GNUNET_HashCode * hash) | ||
1047 | { | ||
1048 | memset (hash, 0, sizeof (struct GNUNET_HashCode)); | ||
1049 | *((uint32_t *) hash) = uid; | ||
1050 | } | ||
1051 | |||
1052 | /** | ||
1053 | * Convert hash code to unique ID. | ||
1054 | * | ||
1055 | * @param uid unique ID to convert | ||
1056 | * @param hash set to uid (extended with zeros) | ||
1057 | */ | ||
1058 | static void | ||
1059 | uid_from_hash (const struct GNUNET_HashCode * hash, uint32_t * uid) | ||
1060 | { | ||
1061 | memcpy (uid, hash, sizeof (uint32_t)); | ||
1062 | } | ||
1063 | #endif | ||
1064 | |||
1065 | #if USE_SEND_HELLOS | ||
1066 | static struct GNUNET_CORE_MessageHandler no_handlers[] = { | ||
1067 | {NULL, 0, 0} | ||
1068 | }; | ||
1069 | #endif | ||
1070 | |||
1071 | /** | ||
1072 | * Create a meter to keep track of the progress of some task. | ||
1073 | * | ||
1074 | * @param total the total number of items to complete | ||
1075 | * @param start_string a string to prefix the meter with (if printing) | ||
1076 | * @param print GNUNET_YES to print the meter, GNUNET_NO to count | ||
1077 | * internally only | ||
1078 | * | ||
1079 | * @return the progress meter | ||
1080 | */ | ||
1081 | static struct ProgressMeter * | ||
1082 | create_meter (unsigned int total, char *start_string, int print) | ||
1083 | { | ||
1084 | struct ProgressMeter *ret; | ||
1085 | |||
1086 | ret = GNUNET_malloc (sizeof (struct ProgressMeter)); | ||
1087 | ret->print = print; | ||
1088 | ret->total = total; | ||
1089 | ret->modnum = total / 4; | ||
1090 | if (ret->modnum == 0) /* Divide by zero check */ | ||
1091 | ret->modnum = 1; | ||
1092 | ret->dotnum = (total / 50) + 1; | ||
1093 | if (start_string != NULL) | ||
1094 | ret->startup_string = GNUNET_strdup (start_string); | ||
1095 | else | ||
1096 | ret->startup_string = GNUNET_strdup (""); | ||
1097 | |||
1098 | return ret; | ||
1099 | } | ||
1100 | |||
1101 | /** | ||
1102 | * Update progress meter (increment by one). | ||
1103 | * | ||
1104 | * @param meter the meter to update and print info for | ||
1105 | * | ||
1106 | * @return GNUNET_YES if called the total requested, | ||
1107 | * GNUNET_NO if more items expected | ||
1108 | */ | ||
1109 | static int | ||
1110 | update_meter (struct ProgressMeter *meter) | ||
1111 | { | ||
1112 | if (meter->print == GNUNET_YES) | ||
1113 | { | ||
1114 | if (meter->completed % meter->modnum == 0) | ||
1115 | { | ||
1116 | if (meter->completed == 0) | ||
1117 | { | ||
1118 | FPRINTF (stdout, "%sProgress: [0%%", meter->startup_string); | ||
1119 | } | ||
1120 | else | ||
1121 | FPRINTF (stdout, "%d%%", | ||
1122 | (int) (((float) meter->completed / meter->total) * 100)); | ||
1123 | } | ||
1124 | else if (meter->completed % meter->dotnum == 0) | ||
1125 | FPRINTF (stdout, "%s", "."); | ||
1126 | |||
1127 | if (meter->completed + 1 == meter->total) | ||
1128 | FPRINTF (stdout, "%d%%]\n", 100); | ||
1129 | fflush (stdout); | ||
1130 | } | ||
1131 | meter->completed++; | ||
1132 | |||
1133 | if (meter->completed == meter->total) | ||
1134 | return GNUNET_YES; | ||
1135 | if (meter->completed > meter->total) | ||
1136 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Progress meter overflow!!\n"); | ||
1137 | return GNUNET_NO; | ||
1138 | } | ||
1139 | |||
1140 | /** | ||
1141 | * Reset progress meter. | ||
1142 | * | ||
1143 | * @param meter the meter to reset | ||
1144 | * | ||
1145 | * @return GNUNET_YES if meter reset, | ||
1146 | * GNUNET_SYSERR on error | ||
1147 | */ | ||
1148 | static int | ||
1149 | reset_meter (struct ProgressMeter *meter) | ||
1150 | { | ||
1151 | if (meter == NULL) | ||
1152 | return GNUNET_SYSERR; | ||
1153 | |||
1154 | meter->completed = 0; | ||
1155 | return GNUNET_YES; | ||
1156 | } | ||
1157 | |||
1158 | /** | ||
1159 | * Release resources for meter | ||
1160 | * | ||
1161 | * @param meter the meter to free | ||
1162 | */ | ||
1163 | static void | ||
1164 | free_meter (struct ProgressMeter *meter) | ||
1165 | { | ||
1166 | GNUNET_free_non_null (meter->startup_string); | ||
1167 | GNUNET_free (meter); | ||
1168 | } | ||
1169 | |||
1170 | /** | ||
1171 | * Get a topology from a string input. | ||
1172 | * | ||
1173 | * @param topology where to write the retrieved topology | ||
1174 | * @param topology_string The string to attempt to | ||
1175 | * get a configuration value from | ||
1176 | * @return GNUNET_YES if topology string matched a | ||
1177 | * known topology, GNUNET_NO if not | ||
1178 | */ | ||
1179 | int | ||
1180 | GNUNET_TESTING_topology_get (enum GNUNET_TESTING_Topology *topology, | ||
1181 | const char *topology_string) | ||
1182 | { | ||
1183 | /** | ||
1184 | * Strings representing topologies in enum | ||
1185 | */ | ||
1186 | static const char *topology_strings[] = { | ||
1187 | /** | ||
1188 | * A clique (everyone connected to everyone else). | ||
1189 | */ | ||
1190 | "CLIQUE", | ||
1191 | |||
1192 | /** | ||
1193 | * Small-world network (2d torus plus random links). | ||
1194 | */ | ||
1195 | "SMALL_WORLD", | ||
1196 | |||
1197 | /** | ||
1198 | * Small-world network (ring plus random links). | ||
1199 | */ | ||
1200 | "SMALL_WORLD_RING", | ||
1201 | |||
1202 | /** | ||
1203 | * Ring topology. | ||
1204 | */ | ||
1205 | "RING", | ||
1206 | |||
1207 | /** | ||
1208 | * 2-d torus. | ||
1209 | */ | ||
1210 | "2D_TORUS", | ||
1211 | |||
1212 | /** | ||
1213 | * Random graph. | ||
1214 | */ | ||
1215 | "ERDOS_RENYI", | ||
1216 | |||
1217 | /** | ||
1218 | * Certain percentage of peers are unable to communicate directly | ||
1219 | * replicating NAT conditions | ||
1220 | */ | ||
1221 | "INTERNAT", | ||
1222 | |||
1223 | /** | ||
1224 | * Scale free topology. | ||
1225 | */ | ||
1226 | "SCALE_FREE", | ||
1227 | |||
1228 | /** | ||
1229 | * Straight line topology. | ||
1230 | */ | ||
1231 | "LINE", | ||
1232 | |||
1233 | /** | ||
1234 | * All peers are disconnected. | ||
1235 | */ | ||
1236 | "NONE", | ||
1237 | |||
1238 | /** | ||
1239 | * Read the topology from a file. | ||
1240 | */ | ||
1241 | "FROM_FILE", | ||
1242 | |||
1243 | NULL | ||
1244 | }; | ||
1245 | |||
1246 | int curr = 0; | ||
1247 | |||
1248 | if (topology_string == NULL) | ||
1249 | return GNUNET_NO; | ||
1250 | while (topology_strings[curr] != NULL) | ||
1251 | { | ||
1252 | if (strcasecmp (topology_strings[curr], topology_string) == 0) | ||
1253 | { | ||
1254 | *topology = curr; | ||
1255 | return GNUNET_YES; | ||
1256 | } | ||
1257 | curr++; | ||
1258 | } | ||
1259 | *topology = GNUNET_TESTING_TOPOLOGY_NONE; | ||
1260 | return GNUNET_NO; | ||
1261 | } | ||
1262 | |||
1263 | /** | ||
1264 | * Get connect topology option from string input. | ||
1265 | * | ||
1266 | * @param topology_option where to write the retrieved topology | ||
1267 | * @param topology_string The string to attempt to | ||
1268 | * get a configuration value from | ||
1269 | * @return GNUNET_YES if string matched a known | ||
1270 | * topology option, GNUNET_NO if not | ||
1271 | */ | ||
1272 | int | ||
1273 | GNUNET_TESTING_topology_option_get (enum GNUNET_TESTING_TopologyOption | ||
1274 | *topology_option, | ||
1275 | const char *topology_string) | ||
1276 | { | ||
1277 | /** | ||
1278 | * Options for connecting a topology as strings. | ||
1279 | */ | ||
1280 | static const char *topology_option_strings[] = { | ||
1281 | /** | ||
1282 | * Try to connect all peers specified in the topology. | ||
1283 | */ | ||
1284 | "CONNECT_ALL", | ||
1285 | |||
1286 | /** | ||
1287 | * Choose a random subset of connections to create. | ||
1288 | */ | ||
1289 | "CONNECT_RANDOM_SUBSET", | ||
1290 | |||
1291 | /** | ||
1292 | * Create at least X connections for each peer. | ||
1293 | */ | ||
1294 | "CONNECT_MINIMUM", | ||
1295 | |||
1296 | /** | ||
1297 | * Using a depth first search, create one connection | ||
1298 | * per peer. If any are missed (graph disconnected) | ||
1299 | * start over at those peers until all have at least one | ||
1300 | * connection. | ||
1301 | */ | ||
1302 | "CONNECT_DFS", | ||
1303 | |||
1304 | /** | ||
1305 | * Find the N closest peers to each allowed peer in the | ||
1306 | * topology and make sure a connection to those peers | ||
1307 | * exists in the connect topology. | ||
1308 | */ | ||
1309 | "CONNECT_CLOSEST", | ||
1310 | |||
1311 | /** | ||
1312 | * No options specified. | ||
1313 | */ | ||
1314 | "CONNECT_NONE", | ||
1315 | |||
1316 | NULL | ||
1317 | }; | ||
1318 | int curr = 0; | ||
1319 | |||
1320 | if (topology_string == NULL) | ||
1321 | return GNUNET_NO; | ||
1322 | while (NULL != topology_option_strings[curr]) | ||
1323 | { | ||
1324 | if (strcasecmp (topology_option_strings[curr], topology_string) == 0) | ||
1325 | { | ||
1326 | *topology_option = curr; | ||
1327 | return GNUNET_YES; | ||
1328 | } | ||
1329 | curr++; | ||
1330 | } | ||
1331 | *topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_NONE; | ||
1332 | return GNUNET_NO; | ||
1333 | } | ||
1334 | |||
1335 | /** | ||
1336 | * Function to iterate over options. Copies | ||
1337 | * the options to the target configuration, | ||
1338 | * updating PORT values as needed. | ||
1339 | * | ||
1340 | * @param cls closure | ||
1341 | * @param section name of the section | ||
1342 | * @param option name of the option | ||
1343 | * @param value value of the option | ||
1344 | */ | ||
1345 | static void | ||
1346 | update_config (void *cls, const char *section, const char *option, | ||
1347 | const char *value) | ||
1348 | { | ||
1349 | struct UpdateContext *ctx = cls; | ||
1350 | unsigned int ival; | ||
1351 | char cval[12]; | ||
1352 | char uval[128]; | ||
1353 | char *single_variable; | ||
1354 | char *per_host_variable; | ||
1355 | unsigned long long num_per_host; | ||
1356 | |||
1357 | GNUNET_asprintf (&single_variable, "single_%s_per_host", section); | ||
1358 | GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section); | ||
1359 | |||
1360 | if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival))) | ||
1361 | { | ||
1362 | if ((ival != 0) && | ||
1363 | (GNUNET_YES != | ||
1364 | GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing_old", | ||
1365 | single_variable))) | ||
1366 | { | ||
1367 | GNUNET_snprintf (cval, sizeof (cval), "%u", ctx->nport++); | ||
1368 | value = cval; | ||
1369 | } | ||
1370 | else if ((ival != 0) && | ||
1371 | (GNUNET_YES == | ||
1372 | GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing_old", | ||
1373 | single_variable)) && | ||
1374 | GNUNET_CONFIGURATION_get_value_number (ctx->orig, "testing_old", | ||
1375 | per_host_variable, | ||
1376 | &num_per_host)) | ||
1377 | { | ||
1378 | GNUNET_snprintf (cval, sizeof (cval), "%u", | ||
1379 | ival + ctx->fdnum % num_per_host); | ||
1380 | value = cval; | ||
1381 | } | ||
1382 | |||
1383 | /* FIXME: REMOVE FOREVER HACK HACK HACK */ | ||
1384 | if (0 == strcasecmp (section, "transport-tcp")) | ||
1385 | GNUNET_CONFIGURATION_set_value_string (ctx->ret, section, | ||
1386 | "ADVERTISED_PORT", value); | ||
1387 | } | ||
1388 | |||
1389 | if (0 == strcmp (option, "UNIXPATH")) | ||
1390 | { | ||
1391 | if (GNUNET_YES != | ||
1392 | GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing_old", | ||
1393 | single_variable)) | ||
1394 | { | ||
1395 | GNUNET_snprintf (uval, sizeof (uval), "/tmp/test-service-%s-%u", section, | ||
1396 | ctx->upnum++); | ||
1397 | value = uval; | ||
1398 | } | ||
1399 | else if ((GNUNET_YES == | ||
1400 | GNUNET_CONFIGURATION_get_value_number (ctx->orig, "testing_old", | ||
1401 | per_host_variable, | ||
1402 | &num_per_host)) && | ||
1403 | (num_per_host > 0)) | ||
1404 | |||
1405 | { | ||
1406 | GNUNET_snprintf (uval, sizeof (uval), "/tmp/test-service-%s-%u", section, | ||
1407 | ctx->fdnum % num_per_host); | ||
1408 | value = uval; | ||
1409 | } | ||
1410 | } | ||
1411 | |||
1412 | if ((0 == strcmp (option, "HOSTNAME")) && (ctx->hostname != NULL)) | ||
1413 | { | ||
1414 | value = ctx->hostname; | ||
1415 | } | ||
1416 | GNUNET_free (single_variable); | ||
1417 | GNUNET_free (per_host_variable); | ||
1418 | GNUNET_CONFIGURATION_set_value_string (ctx->ret, section, option, value); | ||
1419 | } | ||
1420 | |||
1421 | /** | ||
1422 | * Create a new configuration using the given configuration | ||
1423 | * as a template; however, each PORT in the existing cfg | ||
1424 | * must be renumbered by incrementing "*port". If we run | ||
1425 | * out of "*port" numbers, return NULL. | ||
1426 | * | ||
1427 | * @param cfg template configuration | ||
1428 | * @param off the current peer offset | ||
1429 | * @param port port numbers to use, update to reflect | ||
1430 | * port numbers that were used | ||
1431 | * @param upnum number to make unix domain socket names unique | ||
1432 | * @param hostname hostname of the controlling host, to allow control connections from | ||
1433 | * @param fdnum number used to offset the unix domain socket for grouped processes | ||
1434 | * (such as statistics or peerinfo, which can be shared among others) | ||
1435 | * | ||
1436 | * @return new configuration, NULL on error | ||
1437 | */ | ||
1438 | struct GNUNET_CONFIGURATION_Handle * | ||
1439 | GNUNET_TESTING_create_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg, uint32_t off, | ||
1440 | uint16_t * port, uint32_t * upnum, const char *hostname, | ||
1441 | uint32_t * fdnum) | ||
1442 | { | ||
1443 | struct UpdateContext uc; | ||
1444 | uint16_t orig; | ||
1445 | char *control_host; | ||
1446 | char *allowed_hosts; | ||
1447 | unsigned long long skew_variance; | ||
1448 | unsigned long long skew_offset; | ||
1449 | long long actual_offset; | ||
1450 | |||
1451 | orig = *port; | ||
1452 | uc.nport = *port; | ||
1453 | uc.upnum = *upnum; | ||
1454 | uc.fdnum = *fdnum; | ||
1455 | uc.ret = GNUNET_CONFIGURATION_create (); | ||
1456 | uc.hostname = hostname; | ||
1457 | uc.orig = cfg; | ||
1458 | |||
1459 | GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc); | ||
1460 | if (uc.nport >= HIGH_PORT) | ||
1461 | { | ||
1462 | *port = orig; | ||
1463 | GNUNET_CONFIGURATION_destroy (uc.ret); | ||
1464 | return NULL; | ||
1465 | } | ||
1466 | |||
1467 | if ((GNUNET_OK == | ||
1468 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "skew_variance", | ||
1469 | &skew_variance)) && | ||
1470 | (skew_variance > 0)) | ||
1471 | { | ||
1472 | skew_offset = | ||
1473 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
1474 | skew_variance + 1); | ||
1475 | actual_offset = | ||
1476 | skew_offset - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
1477 | skew_variance + 1); | ||
1478 | /* Min is -skew_variance, Max is skew_variance */ | ||
1479 | skew_offset = skew_variance + actual_offset; /* Normal distribution around 0 */ | ||
1480 | GNUNET_CONFIGURATION_set_value_number (uc.ret, "testing_old", "skew_offset", | ||
1481 | skew_offset); | ||
1482 | } | ||
1483 | |||
1484 | if (GNUNET_CONFIGURATION_get_value_string | ||
1485 | (cfg, "testing_old", "control_host", &control_host) == GNUNET_OK) | ||
1486 | { | ||
1487 | if (hostname != NULL) | ||
1488 | GNUNET_asprintf (&allowed_hosts, "%s; 127.0.0.1; %s;", control_host, | ||
1489 | hostname); | ||
1490 | else | ||
1491 | GNUNET_asprintf (&allowed_hosts, "%s; 127.0.0.1;", control_host); | ||
1492 | |||
1493 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "core", "ACCEPT_FROM", | ||
1494 | allowed_hosts); | ||
1495 | |||
1496 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "nse", "ACCEPT_FROM", | ||
1497 | allowed_hosts); | ||
1498 | |||
1499 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport", "ACCEPT_FROM", | ||
1500 | allowed_hosts); | ||
1501 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "dht", "ACCEPT_FROM", | ||
1502 | allowed_hosts); | ||
1503 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "statistics", "ACCEPT_FROM", | ||
1504 | allowed_hosts); | ||
1505 | |||
1506 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "core", "UNIXPATH", ""); | ||
1507 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport", "UNIXPATH", ""); | ||
1508 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "dht", "UNIXPATH", ""); | ||
1509 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "statistics", "UNIXPATH", | ||
1510 | ""); | ||
1511 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "nse", "UNIXPATH", ""); | ||
1512 | |||
1513 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", | ||
1514 | "USE_LOCALADDR", "YES"); | ||
1515 | GNUNET_free_non_null (control_host); | ||
1516 | GNUNET_free (allowed_hosts); | ||
1517 | } | ||
1518 | |||
1519 | /* arm needs to know to allow connections from the host on which it is running, | ||
1520 | * otherwise gnunet-arm is unable to connect to it in some instances */ | ||
1521 | if (hostname != NULL) | ||
1522 | { | ||
1523 | GNUNET_asprintf (&allowed_hosts, "%s; 127.0.0.1;", hostname); | ||
1524 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "BINDTO", hostname); | ||
1525 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "INTERNAL_ADDRESS", | ||
1526 | hostname); | ||
1527 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "EXTERNAL_ADDRESS", | ||
1528 | hostname); | ||
1529 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "disablev6", "BINDTO", | ||
1530 | "YES"); | ||
1531 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport-tcp", | ||
1532 | "USE_LOCALADDR", "YES"); | ||
1533 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport-udp", | ||
1534 | "USE_LOCALADDR", "YES"); | ||
1535 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "arm", "ACCEPT_FROM", | ||
1536 | allowed_hosts); | ||
1537 | GNUNET_free (allowed_hosts); | ||
1538 | } | ||
1539 | else | ||
1540 | { | ||
1541 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", | ||
1542 | "USE_LOCALADDR", "YES"); | ||
1543 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "BINDTO", | ||
1544 | "127.0.0.1"); | ||
1545 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "INTERNAL_ADDRESS", | ||
1546 | "127.0.0.1"); | ||
1547 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "EXTERNAL_ADDRESS", | ||
1548 | "127.0.0.1"); | ||
1549 | GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "disablev6", | ||
1550 | "YES"); | ||
1551 | } | ||
1552 | |||
1553 | *port = (uint16_t) uc.nport; | ||
1554 | *upnum = uc.upnum; | ||
1555 | uc.fdnum++; | ||
1556 | *fdnum = uc.fdnum; | ||
1557 | return uc.ret; | ||
1558 | } | ||
1559 | |||
1560 | /* | ||
1561 | * Remove entries from the peer connection list | ||
1562 | * | ||
1563 | * @param pg the peer group we are working with | ||
1564 | * @param first index of the first peer | ||
1565 | * @param second index of the second peer | ||
1566 | * @param list the peer list to use | ||
1567 | * @param check UNUSED | ||
1568 | * | ||
1569 | * @return the number of connections added (can be 0, 1 or 2) | ||
1570 | * | ||
1571 | */ | ||
1572 | static unsigned int | ||
1573 | remove_connections (struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, | ||
1574 | unsigned int second, enum PeerLists list, | ||
1575 | unsigned int check) | ||
1576 | { | ||
1577 | int removed; | ||
1578 | |||
1579 | #if OLD | ||
1580 | struct PeerConnection **first_list; | ||
1581 | struct PeerConnection **second_list; | ||
1582 | struct PeerConnection *first_iter; | ||
1583 | struct PeerConnection *second_iter; | ||
1584 | struct PeerConnection **first_tail; | ||
1585 | struct PeerConnection **second_tail; | ||
1586 | |||
1587 | #else | ||
1588 | struct GNUNET_HashCode hash_first; | ||
1589 | struct GNUNET_HashCode hash_second; | ||
1590 | |||
1591 | hash_from_uid (first, &hash_first); | ||
1592 | hash_from_uid (second, &hash_second); | ||
1593 | #endif | ||
1594 | |||
1595 | removed = 0; | ||
1596 | #if OLD | ||
1597 | switch (list) | ||
1598 | { | ||
1599 | case ALLOWED: | ||
1600 | first_list = &pg->peers[first].allowed_peers_head; | ||
1601 | second_list = &pg->peers[second].allowed_peers_head; | ||
1602 | first_tail = &pg->peers[first].allowed_peers_tail; | ||
1603 | second_tail = &pg->peers[second].allowed_peers_tail; | ||
1604 | break; | ||
1605 | case CONNECT: | ||
1606 | first_list = &pg->peers[first].connect_peers_head; | ||
1607 | second_list = &pg->peers[second].connect_peers_head; | ||
1608 | first_tail = &pg->peers[first].connect_peers_tail; | ||
1609 | second_tail = &pg->peers[second].connect_peers_tail; | ||
1610 | break; | ||
1611 | case BLACKLIST: | ||
1612 | first_list = &pg->peers[first].blacklisted_peers_head; | ||
1613 | second_list = &pg->peers[second].blacklisted_peers_head; | ||
1614 | first_tail = &pg->peers[first].blacklisted_peers_tail; | ||
1615 | second_tail = &pg->peers[second].blacklisted_peers_tail; | ||
1616 | break; | ||
1617 | case WORKING_SET: | ||
1618 | first_list = &pg->peers[first].connect_peers_working_set_head; | ||
1619 | second_list = &pg->peers[second].connect_peers_working_set_head; | ||
1620 | first_tail = &pg->peers[first].connect_peers_working_set_tail; | ||
1621 | second_tail = &pg->peers[second].connect_peers_working_set_tail; | ||
1622 | break; | ||
1623 | default: | ||
1624 | GNUNET_break (0); | ||
1625 | return 0; | ||
1626 | } | ||
1627 | |||
1628 | first_iter = *first_list; | ||
1629 | while (first_iter != NULL) | ||
1630 | { | ||
1631 | if (first_iter->index == second) | ||
1632 | { | ||
1633 | GNUNET_CONTAINER_DLL_remove (*first_list, *first_tail, first_iter); | ||
1634 | GNUNET_free (first_iter); | ||
1635 | removed++; | ||
1636 | break; | ||
1637 | } | ||
1638 | first_iter = first_iter->next; | ||
1639 | } | ||
1640 | |||
1641 | second_iter = *second_list; | ||
1642 | while (second_iter != NULL) | ||
1643 | { | ||
1644 | if (second_iter->index == first) | ||
1645 | { | ||
1646 | GNUNET_CONTAINER_DLL_remove (*second_list, *second_tail, second_iter); | ||
1647 | GNUNET_free (second_iter); | ||
1648 | removed++; | ||
1649 | break; | ||
1650 | } | ||
1651 | second_iter = second_iter->next; | ||
1652 | } | ||
1653 | #else | ||
1654 | if (GNUNET_YES == | ||
1655 | GNUNET_CONTAINER_multihashmap_contains (pg-> | ||
1656 | peers[first].blacklisted_peers, | ||
1657 | &hash_second)) | ||
1658 | { | ||
1659 | GNUNET_CONTAINER_multihashmap_remove_all (pg-> | ||
1660 | peers[first].blacklisted_peers, | ||
1661 | &hash_second); | ||
1662 | } | ||
1663 | |||
1664 | if (GNUNET_YES == | ||
1665 | GNUNET_CONTAINER_multihashmap_contains (pg-> | ||
1666 | peers[second].blacklisted_peers, | ||
1667 | &hash_first)) | ||
1668 | { | ||
1669 | GNUNET_CONTAINER_multihashmap_remove_all (pg-> | ||
1670 | peers[second].blacklisted_peers, | ||
1671 | &hash_first); | ||
1672 | } | ||
1673 | #endif | ||
1674 | |||
1675 | return removed; | ||
1676 | } | ||
1677 | |||
1678 | /** | ||
1679 | * Add entries to the some list | ||
1680 | * | ||
1681 | * @param pg the peer group we are working with | ||
1682 | * @param first index of the first peer | ||
1683 | * @param second index of the second peer | ||
1684 | * @param list the list type that we should modify | ||
1685 | * @param check GNUNET_YES to check lists before adding | ||
1686 | * GNUNET_NO to force add | ||
1687 | * | ||
1688 | * @return the number of connections added (can be 0, 1 or 2) | ||
1689 | * | ||
1690 | */ | ||
1691 | static unsigned int | ||
1692 | add_connections (struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, | ||
1693 | unsigned int second, enum PeerLists list, unsigned int check) | ||
1694 | { | ||
1695 | int added; | ||
1696 | int add_first; | ||
1697 | int add_second; | ||
1698 | |||
1699 | struct PeerConnection **first_list; | ||
1700 | struct PeerConnection **second_list; | ||
1701 | struct PeerConnection *first_iter; | ||
1702 | struct PeerConnection *second_iter; | ||
1703 | struct PeerConnection *new_first; | ||
1704 | struct PeerConnection *new_second; | ||
1705 | struct PeerConnection **first_tail; | ||
1706 | struct PeerConnection **second_tail; | ||
1707 | |||
1708 | switch (list) | ||
1709 | { | ||
1710 | case ALLOWED: | ||
1711 | first_list = &pg->peers[first].allowed_peers_head; | ||
1712 | second_list = &pg->peers[second].allowed_peers_head; | ||
1713 | first_tail = &pg->peers[first].allowed_peers_tail; | ||
1714 | second_tail = &pg->peers[second].allowed_peers_tail; | ||
1715 | break; | ||
1716 | case CONNECT: | ||
1717 | first_list = &pg->peers[first].connect_peers_head; | ||
1718 | second_list = &pg->peers[second].connect_peers_head; | ||
1719 | first_tail = &pg->peers[first].connect_peers_tail; | ||
1720 | second_tail = &pg->peers[second].connect_peers_tail; | ||
1721 | break; | ||
1722 | case BLACKLIST: | ||
1723 | first_list = &pg->peers[first].blacklisted_peers_head; | ||
1724 | second_list = &pg->peers[second].blacklisted_peers_head; | ||
1725 | first_tail = &pg->peers[first].blacklisted_peers_tail; | ||
1726 | second_tail = &pg->peers[second].blacklisted_peers_tail; | ||
1727 | break; | ||
1728 | case WORKING_SET: | ||
1729 | first_list = &pg->peers[first].connect_peers_working_set_head; | ||
1730 | second_list = &pg->peers[second].connect_peers_working_set_head; | ||
1731 | first_tail = &pg->peers[first].connect_peers_working_set_tail; | ||
1732 | second_tail = &pg->peers[second].connect_peers_working_set_tail; | ||
1733 | break; | ||
1734 | default: | ||
1735 | GNUNET_break (0); | ||
1736 | return 0; | ||
1737 | } | ||
1738 | |||
1739 | add_first = GNUNET_YES; | ||
1740 | add_second = GNUNET_YES; | ||
1741 | |||
1742 | if (check == GNUNET_YES) | ||
1743 | { | ||
1744 | first_iter = *first_list; | ||
1745 | while (first_iter != NULL) | ||
1746 | { | ||
1747 | if (first_iter->index == second) | ||
1748 | { | ||
1749 | add_first = GNUNET_NO; | ||
1750 | break; | ||
1751 | } | ||
1752 | first_iter = first_iter->next; | ||
1753 | } | ||
1754 | |||
1755 | second_iter = *second_list; | ||
1756 | while (second_iter != NULL) | ||
1757 | { | ||
1758 | if (second_iter->index == first) | ||
1759 | { | ||
1760 | add_second = GNUNET_NO; | ||
1761 | break; | ||
1762 | } | ||
1763 | second_iter = second_iter->next; | ||
1764 | } | ||
1765 | } | ||
1766 | |||
1767 | added = 0; | ||
1768 | if (add_first) | ||
1769 | { | ||
1770 | new_first = GNUNET_malloc (sizeof (struct PeerConnection)); | ||
1771 | new_first->index = second; | ||
1772 | GNUNET_CONTAINER_DLL_insert (*first_list, *first_tail, new_first); | ||
1773 | pg->peers[first].num_connections++; | ||
1774 | added++; | ||
1775 | } | ||
1776 | |||
1777 | if (add_second) | ||
1778 | { | ||
1779 | new_second = GNUNET_malloc (sizeof (struct PeerConnection)); | ||
1780 | new_second->index = first; | ||
1781 | GNUNET_CONTAINER_DLL_insert (*second_list, *second_tail, new_second); | ||
1782 | pg->peers[second].num_connections++; | ||
1783 | added++; | ||
1784 | } | ||
1785 | |||
1786 | return added; | ||
1787 | } | ||
1788 | |||
1789 | /** | ||
1790 | * Scale free network construction as described in: | ||
1791 | * | ||
1792 | * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999. | ||
1793 | * | ||
1794 | * Start with a network of "one" peer, then progressively add | ||
1795 | * peers up to the total number. At each step, iterate over | ||
1796 | * all possible peers and connect new peer based on number of | ||
1797 | * existing connections of the target peer. | ||
1798 | * | ||
1799 | * @param pg the peer group we are dealing with | ||
1800 | * @param proc the connection processor to use | ||
1801 | * @param list the peer list to use | ||
1802 | * | ||
1803 | * @return the number of connections created | ||
1804 | */ | ||
1805 | static unsigned int | ||
1806 | create_scale_free (struct GNUNET_TESTING_PeerGroup *pg, | ||
1807 | GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list) | ||
1808 | { | ||
1809 | |||
1810 | unsigned int total_connections; | ||
1811 | unsigned int outer_count; | ||
1812 | unsigned int i; | ||
1813 | unsigned int previous_total_connections; | ||
1814 | double random; | ||
1815 | double probability; | ||
1816 | |||
1817 | GNUNET_assert (pg->total > 1); | ||
1818 | |||
1819 | /* Add a connection between the first two nodes */ | ||
1820 | total_connections = proc (pg, 0, 1, list, GNUNET_YES); | ||
1821 | |||
1822 | for (outer_count = 1; outer_count < pg->total; outer_count++) | ||
1823 | { | ||
1824 | previous_total_connections = total_connections; | ||
1825 | for (i = 0; i < outer_count; i++) | ||
1826 | { | ||
1827 | probability = | ||
1828 | pg->peers[i].num_connections / (double) previous_total_connections; | ||
1829 | random = | ||
1830 | ((double) | ||
1831 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
1832 | UINT64_MAX)) / ((double) UINT64_MAX); | ||
1833 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1834 | "Considering connecting peer %d to peer %d\n", outer_count, | ||
1835 | i); | ||
1836 | if (random < probability) | ||
1837 | { | ||
1838 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", | ||
1839 | outer_count, i); | ||
1840 | total_connections += proc (pg, outer_count, i, list, GNUNET_YES); | ||
1841 | } | ||
1842 | } | ||
1843 | } | ||
1844 | |||
1845 | return total_connections; | ||
1846 | } | ||
1847 | |||
1848 | /** | ||
1849 | * Create a topology given a peer group (set of running peers) | ||
1850 | * and a connection processor. Creates a small world topology | ||
1851 | * according to the rewired ring construction. The basic | ||
1852 | * behavior is that a ring topology is created, but with some | ||
1853 | * probability instead of connecting a peer to the next | ||
1854 | * neighbor in the ring a connection will be created to a peer | ||
1855 | * selected uniformly at random. We use the TESTING | ||
1856 | * PERCENTAGE option to specify what number of | ||
1857 | * connections each peer should have. Default is 2, | ||
1858 | * which makes the ring, any given number is multiplied by | ||
1859 | * the log of the network size; i.e. a PERCENTAGE of 2 makes | ||
1860 | * each peer have on average 2logn connections. The additional | ||
1861 | * connections are made at increasing distance around the ring | ||
1862 | * from the original peer, or to random peers based on the re- | ||
1863 | * wiring probability. The TESTING | ||
1864 | * PROBABILITY option is used as the probability that a given | ||
1865 | * connection is rewired. | ||
1866 | * | ||
1867 | * @param pg the peergroup to create the topology on | ||
1868 | * @param proc the connection processor to call to actually set | ||
1869 | * up connections between two peers | ||
1870 | * @param list the peer list to use | ||
1871 | * | ||
1872 | * @return the number of connections that were set up | ||
1873 | * | ||
1874 | */ | ||
1875 | static unsigned int | ||
1876 | create_small_world_ring (struct GNUNET_TESTING_PeerGroup *pg, | ||
1877 | GNUNET_TESTING_ConnectionProcessor proc, | ||
1878 | enum PeerLists list) | ||
1879 | { | ||
1880 | unsigned int i, j; | ||
1881 | int nodeToConnect; | ||
1882 | unsigned int natLog; | ||
1883 | unsigned int randomPeer; | ||
1884 | double random, logNModifier, probability; | ||
1885 | unsigned int smallWorldConnections; | ||
1886 | int connsPerPeer; | ||
1887 | char *p_string; | ||
1888 | int max; | ||
1889 | int min; | ||
1890 | unsigned int useAnd; | ||
1891 | int connect_attempts; | ||
1892 | |||
1893 | logNModifier = 0.5; /* FIXME: default value? */ | ||
1894 | if (GNUNET_OK == | ||
1895 | GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PERCENTAGE", | ||
1896 | &p_string)) | ||
1897 | { | ||
1898 | if (SSCANF (p_string, "%lf", &logNModifier) != 1) | ||
1899 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1900 | _ | ||
1901 | ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), | ||
1902 | p_string, "LOGNMODIFIER", "TESTING_OLD"); | ||
1903 | GNUNET_free (p_string); | ||
1904 | } | ||
1905 | probability = 0.5; /* FIXME: default percentage? */ | ||
1906 | if (GNUNET_OK == | ||
1907 | GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PROBABILITY", | ||
1908 | &p_string)) | ||
1909 | { | ||
1910 | if (SSCANF (p_string, "%lf", &probability) != 1) | ||
1911 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1912 | _ | ||
1913 | ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), | ||
1914 | p_string, "PERCENTAGE", "TESTING_OLD"); | ||
1915 | GNUNET_free (p_string); | ||
1916 | } | ||
1917 | natLog = log (pg->total); | ||
1918 | connsPerPeer = ceil (natLog * logNModifier); | ||
1919 | |||
1920 | if (connsPerPeer % 2 == 1) | ||
1921 | connsPerPeer += 1; | ||
1922 | |||
1923 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Target is %d connections per peer.", | ||
1924 | connsPerPeer); | ||
1925 | |||
1926 | smallWorldConnections = 0; | ||
1927 | connect_attempts = 0; | ||
1928 | for (i = 0; i < pg->total; i++) | ||
1929 | { | ||
1930 | useAnd = 0; | ||
1931 | max = i + connsPerPeer / 2; | ||
1932 | min = i - connsPerPeer / 2; | ||
1933 | |||
1934 | if (max > pg->total - 1) | ||
1935 | { | ||
1936 | max = max - pg->total; | ||
1937 | useAnd = 1; | ||
1938 | } | ||
1939 | |||
1940 | if (min < 0) | ||
1941 | { | ||
1942 | min = pg->total - 1 + min; | ||
1943 | useAnd = 1; | ||
1944 | } | ||
1945 | |||
1946 | for (j = 0; j < connsPerPeer / 2; j++) | ||
1947 | { | ||
1948 | random = | ||
1949 | ((double) | ||
1950 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
1951 | UINT64_MAX) / ((double) UINT64_MAX)); | ||
1952 | if (random < probability) | ||
1953 | { | ||
1954 | /* Connect to uniformly selected random peer */ | ||
1955 | randomPeer = | ||
1956 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total); | ||
1957 | while ((((randomPeer < max) && (randomPeer > min)) && (useAnd == 0)) || | ||
1958 | (((randomPeer > max) || (randomPeer < min)) && (useAnd == 1))) | ||
1959 | |||
1960 | { | ||
1961 | randomPeer = | ||
1962 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total); | ||
1963 | } | ||
1964 | smallWorldConnections += proc (pg, i, randomPeer, list, GNUNET_YES); | ||
1965 | } | ||
1966 | else | ||
1967 | { | ||
1968 | nodeToConnect = i + j + 1; | ||
1969 | if (nodeToConnect > pg->total - 1) | ||
1970 | { | ||
1971 | nodeToConnect = nodeToConnect - pg->total; | ||
1972 | } | ||
1973 | connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES); | ||
1974 | } | ||
1975 | } | ||
1976 | |||
1977 | } | ||
1978 | |||
1979 | connect_attempts += smallWorldConnections; | ||
1980 | |||
1981 | return connect_attempts; | ||
1982 | } | ||
1983 | |||
1984 | /** | ||
1985 | * Create a topology given a peer group (set of running peers) | ||
1986 | * and a connection processor. | ||
1987 | * | ||
1988 | * @param pg the peergroup to create the topology on | ||
1989 | * @param proc the connection processor to call to actually set | ||
1990 | * up connections between two peers | ||
1991 | * @param list the peer list to use | ||
1992 | * | ||
1993 | * @return the number of connections that were set up | ||
1994 | * | ||
1995 | */ | ||
1996 | static unsigned int | ||
1997 | create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg, | ||
1998 | GNUNET_TESTING_ConnectionProcessor proc, | ||
1999 | enum PeerLists list) | ||
2000 | { | ||
2001 | unsigned int outer_count, inner_count; | ||
2002 | unsigned int cutoff; | ||
2003 | int connect_attempts; | ||
2004 | double nat_percentage; | ||
2005 | char *p_string; | ||
2006 | |||
2007 | nat_percentage = 0.6; /* FIXME: default percentage? */ | ||
2008 | if (GNUNET_OK == | ||
2009 | GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PERCENTAGE", | ||
2010 | &p_string)) | ||
2011 | { | ||
2012 | if (SSCANF (p_string, "%lf", &nat_percentage) != 1) | ||
2013 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2014 | _ | ||
2015 | ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), | ||
2016 | p_string, "PERCENTAGE", "TESTING_OLD"); | ||
2017 | GNUNET_free (p_string); | ||
2018 | } | ||
2019 | |||
2020 | cutoff = (unsigned int) (nat_percentage * pg->total); | ||
2021 | connect_attempts = 0; | ||
2022 | for (outer_count = 0; outer_count < pg->total - 1; outer_count++) | ||
2023 | { | ||
2024 | for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++) | ||
2025 | { | ||
2026 | if ((outer_count > cutoff) || (inner_count > cutoff)) | ||
2027 | { | ||
2028 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", | ||
2029 | outer_count, inner_count); | ||
2030 | connect_attempts += | ||
2031 | proc (pg, outer_count, inner_count, list, GNUNET_YES); | ||
2032 | } | ||
2033 | } | ||
2034 | } | ||
2035 | return connect_attempts; | ||
2036 | } | ||
2037 | |||
2038 | #if TOPOLOGY_HACK | ||
2039 | /** | ||
2040 | * Create a topology given a peer group (set of running peers) | ||
2041 | * and a connection processor. | ||
2042 | * | ||
2043 | * @param pg the peergroup to create the topology on | ||
2044 | * @param proc the connection processor to call to actually set | ||
2045 | * up connections between two peers | ||
2046 | * @param list the peer list to use | ||
2047 | * | ||
2048 | * @return the number of connections that were set up | ||
2049 | * | ||
2050 | */ | ||
2051 | static unsigned int | ||
2052 | create_nated_internet_copy (struct GNUNET_TESTING_PeerGroup *pg, | ||
2053 | GNUNET_TESTING_ConnectionProcessor proc, | ||
2054 | enum PeerLists list) | ||
2055 | { | ||
2056 | unsigned int outer_count, inner_count; | ||
2057 | unsigned int cutoff; | ||
2058 | int connect_attempts; | ||
2059 | double nat_percentage; | ||
2060 | char *p_string; | ||
2061 | unsigned int count; | ||
2062 | struct ProgressMeter *conn_meter; | ||
2063 | |||
2064 | nat_percentage = 0.6; /* FIXME: default percentage? */ | ||
2065 | if (GNUNET_OK == | ||
2066 | GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PERCENTAGE", | ||
2067 | &p_string)) | ||
2068 | { | ||
2069 | if (SSCANF (p_string, "%lf", &nat_percentage) != 1) | ||
2070 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2071 | _ | ||
2072 | ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), | ||
2073 | p_string, "PERCENTAGE", "TESTING_OLD"); | ||
2074 | GNUNET_free (p_string); | ||
2075 | } | ||
2076 | |||
2077 | cutoff = (unsigned int) (nat_percentage * pg->total); | ||
2078 | count = 0; | ||
2079 | for (outer_count = 0; outer_count < pg->total - 1; outer_count++) | ||
2080 | { | ||
2081 | for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++) | ||
2082 | { | ||
2083 | if ((outer_count > cutoff) || (inner_count > cutoff)) | ||
2084 | { | ||
2085 | count++; | ||
2086 | } | ||
2087 | } | ||
2088 | } | ||
2089 | conn_meter = create_meter (count, "NAT COPY", GNUNET_YES); | ||
2090 | connect_attempts = 0; | ||
2091 | for (outer_count = 0; outer_count < pg->total - 1; outer_count++) | ||
2092 | { | ||
2093 | for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++) | ||
2094 | { | ||
2095 | if ((outer_count > cutoff) || (inner_count > cutoff)) | ||
2096 | { | ||
2097 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", | ||
2098 | outer_count, inner_count); | ||
2099 | connect_attempts += | ||
2100 | proc (pg, outer_count, inner_count, list, GNUNET_YES); | ||
2101 | add_connections (pg, outer_count, inner_count, ALLOWED, GNUNET_NO); | ||
2102 | update_meter (conn_meter); | ||
2103 | } | ||
2104 | } | ||
2105 | } | ||
2106 | free_meter (conn_meter); | ||
2107 | |||
2108 | return connect_attempts; | ||
2109 | } | ||
2110 | #endif | ||
2111 | |||
2112 | /** | ||
2113 | * Create a topology given a peer group (set of running peers) | ||
2114 | * and a connection processor. | ||
2115 | * | ||
2116 | * @param pg the peergroup to create the topology on | ||
2117 | * @param proc the connection processor to call to actually set | ||
2118 | * up connections between two peers | ||
2119 | * @param list the peer list to use | ||
2120 | * | ||
2121 | * @return the number of connections that were set up | ||
2122 | * | ||
2123 | */ | ||
2124 | static unsigned int | ||
2125 | create_small_world (struct GNUNET_TESTING_PeerGroup *pg, | ||
2126 | GNUNET_TESTING_ConnectionProcessor proc, | ||
2127 | enum PeerLists list) | ||
2128 | { | ||
2129 | unsigned int i, j, k; | ||
2130 | unsigned int square; | ||
2131 | unsigned int rows; | ||
2132 | unsigned int cols; | ||
2133 | unsigned int toggle = 1; | ||
2134 | unsigned int nodeToConnect; | ||
2135 | unsigned int natLog; | ||
2136 | unsigned int node1Row; | ||
2137 | unsigned int node1Col; | ||
2138 | unsigned int node2Row; | ||
2139 | unsigned int node2Col; | ||
2140 | unsigned int distance; | ||
2141 | double probability, random, percentage; | ||
2142 | unsigned int smallWorldConnections; | ||
2143 | unsigned int small_world_it; | ||
2144 | char *p_string; | ||
2145 | int connect_attempts; | ||
2146 | |||
2147 | square = floor (sqrt (pg->total)); | ||
2148 | rows = square; | ||
2149 | cols = square; | ||
2150 | |||
2151 | percentage = 0.5; /* FIXME: default percentage? */ | ||
2152 | if (GNUNET_OK == | ||
2153 | GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PERCENTAGE", | ||
2154 | &p_string)) | ||
2155 | { | ||
2156 | if (SSCANF (p_string, "%lf", &percentage) != 1) | ||
2157 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2158 | _ | ||
2159 | ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), | ||
2160 | p_string, "PERCENTAGE", "TESTING_OLD"); | ||
2161 | GNUNET_free (p_string); | ||
2162 | } | ||
2163 | if (percentage < 0.0) | ||
2164 | { | ||
2165 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2166 | _ | ||
2167 | ("Invalid value `%s' for option `%s' in section `%s': got %f, needed value greater than 0\n"), | ||
2168 | "PERCENTAGE", "TESTING_OLD", percentage); | ||
2169 | percentage = 0.5; | ||
2170 | } | ||
2171 | probability = 0.5; /* FIXME: default percentage? */ | ||
2172 | if (GNUNET_OK == | ||
2173 | GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PROBABILITY", | ||
2174 | &p_string)) | ||
2175 | { | ||
2176 | if (SSCANF (p_string, "%lf", &probability) != 1) | ||
2177 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2178 | _ | ||
2179 | ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), | ||
2180 | p_string, "PROBABILITY", "TESTING_OLD"); | ||
2181 | GNUNET_free (p_string); | ||
2182 | } | ||
2183 | if (square * square != pg->total) | ||
2184 | { | ||
2185 | while (rows * cols < pg->total) | ||
2186 | { | ||
2187 | if (toggle % 2 == 0) | ||
2188 | rows++; | ||
2189 | else | ||
2190 | cols++; | ||
2191 | |||
2192 | toggle++; | ||
2193 | } | ||
2194 | } | ||
2195 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2196 | "Connecting nodes in 2d torus topology: %u rows %u columns\n", | ||
2197 | rows, cols); | ||
2198 | connect_attempts = 0; | ||
2199 | /* Rows and columns are all sorted out, now iterate over all nodes and connect each | ||
2200 | * to the node to its right and above. Once this is over, we'll have our torus! | ||
2201 | * Special case for the last node (if the rows and columns are not equal), connect | ||
2202 | * to the first in the row to maintain topology. | ||
2203 | */ | ||
2204 | for (i = 0; i < pg->total; i++) | ||
2205 | { | ||
2206 | /* First connect to the node to the right */ | ||
2207 | if (((i + 1) % cols != 0) && (i + 1 != pg->total)) | ||
2208 | nodeToConnect = i + 1; | ||
2209 | else if (i + 1 == pg->total) | ||
2210 | nodeToConnect = rows * cols - cols; | ||
2211 | else | ||
2212 | nodeToConnect = i - cols + 1; | ||
2213 | |||
2214 | connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES); | ||
2215 | |||
2216 | if (i < cols) | ||
2217 | { | ||
2218 | nodeToConnect = (rows * cols) - cols + i; | ||
2219 | if (nodeToConnect >= pg->total) | ||
2220 | nodeToConnect -= cols; | ||
2221 | } | ||
2222 | else | ||
2223 | nodeToConnect = i - cols; | ||
2224 | |||
2225 | if (nodeToConnect < pg->total) | ||
2226 | connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES); | ||
2227 | } | ||
2228 | natLog = log (pg->total); | ||
2229 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2230 | "natural log of %d is %d, will run %d iterations\n", pg->total, | ||
2231 | natLog, (int) (natLog * percentage)); | ||
2232 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2233 | "Total connections added thus far: %u!\n", connect_attempts); | ||
2234 | smallWorldConnections = 0; | ||
2235 | small_world_it = (unsigned int) (natLog * percentage); | ||
2236 | if (small_world_it < 1) | ||
2237 | small_world_it = 1; | ||
2238 | GNUNET_assert (small_world_it > 0 && small_world_it < (unsigned int) -1); | ||
2239 | for (i = 0; i < small_world_it; i++) | ||
2240 | { | ||
2241 | for (j = 0; j < pg->total; j++) | ||
2242 | { | ||
2243 | /* Determine the row and column of node at position j on the 2d torus */ | ||
2244 | node1Row = j / cols; | ||
2245 | node1Col = j - (node1Row * cols); | ||
2246 | for (k = 0; k < pg->total; k++) | ||
2247 | { | ||
2248 | /* Determine the row and column of node at position k on the 2d torus */ | ||
2249 | node2Row = k / cols; | ||
2250 | node2Col = k - (node2Row * cols); | ||
2251 | /* Simple Cartesian distance */ | ||
2252 | distance = abs (node1Row - node2Row) + abs (node1Col - node2Col); | ||
2253 | if (distance > 1) | ||
2254 | { | ||
2255 | /* Calculate probability as 1 over the square of the distance */ | ||
2256 | probability = 1.0 / (distance * distance); | ||
2257 | /* Choose a random value between 0 and 1 */ | ||
2258 | random = | ||
2259 | ((double) | ||
2260 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
2261 | UINT64_MAX)) / ((double) UINT64_MAX); | ||
2262 | /* If random < probability, then connect the two nodes */ | ||
2263 | if (random < probability) | ||
2264 | smallWorldConnections += proc (pg, j, k, list, GNUNET_YES); | ||
2265 | |||
2266 | } | ||
2267 | } | ||
2268 | } | ||
2269 | } | ||
2270 | connect_attempts += smallWorldConnections; | ||
2271 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2272 | "Total connections added for small world: %d!\n", | ||
2273 | smallWorldConnections); | ||
2274 | return connect_attempts; | ||
2275 | } | ||
2276 | |||
2277 | /** | ||
2278 | * Create a topology given a peer group (set of running peers) | ||
2279 | * and a connection processor. | ||
2280 | * | ||
2281 | * @param pg the peergroup to create the topology on | ||
2282 | * @param proc the connection processor to call to actually set | ||
2283 | * up connections between two peers | ||
2284 | * @param list the peer list to use | ||
2285 | * | ||
2286 | * @return the number of connections that were set up | ||
2287 | * | ||
2288 | */ | ||
2289 | static unsigned int | ||
2290 | create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg, | ||
2291 | GNUNET_TESTING_ConnectionProcessor proc, | ||
2292 | enum PeerLists list) | ||
2293 | { | ||
2294 | double temp_rand; | ||
2295 | unsigned int outer_count; | ||
2296 | unsigned int inner_count; | ||
2297 | int connect_attempts; | ||
2298 | double probability; | ||
2299 | char *p_string; | ||
2300 | |||
2301 | probability = 0.5; /* FIXME: default percentage? */ | ||
2302 | if (GNUNET_OK == | ||
2303 | GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PROBABILITY", | ||
2304 | &p_string)) | ||
2305 | { | ||
2306 | if (SSCANF (p_string, "%lf", &probability) != 1) | ||
2307 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2308 | _ | ||
2309 | ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), | ||
2310 | p_string, "PROBABILITY", "TESTING_OLD"); | ||
2311 | GNUNET_free (p_string); | ||
2312 | } | ||
2313 | connect_attempts = 0; | ||
2314 | for (outer_count = 0; outer_count < pg->total - 1; outer_count++) | ||
2315 | { | ||
2316 | for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++) | ||
2317 | { | ||
2318 | temp_rand = | ||
2319 | ((double) | ||
2320 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
2321 | UINT64_MAX)) / ((double) UINT64_MAX); | ||
2322 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "rand is %f probability is %f\n", | ||
2323 | temp_rand, probability); | ||
2324 | if (temp_rand < probability) | ||
2325 | { | ||
2326 | connect_attempts += | ||
2327 | proc (pg, outer_count, inner_count, list, GNUNET_YES); | ||
2328 | } | ||
2329 | } | ||
2330 | } | ||
2331 | |||
2332 | return connect_attempts; | ||
2333 | } | ||
2334 | |||
2335 | /** | ||
2336 | * Create a topology given a peer group (set of running peers) | ||
2337 | * and a connection processor. This particular function creates | ||
2338 | * the connections for a 2d-torus, plus additional "closest" | ||
2339 | * connections per peer. | ||
2340 | * | ||
2341 | * @param pg the peergroup to create the topology on | ||
2342 | * @param proc the connection processor to call to actually set | ||
2343 | * up connections between two peers | ||
2344 | * @param list the peer list to use | ||
2345 | * | ||
2346 | * @return the number of connections that were set up | ||
2347 | * | ||
2348 | */ | ||
2349 | static unsigned int | ||
2350 | create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg, | ||
2351 | GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list) | ||
2352 | { | ||
2353 | unsigned int i; | ||
2354 | unsigned int square; | ||
2355 | unsigned int rows; | ||
2356 | unsigned int cols; | ||
2357 | unsigned int toggle = 1; | ||
2358 | unsigned int nodeToConnect; | ||
2359 | int connect_attempts; | ||
2360 | |||
2361 | connect_attempts = 0; | ||
2362 | |||
2363 | square = floor (sqrt (pg->total)); | ||
2364 | rows = square; | ||
2365 | cols = square; | ||
2366 | |||
2367 | if (square * square != pg->total) | ||
2368 | { | ||
2369 | while (rows * cols < pg->total) | ||
2370 | { | ||
2371 | if (toggle % 2 == 0) | ||
2372 | rows++; | ||
2373 | else | ||
2374 | cols++; | ||
2375 | |||
2376 | toggle++; | ||
2377 | } | ||
2378 | } | ||
2379 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2380 | "Connecting nodes in 2d torus topology: %u rows %u columns\n", | ||
2381 | rows, cols); | ||
2382 | /* Rows and columns are all sorted out, now iterate over all nodes and connect each | ||
2383 | * to the node to its right and above. Once this is over, we'll have our torus! | ||
2384 | * Special case for the last node (if the rows and columns are not equal), connect | ||
2385 | * to the first in the row to maintain topology. | ||
2386 | */ | ||
2387 | for (i = 0; i < pg->total; i++) | ||
2388 | { | ||
2389 | /* First connect to the node to the right */ | ||
2390 | if (((i + 1) % cols != 0) && (i + 1 != pg->total)) | ||
2391 | nodeToConnect = i + 1; | ||
2392 | else if (i + 1 == pg->total) | ||
2393 | nodeToConnect = rows * cols - cols; | ||
2394 | else | ||
2395 | nodeToConnect = i - cols + 1; | ||
2396 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", i, | ||
2397 | nodeToConnect); | ||
2398 | connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES); | ||
2399 | |||
2400 | /* Second connect to the node immediately above */ | ||
2401 | if (i < cols) | ||
2402 | { | ||
2403 | nodeToConnect = (rows * cols) - cols + i; | ||
2404 | if (nodeToConnect >= pg->total) | ||
2405 | nodeToConnect -= cols; | ||
2406 | } | ||
2407 | else | ||
2408 | nodeToConnect = i - cols; | ||
2409 | |||
2410 | if (nodeToConnect < pg->total) | ||
2411 | { | ||
2412 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", i, | ||
2413 | nodeToConnect); | ||
2414 | connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES); | ||
2415 | } | ||
2416 | |||
2417 | } | ||
2418 | |||
2419 | return connect_attempts; | ||
2420 | } | ||
2421 | |||
2422 | /** | ||
2423 | * Create a topology given a peer group (set of running peers) | ||
2424 | * and a connection processor. | ||
2425 | * | ||
2426 | * @param pg the peergroup to create the topology on | ||
2427 | * @param proc the connection processor to call to actually set | ||
2428 | * up connections between two peers | ||
2429 | * @param list the peer list to use | ||
2430 | * @param check does the connection processor need to check before | ||
2431 | * performing an action on the list? | ||
2432 | * | ||
2433 | * @return the number of connections that were set up | ||
2434 | * | ||
2435 | */ | ||
2436 | static unsigned int | ||
2437 | create_clique (struct GNUNET_TESTING_PeerGroup *pg, | ||
2438 | GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list, | ||
2439 | unsigned int check) | ||
2440 | { | ||
2441 | unsigned int outer_count; | ||
2442 | unsigned int inner_count; | ||
2443 | int connect_attempts; | ||
2444 | struct ProgressMeter *conn_meter; | ||
2445 | |||
2446 | connect_attempts = 0; | ||
2447 | |||
2448 | conn_meter = | ||
2449 | create_meter ((((pg->total * pg->total) + pg->total) / 2) - pg->total, | ||
2450 | "Create Clique ", GNUNET_NO); | ||
2451 | for (outer_count = 0; outer_count < pg->total - 1; outer_count++) | ||
2452 | { | ||
2453 | for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++) | ||
2454 | { | ||
2455 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", | ||
2456 | outer_count, inner_count); | ||
2457 | connect_attempts += proc (pg, outer_count, inner_count, list, check); | ||
2458 | update_meter (conn_meter); | ||
2459 | } | ||
2460 | } | ||
2461 | reset_meter (conn_meter); | ||
2462 | free_meter (conn_meter); | ||
2463 | return connect_attempts; | ||
2464 | } | ||
2465 | |||
2466 | #if !OLD | ||
2467 | /** | ||
2468 | * Iterator over hash map entries. | ||
2469 | * | ||
2470 | * @param cls closure the peer group | ||
2471 | * @param key the key stored in the hashmap is the | ||
2472 | * index of the peer to connect to | ||
2473 | * @param value value in the hash map, handle to the peer daemon | ||
2474 | * @return GNUNET_YES if we should continue to | ||
2475 | * iterate, | ||
2476 | * GNUNET_NO if not. | ||
2477 | */ | ||
2478 | static int | ||
2479 | unblacklist_iterator (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
2480 | { | ||
2481 | struct UnblacklistContext *un_ctx = cls; | ||
2482 | uint32_t second_pos; | ||
2483 | |||
2484 | uid_from_hash (key, &second_pos); | ||
2485 | |||
2486 | unblacklist_connections (un_ctx->pg, un_ctx->first_uid, second_pos); | ||
2487 | |||
2488 | return GNUNET_YES; | ||
2489 | } | ||
2490 | #endif | ||
2491 | |||
2492 | #if !OLD | ||
2493 | /** | ||
2494 | * Create a blacklist topology based on the allowed topology | ||
2495 | * which disallows any connections not in the allowed topology | ||
2496 | * at the transport level. | ||
2497 | * | ||
2498 | * @param pg the peergroup to create the topology on | ||
2499 | * @param proc the connection processor to call to allow | ||
2500 | * up connections between two peers | ||
2501 | * | ||
2502 | * @return the number of connections that were set up | ||
2503 | * | ||
2504 | */ | ||
2505 | static unsigned int | ||
2506 | copy_allowed (struct GNUNET_TESTING_PeerGroup *pg, | ||
2507 | GNUNET_TESTING_ConnectionProcessor proc) | ||
2508 | { | ||
2509 | unsigned int count; | ||
2510 | unsigned int total; | ||
2511 | struct PeerConnection *iter; | ||
2512 | |||
2513 | #if !OLD | ||
2514 | struct UnblacklistContext un_ctx; | ||
2515 | |||
2516 | un_ctx.pg = pg; | ||
2517 | #endif | ||
2518 | total = 0; | ||
2519 | for (count = 0; count < pg->total - 1; count++) | ||
2520 | { | ||
2521 | #if OLD | ||
2522 | iter = pg->peers[count].allowed_peers_head; | ||
2523 | while (iter != NULL) | ||
2524 | { | ||
2525 | remove_connections (pg, count, iter->index, BLACKLIST, GNUNET_YES); | ||
2526 | //unblacklist_connections(pg, count, iter->index); | ||
2527 | iter = iter->next; | ||
2528 | } | ||
2529 | #else | ||
2530 | un_ctx.first_uid = count; | ||
2531 | total += | ||
2532 | GNUNET_CONTAINER_multihashmap_iterate (pg->peers[count].allowed_peers, | ||
2533 | &unblacklist_iterator, &un_ctx); | ||
2534 | #endif | ||
2535 | } | ||
2536 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unblacklisted %u peers\n", total); | ||
2537 | return total; | ||
2538 | } | ||
2539 | #endif | ||
2540 | |||
2541 | /** | ||
2542 | * Create a topology given a peer group (set of running peers) | ||
2543 | * and a connection processor. | ||
2544 | * | ||
2545 | * @param pg the peergroup to create the topology on | ||
2546 | * @param proc the connection processor to call to actually set | ||
2547 | * up connections between two peers | ||
2548 | * @param list which list should be modified | ||
2549 | * | ||
2550 | * @return the number of connections that were set up | ||
2551 | * | ||
2552 | */ | ||
2553 | static unsigned int | ||
2554 | create_line (struct GNUNET_TESTING_PeerGroup *pg, | ||
2555 | GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list) | ||
2556 | { | ||
2557 | unsigned int count; | ||
2558 | unsigned int connect_attempts; | ||
2559 | |||
2560 | connect_attempts = 0; | ||
2561 | /* Connect each peer to the next highest numbered peer */ | ||
2562 | for (count = 0; count < pg->total - 1; count++) | ||
2563 | { | ||
2564 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", | ||
2565 | count, count + 1); | ||
2566 | connect_attempts += proc (pg, count, count + 1, list, GNUNET_YES); | ||
2567 | } | ||
2568 | |||
2569 | return connect_attempts; | ||
2570 | } | ||
2571 | |||
2572 | /** | ||
2573 | * Create a topology given a peer group (set of running peers) | ||
2574 | * and a connection processor. | ||
2575 | * | ||
2576 | * @param pg the peergroup to create the topology on | ||
2577 | * @param filename the file to read topology information from | ||
2578 | * @param proc the connection processor to call to actually set | ||
2579 | * up connections between two peers | ||
2580 | * @param list the peer list to use | ||
2581 | * | ||
2582 | * @return the number of connections that were set up | ||
2583 | * | ||
2584 | */ | ||
2585 | static unsigned int | ||
2586 | create_from_file (struct GNUNET_TESTING_PeerGroup *pg, char *filename, | ||
2587 | GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list) | ||
2588 | { | ||
2589 | int connect_attempts; | ||
2590 | unsigned int first_peer_index; | ||
2591 | unsigned int second_peer_index; | ||
2592 | struct stat frstat; | ||
2593 | int count; | ||
2594 | char *data; | ||
2595 | const char *buf; | ||
2596 | unsigned int total_peers; | ||
2597 | enum States curr_state; | ||
2598 | |||
2599 | connect_attempts = 0; | ||
2600 | if (GNUNET_OK != GNUNET_DISK_file_test (filename)) | ||
2601 | GNUNET_DISK_fn_write (filename, NULL, 0, GNUNET_DISK_PERM_USER_READ); | ||
2602 | |||
2603 | if ((0 != STAT (filename, &frstat)) || (frstat.st_size == 0)) | ||
2604 | { | ||
2605 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2606 | "Could not open file `%s' specified for topology!", filename); | ||
2607 | return connect_attempts; | ||
2608 | } | ||
2609 | |||
2610 | data = GNUNET_malloc_large (frstat.st_size); | ||
2611 | GNUNET_assert (data != NULL); | ||
2612 | if (frstat.st_size != GNUNET_DISK_fn_read (filename, data, frstat.st_size)) | ||
2613 | { | ||
2614 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2615 | "Could not read file %s specified for host list, ending test!", | ||
2616 | filename); | ||
2617 | GNUNET_free (data); | ||
2618 | return connect_attempts; | ||
2619 | } | ||
2620 | |||
2621 | buf = data; | ||
2622 | count = 0; | ||
2623 | first_peer_index = 0; | ||
2624 | /* First line should contain a single integer, specifying the number of peers */ | ||
2625 | /* Each subsequent line should contain this format PEER_INDEX:OTHER_PEER_INDEX[,...] */ | ||
2626 | curr_state = NUM_PEERS; | ||
2627 | while (count < frstat.st_size - 1) | ||
2628 | { | ||
2629 | if ((buf[count] == '\n') || (buf[count] == ' ')) | ||
2630 | { | ||
2631 | count++; | ||
2632 | continue; | ||
2633 | } | ||
2634 | |||
2635 | switch (curr_state) | ||
2636 | { | ||
2637 | case NUM_PEERS: | ||
2638 | errno = 0; | ||
2639 | total_peers = strtoul (&buf[count], NULL, 10); | ||
2640 | if (errno != 0) | ||
2641 | { | ||
2642 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2643 | "Failed to read number of peers from topology file!\n"); | ||
2644 | GNUNET_free (data); | ||
2645 | return connect_attempts; | ||
2646 | } | ||
2647 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u total peers in topology\n", | ||
2648 | total_peers); | ||
2649 | GNUNET_assert (total_peers == pg->total); | ||
2650 | curr_state = PEER_INDEX; | ||
2651 | while ((buf[count] != '\n') && (count < frstat.st_size - 1)) | ||
2652 | count++; | ||
2653 | count++; | ||
2654 | break; | ||
2655 | case PEER_INDEX: | ||
2656 | errno = 0; | ||
2657 | first_peer_index = strtoul (&buf[count], NULL, 10); | ||
2658 | if (errno != 0) | ||
2659 | { | ||
2660 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2661 | "Failed to read peer index from topology file!\n"); | ||
2662 | GNUNET_free (data); | ||
2663 | return connect_attempts; | ||
2664 | } | ||
2665 | while ((buf[count] != ':') && (count < frstat.st_size - 1)) | ||
2666 | count++; | ||
2667 | count++; | ||
2668 | curr_state = OTHER_PEER_INDEX; | ||
2669 | break; | ||
2670 | case COLON: | ||
2671 | if (1 == sscanf (&buf[count], ":")) | ||
2672 | curr_state = OTHER_PEER_INDEX; | ||
2673 | count++; | ||
2674 | break; | ||
2675 | case OTHER_PEER_INDEX: | ||
2676 | errno = 0; | ||
2677 | second_peer_index = strtoul (&buf[count], NULL, 10); | ||
2678 | if (errno != 0) | ||
2679 | { | ||
2680 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2681 | "Failed to peer index from topology file!\n"); | ||
2682 | GNUNET_free (data); | ||
2683 | return connect_attempts; | ||
2684 | } | ||
2685 | /* Assume file is written with first peer 1, but array index is 0 */ | ||
2686 | connect_attempts += | ||
2687 | proc (pg, first_peer_index - 1, second_peer_index - 1, list, | ||
2688 | GNUNET_YES); | ||
2689 | while ((buf[count] != '\n') && (buf[count] != ',') && | ||
2690 | (count < frstat.st_size - 1)) | ||
2691 | count++; | ||
2692 | if (buf[count] == '\n') | ||
2693 | { | ||
2694 | curr_state = PEER_INDEX; | ||
2695 | } | ||
2696 | else if (buf[count] != ',') | ||
2697 | { | ||
2698 | curr_state = OTHER_PEER_INDEX; | ||
2699 | } | ||
2700 | count++; | ||
2701 | break; | ||
2702 | default: | ||
2703 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2704 | "Found bad data in topology file while in state %d!\n", | ||
2705 | curr_state); | ||
2706 | GNUNET_break (0); | ||
2707 | GNUNET_free (data); | ||
2708 | return connect_attempts; | ||
2709 | } | ||
2710 | } | ||
2711 | GNUNET_free (data); | ||
2712 | return connect_attempts; | ||
2713 | } | ||
2714 | |||
2715 | /** | ||
2716 | * Create a topology given a peer group (set of running peers) | ||
2717 | * and a connection processor. | ||
2718 | * | ||
2719 | * @param pg the peergroup to create the topology on | ||
2720 | * @param proc the connection processor to call to actually set | ||
2721 | * up connections between two peers | ||
2722 | * @param list the peer list to use | ||
2723 | * | ||
2724 | * @return the number of connections that were set up | ||
2725 | * | ||
2726 | */ | ||
2727 | static unsigned int | ||
2728 | create_ring (struct GNUNET_TESTING_PeerGroup *pg, | ||
2729 | GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list) | ||
2730 | { | ||
2731 | unsigned int count; | ||
2732 | int connect_attempts; | ||
2733 | |||
2734 | connect_attempts = 0; | ||
2735 | |||
2736 | /* Connect each peer to the next highest numbered peer */ | ||
2737 | for (count = 0; count < pg->total - 1; count++) | ||
2738 | { | ||
2739 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", | ||
2740 | count, count + 1); | ||
2741 | connect_attempts += proc (pg, count, count + 1, list, GNUNET_YES); | ||
2742 | } | ||
2743 | |||
2744 | /* Connect the last peer to the first peer */ | ||
2745 | connect_attempts += proc (pg, pg->total - 1, 0, list, GNUNET_YES); | ||
2746 | |||
2747 | return connect_attempts; | ||
2748 | } | ||
2749 | |||
2750 | #if !OLD | ||
2751 | /** | ||
2752 | * Iterator for writing friends of a peer to a file. | ||
2753 | * | ||
2754 | * @param cls closure, an open writable file handle | ||
2755 | * @param key the key the daemon was stored under | ||
2756 | * @param value the GNUNET_TESTING_Daemon that needs to be written. | ||
2757 | * | ||
2758 | * @return GNUNET_YES to continue iteration | ||
2759 | * | ||
2760 | * TODO: Could replace friend_file_iterator and blacklist_file_iterator | ||
2761 | * with a single file_iterator that takes a closure which contains | ||
2762 | * the prefix to write before the peer. Then this could be used | ||
2763 | * for blacklisting multiple transports and writing the friend | ||
2764 | * file. I'm sure *someone* will complain loudly about other | ||
2765 | * things that negate these functions even existing so no point in | ||
2766 | * "fixing" now. | ||
2767 | */ | ||
2768 | static int | ||
2769 | friend_file_iterator (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
2770 | { | ||
2771 | FILE *temp_friend_handle = cls; | ||
2772 | struct GNUNET_TESTING_Daemon *peer = value; | ||
2773 | struct GNUNET_PeerIdentity *temppeer; | ||
2774 | struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc; | ||
2775 | |||
2776 | temppeer = &peer->id; | ||
2777 | GNUNET_CRYPTO_hash_to_enc (&temppeer->hashPubKey, &peer_enc); | ||
2778 | FPRINTF (temp_friend_handle, "%s\n", (char *) &peer_enc); | ||
2779 | |||
2780 | return GNUNET_YES; | ||
2781 | } | ||
2782 | |||
2783 | struct BlacklistContext | ||
2784 | { | ||
2785 | /* | ||
2786 | * The (open) file handle to write to | ||
2787 | */ | ||
2788 | FILE *temp_file_handle; | ||
2789 | |||
2790 | /* | ||
2791 | * The transport that this peer will be blacklisted on. | ||
2792 | */ | ||
2793 | char *transport; | ||
2794 | }; | ||
2795 | |||
2796 | /** | ||
2797 | * Iterator for writing blacklist data to appropriate files. | ||
2798 | * | ||
2799 | * @param cls closure, an open writable file handle | ||
2800 | * @param key the key the daemon was stored under | ||
2801 | * @param value the GNUNET_TESTING_Daemon that needs to be written. | ||
2802 | * | ||
2803 | * @return GNUNET_YES to continue iteration | ||
2804 | */ | ||
2805 | static int | ||
2806 | blacklist_file_iterator (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
2807 | { | ||
2808 | struct BlacklistContext *blacklist_ctx = cls; | ||
2809 | struct GNUNET_TESTING_Daemon *peer = value; | ||
2810 | struct GNUNET_PeerIdentity *temppeer; | ||
2811 | struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc; | ||
2812 | |||
2813 | temppeer = &peer->id; | ||
2814 | GNUNET_CRYPTO_hash_to_enc (&temppeer->hashPubKey, &peer_enc); | ||
2815 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing entry %s:%s to file\n", | ||
2816 | blacklist_ctx->transport, (char *) &peer_enc); | ||
2817 | FPRINTF (blacklist_ctx->temp_file_handle, "%s:%s\n", blacklist_ctx->transport, | ||
2818 | (char *) &peer_enc); | ||
2819 | |||
2820 | return GNUNET_YES; | ||
2821 | } | ||
2822 | #endif | ||
2823 | |||
2824 | /* | ||
2825 | * Create the friend files based on the PeerConnection's | ||
2826 | * of each peer in the peer group, and copy the files | ||
2827 | * to the appropriate place | ||
2828 | * | ||
2829 | * @param pg the peer group we are dealing with | ||
2830 | */ | ||
2831 | static int | ||
2832 | create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg) | ||
2833 | { | ||
2834 | FILE *temp_friend_handle; | ||
2835 | unsigned int pg_iter; | ||
2836 | char *temp_service_path; | ||
2837 | struct GNUNET_OS_Process **procarr; | ||
2838 | char *arg; | ||
2839 | char *mytemp; | ||
2840 | |||
2841 | #if NOT_STUPID | ||
2842 | enum GNUNET_OS_ProcessStatusType type; | ||
2843 | unsigned long return_code; | ||
2844 | int count; | ||
2845 | int max_wait = 10; | ||
2846 | #endif | ||
2847 | int ret; | ||
2848 | |||
2849 | ret = GNUNET_OK; | ||
2850 | #if OLD | ||
2851 | struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc; | ||
2852 | struct PeerConnection *conn_iter; | ||
2853 | #endif | ||
2854 | procarr = GNUNET_malloc (sizeof (struct GNUNET_OS_Process *) * pg->total); | ||
2855 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
2856 | { | ||
2857 | mytemp = GNUNET_DISK_mktemp ("friends"); | ||
2858 | GNUNET_assert (mytemp != NULL); | ||
2859 | temp_friend_handle = FOPEN (mytemp, "wt"); | ||
2860 | GNUNET_assert (temp_friend_handle != NULL); | ||
2861 | #if OLD | ||
2862 | conn_iter = pg->peers[pg_iter].allowed_peers_head; | ||
2863 | while (conn_iter != NULL) | ||
2864 | { | ||
2865 | GNUNET_CRYPTO_hash_to_enc (&pg->peers[conn_iter->index].daemon-> | ||
2866 | id.hashPubKey, &peer_enc); | ||
2867 | FPRINTF (temp_friend_handle, "%s\n", (char *) &peer_enc); | ||
2868 | conn_iter = conn_iter->next; | ||
2869 | } | ||
2870 | #else | ||
2871 | GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].allowed_peers, | ||
2872 | &friend_file_iterator, | ||
2873 | temp_friend_handle); | ||
2874 | #endif | ||
2875 | FCLOSE (temp_friend_handle); | ||
2876 | |||
2877 | if (GNUNET_OK != | ||
2878 | GNUNET_CONFIGURATION_get_value_string (pg->peers[pg_iter].daemon->cfg, | ||
2879 | "PATHS", "SERVICEHOME", | ||
2880 | &temp_service_path)) | ||
2881 | { | ||
2882 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2883 | _ | ||
2884 | ("No `%s' specified in peer configuration in section `%s', cannot copy friends file!\n"), | ||
2885 | "SERVICEHOME", "PATHS"); | ||
2886 | if (UNLINK (mytemp) != 0) | ||
2887 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", mytemp); | ||
2888 | GNUNET_free (mytemp); | ||
2889 | break; | ||
2890 | } | ||
2891 | |||
2892 | if (pg->peers[pg_iter].daemon->hostname == NULL) /* Local, just copy the file */ | ||
2893 | { | ||
2894 | GNUNET_asprintf (&arg, "%s/friends", temp_service_path); | ||
2895 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2896 | "Copying file with RENAME(%s,%s)\n", mytemp, arg); | ||
2897 | RENAME (mytemp, arg); | ||
2898 | procarr[pg_iter] = NULL; | ||
2899 | GNUNET_free (arg); | ||
2900 | } | ||
2901 | else /* Remote, scp the file to the correct place */ | ||
2902 | { | ||
2903 | if (NULL != pg->peers[pg_iter].daemon->username) | ||
2904 | GNUNET_asprintf (&arg, "%s@%s:%s/friends", | ||
2905 | pg->peers[pg_iter].daemon->username, | ||
2906 | pg->peers[pg_iter].daemon->hostname, | ||
2907 | temp_service_path); | ||
2908 | else | ||
2909 | GNUNET_asprintf (&arg, "%s:%s/friends", | ||
2910 | pg->peers[pg_iter].daemon->hostname, | ||
2911 | temp_service_path); | ||
2912 | procarr[pg_iter] = | ||
2913 | GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "scp", "scp", mytemp, arg, NULL); | ||
2914 | GNUNET_assert (procarr[pg_iter] != NULL); | ||
2915 | ret = GNUNET_OS_process_wait (procarr[pg_iter]); /* FIXME: schedule this, throttle! */ | ||
2916 | GNUNET_OS_process_destroy (procarr[pg_iter]); | ||
2917 | if (ret != GNUNET_OK) | ||
2918 | { | ||
2919 | /* FIXME: free contents of 'procarr' array */ | ||
2920 | GNUNET_free (procarr); | ||
2921 | GNUNET_free (temp_service_path); | ||
2922 | GNUNET_free (mytemp); | ||
2923 | GNUNET_free (arg); | ||
2924 | return ret; | ||
2925 | } | ||
2926 | procarr[pg_iter] = NULL; | ||
2927 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2928 | "Copying file with command scp %s %s\n", mytemp, arg); | ||
2929 | GNUNET_free (arg); | ||
2930 | } | ||
2931 | GNUNET_free (temp_service_path); | ||
2932 | GNUNET_free (mytemp); | ||
2933 | } | ||
2934 | |||
2935 | #if NOT_STUPID | ||
2936 | count = 0; | ||
2937 | ret = GNUNET_SYSERR; | ||
2938 | while ((count < max_wait) && (ret != GNUNET_OK)) | ||
2939 | { | ||
2940 | ret = GNUNET_OK; | ||
2941 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
2942 | { | ||
2943 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking copy status of file %d\n", | ||
2944 | pg_iter); | ||
2945 | if (procarr[pg_iter] != NULL) /* Check for already completed! */ | ||
2946 | { | ||
2947 | if (GNUNET_OS_process_status (procarr[pg_iter], &type, &return_code) != | ||
2948 | GNUNET_OK) | ||
2949 | { | ||
2950 | ret = GNUNET_SYSERR; | ||
2951 | } | ||
2952 | else if ((type != GNUNET_OS_PROCESS_EXITED) || (return_code != 0)) | ||
2953 | { | ||
2954 | ret = GNUNET_SYSERR; | ||
2955 | } | ||
2956 | else | ||
2957 | { | ||
2958 | GNUNET_OS_process_destroy (procarr[pg_iter]); | ||
2959 | procarr[pg_iter] = NULL; | ||
2960 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "File %d copied\n", pg_iter); | ||
2961 | } | ||
2962 | } | ||
2963 | } | ||
2964 | count++; | ||
2965 | if (ret == GNUNET_SYSERR) | ||
2966 | { | ||
2967 | /* FIXME: why sleep here? -CG */ | ||
2968 | sleep (1); | ||
2969 | } | ||
2970 | } | ||
2971 | |||
2972 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2973 | "Finished copying all friend files!\n"); | ||
2974 | #endif | ||
2975 | GNUNET_free (procarr); | ||
2976 | return ret; | ||
2977 | } | ||
2978 | |||
2979 | /* | ||
2980 | * Create the blacklist files based on the PeerConnection's | ||
2981 | * of each peer in the peer group, and copy the files | ||
2982 | * to the appropriate place. | ||
2983 | * | ||
2984 | * @param pg the peer group we are dealing with | ||
2985 | * @param transports space delimited list of transports to blacklist | ||
2986 | */ | ||
2987 | static int | ||
2988 | create_and_copy_blacklist_files (struct GNUNET_TESTING_PeerGroup *pg, | ||
2989 | const char *transports) | ||
2990 | { | ||
2991 | FILE *temp_file_handle; | ||
2992 | unsigned int pg_iter; | ||
2993 | char *temp_service_path; | ||
2994 | struct GNUNET_OS_Process **procarr; | ||
2995 | char *arg; | ||
2996 | char *mytemp; | ||
2997 | enum GNUNET_OS_ProcessStatusType type; | ||
2998 | unsigned long return_code; | ||
2999 | int count; | ||
3000 | int ret; | ||
3001 | int max_wait = 10; | ||
3002 | int transport_len; | ||
3003 | unsigned int i; | ||
3004 | char *pos; | ||
3005 | char *temp_transports; | ||
3006 | |||
3007 | #if OLD | ||
3008 | struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc; | ||
3009 | struct PeerConnection *conn_iter; | ||
3010 | #else | ||
3011 | static struct BlacklistContext blacklist_ctx; | ||
3012 | #endif | ||
3013 | |||
3014 | procarr = GNUNET_malloc (sizeof (struct GNUNET_OS_Process *) * pg->total); | ||
3015 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
3016 | { | ||
3017 | mytemp = GNUNET_DISK_mktemp ("blacklist"); | ||
3018 | GNUNET_assert (mytemp != NULL); | ||
3019 | temp_file_handle = FOPEN (mytemp, "wt"); | ||
3020 | GNUNET_assert (temp_file_handle != NULL); | ||
3021 | temp_transports = GNUNET_strdup (transports); | ||
3022 | #if !OLD | ||
3023 | blacklist_ctx.temp_file_handle = temp_file_handle; | ||
3024 | #endif | ||
3025 | transport_len = strlen (temp_transports) + 1; | ||
3026 | pos = NULL; | ||
3027 | |||
3028 | for (i = 0; i < transport_len; i++) | ||
3029 | { | ||
3030 | if ((temp_transports[i] == ' ') && (pos == NULL)) | ||
3031 | continue; /* At start of string (whitespace) */ | ||
3032 | else if ((temp_transports[i] == ' ') || (temp_transports[i] == '\0')) /* At end of string */ | ||
3033 | { | ||
3034 | temp_transports[i] = '\0'; | ||
3035 | #if OLD | ||
3036 | conn_iter = pg->peers[pg_iter].blacklisted_peers_head; | ||
3037 | while (conn_iter != NULL) | ||
3038 | { | ||
3039 | GNUNET_CRYPTO_hash_to_enc (&pg->peers[conn_iter->index].daemon-> | ||
3040 | id.hashPubKey, &peer_enc); | ||
3041 | FPRINTF (temp_file_handle, "%s:%s\n", pos, (char *) &peer_enc); | ||
3042 | conn_iter = conn_iter->next; | ||
3043 | } | ||
3044 | #else | ||
3045 | blacklist_ctx.transport = pos; | ||
3046 | (void) GNUNET_CONTAINER_multihashmap_iterate (pg-> | ||
3047 | peers | ||
3048 | [pg_iter].blacklisted_peers, | ||
3049 | &blacklist_file_iterator, | ||
3050 | &blacklist_ctx); | ||
3051 | #endif | ||
3052 | pos = NULL; | ||
3053 | } /* At beginning of actual string */ | ||
3054 | else if (pos == NULL) | ||
3055 | { | ||
3056 | pos = &temp_transports[i]; | ||
3057 | } | ||
3058 | } | ||
3059 | |||
3060 | GNUNET_free (temp_transports); | ||
3061 | FCLOSE (temp_file_handle); | ||
3062 | |||
3063 | if (GNUNET_OK != | ||
3064 | GNUNET_CONFIGURATION_get_value_string (pg->peers[pg_iter].daemon->cfg, | ||
3065 | "PATHS", "SERVICEHOME", | ||
3066 | &temp_service_path)) | ||
3067 | { | ||
3068 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
3069 | _ | ||
3070 | ("No `%s' specified in peer configuration in section `%s', cannot copy friends file!\n"), | ||
3071 | "SERVICEHOME", "PATHS"); | ||
3072 | if (UNLINK (mytemp) != 0) | ||
3073 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", mytemp); | ||
3074 | GNUNET_free (mytemp); | ||
3075 | break; | ||
3076 | } | ||
3077 | |||
3078 | if (pg->peers[pg_iter].daemon->hostname == NULL) /* Local, just copy the file */ | ||
3079 | { | ||
3080 | GNUNET_asprintf (&arg, "%s/blacklist", temp_service_path); | ||
3081 | RENAME (mytemp, arg); | ||
3082 | procarr[pg_iter] = NULL; | ||
3083 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3084 | "Copying file with RENAME (%s,%s)\n", mytemp, arg); | ||
3085 | GNUNET_free (arg); | ||
3086 | } | ||
3087 | else /* Remote, scp the file to the correct place */ | ||
3088 | { | ||
3089 | if (NULL != pg->peers[pg_iter].daemon->username) | ||
3090 | GNUNET_asprintf (&arg, "%s@%s:%s/blacklist", | ||
3091 | pg->peers[pg_iter].daemon->username, | ||
3092 | pg->peers[pg_iter].daemon->hostname, | ||
3093 | temp_service_path); | ||
3094 | else | ||
3095 | GNUNET_asprintf (&arg, "%s:%s/blacklist", | ||
3096 | pg->peers[pg_iter].daemon->hostname, | ||
3097 | temp_service_path); | ||
3098 | procarr[pg_iter] = | ||
3099 | GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "scp", "scp", mytemp, arg, NULL); | ||
3100 | GNUNET_assert (procarr[pg_iter] != NULL); | ||
3101 | GNUNET_OS_process_wait (procarr[pg_iter]); /* FIXME: add scheduled blacklist file copy that parallelizes file copying! */ | ||
3102 | |||
3103 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3104 | "Copying file with command scp %s %s\n", mytemp, arg); | ||
3105 | GNUNET_free (arg); | ||
3106 | } | ||
3107 | GNUNET_free (temp_service_path); | ||
3108 | GNUNET_free (mytemp); | ||
3109 | } | ||
3110 | |||
3111 | count = 0; | ||
3112 | ret = GNUNET_SYSERR; | ||
3113 | while ((count < max_wait) && (ret != GNUNET_OK)) | ||
3114 | { | ||
3115 | ret = GNUNET_OK; | ||
3116 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
3117 | { | ||
3118 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3119 | "Checking copy status of file %d\n", pg_iter); | ||
3120 | if (procarr[pg_iter] != NULL) /* Check for already completed! */ | ||
3121 | { | ||
3122 | if (GNUNET_OS_process_status (procarr[pg_iter], &type, &return_code) != | ||
3123 | GNUNET_OK) | ||
3124 | { | ||
3125 | ret = GNUNET_SYSERR; | ||
3126 | } | ||
3127 | else if ((type != GNUNET_OS_PROCESS_EXITED) || (return_code != 0)) | ||
3128 | { | ||
3129 | ret = GNUNET_SYSERR; | ||
3130 | } | ||
3131 | else | ||
3132 | { | ||
3133 | GNUNET_OS_process_destroy (procarr[pg_iter]); | ||
3134 | procarr[pg_iter] = NULL; | ||
3135 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "File %d copied\n", pg_iter); | ||
3136 | } | ||
3137 | } | ||
3138 | } | ||
3139 | count++; | ||
3140 | if (ret == GNUNET_SYSERR) | ||
3141 | { | ||
3142 | /* FIXME: why sleep here? -CG */ | ||
3143 | sleep (1); | ||
3144 | } | ||
3145 | } | ||
3146 | |||
3147 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3148 | "Finished copying all blacklist files!\n"); | ||
3149 | GNUNET_free (procarr); | ||
3150 | return ret; | ||
3151 | } | ||
3152 | |||
3153 | /* Forward Declaration */ | ||
3154 | static void | ||
3155 | schedule_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
3156 | |||
3157 | /** | ||
3158 | * Choose a random peer's next connection to create, and | ||
3159 | * call schedule_connect to set up the connect task. | ||
3160 | * | ||
3161 | * @param pg the peer group to connect | ||
3162 | */ | ||
3163 | static void | ||
3164 | preschedule_connect (struct GNUNET_TESTING_PeerGroup *pg) | ||
3165 | { | ||
3166 | struct ConnectTopologyContext *ct_ctx = &pg->ct_ctx; | ||
3167 | struct PeerConnection *connection_iter; | ||
3168 | struct ConnectContext *connect_context; | ||
3169 | uint32_t random_peer; | ||
3170 | |||
3171 | if (ct_ctx->remaining_connections == 0) | ||
3172 | return; | ||
3173 | random_peer = | ||
3174 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total); | ||
3175 | while (pg->peers[random_peer].connect_peers_head == NULL) | ||
3176 | random_peer = | ||
3177 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total); | ||
3178 | |||
3179 | connection_iter = pg->peers[random_peer].connect_peers_head; | ||
3180 | connect_context = GNUNET_malloc (sizeof (struct ConnectContext)); | ||
3181 | connect_context->first_index = random_peer; | ||
3182 | connect_context->second_index = connection_iter->index; | ||
3183 | connect_context->ct_ctx = ct_ctx; | ||
3184 | connect_context->task = | ||
3185 | GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context); | ||
3186 | GNUNET_CONTAINER_DLL_insert (pg->cc_head, pg->cc_tail, connect_context); | ||
3187 | GNUNET_CONTAINER_DLL_remove (pg->peers[random_peer].connect_peers_head, | ||
3188 | pg->peers[random_peer].connect_peers_tail, | ||
3189 | connection_iter); | ||
3190 | GNUNET_free (connection_iter); | ||
3191 | ct_ctx->remaining_connections--; | ||
3192 | } | ||
3193 | |||
3194 | #if USE_SEND_HELLOS | ||
3195 | /* Forward declaration */ | ||
3196 | static void | ||
3197 | schedule_send_hellos (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
3198 | |||
3199 | /** | ||
3200 | * Close connections and free the hello context. | ||
3201 | * | ||
3202 | * @param cls the 'struct SendHelloContext *' | ||
3203 | * @param tc scheduler context | ||
3204 | */ | ||
3205 | static void | ||
3206 | free_hello_context (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
3207 | { | ||
3208 | struct SendHelloContext *send_hello_context = cls; | ||
3209 | |||
3210 | if (send_hello_context->peer->daemon->server != NULL) | ||
3211 | { | ||
3212 | GNUNET_CORE_disconnect (send_hello_context->peer->daemon->server); | ||
3213 | send_hello_context->peer->daemon->server = NULL; | ||
3214 | } | ||
3215 | if (send_hello_context->peer->daemon->th != NULL) | ||
3216 | { | ||
3217 | GNUNET_TRANSPORT_disconnect (send_hello_context->peer->daemon->th); | ||
3218 | send_hello_context->peer->daemon->th = NULL; | ||
3219 | } | ||
3220 | if (send_hello_context->core_connect_task != GNUNET_SCHEDULER_NO_TASK) | ||
3221 | { | ||
3222 | GNUNET_SCHEDULER_cancel (send_hello_context->core_connect_task); | ||
3223 | send_hello_context->core_connect_task = GNUNET_SCHEDULER_NO_TASK; | ||
3224 | } | ||
3225 | send_hello_context->pg->outstanding_connects--; | ||
3226 | GNUNET_free (send_hello_context); | ||
3227 | } | ||
3228 | |||
3229 | /** | ||
3230 | * For peers that haven't yet connected, notify | ||
3231 | * the caller that they have failed (timeout). | ||
3232 | * | ||
3233 | * @param cls the 'struct SendHelloContext *' | ||
3234 | * @param tc scheduler context | ||
3235 | */ | ||
3236 | static void | ||
3237 | notify_remaining_connections_failed (void *cls, | ||
3238 | const struct GNUNET_SCHEDULER_TaskContext | ||
3239 | *tc) | ||
3240 | { | ||
3241 | struct SendHelloContext *send_hello_context = cls; | ||
3242 | struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg; | ||
3243 | struct PeerConnection *connection; | ||
3244 | |||
3245 | GNUNET_CORE_disconnect (send_hello_context->peer->daemon->server); | ||
3246 | send_hello_context->peer->daemon->server = NULL; | ||
3247 | |||
3248 | connection = send_hello_context->peer->connect_peers_head; | ||
3249 | |||
3250 | while (connection != NULL) | ||
3251 | { | ||
3252 | if (pg->notify_connection != NULL) | ||
3253 | { | ||
3254 | pg->notify_connection (pg->notify_connection_cls, &send_hello_context->peer->daemon->id, &pg->peers[connection->index].daemon->id, 0, /* FIXME */ | ||
3255 | send_hello_context->peer->daemon->cfg, | ||
3256 | pg->peers[connection->index].daemon->cfg, | ||
3257 | send_hello_context->peer->daemon, | ||
3258 | pg->peers[connection->index].daemon, | ||
3259 | "Peers failed to connect (timeout)"); | ||
3260 | } | ||
3261 | GNUNET_CONTAINER_DLL_remove (send_hello_context->peer->connect_peers_head, | ||
3262 | send_hello_context->peer->connect_peers_tail, | ||
3263 | connection); | ||
3264 | GNUNET_free (connection); | ||
3265 | connection = connection->next; | ||
3266 | } | ||
3267 | GNUNET_SCHEDULER_add_now (&free_hello_context, send_hello_context); | ||
3268 | #if BAD | ||
3269 | other_peer = &pg->peers[connection->index]; | ||
3270 | #endif | ||
3271 | } | ||
3272 | |||
3273 | /** | ||
3274 | * For peers that haven't yet connected, send | ||
3275 | * CORE connect requests. | ||
3276 | * | ||
3277 | * @param cls the 'struct SendHelloContext *' | ||
3278 | * @param tc scheduler context | ||
3279 | */ | ||
3280 | static void | ||
3281 | send_core_connect_requests (void *cls, | ||
3282 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
3283 | { | ||
3284 | struct SendHelloContext *send_hello_context = cls; | ||
3285 | struct PeerConnection *conn; | ||
3286 | |||
3287 | GNUNET_assert (send_hello_context->peer->daemon->server != NULL); | ||
3288 | |||
3289 | send_hello_context->core_connect_task = GNUNET_SCHEDULER_NO_TASK; | ||
3290 | |||
3291 | send_hello_context->connect_attempts++; | ||
3292 | if (send_hello_context->connect_attempts < | ||
3293 | send_hello_context->pg->ct_ctx.connect_attempts) | ||
3294 | { | ||
3295 | conn = send_hello_context->peer->connect_peers_head; | ||
3296 | while (conn != NULL) | ||
3297 | { | ||
3298 | GNUNET_TRANSPORT_try_connect (send_hello_context->peer->daemon->th, | ||
3299 | &send_hello_context->pg->peers[conn-> | ||
3300 | index].daemon-> | ||
3301 | id); | ||
3302 | conn = conn->next; | ||
3303 | } | ||
3304 | send_hello_context->core_connect_task = | ||
3305 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide | ||
3306 | (send_hello_context->pg-> | ||
3307 | ct_ctx.connect_timeout, | ||
3308 | send_hello_context->pg-> | ||
3309 | ct_ctx.connect_attempts), | ||
3310 | &send_core_connect_requests, | ||
3311 | send_hello_context); | ||
3312 | } | ||
3313 | else | ||
3314 | { | ||
3315 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
3316 | "Timeout before all connections created, marking rest as failed!\n"); | ||
3317 | GNUNET_SCHEDULER_add_now (¬ify_remaining_connections_failed, | ||
3318 | send_hello_context); | ||
3319 | } | ||
3320 | |||
3321 | } | ||
3322 | |||
3323 | /** | ||
3324 | * Success, connection is up. Signal client our success. | ||
3325 | * | ||
3326 | * @param cls our "struct SendHelloContext" | ||
3327 | * @param peer identity of the peer that has connected | ||
3328 | * @param atsi performance information | ||
3329 | * | ||
3330 | * FIXME: remove peers from BOTH lists, call notify twice, should | ||
3331 | * double the speed of connections as long as the list iteration | ||
3332 | * doesn't take too long! | ||
3333 | */ | ||
3334 | static void | ||
3335 | core_connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
3336 | const struct GNUNET_ATS_Information *atsi) | ||
3337 | { | ||
3338 | struct SendHelloContext *send_hello_context = cls; | ||
3339 | struct PeerConnection *connection; | ||
3340 | struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg; | ||
3341 | |||
3342 | #if BAD | ||
3343 | struct PeerData *other_peer; | ||
3344 | #endif | ||
3345 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected peer %s to peer %s\n", | ||
3346 | ctx->d1->shortname, GNUNET_i2s (peer)); | ||
3347 | if (0 == | ||
3348 | memcmp (&send_hello_context->peer->daemon->id, peer, | ||
3349 | sizeof (struct GNUNET_PeerIdentity))) | ||
3350 | return; | ||
3351 | |||
3352 | connection = send_hello_context->peer->connect_peers_head; | ||
3353 | #if BAD | ||
3354 | other_peer = NULL; | ||
3355 | #endif | ||
3356 | |||
3357 | while ((connection != NULL) && | ||
3358 | (0 != | ||
3359 | memcmp (&pg->peers[connection->index].daemon->id, peer, | ||
3360 | sizeof (struct GNUNET_PeerIdentity)))) | ||
3361 | { | ||
3362 | connection = connection->next; | ||
3363 | } | ||
3364 | |||
3365 | if (connection == NULL) | ||
3366 | { | ||
3367 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3368 | "Connected peer %s to %s, not in list (no problem(?))\n", | ||
3369 | GNUNET_i2s (peer), send_hello_context->peer->daemon->shortname); | ||
3370 | } | ||
3371 | else | ||
3372 | { | ||
3373 | #if BAD | ||
3374 | other_peer = &pg->peers[connection->index]; | ||
3375 | #endif | ||
3376 | if (pg->notify_connection != NULL) | ||
3377 | { | ||
3378 | pg->notify_connection (pg->notify_connection_cls, &send_hello_context->peer->daemon->id, peer, 0, /* FIXME */ | ||
3379 | send_hello_context->peer->daemon->cfg, | ||
3380 | pg->peers[connection->index].daemon->cfg, | ||
3381 | send_hello_context->peer->daemon, | ||
3382 | pg->peers[connection->index].daemon, NULL); | ||
3383 | } | ||
3384 | GNUNET_CONTAINER_DLL_remove (send_hello_context->peer->connect_peers_head, | ||
3385 | send_hello_context->peer->connect_peers_tail, | ||
3386 | connection); | ||
3387 | GNUNET_free (connection); | ||
3388 | } | ||
3389 | |||
3390 | #if BAD | ||
3391 | /* Notify of reverse connection and remove from other peers list of outstanding */ | ||
3392 | if (other_peer != NULL) | ||
3393 | { | ||
3394 | connection = other_peer->connect_peers_head; | ||
3395 | while ((connection != NULL) && | ||
3396 | (0 != | ||
3397 | memcmp (&send_hello_context->peer->daemon->id, | ||
3398 | &pg->peers[connection->index].daemon->id, | ||
3399 | sizeof (struct GNUNET_PeerIdentity)))) | ||
3400 | { | ||
3401 | connection = connection->next; | ||
3402 | } | ||
3403 | if (connection != NULL) | ||
3404 | { | ||
3405 | if (pg->notify_connection != NULL) | ||
3406 | { | ||
3407 | pg->notify_connection (pg->notify_connection_cls, peer, &send_hello_context->peer->daemon->id, 0, /* FIXME */ | ||
3408 | pg->peers[connection->index].daemon->cfg, | ||
3409 | send_hello_context->peer->daemon->cfg, | ||
3410 | pg->peers[connection->index].daemon, | ||
3411 | send_hello_context->peer->daemon, NULL); | ||
3412 | } | ||
3413 | |||
3414 | GNUNET_CONTAINER_DLL_remove (other_peer->connect_peers_head, | ||
3415 | other_peer->connect_peers_tail, connection); | ||
3416 | GNUNET_free (connection); | ||
3417 | } | ||
3418 | } | ||
3419 | #endif | ||
3420 | |||
3421 | if (send_hello_context->peer->connect_peers_head == NULL) | ||
3422 | { | ||
3423 | GNUNET_SCHEDULER_add_now (&free_hello_context, send_hello_context); | ||
3424 | } | ||
3425 | } | ||
3426 | |||
3427 | /** | ||
3428 | * Notify of a successful connection to the core service. | ||
3429 | * | ||
3430 | * @param cls a struct SendHelloContext * | ||
3431 | * @param server handle to the core service | ||
3432 | * @param my_identity the peer identity of this peer | ||
3433 | */ | ||
3434 | void | ||
3435 | core_init (void *cls, struct GNUNET_CORE_Handle *server, | ||
3436 | struct GNUNET_PeerIdentity *my_identity) | ||
3437 | { | ||
3438 | struct SendHelloContext *send_hello_context = cls; | ||
3439 | |||
3440 | send_hello_context->core_ready = GNUNET_YES; | ||
3441 | } | ||
3442 | |||
3443 | /** | ||
3444 | * Function called once a hello has been sent | ||
3445 | * to the transport, move on to the next one | ||
3446 | * or go away forever. | ||
3447 | * | ||
3448 | * @param cls the 'struct SendHelloContext *' | ||
3449 | * @param tc scheduler context | ||
3450 | */ | ||
3451 | static void | ||
3452 | hello_sent_callback (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
3453 | { | ||
3454 | struct SendHelloContext *send_hello_context = cls; | ||
3455 | |||
3456 | //unsigned int pg_iter; | ||
3457 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
3458 | { | ||
3459 | GNUNET_free (send_hello_context); | ||
3460 | return; | ||
3461 | } | ||
3462 | |||
3463 | send_hello_context->pg->remaining_hellos--; | ||
3464 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent HELLO, have %d remaining!\n", | ||
3465 | send_hello_context->pg->remaining_hellos); | ||
3466 | if (send_hello_context->peer_pos == NULL) /* All HELLOs (for this peer!) have been transmitted! */ | ||
3467 | { | ||
3468 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3469 | "All hellos for this peer sent, disconnecting transport!\n"); | ||
3470 | GNUNET_assert (send_hello_context->peer->daemon->th != NULL); | ||
3471 | GNUNET_TRANSPORT_disconnect (send_hello_context->peer->daemon->th); | ||
3472 | send_hello_context->peer->daemon->th = NULL; | ||
3473 | GNUNET_assert (send_hello_context->peer->daemon->server == NULL); | ||
3474 | send_hello_context->peer->daemon->server = | ||
3475 | GNUNET_CORE_connect (send_hello_context->peer->cfg, 1, | ||
3476 | send_hello_context, &core_init, | ||
3477 | &core_connect_notify, NULL, NULL, NULL, GNUNET_NO, | ||
3478 | NULL, GNUNET_NO, no_handlers); | ||
3479 | |||
3480 | send_hello_context->core_connect_task = | ||
3481 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide | ||
3482 | (send_hello_context->pg-> | ||
3483 | ct_ctx.connect_timeout, | ||
3484 | send_hello_context->pg-> | ||
3485 | ct_ctx.connect_attempts), | ||
3486 | &send_core_connect_requests, | ||
3487 | send_hello_context); | ||
3488 | } | ||
3489 | else | ||
3490 | GNUNET_SCHEDULER_add_now (&schedule_send_hellos, send_hello_context); | ||
3491 | } | ||
3492 | |||
3493 | /** | ||
3494 | * Connect to a peer, give it all the HELLO's of those peers | ||
3495 | * we will later ask it to connect to. | ||
3496 | * | ||
3497 | * @param ct_ctx the overall connection context | ||
3498 | */ | ||
3499 | static void | ||
3500 | schedule_send_hellos (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
3501 | { | ||
3502 | struct SendHelloContext *send_hello_context = cls; | ||
3503 | struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg; | ||
3504 | |||
3505 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
3506 | { | ||
3507 | GNUNET_free (send_hello_context); | ||
3508 | return; | ||
3509 | } | ||
3510 | |||
3511 | GNUNET_assert (send_hello_context->peer_pos != NULL); /* All of the HELLO sends to be scheduled have been scheduled! */ | ||
3512 | |||
3513 | if (((send_hello_context->peer->daemon->th == NULL) && | ||
3514 | (pg->outstanding_connects > pg->max_outstanding_connections)) || | ||
3515 | (pg->stop_connects == GNUNET_YES)) | ||
3516 | { | ||
3517 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3518 | "Delaying connect, we have too many outstanding connections!\n"); | ||
3519 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
3520 | (GNUNET_TIME_UNIT_MILLISECONDS, 100), | ||
3521 | &schedule_send_hellos, send_hello_context); | ||
3522 | } | ||
3523 | else | ||
3524 | { | ||
3525 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3526 | "Creating connection, outstanding_connections is %d\n", | ||
3527 | outstanding_connects); | ||
3528 | if (send_hello_context->peer->daemon->th == NULL) | ||
3529 | { | ||
3530 | pg->outstanding_connects++; /* Actual TRANSPORT, CORE connections! */ | ||
3531 | send_hello_context->peer->daemon->th = | ||
3532 | GNUNET_TRANSPORT_connect (send_hello_context->peer->cfg, NULL, | ||
3533 | send_hello_context, NULL, NULL, NULL); | ||
3534 | } | ||
3535 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3536 | "Offering HELLO of peer %s to peer %s\n", | ||
3537 | send_hello_context->peer->daemon->shortname, | ||
3538 | pg->peers[send_hello_context->peer_pos->index]. | ||
3539 | daemon->shortname); | ||
3540 | GNUNET_TRANSPORT_offer_hello (send_hello_context->peer->daemon->th, | ||
3541 | (const struct GNUNET_MessageHeader *) | ||
3542 | pg->peers[send_hello_context->peer_pos-> | ||
3543 | index].daemon->hello, | ||
3544 | &hello_sent_callback, send_hello_context); | ||
3545 | send_hello_context->peer_pos = send_hello_context->peer_pos->next; | ||
3546 | GNUNET_assert (send_hello_context->peer->daemon->th != NULL); | ||
3547 | } | ||
3548 | } | ||
3549 | #endif | ||
3550 | |||
3551 | /** | ||
3552 | * Internal notification of a connection, kept so that we can ensure some connections | ||
3553 | * happen instead of flooding all testing daemons with requests to connect. | ||
3554 | */ | ||
3555 | static void | ||
3556 | internal_connect_notify (void *cls, const struct GNUNET_PeerIdentity *first, | ||
3557 | const struct GNUNET_PeerIdentity *second, | ||
3558 | uint32_t distance, | ||
3559 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
3560 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
3561 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
3562 | struct GNUNET_TESTING_Daemon *second_daemon, | ||
3563 | const char *emsg) | ||
3564 | { | ||
3565 | struct ConnectContext *connect_ctx = cls; | ||
3566 | struct ConnectTopologyContext *ct_ctx = connect_ctx->ct_ctx; | ||
3567 | struct GNUNET_TESTING_PeerGroup *pg = ct_ctx->pg; | ||
3568 | struct PeerConnection *connection; | ||
3569 | |||
3570 | GNUNET_assert (NULL != connect_ctx->cc); | ||
3571 | connect_ctx->cc = NULL; | ||
3572 | GNUNET_assert (0 < pg->outstanding_connects); | ||
3573 | pg->outstanding_connects--; | ||
3574 | GNUNET_CONTAINER_DLL_remove (pg->cc_head, pg->cc_tail, connect_ctx); | ||
3575 | /* | ||
3576 | * Check whether the inverse connection has been scheduled yet, | ||
3577 | * if not, we can remove it from the other peers list and avoid | ||
3578 | * even trying to connect them again! | ||
3579 | */ | ||
3580 | connection = pg->peers[connect_ctx->second_index].connect_peers_head; | ||
3581 | #if BAD | ||
3582 | other_peer = NULL; | ||
3583 | #endif | ||
3584 | |||
3585 | while ((connection != NULL) && | ||
3586 | (0 != | ||
3587 | memcmp (first, &pg->peers[connection->index].daemon->id, | ||
3588 | sizeof (struct GNUNET_PeerIdentity)))) | ||
3589 | connection = connection->next; | ||
3590 | |||
3591 | if (connection != NULL) /* Can safely remove! */ | ||
3592 | { | ||
3593 | GNUNET_assert (0 < ct_ctx->remaining_connections); | ||
3594 | ct_ctx->remaining_connections--; | ||
3595 | if (pg->notify_connection != NULL) /* Notify of reverse connection */ | ||
3596 | pg->notify_connection (pg->notify_connection_cls, second, first, distance, | ||
3597 | second_cfg, first_cfg, second_daemon, first_daemon, | ||
3598 | emsg); | ||
3599 | |||
3600 | GNUNET_CONTAINER_DLL_remove (pg-> | ||
3601 | peers[connect_ctx-> | ||
3602 | second_index].connect_peers_head, | ||
3603 | pg->peers[connect_ctx-> | ||
3604 | second_index].connect_peers_tail, | ||
3605 | connection); | ||
3606 | GNUNET_free (connection); | ||
3607 | } | ||
3608 | |||
3609 | if (ct_ctx->remaining_connections == 0) | ||
3610 | { | ||
3611 | if (ct_ctx->notify_connections_done != NULL) | ||
3612 | { | ||
3613 | ct_ctx->notify_connections_done (ct_ctx->notify_cls, NULL); | ||
3614 | ct_ctx->notify_connections_done = NULL; | ||
3615 | } | ||
3616 | } | ||
3617 | else | ||
3618 | preschedule_connect (pg); | ||
3619 | |||
3620 | if (pg->notify_connection != NULL) | ||
3621 | pg->notify_connection (pg->notify_connection_cls, first, second, distance, | ||
3622 | first_cfg, second_cfg, first_daemon, second_daemon, | ||
3623 | emsg); | ||
3624 | GNUNET_free (connect_ctx); | ||
3625 | } | ||
3626 | |||
3627 | /** | ||
3628 | * Either delay a connection (because there are too many outstanding) | ||
3629 | * or schedule it for right now. | ||
3630 | * | ||
3631 | * @param cls a connection context | ||
3632 | * @param tc the task runtime context | ||
3633 | */ | ||
3634 | static void | ||
3635 | schedule_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
3636 | { | ||
3637 | struct ConnectContext *connect_context = cls; | ||
3638 | struct GNUNET_TESTING_PeerGroup *pg = connect_context->ct_ctx->pg; | ||
3639 | |||
3640 | connect_context->task = GNUNET_SCHEDULER_NO_TASK; | ||
3641 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
3642 | return; | ||
3643 | |||
3644 | if ((pg->outstanding_connects > pg->max_outstanding_connections) || | ||
3645 | (pg->stop_connects == GNUNET_YES)) | ||
3646 | { | ||
3647 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3648 | "Delaying connect, we have too many outstanding connections!\n"); | ||
3649 | connect_context->task = | ||
3650 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
3651 | (GNUNET_TIME_UNIT_MILLISECONDS, 100), | ||
3652 | &schedule_connect, connect_context); | ||
3653 | return; | ||
3654 | } | ||
3655 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3656 | "Creating connection, outstanding_connections is %d (max %d)\n", | ||
3657 | pg->outstanding_connects, pg->max_outstanding_connections); | ||
3658 | pg->outstanding_connects++; | ||
3659 | pg->total_connects_scheduled++; | ||
3660 | GNUNET_assert (NULL == connect_context->cc); | ||
3661 | connect_context->cc = | ||
3662 | GNUNET_TESTING_daemons_connect (pg-> | ||
3663 | peers[connect_context-> | ||
3664 | first_index].daemon, | ||
3665 | pg->peers[connect_context-> | ||
3666 | second_index].daemon, | ||
3667 | connect_context->ct_ctx->connect_timeout, | ||
3668 | connect_context->ct_ctx->connect_attempts, | ||
3669 | #if USE_SEND_HELLOS | ||
3670 | GNUNET_NO, | ||
3671 | #else | ||
3672 | GNUNET_YES, | ||
3673 | #endif | ||
3674 | &internal_connect_notify, | ||
3675 | connect_context); | ||
3676 | |||
3677 | } | ||
3678 | |||
3679 | #if !OLD | ||
3680 | /** | ||
3681 | * Iterator for actually scheduling connections to be created | ||
3682 | * between two peers. | ||
3683 | * | ||
3684 | * @param cls closure, a GNUNET_TESTING_Daemon | ||
3685 | * @param key the key the second Daemon was stored under | ||
3686 | * @param value the GNUNET_TESTING_Daemon that the first is to connect to | ||
3687 | * | ||
3688 | * @return GNUNET_YES to continue iteration | ||
3689 | */ | ||
3690 | static int | ||
3691 | connect_iterator (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
3692 | { | ||
3693 | struct ConnectTopologyContext *ct_ctx = cls; | ||
3694 | struct PeerData *first = ct_ctx->first; | ||
3695 | struct GNUNET_TESTING_Daemon *second = value; | ||
3696 | struct ConnectContext *connect_context; | ||
3697 | |||
3698 | connect_context = GNUNET_malloc (sizeof (struct ConnectContext)); | ||
3699 | connect_context->first = first->daemon; | ||
3700 | connect_context->second = second; | ||
3701 | connect_context->ct_ctx = ct_ctx; | ||
3702 | connect_context->task = | ||
3703 | GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context); | ||
3704 | GNUNET_CONTAINER_DLL_insert (ct_ctx->pg->cc_head, ct_ctx->pg->cc_tail, | ||
3705 | connect_context); | ||
3706 | return GNUNET_YES; | ||
3707 | } | ||
3708 | #endif | ||
3709 | |||
3710 | #if !OLD | ||
3711 | /** | ||
3712 | * Iterator for copying all entries in the allowed hashmap to the | ||
3713 | * connect hashmap. | ||
3714 | * | ||
3715 | * @param cls closure, a GNUNET_TESTING_Daemon | ||
3716 | * @param key the key the second Daemon was stored under | ||
3717 | * @param value the GNUNET_TESTING_Daemon that the first is to connect to | ||
3718 | * | ||
3719 | * @return GNUNET_YES to continue iteration | ||
3720 | */ | ||
3721 | static int | ||
3722 | copy_topology_iterator (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
3723 | { | ||
3724 | struct PeerData *first = cls; | ||
3725 | |||
3726 | GNUNET_assert (GNUNET_OK == | ||
3727 | GNUNET_CONTAINER_multihashmap_put (first->connect_peers, key, | ||
3728 | value, | ||
3729 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
3730 | |||
3731 | return GNUNET_YES; | ||
3732 | } | ||
3733 | #endif | ||
3734 | |||
3735 | /** | ||
3736 | * Make the peers to connect the same as those that are allowed to be | ||
3737 | * connected. | ||
3738 | * | ||
3739 | * @param pg the peer group | ||
3740 | */ | ||
3741 | static int | ||
3742 | copy_allowed_topology (struct GNUNET_TESTING_PeerGroup *pg) | ||
3743 | { | ||
3744 | unsigned int pg_iter; | ||
3745 | int ret; | ||
3746 | int total; | ||
3747 | |||
3748 | #if OLD | ||
3749 | struct PeerConnection *iter; | ||
3750 | #endif | ||
3751 | total = 0; | ||
3752 | ret = 0; | ||
3753 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
3754 | { | ||
3755 | #if OLD | ||
3756 | iter = pg->peers[pg_iter].allowed_peers_head; | ||
3757 | while (iter != NULL) | ||
3758 | { | ||
3759 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3760 | "Creating connection between %d and %d\n", pg_iter, | ||
3761 | iter->index); | ||
3762 | total += add_connections (pg, pg_iter, iter->index, CONNECT, GNUNET_YES); | ||
3763 | //total += add_actual_connections(pg, pg_iter, iter->index); | ||
3764 | iter = iter->next; | ||
3765 | } | ||
3766 | #else | ||
3767 | ret = | ||
3768 | GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].allowed_peers, | ||
3769 | ©_topology_iterator, | ||
3770 | &pg->peers[pg_iter]); | ||
3771 | #endif | ||
3772 | if (GNUNET_SYSERR == ret) | ||
3773 | return GNUNET_SYSERR; | ||
3774 | |||
3775 | total = total + ret; | ||
3776 | } | ||
3777 | |||
3778 | return total; | ||
3779 | } | ||
3780 | |||
3781 | /** | ||
3782 | * Connect the topology as specified by the PeerConnection's | ||
3783 | * of each peer in the peer group | ||
3784 | * | ||
3785 | * @param pg the peer group we are dealing with | ||
3786 | * @param connect_timeout how long try connecting two peers | ||
3787 | * @param connect_attempts how many times (max) to attempt | ||
3788 | * @param notify_callback callback to notify when finished | ||
3789 | * @param notify_cls closure for notify callback | ||
3790 | * | ||
3791 | * @return the number of connections that will be attempted | ||
3792 | */ | ||
3793 | static int | ||
3794 | connect_topology (struct GNUNET_TESTING_PeerGroup *pg, | ||
3795 | struct GNUNET_TIME_Relative connect_timeout, | ||
3796 | unsigned int connect_attempts, | ||
3797 | GNUNET_TESTING_NotifyCompletion notify_callback, | ||
3798 | void *notify_cls) | ||
3799 | { | ||
3800 | unsigned int pg_iter; | ||
3801 | unsigned int total; | ||
3802 | |||
3803 | #if OLD | ||
3804 | struct PeerConnection *connection_iter; | ||
3805 | #endif | ||
3806 | #if USE_SEND_HELLOS | ||
3807 | struct SendHelloContext *send_hello_context; | ||
3808 | #endif | ||
3809 | |||
3810 | total = 0; | ||
3811 | pg->ct_ctx.notify_connections_done = notify_callback; | ||
3812 | pg->ct_ctx.notify_cls = notify_cls; | ||
3813 | pg->ct_ctx.pg = pg; | ||
3814 | |||
3815 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
3816 | { | ||
3817 | #if OLD | ||
3818 | connection_iter = pg->peers[pg_iter].connect_peers_head; | ||
3819 | while (connection_iter != NULL) | ||
3820 | { | ||
3821 | connection_iter = connection_iter->next; | ||
3822 | total++; | ||
3823 | } | ||
3824 | #else | ||
3825 | total += | ||
3826 | GNUNET_CONTAINER_multihashmap_size (pg->peers[pg_iter].connect_peers); | ||
3827 | #endif | ||
3828 | } | ||
3829 | |||
3830 | if (total == 0) | ||
3831 | return total; | ||
3832 | |||
3833 | pg->ct_ctx.connect_timeout = connect_timeout; | ||
3834 | pg->ct_ctx.connect_attempts = connect_attempts; | ||
3835 | pg->ct_ctx.remaining_connections = total; | ||
3836 | |||
3837 | #if USE_SEND_HELLOS | ||
3838 | /* First give all peers the HELLO's of other peers (connect to first peer's transport service, give HELLO's of other peers, continue...) */ | ||
3839 | pg->remaining_hellos = total; | ||
3840 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
3841 | { | ||
3842 | send_hello_context = GNUNET_malloc (sizeof (struct SendHelloContext)); | ||
3843 | send_hello_context->peer = &pg->peers[pg_iter]; | ||
3844 | send_hello_context->peer_pos = pg->peers[pg_iter].connect_peers_head; | ||
3845 | send_hello_context->pg = pg; | ||
3846 | GNUNET_SCHEDULER_add_now (&schedule_send_hellos, send_hello_context); | ||
3847 | } | ||
3848 | #else | ||
3849 | for (pg_iter = 0; pg_iter < pg->max_outstanding_connections; pg_iter++) | ||
3850 | { | ||
3851 | preschedule_connect (pg); | ||
3852 | } | ||
3853 | #endif | ||
3854 | return total; | ||
3855 | |||
3856 | } | ||
3857 | |||
3858 | /** | ||
3859 | * Takes a peer group and creates a topology based on the | ||
3860 | * one specified. Creates a topology means generates friend | ||
3861 | * files for the peers so they can only connect to those allowed | ||
3862 | * by the topology. This will only have an effect once peers | ||
3863 | * are started if the FRIENDS_ONLY option is set in the base | ||
3864 | * config. Also takes an optional restrict topology which | ||
3865 | * disallows connections based on particular transports | ||
3866 | * UNLESS they are specified in the restricted topology. | ||
3867 | * | ||
3868 | * @param pg the peer group struct representing the running peers | ||
3869 | * @param topology which topology to connect the peers in | ||
3870 | * @param restrict_topology disallow restrict_transports transport | ||
3871 | * connections to peers NOT in this topology | ||
3872 | * use GNUNET_TESTING_TOPOLOGY_NONE for no restrictions | ||
3873 | * @param restrict_transports space delimited list of transports to blacklist | ||
3874 | * to create restricted topology | ||
3875 | * | ||
3876 | * @return the maximum number of connections were all allowed peers | ||
3877 | * connected to each other | ||
3878 | */ | ||
3879 | unsigned int | ||
3880 | GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, | ||
3881 | enum GNUNET_TESTING_Topology topology, | ||
3882 | enum GNUNET_TESTING_Topology restrict_topology, | ||
3883 | const char *restrict_transports) | ||
3884 | { | ||
3885 | int ret; | ||
3886 | |||
3887 | unsigned int num_connections; | ||
3888 | int unblacklisted_connections; | ||
3889 | char *filename; | ||
3890 | struct PeerConnection *conn_iter; | ||
3891 | struct PeerConnection *temp_conn; | ||
3892 | unsigned int off; | ||
3893 | |||
3894 | #if !OLD | ||
3895 | unsigned int i; | ||
3896 | |||
3897 | for (i = 0; i < pg->total; i++) | ||
3898 | { | ||
3899 | pg->peers[i].allowed_peers = GNUNET_CONTAINER_multihashmap_create (100, GNUNET_NO); | ||
3900 | pg->peers[i].connect_peers = GNUNET_CONTAINER_multihashmap_create (100, GNUNET_NO); | ||
3901 | pg->peers[i].blacklisted_peers = GNUNET_CONTAINER_multihashmap_create (100, GNUNET_NO); | ||
3902 | pg->peers[i].pg = pg; | ||
3903 | } | ||
3904 | #endif | ||
3905 | |||
3906 | switch (topology) | ||
3907 | { | ||
3908 | case GNUNET_TESTING_TOPOLOGY_CLIQUE: | ||
3909 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating clique topology\n"); | ||
3910 | num_connections = create_clique (pg, &add_connections, ALLOWED, GNUNET_NO); | ||
3911 | break; | ||
3912 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING: | ||
3913 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3914 | "Creating small world (ring) topology\n"); | ||
3915 | num_connections = create_small_world_ring (pg, &add_connections, ALLOWED); | ||
3916 | break; | ||
3917 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD: | ||
3918 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3919 | "Creating small world (2d-torus) topology\n"); | ||
3920 | num_connections = create_small_world (pg, &add_connections, ALLOWED); | ||
3921 | break; | ||
3922 | case GNUNET_TESTING_TOPOLOGY_RING: | ||
3923 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating ring topology\n"); | ||
3924 | num_connections = create_ring (pg, &add_connections, ALLOWED); | ||
3925 | break; | ||
3926 | case GNUNET_TESTING_TOPOLOGY_2D_TORUS: | ||
3927 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating 2d torus topology\n"); | ||
3928 | num_connections = create_2d_torus (pg, &add_connections, ALLOWED); | ||
3929 | break; | ||
3930 | case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI: | ||
3931 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating Erdos-Renyi topology\n"); | ||
3932 | num_connections = create_erdos_renyi (pg, &add_connections, ALLOWED); | ||
3933 | break; | ||
3934 | case GNUNET_TESTING_TOPOLOGY_INTERNAT: | ||
3935 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating InterNAT topology\n"); | ||
3936 | num_connections = create_nated_internet (pg, &add_connections, ALLOWED); | ||
3937 | break; | ||
3938 | case GNUNET_TESTING_TOPOLOGY_SCALE_FREE: | ||
3939 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating Scale Free topology\n"); | ||
3940 | num_connections = create_scale_free (pg, &add_connections, ALLOWED); | ||
3941 | break; | ||
3942 | case GNUNET_TESTING_TOPOLOGY_LINE: | ||
3943 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3944 | "Creating straight line topology\n"); | ||
3945 | num_connections = create_line (pg, &add_connections, ALLOWED); | ||
3946 | break; | ||
3947 | case GNUNET_TESTING_TOPOLOGY_FROM_FILE: | ||
3948 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating topology from file!\n"); | ||
3949 | if (GNUNET_OK == | ||
3950 | GNUNET_CONFIGURATION_get_value_string (pg->cfg, "testing_old", | ||
3951 | "topology_file", &filename)) | ||
3952 | num_connections = | ||
3953 | create_from_file (pg, filename, &add_connections, ALLOWED); | ||
3954 | else | ||
3955 | { | ||
3956 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
3957 | "Missing configuration option TESTING:TOPOLOGY_FILE for creating topology from file!\n"); | ||
3958 | num_connections = 0; | ||
3959 | } | ||
3960 | break; | ||
3961 | case GNUNET_TESTING_TOPOLOGY_NONE: | ||
3962 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3963 | _ | ||
3964 | ("Creating no allowed topology (all peers can connect at core level)\n")); | ||
3965 | num_connections = pg->total * pg->total; /* Clique is allowed! */ | ||
3966 | break; | ||
3967 | default: | ||
3968 | num_connections = 0; | ||
3969 | break; | ||
3970 | } | ||
3971 | |||
3972 | if (GNUNET_YES == | ||
3973 | GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING_OLD", "F2F")) | ||
3974 | { | ||
3975 | ret = create_and_copy_friend_files (pg); | ||
3976 | if (ret != GNUNET_OK) | ||
3977 | { | ||
3978 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3979 | "Failed during friend file copying!\n"); | ||
3980 | return GNUNET_SYSERR; | ||
3981 | } | ||
3982 | else | ||
3983 | { | ||
3984 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3985 | "Friend files created/copied successfully!\n"); | ||
3986 | } | ||
3987 | } | ||
3988 | |||
3989 | /* Use the create clique method to initially set all connections as blacklisted. */ | ||
3990 | if ((restrict_topology != GNUNET_TESTING_TOPOLOGY_NONE) && | ||
3991 | (restrict_topology != GNUNET_TESTING_TOPOLOGY_FROM_FILE)) | ||
3992 | create_clique (pg, &add_connections, BLACKLIST, GNUNET_NO); | ||
3993 | else | ||
3994 | return num_connections; | ||
3995 | |||
3996 | unblacklisted_connections = 0; | ||
3997 | /* Un-blacklist connections as per the topology specified */ | ||
3998 | switch (restrict_topology) | ||
3999 | { | ||
4000 | case GNUNET_TESTING_TOPOLOGY_CLIQUE: | ||
4001 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4002 | "Blacklisting all but clique topology\n"); | ||
4003 | unblacklisted_connections = | ||
4004 | create_clique (pg, &remove_connections, BLACKLIST, GNUNET_NO); | ||
4005 | break; | ||
4006 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING: | ||
4007 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4008 | "Blacklisting all but small world (ring) topology\n"); | ||
4009 | unblacklisted_connections = | ||
4010 | create_small_world_ring (pg, &remove_connections, BLACKLIST); | ||
4011 | break; | ||
4012 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD: | ||
4013 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4014 | "Blacklisting all but small world (2d-torus) topology\n"); | ||
4015 | unblacklisted_connections = | ||
4016 | create_small_world (pg, &remove_connections, BLACKLIST); | ||
4017 | break; | ||
4018 | case GNUNET_TESTING_TOPOLOGY_RING: | ||
4019 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4020 | "Blacklisting all but ring topology\n"); | ||
4021 | unblacklisted_connections = | ||
4022 | create_ring (pg, &remove_connections, BLACKLIST); | ||
4023 | break; | ||
4024 | case GNUNET_TESTING_TOPOLOGY_2D_TORUS: | ||
4025 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4026 | "Blacklisting all but 2d torus topology\n"); | ||
4027 | unblacklisted_connections = | ||
4028 | create_2d_torus (pg, &remove_connections, BLACKLIST); | ||
4029 | break; | ||
4030 | case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI: | ||
4031 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4032 | "Blacklisting all but Erdos-Renyi topology\n"); | ||
4033 | unblacklisted_connections = | ||
4034 | create_erdos_renyi (pg, &remove_connections, BLACKLIST); | ||
4035 | break; | ||
4036 | case GNUNET_TESTING_TOPOLOGY_INTERNAT: | ||
4037 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4038 | "Blacklisting all but InterNAT topology\n"); | ||
4039 | |||
4040 | #if TOPOLOGY_HACK | ||
4041 | for (off = 0; off < pg->total; off++) | ||
4042 | { | ||
4043 | conn_iter = pg->peers[off].allowed_peers_head; | ||
4044 | while (conn_iter != NULL) | ||
4045 | { | ||
4046 | temp_conn = conn_iter->next; | ||
4047 | GNUNET_free (conn_iter); | ||
4048 | conn_iter = temp_conn; | ||
4049 | } | ||
4050 | pg->peers[off].allowed_peers_head = NULL; | ||
4051 | pg->peers[off].allowed_peers_tail = NULL; | ||
4052 | |||
4053 | conn_iter = pg->peers[off].connect_peers_head; | ||
4054 | while (conn_iter != NULL) | ||
4055 | { | ||
4056 | temp_conn = conn_iter->next; | ||
4057 | GNUNET_free (conn_iter); | ||
4058 | conn_iter = temp_conn; | ||
4059 | } | ||
4060 | pg->peers[off].connect_peers_head = NULL; | ||
4061 | pg->peers[off].connect_peers_tail = NULL; | ||
4062 | } | ||
4063 | unblacklisted_connections = | ||
4064 | create_nated_internet_copy (pg, &remove_connections, BLACKLIST); | ||
4065 | #else | ||
4066 | unblacklisted_connections = | ||
4067 | create_nated_internet (pg, &remove_connections, BLACKLIST); | ||
4068 | #endif | ||
4069 | |||
4070 | break; | ||
4071 | case GNUNET_TESTING_TOPOLOGY_SCALE_FREE: | ||
4072 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4073 | "Blacklisting all but Scale Free topology\n"); | ||
4074 | unblacklisted_connections = | ||
4075 | create_scale_free (pg, &remove_connections, BLACKLIST); | ||
4076 | break; | ||
4077 | case GNUNET_TESTING_TOPOLOGY_LINE: | ||
4078 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4079 | "Blacklisting all but straight line topology\n"); | ||
4080 | unblacklisted_connections = | ||
4081 | create_line (pg, &remove_connections, BLACKLIST); | ||
4082 | default: | ||
4083 | break; | ||
4084 | } | ||
4085 | |||
4086 | if ((unblacklisted_connections > 0) && (restrict_transports != NULL)) | ||
4087 | { | ||
4088 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating blacklist with `%s'\n", | ||
4089 | restrict_transports); | ||
4090 | ret = create_and_copy_blacklist_files (pg, restrict_transports); | ||
4091 | if (ret != GNUNET_OK) | ||
4092 | { | ||
4093 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4094 | "Failed during blacklist file copying!\n"); | ||
4095 | return 0; | ||
4096 | } | ||
4097 | else | ||
4098 | { | ||
4099 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4100 | "Blacklist files created/copied successfully!\n"); | ||
4101 | } | ||
4102 | } | ||
4103 | return num_connections; | ||
4104 | } | ||
4105 | |||
4106 | #if !OLD | ||
4107 | /** | ||
4108 | * Iterator for choosing random peers to connect. | ||
4109 | * | ||
4110 | * @param cls closure, a RandomContext | ||
4111 | * @param key the key the second Daemon was stored under | ||
4112 | * @param value the GNUNET_TESTING_Daemon that the first is to connect to | ||
4113 | * | ||
4114 | * @return GNUNET_YES to continue iteration | ||
4115 | */ | ||
4116 | static int | ||
4117 | random_connect_iterator (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
4118 | { | ||
4119 | struct RandomContext *random_ctx = cls; | ||
4120 | double random_number; | ||
4121 | uint32_t second_pos; | ||
4122 | struct GNUNET_HashCode first_hash; | ||
4123 | |||
4124 | random_number = | ||
4125 | ((double) | ||
4126 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
4127 | UINT64_MAX)) / ((double) UINT64_MAX); | ||
4128 | if (random_number < random_ctx->percentage) | ||
4129 | { | ||
4130 | GNUNET_assert (GNUNET_OK == | ||
4131 | GNUNET_CONTAINER_multihashmap_put (random_ctx-> | ||
4132 | first->connect_peers_working_set, | ||
4133 | key, value, | ||
4134 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
4135 | } | ||
4136 | |||
4137 | /* Now we have considered this particular connection, remove it from the second peer so it's not double counted */ | ||
4138 | uid_from_hash (key, &second_pos); | ||
4139 | hash_from_uid (random_ctx->first_uid, &first_hash); | ||
4140 | GNUNET_assert (random_ctx->pg->total > second_pos); | ||
4141 | GNUNET_assert (GNUNET_YES == | ||
4142 | GNUNET_CONTAINER_multihashmap_remove (random_ctx-> | ||
4143 | pg->peers | ||
4144 | [second_pos].connect_peers, | ||
4145 | &first_hash, | ||
4146 | random_ctx-> | ||
4147 | first->daemon)); | ||
4148 | |||
4149 | return GNUNET_YES; | ||
4150 | } | ||
4151 | |||
4152 | /** | ||
4153 | * Iterator for adding at least X peers to a peers connection set. | ||
4154 | * | ||
4155 | * @param cls closure, MinimumContext | ||
4156 | * @param key the key the second Daemon was stored under | ||
4157 | * @param value the GNUNET_TESTING_Daemon that the first is to connect to | ||
4158 | * | ||
4159 | * @return GNUNET_YES to continue iteration | ||
4160 | */ | ||
4161 | static int | ||
4162 | minimum_connect_iterator (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
4163 | { | ||
4164 | struct MinimumContext *min_ctx = cls; | ||
4165 | uint32_t second_pos; | ||
4166 | struct GNUNET_HashCode first_hash; | ||
4167 | unsigned int i; | ||
4168 | |||
4169 | if (GNUNET_CONTAINER_multihashmap_size | ||
4170 | (min_ctx->first->connect_peers_working_set) < min_ctx->num_to_add) | ||
4171 | { | ||
4172 | for (i = 0; i < min_ctx->num_to_add; i++) | ||
4173 | { | ||
4174 | if (min_ctx->pg_array[i] == min_ctx->current) | ||
4175 | { | ||
4176 | GNUNET_assert (GNUNET_OK == | ||
4177 | GNUNET_CONTAINER_multihashmap_put (min_ctx-> | ||
4178 | first->connect_peers_working_set, | ||
4179 | key, value, | ||
4180 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
4181 | uid_from_hash (key, &second_pos); | ||
4182 | hash_from_uid (min_ctx->first_uid, &first_hash); | ||
4183 | GNUNET_assert (min_ctx->pg->total > second_pos); | ||
4184 | GNUNET_assert (GNUNET_OK == | ||
4185 | GNUNET_CONTAINER_multihashmap_put (min_ctx-> | ||
4186 | pg->peers | ||
4187 | [second_pos].connect_peers_working_set, | ||
4188 | &first_hash, | ||
4189 | min_ctx->first-> | ||
4190 | daemon, | ||
4191 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
4192 | /* Now we have added this particular connection, remove it from the second peer's map so it's not double counted */ | ||
4193 | GNUNET_assert (GNUNET_YES == | ||
4194 | GNUNET_CONTAINER_multihashmap_remove (min_ctx-> | ||
4195 | pg->peers | ||
4196 | [second_pos].connect_peers, | ||
4197 | &first_hash, | ||
4198 | min_ctx-> | ||
4199 | first->daemon)); | ||
4200 | } | ||
4201 | } | ||
4202 | min_ctx->current++; | ||
4203 | return GNUNET_YES; | ||
4204 | } | ||
4205 | else | ||
4206 | return GNUNET_NO; /* We can stop iterating, we have enough peers! */ | ||
4207 | |||
4208 | } | ||
4209 | |||
4210 | /** | ||
4211 | * Iterator for adding peers to a connection set based on a depth first search. | ||
4212 | * | ||
4213 | * @param cls closure, MinimumContext | ||
4214 | * @param key the key the second daemon was stored under | ||
4215 | * @param value the GNUNET_TESTING_Daemon that the first is to connect to | ||
4216 | * | ||
4217 | * @return GNUNET_YES to continue iteration | ||
4218 | */ | ||
4219 | static int | ||
4220 | dfs_connect_iterator (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
4221 | { | ||
4222 | struct DFSContext *dfs_ctx = cls; | ||
4223 | struct GNUNET_HashCode first_hash; | ||
4224 | |||
4225 | if (dfs_ctx->current == dfs_ctx->chosen) | ||
4226 | { | ||
4227 | GNUNET_assert (GNUNET_OK == | ||
4228 | GNUNET_CONTAINER_multihashmap_put (dfs_ctx-> | ||
4229 | first->connect_peers_working_set, | ||
4230 | key, value, | ||
4231 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
4232 | uid_from_hash (key, &dfs_ctx->second_uid); | ||
4233 | hash_from_uid (dfs_ctx->first_uid, &first_hash); | ||
4234 | GNUNET_assert (GNUNET_OK == | ||
4235 | GNUNET_CONTAINER_multihashmap_put (dfs_ctx-> | ||
4236 | pg->peers[dfs_ctx-> | ||
4237 | second_uid].connect_peers_working_set, | ||
4238 | &first_hash, | ||
4239 | dfs_ctx->first->daemon, | ||
4240 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
4241 | GNUNET_assert (GNUNET_YES == | ||
4242 | GNUNET_CONTAINER_multihashmap_remove (dfs_ctx-> | ||
4243 | pg->peers | ||
4244 | [dfs_ctx->second_uid].connect_peers, | ||
4245 | &first_hash, | ||
4246 | dfs_ctx-> | ||
4247 | first->daemon)); | ||
4248 | /* Can't remove second from first yet because we are currently iterating, hence the return value in the DFSContext! */ | ||
4249 | return GNUNET_NO; /* We have found our peer, don't iterate more */ | ||
4250 | } | ||
4251 | |||
4252 | dfs_ctx->current++; | ||
4253 | return GNUNET_YES; | ||
4254 | } | ||
4255 | #endif | ||
4256 | |||
4257 | /** | ||
4258 | * From the set of connections possible, choose percentage percent of connections | ||
4259 | * to actually connect. | ||
4260 | * | ||
4261 | * @param pg the peergroup we are dealing with | ||
4262 | * @param percentage what percent of total connections to make | ||
4263 | */ | ||
4264 | void | ||
4265 | choose_random_connections (struct GNUNET_TESTING_PeerGroup *pg, | ||
4266 | double percentage) | ||
4267 | { | ||
4268 | uint32_t pg_iter; | ||
4269 | |||
4270 | #if OLD | ||
4271 | struct PeerConnection *conn_iter; | ||
4272 | double random_number; | ||
4273 | #else | ||
4274 | struct RandomContext random_ctx; | ||
4275 | #endif | ||
4276 | |||
4277 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4278 | { | ||
4279 | #if OLD | ||
4280 | conn_iter = pg->peers[pg_iter].connect_peers_head; | ||
4281 | while (conn_iter != NULL) | ||
4282 | { | ||
4283 | random_number = | ||
4284 | ((double) | ||
4285 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
4286 | UINT64_MAX)) / ((double) UINT64_MAX); | ||
4287 | if (random_number < percentage) | ||
4288 | { | ||
4289 | add_connections (pg, pg_iter, conn_iter->index, WORKING_SET, | ||
4290 | GNUNET_YES); | ||
4291 | } | ||
4292 | conn_iter = conn_iter->next; | ||
4293 | } | ||
4294 | #else | ||
4295 | random_ctx.first_uid = pg_iter; | ||
4296 | random_ctx.first = &pg->peers[pg_iter]; | ||
4297 | random_ctx.percentage = percentage; | ||
4298 | random_ctx.pg = pg; | ||
4299 | pg->peers[pg_iter].connect_peers_working_set = | ||
4300 | GNUNET_CONTAINER_multihashmap_create (pg->total, GNUNET_NO); | ||
4301 | GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].connect_peers, | ||
4302 | &random_connect_iterator, | ||
4303 | &random_ctx); | ||
4304 | /* Now remove the old connections */ | ||
4305 | GNUNET_CONTAINER_multihashmap_destroy (pg->peers[pg_iter].connect_peers); | ||
4306 | /* And replace with the random set */ | ||
4307 | pg->peers[pg_iter].connect_peers = | ||
4308 | pg->peers[pg_iter].connect_peers_working_set; | ||
4309 | #endif | ||
4310 | } | ||
4311 | |||
4312 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4313 | { | ||
4314 | conn_iter = pg->peers[pg_iter].connect_peers_head; | ||
4315 | while (pg->peers[pg_iter].connect_peers_head != NULL) | ||
4316 | remove_connections (pg, pg_iter, | ||
4317 | pg->peers[pg_iter].connect_peers_head->index, CONNECT, | ||
4318 | GNUNET_YES); | ||
4319 | |||
4320 | pg->peers[pg_iter].connect_peers_head = | ||
4321 | pg->peers[pg_iter].connect_peers_working_set_head; | ||
4322 | pg->peers[pg_iter].connect_peers_tail = | ||
4323 | pg->peers[pg_iter].connect_peers_working_set_tail; | ||
4324 | pg->peers[pg_iter].connect_peers_working_set_head = NULL; | ||
4325 | pg->peers[pg_iter].connect_peers_working_set_tail = NULL; | ||
4326 | } | ||
4327 | } | ||
4328 | |||
4329 | /** | ||
4330 | * Count the number of connections in a linked list of connections. | ||
4331 | * | ||
4332 | * @param conn_list the connection list to get the count of | ||
4333 | * | ||
4334 | * @return the number of elements in the list | ||
4335 | */ | ||
4336 | static unsigned int | ||
4337 | count_connections (struct PeerConnection *conn_list) | ||
4338 | { | ||
4339 | struct PeerConnection *iter; | ||
4340 | unsigned int count; | ||
4341 | |||
4342 | count = 0; | ||
4343 | iter = conn_list; | ||
4344 | while (iter != NULL) | ||
4345 | { | ||
4346 | iter = iter->next; | ||
4347 | count++; | ||
4348 | } | ||
4349 | return count; | ||
4350 | } | ||
4351 | |||
4352 | static unsigned int | ||
4353 | count_workingset_connections (struct GNUNET_TESTING_PeerGroup *pg) | ||
4354 | { | ||
4355 | unsigned int count; | ||
4356 | unsigned int pg_iter; | ||
4357 | |||
4358 | #if OLD | ||
4359 | struct PeerConnection *conn_iter; | ||
4360 | #endif | ||
4361 | count = 0; | ||
4362 | |||
4363 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4364 | { | ||
4365 | #if OLD | ||
4366 | conn_iter = pg->peers[pg_iter].connect_peers_working_set_head; | ||
4367 | while (conn_iter != NULL) | ||
4368 | { | ||
4369 | count++; | ||
4370 | conn_iter = conn_iter->next; | ||
4371 | } | ||
4372 | #else | ||
4373 | count += | ||
4374 | GNUNET_CONTAINER_multihashmap_size (pg-> | ||
4375 | peers | ||
4376 | [pg_iter].connect_peers_working_set); | ||
4377 | #endif | ||
4378 | } | ||
4379 | |||
4380 | return count; | ||
4381 | } | ||
4382 | |||
4383 | static unsigned int | ||
4384 | count_allowed_connections (struct GNUNET_TESTING_PeerGroup *pg) | ||
4385 | { | ||
4386 | unsigned int count; | ||
4387 | unsigned int pg_iter; | ||
4388 | |||
4389 | #if OLD | ||
4390 | struct PeerConnection *conn_iter; | ||
4391 | #endif | ||
4392 | |||
4393 | count = 0; | ||
4394 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4395 | { | ||
4396 | #if OLD | ||
4397 | conn_iter = pg->peers[pg_iter].allowed_peers_head; | ||
4398 | while (conn_iter != NULL) | ||
4399 | { | ||
4400 | count++; | ||
4401 | conn_iter = conn_iter->next; | ||
4402 | } | ||
4403 | #else | ||
4404 | count += | ||
4405 | GNUNET_CONTAINER_multihashmap_size (pg->peers[pg_iter].allowed_peers); | ||
4406 | #endif | ||
4407 | } | ||
4408 | |||
4409 | return count; | ||
4410 | } | ||
4411 | |||
4412 | /** | ||
4413 | * From the set of connections possible, choose at least num connections per | ||
4414 | * peer. | ||
4415 | * | ||
4416 | * @param pg the peergroup we are dealing with | ||
4417 | * @param num how many connections at least should each peer have (if possible)? | ||
4418 | */ | ||
4419 | static void | ||
4420 | choose_minimum (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num) | ||
4421 | { | ||
4422 | #if !OLD | ||
4423 | struct MinimumContext minimum_ctx; | ||
4424 | #else | ||
4425 | struct PeerConnection *conn_iter; | ||
4426 | unsigned int temp_list_size; | ||
4427 | unsigned int i; | ||
4428 | unsigned int count; | ||
4429 | uint32_t random; /* Random list entry to connect peer to */ | ||
4430 | #endif | ||
4431 | uint32_t pg_iter; | ||
4432 | |||
4433 | #if OLD | ||
4434 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4435 | { | ||
4436 | temp_list_size = count_connections (pg->peers[pg_iter].connect_peers_head); | ||
4437 | if (temp_list_size == 0) | ||
4438 | { | ||
4439 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Peer %d has 0 connections!?!?\n", | ||
4440 | pg_iter); | ||
4441 | break; | ||
4442 | } | ||
4443 | for (i = 0; i < num; i++) | ||
4444 | { | ||
4445 | random = | ||
4446 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, temp_list_size); | ||
4447 | conn_iter = pg->peers[pg_iter].connect_peers_head; | ||
4448 | for (count = 0; count < random; count++) | ||
4449 | conn_iter = conn_iter->next; | ||
4450 | /* We now have a random connection, connect it! */ | ||
4451 | GNUNET_assert (conn_iter != NULL); | ||
4452 | add_connections (pg, pg_iter, conn_iter->index, WORKING_SET, GNUNET_YES); | ||
4453 | } | ||
4454 | } | ||
4455 | #else | ||
4456 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4457 | { | ||
4458 | pg->peers[pg_iter].connect_peers_working_set = | ||
4459 | GNUNET_CONTAINER_multihashmap_create (num, GNUNET_NO); | ||
4460 | } | ||
4461 | |||
4462 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4463 | { | ||
4464 | minimum_ctx.first_uid = pg_iter; | ||
4465 | minimum_ctx.pg_array = | ||
4466 | GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, | ||
4467 | GNUNET_CONTAINER_multihashmap_size | ||
4468 | (pg->peers[pg_iter].connect_peers)); | ||
4469 | minimum_ctx.first = &pg->peers[pg_iter]; | ||
4470 | minimum_ctx.pg = pg; | ||
4471 | minimum_ctx.num_to_add = num; | ||
4472 | minimum_ctx.current = 0; | ||
4473 | GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].connect_peers, | ||
4474 | &minimum_connect_iterator, | ||
4475 | &minimum_ctx); | ||
4476 | } | ||
4477 | |||
4478 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4479 | { | ||
4480 | /* Remove the "old" connections */ | ||
4481 | GNUNET_CONTAINER_multihashmap_destroy (pg->peers[pg_iter].connect_peers); | ||
4482 | /* And replace with the working set */ | ||
4483 | pg->peers[pg_iter].connect_peers = | ||
4484 | pg->peers[pg_iter].connect_peers_working_set; | ||
4485 | } | ||
4486 | #endif | ||
4487 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4488 | { | ||
4489 | while (pg->peers[pg_iter].connect_peers_head != NULL) | ||
4490 | { | ||
4491 | conn_iter = pg->peers[pg_iter].connect_peers_head; | ||
4492 | GNUNET_CONTAINER_DLL_remove (pg->peers[pg_iter].connect_peers_head, | ||
4493 | pg->peers[pg_iter].connect_peers_tail, | ||
4494 | conn_iter); | ||
4495 | GNUNET_free (conn_iter); | ||
4496 | /*remove_connections(pg, pg_iter, pg->peers[pg_iter].connect_peers_head->index, CONNECT, GNUNET_YES); */ | ||
4497 | } | ||
4498 | |||
4499 | pg->peers[pg_iter].connect_peers_head = | ||
4500 | pg->peers[pg_iter].connect_peers_working_set_head; | ||
4501 | pg->peers[pg_iter].connect_peers_tail = | ||
4502 | pg->peers[pg_iter].connect_peers_working_set_tail; | ||
4503 | pg->peers[pg_iter].connect_peers_working_set_head = NULL; | ||
4504 | pg->peers[pg_iter].connect_peers_working_set_tail = NULL; | ||
4505 | } | ||
4506 | } | ||
4507 | |||
4508 | #if !OLD | ||
4509 | struct FindClosestContext | ||
4510 | { | ||
4511 | /** | ||
4512 | * The currently known closest peer. | ||
4513 | */ | ||
4514 | struct GNUNET_TESTING_Daemon *closest; | ||
4515 | |||
4516 | /** | ||
4517 | * The info for the peer we are adding connections for. | ||
4518 | */ | ||
4519 | struct PeerData *curr_peer; | ||
4520 | |||
4521 | /** | ||
4522 | * The distance (bits) between the current | ||
4523 | * peer and the currently known closest. | ||
4524 | */ | ||
4525 | unsigned int closest_dist; | ||
4526 | |||
4527 | /** | ||
4528 | * The offset of the closest known peer in | ||
4529 | * the peer group. | ||
4530 | */ | ||
4531 | unsigned int closest_num; | ||
4532 | }; | ||
4533 | |||
4534 | /** | ||
4535 | * Iterator over hash map entries of the allowed | ||
4536 | * peer connections. Find the closest, not already | ||
4537 | * connected peer and return it. | ||
4538 | * | ||
4539 | * @param cls closure (struct FindClosestContext) | ||
4540 | * @param key current key code (hash of offset in pg) | ||
4541 | * @param value value in the hash map - a GNUNET_TESTING_Daemon | ||
4542 | * @return GNUNET_YES if we should continue to | ||
4543 | * iterate, | ||
4544 | * GNUNET_NO if not. | ||
4545 | */ | ||
4546 | static int | ||
4547 | find_closest_peers (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
4548 | { | ||
4549 | struct FindClosestContext *closest_ctx = cls; | ||
4550 | struct GNUNET_TESTING_Daemon *daemon = value; | ||
4551 | |||
4552 | if (((closest_ctx->closest == NULL) || | ||
4553 | (GNUNET_CRYPTO_hash_matching_bits | ||
4554 | (&daemon->id.hashPubKey, | ||
4555 | &closest_ctx->curr_peer->daemon->id.hashPubKey) > | ||
4556 | closest_ctx->closest_dist)) && | ||
4557 | (GNUNET_YES != | ||
4558 | GNUNET_CONTAINER_multihashmap_contains (closest_ctx-> | ||
4559 | curr_peer->connect_peers, key))) | ||
4560 | { | ||
4561 | closest_ctx->closest_dist = | ||
4562 | GNUNET_CRYPTO_hash_matching_bits (&daemon->id.hashPubKey, | ||
4563 | &closest_ctx->curr_peer->daemon-> | ||
4564 | id.hashPubKey); | ||
4565 | closest_ctx->closest = daemon; | ||
4566 | uid_from_hash (key, &closest_ctx->closest_num); | ||
4567 | } | ||
4568 | return GNUNET_YES; | ||
4569 | } | ||
4570 | |||
4571 | /** | ||
4572 | * From the set of connections possible, choose at num connections per | ||
4573 | * peer based on depth which are closest out of those allowed. Guaranteed | ||
4574 | * to add num peers to connect to, provided there are that many peers | ||
4575 | * in the underlay topology to connect to. | ||
4576 | * | ||
4577 | * @param pg the peergroup we are dealing with | ||
4578 | * @param num how many connections at least should each peer have (if possible)? | ||
4579 | * @param proc processor to actually add the connections | ||
4580 | * @param list the peer list to use | ||
4581 | */ | ||
4582 | void | ||
4583 | add_closest (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num, | ||
4584 | GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list) | ||
4585 | { | ||
4586 | #if OLD | ||
4587 | |||
4588 | #else | ||
4589 | struct FindClosestContext closest_ctx; | ||
4590 | #endif | ||
4591 | uint32_t pg_iter; | ||
4592 | uint32_t i; | ||
4593 | |||
4594 | for (i = 0; i < num; i++) /* Each time find a closest peer (from those available) */ | ||
4595 | { | ||
4596 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4597 | { | ||
4598 | closest_ctx.curr_peer = &pg->peers[pg_iter]; | ||
4599 | closest_ctx.closest = NULL; | ||
4600 | closest_ctx.closest_dist = 0; | ||
4601 | closest_ctx.closest_num = 0; | ||
4602 | GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].allowed_peers, | ||
4603 | &find_closest_peers, &closest_ctx); | ||
4604 | if (closest_ctx.closest != NULL) | ||
4605 | { | ||
4606 | GNUNET_assert (closest_ctx.closest_num < pg->total); | ||
4607 | proc (pg, pg_iter, closest_ctx.closest_num, list); | ||
4608 | } | ||
4609 | } | ||
4610 | } | ||
4611 | } | ||
4612 | #endif | ||
4613 | |||
4614 | /** | ||
4615 | * From the set of connections possible, choose at least num connections per | ||
4616 | * peer based on depth first traversal of peer connections. If DFS leaves | ||
4617 | * peers unconnected, ensure those peers get connections. | ||
4618 | * | ||
4619 | * @param pg the peergroup we are dealing with | ||
4620 | * @param num how many connections at least should each peer have (if possible)? | ||
4621 | */ | ||
4622 | void | ||
4623 | perform_dfs (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num) | ||
4624 | { | ||
4625 | uint32_t pg_iter; | ||
4626 | uint32_t dfs_count; | ||
4627 | uint32_t starting_peer; | ||
4628 | uint32_t least_connections; | ||
4629 | uint32_t random_connection; | ||
4630 | |||
4631 | #if OLD | ||
4632 | unsigned int temp_count; | ||
4633 | struct PeerConnection *peer_iter; | ||
4634 | #else | ||
4635 | struct DFSContext dfs_ctx; | ||
4636 | struct GNUNET_HashCode second_hash; | ||
4637 | #endif | ||
4638 | |||
4639 | #if OLD | ||
4640 | starting_peer = 0; | ||
4641 | dfs_count = 0; | ||
4642 | while ((count_workingset_connections (pg) < num * pg->total) && | ||
4643 | (count_allowed_connections (pg) > 0)) | ||
4644 | { | ||
4645 | if (dfs_count % pg->total == 0) /* Restart the DFS at some weakly connected peer */ | ||
4646 | { | ||
4647 | least_connections = -1; /* Set to very high number */ | ||
4648 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4649 | { | ||
4650 | temp_count = | ||
4651 | count_connections (pg-> | ||
4652 | peers[pg_iter].connect_peers_working_set_head); | ||
4653 | if (temp_count < least_connections) | ||
4654 | { | ||
4655 | starting_peer = pg_iter; | ||
4656 | least_connections = temp_count; | ||
4657 | } | ||
4658 | } | ||
4659 | } | ||
4660 | |||
4661 | temp_count = | ||
4662 | count_connections (pg->peers[starting_peer].connect_peers_head); | ||
4663 | if (temp_count == 0) | ||
4664 | continue; /* FIXME: infinite loop? */ | ||
4665 | |||
4666 | random_connection = | ||
4667 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, temp_count); | ||
4668 | temp_count = 0; | ||
4669 | peer_iter = pg->peers[starting_peer].connect_peers_head; | ||
4670 | while (temp_count < random_connection) | ||
4671 | { | ||
4672 | peer_iter = peer_iter->next; | ||
4673 | temp_count++; | ||
4674 | } | ||
4675 | GNUNET_assert (peer_iter != NULL); | ||
4676 | add_connections (pg, starting_peer, peer_iter->index, WORKING_SET, | ||
4677 | GNUNET_NO); | ||
4678 | remove_connections (pg, starting_peer, peer_iter->index, CONNECT, | ||
4679 | GNUNET_YES); | ||
4680 | starting_peer = peer_iter->index; | ||
4681 | dfs_count++; | ||
4682 | } | ||
4683 | |||
4684 | #else | ||
4685 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4686 | { | ||
4687 | pg->peers[pg_iter].connect_peers_working_set = | ||
4688 | GNUNET_CONTAINER_multihashmap_create (num, GNUNET_NO); | ||
4689 | } | ||
4690 | |||
4691 | starting_peer = 0; | ||
4692 | dfs_count = 0; | ||
4693 | while ((count_workingset_connections (pg) < num * pg->total) && | ||
4694 | (count_allowed_connections (pg) > 0)) | ||
4695 | { | ||
4696 | if (dfs_count % pg->total == 0) /* Restart the DFS at some weakly connected peer */ | ||
4697 | { | ||
4698 | least_connections = -1; /* Set to very high number */ | ||
4699 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4700 | { | ||
4701 | if (GNUNET_CONTAINER_multihashmap_size | ||
4702 | (pg->peers[pg_iter].connect_peers_working_set) < least_connections) | ||
4703 | { | ||
4704 | starting_peer = pg_iter; | ||
4705 | least_connections = | ||
4706 | GNUNET_CONTAINER_multihashmap_size (pg-> | ||
4707 | peers | ||
4708 | [pg_iter].connect_peers_working_set); | ||
4709 | } | ||
4710 | } | ||
4711 | } | ||
4712 | |||
4713 | if (GNUNET_CONTAINER_multihashmap_size (pg->peers[starting_peer].connect_peers) == 0) /* Ensure there is at least one peer left to connect! */ | ||
4714 | { | ||
4715 | dfs_count = 0; | ||
4716 | continue; | ||
4717 | } | ||
4718 | |||
4719 | /* Choose a random peer from the chosen peers set of connections to add */ | ||
4720 | dfs_ctx.chosen = | ||
4721 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
4722 | GNUNET_CONTAINER_multihashmap_size (pg->peers | ||
4723 | [starting_peer].connect_peers)); | ||
4724 | dfs_ctx.first_uid = starting_peer; | ||
4725 | dfs_ctx.first = &pg->peers[starting_peer]; | ||
4726 | dfs_ctx.pg = pg; | ||
4727 | dfs_ctx.current = 0; | ||
4728 | |||
4729 | GNUNET_CONTAINER_multihashmap_iterate (pg-> | ||
4730 | peers[starting_peer].connect_peers, | ||
4731 | &dfs_connect_iterator, &dfs_ctx); | ||
4732 | /* Remove the second from the first, since we will be continuing the search and may encounter the first peer again! */ | ||
4733 | hash_from_uid (dfs_ctx.second_uid, &second_hash); | ||
4734 | GNUNET_assert (GNUNET_YES == | ||
4735 | GNUNET_CONTAINER_multihashmap_remove (pg->peers | ||
4736 | [starting_peer].connect_peers, | ||
4737 | &second_hash, | ||
4738 | pg-> | ||
4739 | peers | ||
4740 | [dfs_ctx.second_uid].daemon)); | ||
4741 | starting_peer = dfs_ctx.second_uid; | ||
4742 | } | ||
4743 | |||
4744 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
4745 | { | ||
4746 | /* Remove the "old" connections */ | ||
4747 | GNUNET_CONTAINER_multihashmap_destroy (pg->peers[pg_iter].connect_peers); | ||
4748 | /* And replace with the working set */ | ||
4749 | pg->peers[pg_iter].connect_peers = | ||
4750 | pg->peers[pg_iter].connect_peers_working_set; | ||
4751 | } | ||
4752 | #endif | ||
4753 | } | ||
4754 | |||
4755 | /** | ||
4756 | * Internal callback for topology information for a particular peer. | ||
4757 | */ | ||
4758 | static void | ||
4759 | internal_topology_callback (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
4760 | const struct GNUNET_ATS_Information *atsi, | ||
4761 | unsigned int atsi_count) | ||
4762 | { | ||
4763 | struct CoreContext *core_ctx = cls; | ||
4764 | struct TopologyIterateContext *iter_ctx = core_ctx->iter_context; | ||
4765 | |||
4766 | if (peer == NULL) /* Either finished, or something went wrong */ | ||
4767 | { | ||
4768 | iter_ctx->completed++; | ||
4769 | iter_ctx->connected--; | ||
4770 | /* One core context allocated per iteration, must free! */ | ||
4771 | GNUNET_free (core_ctx); | ||
4772 | } | ||
4773 | else | ||
4774 | { | ||
4775 | iter_ctx->topology_cb (iter_ctx->cls, &core_ctx->daemon->id, peer, NULL); | ||
4776 | } | ||
4777 | |||
4778 | if (iter_ctx->completed == iter_ctx->total) | ||
4779 | { | ||
4780 | iter_ctx->topology_cb (iter_ctx->cls, NULL, NULL, NULL); | ||
4781 | /* Once all are done, free the iteration context */ | ||
4782 | GNUNET_free (iter_ctx); | ||
4783 | } | ||
4784 | } | ||
4785 | |||
4786 | /** | ||
4787 | * Check running topology iteration tasks, if below max start a new one, otherwise | ||
4788 | * schedule for some time in the future. | ||
4789 | */ | ||
4790 | static void | ||
4791 | schedule_get_topology (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
4792 | { | ||
4793 | struct CoreContext *core_context = cls; | ||
4794 | struct TopologyIterateContext *topology_context = | ||
4795 | (struct TopologyIterateContext *) core_context->iter_context; | ||
4796 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
4797 | return; | ||
4798 | |||
4799 | if (topology_context->connected > | ||
4800 | topology_context->pg->max_outstanding_connections) | ||
4801 | { | ||
4802 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4803 | "Delaying connect, we have too many outstanding connections!\n"); | ||
4804 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
4805 | (GNUNET_TIME_UNIT_MILLISECONDS, 100), | ||
4806 | &schedule_get_topology, core_context); | ||
4807 | } | ||
4808 | else | ||
4809 | { | ||
4810 | topology_context->connected++; | ||
4811 | |||
4812 | if (GNUNET_OK != | ||
4813 | GNUNET_CORE_iterate_peers (core_context->daemon->cfg, | ||
4814 | &internal_topology_callback, core_context)) | ||
4815 | { | ||
4816 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Topology iteration failed.\n"); | ||
4817 | internal_topology_callback (core_context, NULL, NULL, 0); | ||
4818 | } | ||
4819 | } | ||
4820 | } | ||
4821 | |||
4822 | /** | ||
4823 | * Iterate over all (running) peers in the peer group, retrieve | ||
4824 | * all connections that each currently has. | ||
4825 | */ | ||
4826 | void | ||
4827 | GNUNET_TESTING_get_topology (struct GNUNET_TESTING_PeerGroup *pg, | ||
4828 | GNUNET_TESTING_NotifyTopology cb, void *cls) | ||
4829 | { | ||
4830 | struct TopologyIterateContext *topology_context; | ||
4831 | struct CoreContext *core_ctx; | ||
4832 | unsigned int i; | ||
4833 | unsigned int total_count; | ||
4834 | |||
4835 | /* Allocate a single topology iteration context */ | ||
4836 | topology_context = GNUNET_malloc (sizeof (struct TopologyIterateContext)); | ||
4837 | topology_context->topology_cb = cb; | ||
4838 | topology_context->cls = cls; | ||
4839 | topology_context->pg = pg; | ||
4840 | total_count = 0; | ||
4841 | for (i = 0; i < pg->total; i++) | ||
4842 | { | ||
4843 | if (pg->peers[i].daemon->running == GNUNET_YES) | ||
4844 | { | ||
4845 | /* Allocate one core context per core we need to connect to */ | ||
4846 | core_ctx = GNUNET_malloc (sizeof (struct CoreContext)); | ||
4847 | core_ctx->daemon = pg->peers[i].daemon; | ||
4848 | /* Set back pointer to topology iteration context */ | ||
4849 | core_ctx->iter_context = topology_context; | ||
4850 | GNUNET_SCHEDULER_add_now (&schedule_get_topology, core_ctx); | ||
4851 | total_count++; | ||
4852 | } | ||
4853 | } | ||
4854 | if (total_count == 0) | ||
4855 | { | ||
4856 | cb (cls, NULL, NULL, "Cannot iterate over topology, no running peers!"); | ||
4857 | GNUNET_free (topology_context); | ||
4858 | } | ||
4859 | else | ||
4860 | topology_context->total = total_count; | ||
4861 | return; | ||
4862 | } | ||
4863 | |||
4864 | /** | ||
4865 | * Callback function to process statistic values. | ||
4866 | * This handler is here only really to insert a peer | ||
4867 | * identity (or daemon) so the statistics can be uniquely | ||
4868 | * tied to a single running peer. | ||
4869 | * | ||
4870 | * @param cls closure | ||
4871 | * @param subsystem name of subsystem that created the statistic | ||
4872 | * @param name the name of the datum | ||
4873 | * @param value the current value | ||
4874 | * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not | ||
4875 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | ||
4876 | */ | ||
4877 | static int | ||
4878 | internal_stats_callback (void *cls, const char *subsystem, const char *name, | ||
4879 | uint64_t value, int is_persistent) | ||
4880 | { | ||
4881 | struct StatsCoreContext *core_context = cls; | ||
4882 | struct StatsIterateContext *stats_context = | ||
4883 | (struct StatsIterateContext *) core_context->iter_context; | ||
4884 | |||
4885 | return stats_context->proc (stats_context->cls, &core_context->daemon->id, | ||
4886 | subsystem, name, value, is_persistent); | ||
4887 | } | ||
4888 | |||
4889 | |||
4890 | /** | ||
4891 | * We don't need the statistics handle anymore, destroy it. | ||
4892 | * | ||
4893 | * @param cls Closure (the statistics handle to destroy) | ||
4894 | * @param tc Task Context | ||
4895 | */ | ||
4896 | static void | ||
4897 | internal_destroy_statistics (void *cls, | ||
4898 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
4899 | { | ||
4900 | struct GNUNET_STATISTICS_Handle *h = cls; | ||
4901 | |||
4902 | GNUNET_STATISTICS_destroy (h, GNUNET_NO); | ||
4903 | } | ||
4904 | |||
4905 | |||
4906 | /** | ||
4907 | * Internal continuation call for statistics iteration. | ||
4908 | * | ||
4909 | * @param cls closure, the CoreContext for this iteration | ||
4910 | * @param success whether or not the statistics iterations | ||
4911 | * was canceled or not (we don't care) | ||
4912 | */ | ||
4913 | static void | ||
4914 | internal_stats_cont (void *cls, int success) | ||
4915 | { | ||
4916 | struct StatsCoreContext *core_context = cls; | ||
4917 | struct StatsIterateContext *stats_context = | ||
4918 | (struct StatsIterateContext *) core_context->iter_context; | ||
4919 | |||
4920 | stats_context->connected--; | ||
4921 | stats_context->completed++; | ||
4922 | |||
4923 | if (stats_context->completed == stats_context->total) | ||
4924 | { | ||
4925 | stats_context->cont (stats_context->cls, GNUNET_YES); | ||
4926 | GNUNET_free (stats_context); | ||
4927 | } | ||
4928 | |||
4929 | if (core_context->stats_handle != NULL) | ||
4930 | /* Cannot destroy handle inside the continuation */ | ||
4931 | GNUNET_SCHEDULER_add_now (&internal_destroy_statistics, | ||
4932 | core_context->stats_handle); | ||
4933 | |||
4934 | GNUNET_free (core_context); | ||
4935 | } | ||
4936 | |||
4937 | /** | ||
4938 | * Check running topology iteration tasks, if below max start a new one, otherwise | ||
4939 | * schedule for some time in the future. | ||
4940 | */ | ||
4941 | static void | ||
4942 | schedule_get_statistics (void *cls, | ||
4943 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
4944 | { | ||
4945 | struct StatsCoreContext *core_context = cls; | ||
4946 | struct StatsIterateContext *stats_context = | ||
4947 | (struct StatsIterateContext *) core_context->iter_context; | ||
4948 | |||
4949 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
4950 | return; | ||
4951 | |||
4952 | if (stats_context->connected > stats_context->pg->max_outstanding_connections) | ||
4953 | { | ||
4954 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4955 | "Delaying connect, we have too many outstanding connections!\n"); | ||
4956 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
4957 | (GNUNET_TIME_UNIT_MILLISECONDS, 100), | ||
4958 | &schedule_get_statistics, core_context); | ||
4959 | } | ||
4960 | else | ||
4961 | { | ||
4962 | stats_context->connected++; | ||
4963 | core_context->stats_handle = | ||
4964 | GNUNET_STATISTICS_create ("testing_old", core_context->daemon->cfg); | ||
4965 | if (core_context->stats_handle == NULL) | ||
4966 | { | ||
4967 | internal_stats_cont (core_context, GNUNET_NO); | ||
4968 | return; | ||
4969 | } | ||
4970 | |||
4971 | core_context->stats_get_handle = | ||
4972 | GNUNET_STATISTICS_get (core_context->stats_handle, NULL, NULL, | ||
4973 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
4974 | &internal_stats_cont, &internal_stats_callback, | ||
4975 | core_context); | ||
4976 | if (core_context->stats_get_handle == NULL) | ||
4977 | internal_stats_cont (core_context, GNUNET_NO); | ||
4978 | |||
4979 | } | ||
4980 | } | ||
4981 | |||
4982 | struct DuplicateStats | ||
4983 | { | ||
4984 | /** | ||
4985 | * Next item in the list | ||
4986 | */ | ||
4987 | struct DuplicateStats *next; | ||
4988 | |||
4989 | /** | ||
4990 | * Nasty string, concatenation of relevant information. | ||
4991 | */ | ||
4992 | char *unique_string; | ||
4993 | }; | ||
4994 | |||
4995 | /** | ||
4996 | * Check whether the combination of port/host/unix domain socket | ||
4997 | * already exists in the list of peers being checked for statistics. | ||
4998 | * | ||
4999 | * @param pg the peergroup in question | ||
5000 | * @param specific_peer the peer we're concerned with | ||
5001 | * @param stats_list the list to return to the caller | ||
5002 | * | ||
5003 | * @return GNUNET_YES if the statistics instance has been seen already, | ||
5004 | * GNUNET_NO if not (and we may have added it to the list) | ||
5005 | */ | ||
5006 | static int | ||
5007 | stats_check_existing (struct GNUNET_TESTING_PeerGroup *pg, | ||
5008 | struct PeerData *specific_peer, | ||
5009 | struct DuplicateStats **stats_list) | ||
5010 | { | ||
5011 | struct DuplicateStats *pos; | ||
5012 | char *unix_domain_socket; | ||
5013 | unsigned long long port; | ||
5014 | char *to_match; | ||
5015 | |||
5016 | if (GNUNET_YES != | ||
5017 | GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "testing_old", | ||
5018 | "single_statistics_per_host")) | ||
5019 | return GNUNET_NO; /* Each peer has its own statistics instance, do nothing! */ | ||
5020 | |||
5021 | pos = *stats_list; | ||
5022 | if (GNUNET_OK != | ||
5023 | GNUNET_CONFIGURATION_get_value_string (specific_peer->cfg, "statistics", | ||
5024 | "unixpath", &unix_domain_socket)) | ||
5025 | return GNUNET_NO; | ||
5026 | |||
5027 | if (GNUNET_OK != | ||
5028 | GNUNET_CONFIGURATION_get_value_number (specific_peer->cfg, "statistics", | ||
5029 | "port", &port)) | ||
5030 | { | ||
5031 | GNUNET_free (unix_domain_socket); | ||
5032 | return GNUNET_NO; | ||
5033 | } | ||
5034 | |||
5035 | if (specific_peer->daemon->hostname != NULL) | ||
5036 | GNUNET_asprintf (&to_match, "%s%s%llu", specific_peer->daemon->hostname, | ||
5037 | unix_domain_socket, port); | ||
5038 | else | ||
5039 | GNUNET_asprintf (&to_match, "%s%llu", unix_domain_socket, port); | ||
5040 | |||
5041 | while (pos != NULL) | ||
5042 | { | ||
5043 | if (0 == strcmp (to_match, pos->unique_string)) | ||
5044 | { | ||
5045 | GNUNET_free (unix_domain_socket); | ||
5046 | GNUNET_free (to_match); | ||
5047 | return GNUNET_YES; | ||
5048 | } | ||
5049 | pos = pos->next; | ||
5050 | } | ||
5051 | pos = GNUNET_malloc (sizeof (struct DuplicateStats)); | ||
5052 | pos->unique_string = to_match; | ||
5053 | pos->next = *stats_list; | ||
5054 | *stats_list = pos; | ||
5055 | GNUNET_free (unix_domain_socket); | ||
5056 | return GNUNET_NO; | ||
5057 | } | ||
5058 | |||
5059 | /** | ||
5060 | * Iterate over all (running) peers in the peer group, retrieve | ||
5061 | * all statistics from each. | ||
5062 | * | ||
5063 | * @param pg the peergroup to iterate statistics of | ||
5064 | * @param cont continuation to call once all stats have been retrieved | ||
5065 | * @param proc processing function for each statistic from each peer | ||
5066 | * @param cls closure to pass to proc | ||
5067 | * | ||
5068 | */ | ||
5069 | void | ||
5070 | GNUNET_TESTING_get_statistics (struct GNUNET_TESTING_PeerGroup *pg, | ||
5071 | GNUNET_STATISTICS_Callback cont, | ||
5072 | GNUNET_TESTING_STATISTICS_Iterator proc, | ||
5073 | void *cls) | ||
5074 | { | ||
5075 | struct StatsIterateContext *stats_context; | ||
5076 | struct StatsCoreContext *core_ctx; | ||
5077 | unsigned int i; | ||
5078 | unsigned int total_count; | ||
5079 | struct DuplicateStats *stats_list; | ||
5080 | struct DuplicateStats *pos; | ||
5081 | |||
5082 | stats_list = NULL; | ||
5083 | |||
5084 | /* Allocate a single stats iteration context */ | ||
5085 | stats_context = GNUNET_malloc (sizeof (struct StatsIterateContext)); | ||
5086 | stats_context->cont = cont; | ||
5087 | stats_context->proc = proc; | ||
5088 | stats_context->cls = cls; | ||
5089 | stats_context->pg = pg; | ||
5090 | total_count = 0; | ||
5091 | |||
5092 | for (i = 0; i < pg->total; i++) | ||
5093 | { | ||
5094 | if ((pg->peers[i].daemon->running == GNUNET_YES) && | ||
5095 | (GNUNET_NO == stats_check_existing (pg, &pg->peers[i], &stats_list))) | ||
5096 | { | ||
5097 | /* Allocate one core context per core we need to connect to */ | ||
5098 | core_ctx = GNUNET_malloc (sizeof (struct StatsCoreContext)); | ||
5099 | core_ctx->daemon = pg->peers[i].daemon; | ||
5100 | /* Set back pointer to topology iteration context */ | ||
5101 | core_ctx->iter_context = stats_context; | ||
5102 | GNUNET_SCHEDULER_add_now (&schedule_get_statistics, core_ctx); | ||
5103 | total_count++; | ||
5104 | } | ||
5105 | } | ||
5106 | |||
5107 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5108 | "Retrieving stats from %u total instances.\n", total_count); | ||
5109 | if (0 != total_count) | ||
5110 | stats_context->total = total_count; | ||
5111 | else | ||
5112 | GNUNET_free (stats_context); | ||
5113 | if (stats_list != NULL) | ||
5114 | { | ||
5115 | pos = stats_list; | ||
5116 | while (pos != NULL) | ||
5117 | { | ||
5118 | GNUNET_free (pos->unique_string); | ||
5119 | stats_list = pos->next; | ||
5120 | GNUNET_free (pos); | ||
5121 | pos = stats_list->next; | ||
5122 | } | ||
5123 | } | ||
5124 | return; | ||
5125 | } | ||
5126 | |||
5127 | /** | ||
5128 | * Stop the connection process temporarily. | ||
5129 | * | ||
5130 | * @param pg the peer group to stop connecting | ||
5131 | */ | ||
5132 | void | ||
5133 | GNUNET_TESTING_stop_connections (struct GNUNET_TESTING_PeerGroup *pg) | ||
5134 | { | ||
5135 | pg->stop_connects = GNUNET_YES; | ||
5136 | } | ||
5137 | |||
5138 | /** | ||
5139 | * Resume the connection process temporarily. | ||
5140 | * | ||
5141 | * @param pg the peer group to resume connecting | ||
5142 | */ | ||
5143 | void | ||
5144 | GNUNET_TESTING_resume_connections (struct GNUNET_TESTING_PeerGroup *pg) | ||
5145 | { | ||
5146 | pg->stop_connects = GNUNET_NO; | ||
5147 | } | ||
5148 | |||
5149 | /** | ||
5150 | * There are many ways to connect peers that are supported by this function. | ||
5151 | * To connect peers in the same topology that was created via the | ||
5152 | * GNUNET_TESTING_create_topology, the topology variable must be set to | ||
5153 | * GNUNET_TESTING_TOPOLOGY_NONE. If the topology variable is specified, | ||
5154 | * a new instance of that topology will be generated and attempted to be | ||
5155 | * connected. This could result in some connections being impossible, | ||
5156 | * because some topologies are non-deterministic. | ||
5157 | * | ||
5158 | * @param pg the peer group struct representing the running peers | ||
5159 | * @param topology which topology to connect the peers in | ||
5160 | * @param options options for connecting the topology | ||
5161 | * @param option_modifier modifier for options that take a parameter | ||
5162 | * @param connect_timeout how long to wait before giving up on connecting | ||
5163 | * two peers | ||
5164 | * @param connect_attempts how many times to attempt to connect two peers | ||
5165 | * over the connect_timeout duration | ||
5166 | * @param notify_callback notification to be called once all connections completed | ||
5167 | * @param notify_cls closure for notification callback | ||
5168 | * | ||
5169 | * @return the number of connections that will be attempted, GNUNET_SYSERR on error | ||
5170 | */ | ||
5171 | int | ||
5172 | GNUNET_TESTING_connect_topology (struct GNUNET_TESTING_PeerGroup *pg, | ||
5173 | enum GNUNET_TESTING_Topology topology, | ||
5174 | enum GNUNET_TESTING_TopologyOption options, | ||
5175 | double option_modifier, | ||
5176 | struct GNUNET_TIME_Relative connect_timeout, | ||
5177 | unsigned int connect_attempts, | ||
5178 | GNUNET_TESTING_NotifyCompletion | ||
5179 | notify_callback, void *notify_cls) | ||
5180 | { | ||
5181 | switch (topology) | ||
5182 | { | ||
5183 | case GNUNET_TESTING_TOPOLOGY_CLIQUE: | ||
5184 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5185 | "Creating clique CONNECT topology\n"); | ||
5186 | create_clique (pg, &add_connections, CONNECT, GNUNET_NO); | ||
5187 | break; | ||
5188 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING: | ||
5189 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5190 | "Creating small world (ring) CONNECT topology\n"); | ||
5191 | create_small_world_ring (pg, &add_connections, CONNECT); | ||
5192 | break; | ||
5193 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD: | ||
5194 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5195 | "Creating small world (2d-torus) CONNECT topology\n"); | ||
5196 | create_small_world (pg, &add_connections, CONNECT); | ||
5197 | break; | ||
5198 | case GNUNET_TESTING_TOPOLOGY_RING: | ||
5199 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating ring CONNECT topology\n"); | ||
5200 | create_ring (pg, &add_connections, CONNECT); | ||
5201 | break; | ||
5202 | case GNUNET_TESTING_TOPOLOGY_2D_TORUS: | ||
5203 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5204 | "Creating 2d torus CONNECT topology\n"); | ||
5205 | create_2d_torus (pg, &add_connections, CONNECT); | ||
5206 | break; | ||
5207 | case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI: | ||
5208 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5209 | "Creating Erdos-Renyi CONNECT topology\n"); | ||
5210 | create_erdos_renyi (pg, &add_connections, CONNECT); | ||
5211 | break; | ||
5212 | case GNUNET_TESTING_TOPOLOGY_INTERNAT: | ||
5213 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5214 | "Creating InterNAT CONNECT topology\n"); | ||
5215 | create_nated_internet (pg, &add_connections, CONNECT); | ||
5216 | break; | ||
5217 | case GNUNET_TESTING_TOPOLOGY_SCALE_FREE: | ||
5218 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5219 | "Creating Scale Free CONNECT topology\n"); | ||
5220 | create_scale_free (pg, &add_connections, CONNECT); | ||
5221 | break; | ||
5222 | case GNUNET_TESTING_TOPOLOGY_LINE: | ||
5223 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5224 | "Creating straight line CONNECT topology\n"); | ||
5225 | create_line (pg, &add_connections, CONNECT); | ||
5226 | break; | ||
5227 | case GNUNET_TESTING_TOPOLOGY_NONE: | ||
5228 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating no CONNECT topology\n"); | ||
5229 | copy_allowed_topology (pg); | ||
5230 | break; | ||
5231 | default: | ||
5232 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
5233 | _("Unknown topology specification, can't connect peers!\n")); | ||
5234 | return GNUNET_SYSERR; | ||
5235 | } | ||
5236 | |||
5237 | switch (options) | ||
5238 | { | ||
5239 | case GNUNET_TESTING_TOPOLOGY_OPTION_RANDOM: | ||
5240 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5241 | "Connecting random subset (%'.2f percent) of possible peers\n", | ||
5242 | 100 * option_modifier); | ||
5243 | choose_random_connections (pg, option_modifier); | ||
5244 | break; | ||
5245 | case GNUNET_TESTING_TOPOLOGY_OPTION_MINIMUM: | ||
5246 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5247 | "Connecting a minimum of %u peers each (if possible)\n", | ||
5248 | (unsigned int) option_modifier); | ||
5249 | choose_minimum (pg, (unsigned int) option_modifier); | ||
5250 | break; | ||
5251 | case GNUNET_TESTING_TOPOLOGY_OPTION_DFS: | ||
5252 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5253 | "Using DFS to connect a minimum of %u peers each (if possible)\n", | ||
5254 | (unsigned int) option_modifier); | ||
5255 | #if FIXME | ||
5256 | perform_dfs (pg, (int) option_modifier); | ||
5257 | #endif | ||
5258 | break; | ||
5259 | case GNUNET_TESTING_TOPOLOGY_OPTION_ADD_CLOSEST: | ||
5260 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5261 | "Finding additional %u closest peers each (if possible)\n", | ||
5262 | (unsigned int) option_modifier); | ||
5263 | #if FIXME | ||
5264 | add_closest (pg, (unsigned int) option_modifier, &add_connections, CONNECT); | ||
5265 | #endif | ||
5266 | break; | ||
5267 | case GNUNET_TESTING_TOPOLOGY_OPTION_NONE: | ||
5268 | break; | ||
5269 | case GNUNET_TESTING_TOPOLOGY_OPTION_ALL: | ||
5270 | break; | ||
5271 | default: | ||
5272 | break; | ||
5273 | } | ||
5274 | |||
5275 | return connect_topology (pg, connect_timeout, connect_attempts, | ||
5276 | notify_callback, notify_cls); | ||
5277 | } | ||
5278 | |||
5279 | /** | ||
5280 | * Lookup and return the number of SSH connections to a host. | ||
5281 | * | ||
5282 | * @param hostname the hostname to lookup in the list | ||
5283 | * @param pg the peergroup that the host belongs to | ||
5284 | * | ||
5285 | * @return the number of current ssh connections to the host | ||
5286 | */ | ||
5287 | static unsigned int | ||
5288 | count_outstanding_at_host (const char *hostname, | ||
5289 | struct GNUNET_TESTING_PeerGroup *pg) | ||
5290 | { | ||
5291 | struct OutstandingSSH *pos; | ||
5292 | |||
5293 | pos = pg->ssh_head; | ||
5294 | while ((pos != NULL) && (strcmp (pos->hostname, hostname) != 0)) | ||
5295 | pos = pos->next; | ||
5296 | GNUNET_assert (pos != NULL); | ||
5297 | return pos->outstanding; | ||
5298 | } | ||
5299 | |||
5300 | /** | ||
5301 | * Increment the number of SSH connections to a host by one. | ||
5302 | * | ||
5303 | * @param hostname the hostname to lookup in the list | ||
5304 | * @param pg the peergroup that the host belongs to | ||
5305 | * | ||
5306 | */ | ||
5307 | static void | ||
5308 | increment_outstanding_at_host (const char *hostname, | ||
5309 | struct GNUNET_TESTING_PeerGroup *pg) | ||
5310 | { | ||
5311 | struct OutstandingSSH *pos; | ||
5312 | |||
5313 | pos = pg->ssh_head; | ||
5314 | while ((NULL != pos) && (strcmp (pos->hostname, hostname) != 0)) | ||
5315 | pos = pos->next; | ||
5316 | GNUNET_assert (NULL != pos); | ||
5317 | pos->outstanding++; | ||
5318 | } | ||
5319 | |||
5320 | /** | ||
5321 | * Decrement the number of SSH connections to a host by one. | ||
5322 | * | ||
5323 | * @param hostname the hostname to lookup in the list | ||
5324 | * @param pg the peergroup that the host belongs to | ||
5325 | * | ||
5326 | */ | ||
5327 | static void | ||
5328 | decrement_outstanding_at_host (const char *hostname, | ||
5329 | struct GNUNET_TESTING_PeerGroup *pg) | ||
5330 | { | ||
5331 | struct OutstandingSSH *pos; | ||
5332 | |||
5333 | pos = pg->ssh_head; | ||
5334 | while ((pos != NULL) && (strcmp (pos->hostname, hostname) != 0)) | ||
5335 | pos = pos->next; | ||
5336 | GNUNET_assert (pos != NULL); | ||
5337 | pos->outstanding--; | ||
5338 | } | ||
5339 | |||
5340 | /** | ||
5341 | * Callback that is called whenever a hostkey is generated | ||
5342 | * for a peer. Call the real callback and decrement the | ||
5343 | * starting counter for the peergroup. | ||
5344 | * | ||
5345 | * @param cls closure | ||
5346 | * @param id identifier for the daemon, NULL on error | ||
5347 | * @param d handle for the daemon | ||
5348 | * @param emsg error message (NULL on success) | ||
5349 | */ | ||
5350 | static void | ||
5351 | internal_hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
5352 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
5353 | { | ||
5354 | struct InternalStartContext *internal_context = cls; | ||
5355 | |||
5356 | internal_context->peer->pg->starting--; | ||
5357 | internal_context->peer->pg->started++; | ||
5358 | if (internal_context->hostname != NULL) | ||
5359 | decrement_outstanding_at_host (internal_context->hostname, | ||
5360 | internal_context->peer->pg); | ||
5361 | if (internal_context->hostkey_callback != NULL) | ||
5362 | internal_context->hostkey_callback (internal_context->hostkey_cls, id, d, | ||
5363 | emsg); | ||
5364 | else if (internal_context->peer->pg->started == | ||
5365 | internal_context->peer->pg->total) | ||
5366 | { | ||
5367 | internal_context->peer->pg->started = 0; /* Internal startup may use this counter! */ | ||
5368 | GNUNET_TESTING_daemons_continue_startup (internal_context->peer->pg); | ||
5369 | } | ||
5370 | } | ||
5371 | |||
5372 | /** | ||
5373 | * Callback that is called whenever a peer has finished starting. | ||
5374 | * Call the real callback and decrement the starting counter | ||
5375 | * for the peergroup. | ||
5376 | * | ||
5377 | * @param cls closure | ||
5378 | * @param id identifier for the daemon, NULL on error | ||
5379 | * @param cfg config | ||
5380 | * @param d handle for the daemon | ||
5381 | * @param emsg error message (NULL on success) | ||
5382 | */ | ||
5383 | static void | ||
5384 | internal_startup_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
5385 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
5386 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
5387 | { | ||
5388 | struct InternalStartContext *internal_context = cls; | ||
5389 | |||
5390 | internal_context->peer->pg->starting--; | ||
5391 | if (internal_context->hostname != NULL) | ||
5392 | decrement_outstanding_at_host (internal_context->hostname, | ||
5393 | internal_context->peer->pg); | ||
5394 | if (internal_context->start_cb != NULL) | ||
5395 | internal_context->start_cb (internal_context->start_cb_cls, id, cfg, d, | ||
5396 | emsg); | ||
5397 | } | ||
5398 | |||
5399 | |||
5400 | /** | ||
5401 | * Calls GNUNET_TESTING_daemon_continue_startup to set the daemon's state | ||
5402 | * from HOSTKEY_CREATED to TOPOLOGY_SETUP. Makes sure not to saturate a host | ||
5403 | * with requests delaying them when needed. | ||
5404 | * | ||
5405 | * @param cls closure: internal context of the daemon. | ||
5406 | * @param tc TaskContext | ||
5407 | */ | ||
5408 | static void | ||
5409 | internal_continue_startup (void *cls, | ||
5410 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
5411 | { | ||
5412 | struct InternalStartContext *internal_context = cls; | ||
5413 | |||
5414 | internal_context->peer->startup_task = GNUNET_SCHEDULER_NO_TASK; | ||
5415 | |||
5416 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
5417 | { | ||
5418 | return; | ||
5419 | } | ||
5420 | |||
5421 | if ((internal_context->peer->pg->starting < | ||
5422 | internal_context->peer->pg->max_concurrent_ssh) || | ||
5423 | ((internal_context->hostname != NULL) && | ||
5424 | (count_outstanding_at_host | ||
5425 | (internal_context->hostname, | ||
5426 | internal_context->peer->pg) < | ||
5427 | internal_context->peer->pg->max_concurrent_ssh))) | ||
5428 | { | ||
5429 | if (internal_context->hostname != NULL) | ||
5430 | increment_outstanding_at_host (internal_context->hostname, | ||
5431 | internal_context->peer->pg); | ||
5432 | internal_context->peer->pg->starting++; | ||
5433 | GNUNET_TESTING_daemon_continue_startup (internal_context->peer->daemon); | ||
5434 | } | ||
5435 | else | ||
5436 | { | ||
5437 | internal_context->peer->startup_task = | ||
5438 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
5439 | (GNUNET_TIME_UNIT_MILLISECONDS, 100), | ||
5440 | &internal_continue_startup, | ||
5441 | internal_context); | ||
5442 | } | ||
5443 | } | ||
5444 | |||
5445 | /** | ||
5446 | * Callback for informing us about a successful | ||
5447 | * or unsuccessful churn start call. | ||
5448 | * | ||
5449 | * @param cls a ChurnContext | ||
5450 | * @param id the peer identity of the started peer | ||
5451 | * @param cfg the handle to the configuration of the peer | ||
5452 | * @param d handle to the daemon for the peer | ||
5453 | * @param emsg NULL on success, non-NULL on failure | ||
5454 | * | ||
5455 | */ | ||
5456 | void | ||
5457 | churn_start_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
5458 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
5459 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
5460 | { | ||
5461 | struct ChurnRestartContext *startup_ctx = cls; | ||
5462 | struct ChurnContext *churn_ctx = startup_ctx->churn_ctx; | ||
5463 | |||
5464 | unsigned int total_left; | ||
5465 | char *error_message; | ||
5466 | |||
5467 | error_message = NULL; | ||
5468 | if (emsg != NULL) | ||
5469 | { | ||
5470 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
5471 | "Churn stop callback failed with error `%s'\n", emsg); | ||
5472 | churn_ctx->num_failed_start++; | ||
5473 | } | ||
5474 | else | ||
5475 | { | ||
5476 | churn_ctx->num_to_start--; | ||
5477 | } | ||
5478 | |||
5479 | total_left = | ||
5480 | (churn_ctx->num_to_stop - churn_ctx->num_failed_stop) + | ||
5481 | (churn_ctx->num_to_start - churn_ctx->num_failed_start); | ||
5482 | |||
5483 | if (total_left == 0) | ||
5484 | { | ||
5485 | if ((churn_ctx->num_failed_stop > 0) || (churn_ctx->num_failed_start > 0)) | ||
5486 | GNUNET_asprintf (&error_message, | ||
5487 | "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!", | ||
5488 | churn_ctx->num_failed_start, churn_ctx->num_failed_stop); | ||
5489 | churn_ctx->cb (churn_ctx->cb_cls, error_message); | ||
5490 | GNUNET_free_non_null (error_message); | ||
5491 | GNUNET_free (churn_ctx); | ||
5492 | GNUNET_free (startup_ctx); | ||
5493 | } | ||
5494 | } | ||
5495 | |||
5496 | static void | ||
5497 | schedule_churn_restart (void *cls, | ||
5498 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
5499 | { | ||
5500 | struct PeerRestartContext *peer_restart_ctx = cls; | ||
5501 | struct ChurnRestartContext *startup_ctx = peer_restart_ctx->churn_restart_ctx; | ||
5502 | |||
5503 | if (startup_ctx->outstanding > startup_ctx->pg->max_concurrent_ssh) | ||
5504 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
5505 | (GNUNET_TIME_UNIT_MILLISECONDS, 100), | ||
5506 | &schedule_churn_restart, peer_restart_ctx); | ||
5507 | else | ||
5508 | { | ||
5509 | if (startup_ctx->churn_ctx->service != NULL) | ||
5510 | GNUNET_TESTING_daemon_start_stopped_service (peer_restart_ctx->daemon, | ||
5511 | startup_ctx-> | ||
5512 | churn_ctx->service, | ||
5513 | startup_ctx->timeout, | ||
5514 | &churn_start_callback, | ||
5515 | startup_ctx); | ||
5516 | else | ||
5517 | GNUNET_TESTING_daemon_start_stopped (peer_restart_ctx->daemon, | ||
5518 | startup_ctx->timeout, | ||
5519 | &churn_start_callback, startup_ctx); | ||
5520 | GNUNET_free (peer_restart_ctx); | ||
5521 | } | ||
5522 | } | ||
5523 | |||
5524 | /** | ||
5525 | * Callback for informing us about a successful | ||
5526 | * or unsuccessful churn start call. | ||
5527 | * | ||
5528 | * @param cls a struct ServiceStartContext *startup_ctx | ||
5529 | * @param id the peer identity of the started peer | ||
5530 | * @param cfg the handle to the configuration of the peer | ||
5531 | * @param d handle to the daemon for the peer | ||
5532 | * @param emsg NULL on success, non-NULL on failure | ||
5533 | * | ||
5534 | */ | ||
5535 | void | ||
5536 | service_start_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
5537 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
5538 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
5539 | { | ||
5540 | struct ServiceStartContext *startup_ctx = (struct ServiceStartContext *) cls; | ||
5541 | |||
5542 | if (emsg != NULL) | ||
5543 | { | ||
5544 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
5545 | "Service start failed with error `%s'\n", emsg); | ||
5546 | } | ||
5547 | |||
5548 | startup_ctx->outstanding--; | ||
5549 | startup_ctx->remaining--; | ||
5550 | |||
5551 | if (startup_ctx->remaining == 0) | ||
5552 | { | ||
5553 | startup_ctx->cb (startup_ctx->cb_cls, NULL); | ||
5554 | GNUNET_free (startup_ctx->service); | ||
5555 | GNUNET_free (startup_ctx); | ||
5556 | } | ||
5557 | } | ||
5558 | |||
5559 | static void | ||
5560 | schedule_service_start (void *cls, | ||
5561 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
5562 | { | ||
5563 | struct PeerServiceStartContext *peer_ctx = cls; | ||
5564 | struct ServiceStartContext *startup_ctx = peer_ctx->start_ctx; | ||
5565 | |||
5566 | if (startup_ctx->outstanding > startup_ctx->pg->max_concurrent_ssh) | ||
5567 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
5568 | (GNUNET_TIME_UNIT_MILLISECONDS, 100), | ||
5569 | &schedule_service_start, peer_ctx); | ||
5570 | else | ||
5571 | { | ||
5572 | |||
5573 | GNUNET_TESTING_daemon_start_service (peer_ctx->daemon, startup_ctx->service, | ||
5574 | startup_ctx->timeout, | ||
5575 | &service_start_callback, startup_ctx); | ||
5576 | GNUNET_free (peer_ctx); | ||
5577 | } | ||
5578 | } | ||
5579 | |||
5580 | |||
5581 | static void | ||
5582 | internal_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
5583 | { | ||
5584 | struct InternalStartContext *internal_context = cls; | ||
5585 | |||
5586 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
5587 | { | ||
5588 | return; | ||
5589 | } | ||
5590 | |||
5591 | if ((internal_context->peer->pg->starting < | ||
5592 | internal_context->peer->pg->max_concurrent_ssh) || | ||
5593 | ((internal_context->hostname != NULL) && | ||
5594 | (count_outstanding_at_host | ||
5595 | (internal_context->hostname, | ||
5596 | internal_context->peer->pg) < | ||
5597 | internal_context->peer->pg->max_concurrent_ssh))) | ||
5598 | { | ||
5599 | if (internal_context->hostname != NULL) | ||
5600 | increment_outstanding_at_host (internal_context->hostname, | ||
5601 | internal_context->peer->pg); | ||
5602 | internal_context->peer->pg->starting++; | ||
5603 | internal_context->peer->daemon = | ||
5604 | GNUNET_TESTING_daemon_start (internal_context->peer->cfg, | ||
5605 | internal_context->timeout, GNUNET_NO, | ||
5606 | internal_context->hostname, | ||
5607 | internal_context->username, | ||
5608 | internal_context->sshport, | ||
5609 | internal_context->hostkey, | ||
5610 | &internal_hostkey_callback, | ||
5611 | internal_context, | ||
5612 | &internal_startup_callback, | ||
5613 | internal_context); | ||
5614 | } | ||
5615 | else | ||
5616 | { | ||
5617 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
5618 | (GNUNET_TIME_UNIT_MILLISECONDS, 100), | ||
5619 | &internal_start, internal_context); | ||
5620 | } | ||
5621 | } | ||
5622 | |||
5623 | #if USE_START_HELPER | ||
5624 | |||
5625 | struct PeerStartHelperContext | ||
5626 | { | ||
5627 | struct GNUNET_TESTING_PeerGroup *pg; | ||
5628 | |||
5629 | struct HostData *host; | ||
5630 | |||
5631 | struct GNUNET_OS_Process *proc; | ||
5632 | }; | ||
5633 | |||
5634 | static void | ||
5635 | check_peers_started (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
5636 | { | ||
5637 | struct PeerStartHelperContext *helper = cls; | ||
5638 | enum GNUNET_OS_ProcessStatusType type; | ||
5639 | unsigned long code; | ||
5640 | unsigned int i; | ||
5641 | GNUNET_TESTING_NotifyDaemonRunning cb; | ||
5642 | |||
5643 | if (GNUNET_NO == GNUNET_OS_process_status (helper->proc, &type, &code)) /* Still running, wait some more! */ | ||
5644 | { | ||
5645 | GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, | ||
5646 | &check_peers_started, helper); | ||
5647 | return; | ||
5648 | } | ||
5649 | |||
5650 | helper->pg->starting--; | ||
5651 | if (helper->pg->starting == 0) /* All peers have finished starting! */ | ||
5652 | { | ||
5653 | /* Call the peer started callback for each peer, set proper FSM state (?) */ | ||
5654 | for (i = 0; i < helper->pg->total; i++) | ||
5655 | { | ||
5656 | cb = helper->pg->peers[i].daemon->cb; | ||
5657 | helper->pg->peers[i].daemon->cb = NULL; | ||
5658 | helper->pg->peers[i].daemon->running = GNUNET_YES; | ||
5659 | helper->pg->peers[i].daemon->phase = SP_START_DONE; | ||
5660 | if (NULL != cb) | ||
5661 | { | ||
5662 | if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0)) | ||
5663 | cb (helper->pg->peers[i].daemon->cb_cls, | ||
5664 | &helper->pg->peers[i].daemon->id, | ||
5665 | helper->pg->peers[i].daemon->cfg, helper->pg->peers[i].daemon, | ||
5666 | "Failed to execute peerStartHelper.pl, or return code bad!"); | ||
5667 | else | ||
5668 | cb (helper->pg->peers[i].daemon->cb_cls, | ||
5669 | &helper->pg->peers[i].daemon->id, | ||
5670 | helper->pg->peers[i].daemon->cfg, helper->pg->peers[i].daemon, | ||
5671 | NULL); | ||
5672 | |||
5673 | } | ||
5674 | |||
5675 | } | ||
5676 | } | ||
5677 | GNUNET_OS_process_destroy (helper->proc); | ||
5678 | } | ||
5679 | |||
5680 | static void | ||
5681 | start_peer_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
5682 | { | ||
5683 | struct PeerStartHelperContext *helper = cls; | ||
5684 | char *baseservicehome; | ||
5685 | char *tempdir; | ||
5686 | char *arg; | ||
5687 | |||
5688 | /* ssh user@host peerStartHelper /path/to/basedirectory */ | ||
5689 | GNUNET_assert (GNUNET_OK == | ||
5690 | GNUNET_CONFIGURATION_get_value_string (helper->pg->cfg, | ||
5691 | "PATHS", "SERVICEHOME", | ||
5692 | &baseservicehome)); | ||
5693 | GNUNET_asprintf (&tempdir, "%s/%s/", baseservicehome, helper->host->hostname); | ||
5694 | if (NULL != helper->host->username) | ||
5695 | GNUNET_asprintf (&arg, "%s@%s", helper->host->username, | ||
5696 | helper->host->hostname); | ||
5697 | else | ||
5698 | GNUNET_asprintf (&arg, "%s", helper->host->hostname); | ||
5699 | |||
5700 | /* FIXME: Doesn't support ssh_port option! */ | ||
5701 | helper->proc = | ||
5702 | GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "ssh", "ssh", arg, | ||
5703 | "peerStartHelper.pl", tempdir, NULL); | ||
5704 | GNUNET_assert (helper->proc != NULL); | ||
5705 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting peers with cmd ssh %s %s %s\n", | ||
5706 | arg, "peerStartHelper.pl", tempdir); | ||
5707 | GNUNET_SCHEDULER_add_now (&check_peers_started, helper); | ||
5708 | GNUNET_free (tempdir); | ||
5709 | GNUNET_free (baseservicehome); | ||
5710 | GNUNET_free (arg); | ||
5711 | } | ||
5712 | #endif | ||
5713 | |||
5714 | /** | ||
5715 | * Function which continues a peer group starting up | ||
5716 | * after successfully generating hostkeys for each peer. | ||
5717 | * | ||
5718 | * @param pg the peer group to continue starting | ||
5719 | * | ||
5720 | */ | ||
5721 | void | ||
5722 | GNUNET_TESTING_daemons_continue_startup (struct GNUNET_TESTING_PeerGroup *pg) | ||
5723 | { | ||
5724 | unsigned int i; | ||
5725 | |||
5726 | #if USE_START_HELPER | ||
5727 | if ((pg->num_hosts > 0) && (pg->hostkey_data != NULL)) | ||
5728 | { | ||
5729 | struct PeerStartHelperContext *helper; | ||
5730 | |||
5731 | pg->starting = pg->num_hosts; | ||
5732 | for (i = 0; i < pg->num_hosts; i++) | ||
5733 | { | ||
5734 | helper = GNUNET_malloc (sizeof (struct PeerStartHelperContext)); | ||
5735 | helper->pg = pg; | ||
5736 | helper->host = &pg->hosts[i]; | ||
5737 | GNUNET_SCHEDULER_add_now (&start_peer_helper, helper); | ||
5738 | } | ||
5739 | } | ||
5740 | else | ||
5741 | { | ||
5742 | pg->starting = 0; | ||
5743 | for (i = 0; i < pg->total; i++) | ||
5744 | { | ||
5745 | pg->peers[i].startup_task = | ||
5746 | GNUNET_SCHEDULER_add_now (&internal_continue_startup, | ||
5747 | &pg->peers[i].internal_context); | ||
5748 | } | ||
5749 | } | ||
5750 | #else | ||
5751 | pg->starting = 0; | ||
5752 | for (i = 0; i < pg->total; i++) | ||
5753 | { | ||
5754 | pg->peers[i].startup_task = | ||
5755 | GNUNET_SCHEDULER_add_now (&internal_continue_startup, | ||
5756 | &pg->peers[i].internal_context); | ||
5757 | } | ||
5758 | #endif | ||
5759 | } | ||
5760 | |||
5761 | #if USE_START_HELPER | ||
5762 | static void | ||
5763 | call_hostkey_callbacks (void *cls, | ||
5764 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
5765 | { | ||
5766 | struct GNUNET_TESTING_PeerGroup *pg = cls; | ||
5767 | unsigned int i; | ||
5768 | |||
5769 | for (i = 0; i < pg->total; i++) | ||
5770 | { | ||
5771 | if (pg->peers[i].internal_context.hostkey_callback != NULL) | ||
5772 | pg->peers[i].internal_context.hostkey_callback (pg->peers[i]. | ||
5773 | internal_context.hostkey_cls, | ||
5774 | &pg->peers[i].daemon->id, | ||
5775 | pg->peers[i].daemon, | ||
5776 | NULL); | ||
5777 | } | ||
5778 | |||
5779 | if (pg->peers[0].internal_context.hostkey_callback == NULL) | ||
5780 | GNUNET_TESTING_daemons_continue_startup (pg); | ||
5781 | } | ||
5782 | #endif | ||
5783 | |||
5784 | /** | ||
5785 | * Start count gnunet instances with the same set of transports and | ||
5786 | * applications. The port numbers (any option called "PORT") will be | ||
5787 | * adjusted to ensure that no two peers running on the same system | ||
5788 | * have the same port(s) in their respective configurations. | ||
5789 | * | ||
5790 | * @param cfg configuration template to use | ||
5791 | * @param total number of daemons to start | ||
5792 | * @param max_concurrent_connections for testing, how many peers can | ||
5793 | * we connect to simultaneously | ||
5794 | * @param max_concurrent_ssh when starting with ssh, how many ssh | ||
5795 | * connections will we allow at once (based on remote hosts allowed!) | ||
5796 | * @param timeout total time allowed for peers to start | ||
5797 | * @param hostkey_callback function to call on each peers hostkey generation | ||
5798 | * if NULL, peers will be started by this call, if non-null, | ||
5799 | * GNUNET_TESTING_daemons_continue_startup must be called after | ||
5800 | * successful hostkey generation | ||
5801 | * @param hostkey_cls closure for hostkey callback | ||
5802 | * @param cb function to call on each daemon that was started | ||
5803 | * @param cb_cls closure for cb | ||
5804 | * @param connect_callback function to call each time two hosts are connected | ||
5805 | * @param connect_callback_cls closure for connect_callback | ||
5806 | * @param hostnames linked list of host structs to use to start peers on | ||
5807 | * (NULL to run on localhost only) | ||
5808 | * | ||
5809 | * @return NULL on error, otherwise handle to control peer group | ||
5810 | */ | ||
5811 | struct GNUNET_TESTING_PeerGroup * | ||
5812 | GNUNET_TESTING_daemons_start (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
5813 | unsigned int total, | ||
5814 | unsigned int max_concurrent_connections, | ||
5815 | unsigned int max_concurrent_ssh, | ||
5816 | struct GNUNET_TIME_Relative timeout, | ||
5817 | GNUNET_TESTING_NotifyHostkeyCreated | ||
5818 | hostkey_callback, void *hostkey_cls, | ||
5819 | GNUNET_TESTING_NotifyDaemonRunning cb, | ||
5820 | void *cb_cls, | ||
5821 | GNUNET_TESTING_NotifyConnection connect_callback, | ||
5822 | void *connect_callback_cls, | ||
5823 | const struct GNUNET_TESTING_Host *hostnames) | ||
5824 | { | ||
5825 | struct GNUNET_TESTING_PeerGroup *pg; | ||
5826 | const struct GNUNET_TESTING_Host *hostpos; | ||
5827 | const char *hostname; | ||
5828 | const char *username; | ||
5829 | char *baseservicehome; | ||
5830 | char *newservicehome; | ||
5831 | char *tmpdir; | ||
5832 | char *hostkeys_file; | ||
5833 | char *arg; | ||
5834 | char *ssh_port_str; | ||
5835 | struct GNUNET_DISK_FileHandle *fd; | ||
5836 | struct GNUNET_CONFIGURATION_Handle *pcfg; | ||
5837 | unsigned int off; | ||
5838 | struct OutstandingSSH *ssh_entry; | ||
5839 | unsigned int hostcnt; | ||
5840 | unsigned int i; | ||
5841 | uint16_t minport; | ||
5842 | uint16_t sshport; | ||
5843 | uint32_t upnum; | ||
5844 | uint32_t fdnum; | ||
5845 | uint64_t fs; | ||
5846 | uint64_t total_hostkeys; | ||
5847 | struct GNUNET_OS_Process *proc; | ||
5848 | |||
5849 | username = NULL; | ||
5850 | if (0 == total) | ||
5851 | { | ||
5852 | GNUNET_break (0); | ||
5853 | return NULL; | ||
5854 | } | ||
5855 | |||
5856 | upnum = 0; | ||
5857 | fdnum = 0; | ||
5858 | pg = GNUNET_malloc (sizeof (struct GNUNET_TESTING_PeerGroup)); | ||
5859 | pg->cfg = cfg; | ||
5860 | pg->notify_connection = connect_callback; | ||
5861 | pg->notify_connection_cls = connect_callback_cls; | ||
5862 | pg->total = total; | ||
5863 | pg->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
5864 | pg->peers = GNUNET_malloc (total * sizeof (struct PeerData)); | ||
5865 | pg->max_outstanding_connections = max_concurrent_connections; | ||
5866 | pg->max_concurrent_ssh = max_concurrent_ssh; | ||
5867 | if (NULL != hostnames) | ||
5868 | { | ||
5869 | off = 0; | ||
5870 | hostpos = hostnames; | ||
5871 | while (hostpos != NULL) | ||
5872 | { | ||
5873 | hostpos = hostpos->next; | ||
5874 | off++; | ||
5875 | } | ||
5876 | pg->hosts = GNUNET_malloc (off * sizeof (struct HostData)); | ||
5877 | off = 0; | ||
5878 | |||
5879 | hostpos = hostnames; | ||
5880 | while (hostpos != NULL) | ||
5881 | { | ||
5882 | pg->hosts[off].minport = LOW_PORT; | ||
5883 | pg->hosts[off].hostname = GNUNET_strdup (hostpos->hostname); | ||
5884 | if (hostpos->username != NULL) | ||
5885 | pg->hosts[off].username = GNUNET_strdup (hostpos->username); | ||
5886 | pg->hosts[off].sshport = hostpos->port; | ||
5887 | hostpos = hostpos->next; | ||
5888 | off++; | ||
5889 | } | ||
5890 | |||
5891 | if (off == 0) | ||
5892 | { | ||
5893 | pg->hosts = NULL; | ||
5894 | } | ||
5895 | hostcnt = off; | ||
5896 | minport = 0; | ||
5897 | pg->num_hosts = off; | ||
5898 | } | ||
5899 | else | ||
5900 | { | ||
5901 | hostcnt = 0; | ||
5902 | minport = LOW_PORT; | ||
5903 | } | ||
5904 | |||
5905 | /* Create the servicehome directory for each remote peer */ | ||
5906 | GNUNET_assert (GNUNET_OK == | ||
5907 | GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", | ||
5908 | "SERVICEHOME", | ||
5909 | &baseservicehome)); | ||
5910 | for (i = 0; i < pg->num_hosts; i++) | ||
5911 | { | ||
5912 | ssh_entry = GNUNET_malloc (sizeof (struct OutstandingSSH)); | ||
5913 | ssh_entry->hostname = pg->hosts[i].hostname; /* Don't free! */ | ||
5914 | GNUNET_CONTAINER_DLL_insert (pg->ssh_head, pg->ssh_tail, ssh_entry); | ||
5915 | GNUNET_asprintf (&tmpdir, "%s/%s", baseservicehome, pg->hosts[i].hostname); | ||
5916 | if (NULL != pg->hosts[i].username) | ||
5917 | GNUNET_asprintf (&arg, "%s@%s", pg->hosts[i].username, | ||
5918 | pg->hosts[i].hostname); | ||
5919 | else | ||
5920 | GNUNET_asprintf (&arg, "%s", pg->hosts[i].hostname); | ||
5921 | if (pg->hosts[i].sshport != 0) | ||
5922 | { | ||
5923 | GNUNET_asprintf (&ssh_port_str, "%d", pg->hosts[i].sshport); | ||
5924 | proc = | ||
5925 | GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "ssh", "ssh", "-P", ssh_port_str, | ||
5926 | "-q", | ||
5927 | arg, "mkdir -p", tmpdir, NULL); | ||
5928 | } | ||
5929 | else | ||
5930 | proc = | ||
5931 | GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "ssh", "ssh", arg, "mkdir -p", | ||
5932 | tmpdir, NULL); | ||
5933 | GNUNET_assert (proc != NULL); | ||
5934 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5935 | "Creating remote dir with command ssh %s %s %s\n", arg, | ||
5936 | " mkdir -p ", tmpdir); | ||
5937 | GNUNET_free (tmpdir); | ||
5938 | GNUNET_free (arg); | ||
5939 | GNUNET_OS_process_wait (proc); | ||
5940 | GNUNET_OS_process_destroy (proc); | ||
5941 | } | ||
5942 | GNUNET_free (baseservicehome); | ||
5943 | baseservicehome = NULL; | ||
5944 | |||
5945 | if (GNUNET_YES == | ||
5946 | GNUNET_CONFIGURATION_get_value_string (cfg, "TESTING_OLD", "HOSTKEYSFILE", | ||
5947 | &hostkeys_file)) | ||
5948 | { | ||
5949 | /* This is a hack to make old testing able to load keys from datadir, | ||
5950 | * just as new testing does. | ||
5951 | * No need to document it, just convert everything to the new testing | ||
5952 | * framework... | ||
5953 | */ | ||
5954 | char *DATADIR = "${DATADIR}"; | ||
5955 | size_t ddl = strlen (DATADIR); | ||
5956 | if (strncmp (hostkeys_file, DATADIR, ddl) == 0) | ||
5957 | { | ||
5958 | char *data_dir; | ||
5959 | char *filename; | ||
5960 | data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); | ||
5961 | GNUNET_asprintf (&filename, "%s%s", data_dir, &hostkeys_file[ddl]); | ||
5962 | GNUNET_free (data_dir); | ||
5963 | GNUNET_free (hostkeys_file); | ||
5964 | hostkeys_file = filename; | ||
5965 | } | ||
5966 | if (GNUNET_YES != GNUNET_DISK_file_test (hostkeys_file)) | ||
5967 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
5968 | _("Could not read hostkeys file `%s'!\n"), hostkeys_file); | ||
5969 | else | ||
5970 | { | ||
5971 | /* Check hostkey file size, read entire thing into memory */ | ||
5972 | fd = GNUNET_DISK_file_open (hostkeys_file, GNUNET_DISK_OPEN_READ, | ||
5973 | GNUNET_DISK_PERM_NONE); | ||
5974 | if (NULL == fd) | ||
5975 | { | ||
5976 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", | ||
5977 | hostkeys_file); | ||
5978 | GNUNET_free (hostkeys_file); | ||
5979 | for (i = 0; i < pg->num_hosts; i++) | ||
5980 | { | ||
5981 | GNUNET_free (pg->hosts[i].hostname); | ||
5982 | GNUNET_free_non_null (pg->hosts[i].username); | ||
5983 | } | ||
5984 | GNUNET_free (pg->peers); | ||
5985 | GNUNET_free (pg->hosts); | ||
5986 | GNUNET_free (pg); | ||
5987 | return NULL; | ||
5988 | } | ||
5989 | |||
5990 | if (GNUNET_OK != GNUNET_DISK_file_size (hostkeys_file, &fs, GNUNET_YES, GNUNET_YES)) | ||
5991 | fs = 0; | ||
5992 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5993 | "Found file size %llu for hostkeys\n", fs); | ||
5994 | if (0 != (fs % HOSTKEYFILESIZE)) | ||
5995 | { | ||
5996 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
5997 | "File size %llu seems incorrect for hostkeys...\n", fs); | ||
5998 | } | ||
5999 | else | ||
6000 | { | ||
6001 | total_hostkeys = fs / HOSTKEYFILESIZE; | ||
6002 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
6003 | "Will read %llu hostkeys from file\n", total_hostkeys); | ||
6004 | pg->hostkey_data = GNUNET_malloc_large (fs); | ||
6005 | GNUNET_assert (fs == GNUNET_DISK_file_read (fd, pg->hostkey_data, fs)); | ||
6006 | } | ||
6007 | GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd)); | ||
6008 | } | ||
6009 | GNUNET_free (hostkeys_file); | ||
6010 | } | ||
6011 | |||
6012 | for (off = 0; off < total; off++) | ||
6013 | { | ||
6014 | if (hostcnt > 0) | ||
6015 | { | ||
6016 | hostname = pg->hosts[off % hostcnt].hostname; | ||
6017 | username = pg->hosts[off % hostcnt].username; | ||
6018 | sshport = pg->hosts[off % hostcnt].sshport; | ||
6019 | pcfg = | ||
6020 | GNUNET_TESTING_create_cfg (cfg, off, &pg->hosts[off % hostcnt].minport, &upnum, | ||
6021 | hostname, &fdnum); | ||
6022 | } | ||
6023 | else | ||
6024 | { | ||
6025 | hostname = NULL; | ||
6026 | username = NULL; | ||
6027 | sshport = 0; | ||
6028 | pcfg = GNUNET_TESTING_create_cfg (cfg, off, &minport, &upnum, hostname, &fdnum); | ||
6029 | } | ||
6030 | |||
6031 | if (NULL == pcfg) | ||
6032 | { | ||
6033 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
6034 | _ | ||
6035 | ("Could not create configuration for peer number %u on `%s'!\n"), | ||
6036 | off, hostname == NULL ? "localhost" : hostname); | ||
6037 | continue; | ||
6038 | } | ||
6039 | |||
6040 | if (GNUNET_YES == | ||
6041 | GNUNET_CONFIGURATION_get_value_string (pcfg, "PATHS", "SERVICEHOME", | ||
6042 | &baseservicehome)) | ||
6043 | { | ||
6044 | if (hostname != NULL) | ||
6045 | GNUNET_asprintf (&newservicehome, "%s/%s/%d/", baseservicehome, | ||
6046 | hostname, off); | ||
6047 | else | ||
6048 | GNUNET_asprintf (&newservicehome, "%s/%d/", baseservicehome, off); | ||
6049 | GNUNET_free (baseservicehome); | ||
6050 | baseservicehome = NULL; | ||
6051 | } | ||
6052 | else | ||
6053 | { | ||
6054 | tmpdir = getenv ("TMPDIR"); | ||
6055 | tmpdir = tmpdir ? tmpdir : "/tmp"; | ||
6056 | if (hostname != NULL) | ||
6057 | GNUNET_asprintf (&newservicehome, "%s/%s/%s/%d/", tmpdir, hostname, | ||
6058 | "gnunet-testing-test-test", off); | ||
6059 | else | ||
6060 | GNUNET_asprintf (&newservicehome, "%s/%s/%d/", tmpdir, | ||
6061 | "gnunet-testing-test-test", off); | ||
6062 | } | ||
6063 | GNUNET_CONFIGURATION_set_value_string (pcfg, "PATHS", "SERVICEHOME", | ||
6064 | newservicehome); | ||
6065 | GNUNET_free (newservicehome); | ||
6066 | pg->peers[off].cfg = pcfg; | ||
6067 | pg->peers[off].pg = pg; | ||
6068 | pg->peers[off].internal_context.peer = &pg->peers[off]; | ||
6069 | pg->peers[off].internal_context.timeout = timeout; | ||
6070 | pg->peers[off].internal_context.hostname = hostname; | ||
6071 | pg->peers[off].internal_context.username = username; | ||
6072 | pg->peers[off].internal_context.sshport = sshport; | ||
6073 | if (pg->hostkey_data != NULL) | ||
6074 | pg->peers[off].internal_context.hostkey = | ||
6075 | &pg->hostkey_data[off * HOSTKEYFILESIZE]; | ||
6076 | pg->peers[off].internal_context.hostkey_callback = hostkey_callback; | ||
6077 | pg->peers[off].internal_context.hostkey_cls = hostkey_cls; | ||
6078 | pg->peers[off].internal_context.start_cb = cb; | ||
6079 | pg->peers[off].internal_context.start_cb_cls = cb_cls; | ||
6080 | #if !USE_START_HELPER | ||
6081 | GNUNET_SCHEDULER_add_now (&internal_start, | ||
6082 | &pg->peers[off].internal_context); | ||
6083 | #else | ||
6084 | if ((pg->hostkey_data != NULL) && (hostcnt > 0)) | ||
6085 | { | ||
6086 | pg->peers[off].daemon = | ||
6087 | GNUNET_TESTING_daemon_start (pcfg, timeout, GNUNET_YES, hostname, | ||
6088 | username, sshport, | ||
6089 | pg->peers[off].internal_context.hostkey, | ||
6090 | &internal_hostkey_callback, | ||
6091 | &pg->peers[off].internal_context, | ||
6092 | &internal_startup_callback, | ||
6093 | &pg->peers[off].internal_context); | ||
6094 | /** | ||
6095 | * At this point, given that we had a hostkeyfile, | ||
6096 | * we can call the hostkey callback! | ||
6097 | * But first, we should copy (rsync) all of the configs | ||
6098 | * and hostkeys to the remote peers. Then let topology | ||
6099 | * creation happen, then call the peer start helper processes, | ||
6100 | * then set pg->whatever_phase for each peer and let them | ||
6101 | * enter the fsm to get the HELLO's for peers and start connecting. | ||
6102 | */ | ||
6103 | } | ||
6104 | else | ||
6105 | { | ||
6106 | GNUNET_SCHEDULER_add_now (&internal_start, | ||
6107 | &pg->peers[off].internal_context); | ||
6108 | } | ||
6109 | |||
6110 | #endif | ||
6111 | } | ||
6112 | |||
6113 | #if USE_START_HELPER /* Now the peergroup has been set up, hostkeys and configs written to files. */ | ||
6114 | if ((pg->hostkey_data != NULL) && (hostcnt > 0)) | ||
6115 | { | ||
6116 | for (off = 0; off < hostcnt; off++) | ||
6117 | { | ||
6118 | |||
6119 | if (hostcnt > 0) | ||
6120 | { | ||
6121 | hostname = pg->hosts[off % hostcnt].hostname; | ||
6122 | username = pg->hosts[off % hostcnt].username; | ||
6123 | sshport = pg->hosts[off % hostcnt].sshport; | ||
6124 | } | ||
6125 | else | ||
6126 | { | ||
6127 | hostname = NULL; | ||
6128 | username = NULL; | ||
6129 | sshport = 0; | ||
6130 | } | ||
6131 | |||
6132 | if (GNUNET_YES == | ||
6133 | GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "SERVICEHOME", | ||
6134 | &baseservicehome)) | ||
6135 | { | ||
6136 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "baseservice home is %s\n", | ||
6137 | baseservicehome); | ||
6138 | if (hostname != NULL) | ||
6139 | GNUNET_asprintf (&newservicehome, "%s/%s/", baseservicehome, | ||
6140 | hostname); | ||
6141 | else | ||
6142 | GNUNET_asprintf (&newservicehome, "%s/", baseservicehome); | ||
6143 | GNUNET_free (baseservicehome); | ||
6144 | baseservicehome = NULL; | ||
6145 | } | ||
6146 | else | ||
6147 | { | ||
6148 | tmpdir = getenv ("TMPDIR"); | ||
6149 | tmpdir = tmpdir ? tmpdir : "/tmp"; | ||
6150 | if (hostname != NULL) | ||
6151 | GNUNET_asprintf (&newservicehome, "%s/%s/%s/", tmpdir, hostname, | ||
6152 | "gnunet-testing-test-test"); | ||
6153 | else | ||
6154 | GNUNET_asprintf (&newservicehome, "%s/%s/", tmpdir, | ||
6155 | "gnunet-testing-test-test", off); | ||
6156 | } | ||
6157 | |||
6158 | if (NULL != username) | ||
6159 | GNUNET_asprintf (&arg, "%s@%s:%s", username, pg->hosts[off].hostname, | ||
6160 | newservicehome); | ||
6161 | else | ||
6162 | GNUNET_asprintf (&arg, "%s:%s", pg->hosts[off].hostname, | ||
6163 | newservicehome); | ||
6164 | |||
6165 | /* FIXME: Doesn't support ssh_port option! */ | ||
6166 | proc = | ||
6167 | GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "rsync", "rsync", "-r", | ||
6168 | newservicehome, arg, NULL); | ||
6169 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
6170 | "copying directory with command rsync -r %s %s\n", | ||
6171 | newservicehome, arg); | ||
6172 | GNUNET_free (newservicehome); | ||
6173 | GNUNET_free (arg); | ||
6174 | if (NULL == proc) | ||
6175 | { | ||
6176 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
6177 | _ | ||
6178 | ("Could not start `%s' process to copy configuration directory.\n"), | ||
6179 | "scp"); | ||
6180 | GNUNET_assert (0); | ||
6181 | } | ||
6182 | GNUNET_OS_process_wait (proc); | ||
6183 | GNUNET_OS_process_destroy (proc); | ||
6184 | } | ||
6185 | /* Now all the configuration files and hostkeys are copied to the remote host. Call the hostkey callback for each peer! */ | ||
6186 | GNUNET_SCHEDULER_add_now (&call_hostkey_callbacks, pg); | ||
6187 | } | ||
6188 | #endif | ||
6189 | return pg; | ||
6190 | } | ||
6191 | |||
6192 | /* | ||
6193 | * Get a daemon by number, so callers don't have to do nasty | ||
6194 | * offsetting operation. | ||
6195 | */ | ||
6196 | struct GNUNET_TESTING_Daemon * | ||
6197 | GNUNET_TESTING_daemon_get (struct GNUNET_TESTING_PeerGroup *pg, | ||
6198 | unsigned int position) | ||
6199 | { | ||
6200 | if (position < pg->total) | ||
6201 | return pg->peers[position].daemon; | ||
6202 | return NULL; | ||
6203 | } | ||
6204 | |||
6205 | /* | ||
6206 | * Get a daemon by peer identity, so callers can | ||
6207 | * retrieve the daemon without knowing it's offset. | ||
6208 | * | ||
6209 | * @param pg the peer group to retrieve the daemon from | ||
6210 | * @param peer_id the peer identity of the daemon to retrieve | ||
6211 | * | ||
6212 | * @return the daemon on success, or NULL if no such peer identity is found | ||
6213 | */ | ||
6214 | struct GNUNET_TESTING_Daemon * | ||
6215 | GNUNET_TESTING_daemon_get_by_id (struct GNUNET_TESTING_PeerGroup *pg, | ||
6216 | const struct GNUNET_PeerIdentity *peer_id) | ||
6217 | { | ||
6218 | unsigned int i; | ||
6219 | |||
6220 | for (i = 0; i < pg->total; i++) | ||
6221 | { | ||
6222 | if (0 == | ||
6223 | memcmp (&pg->peers[i].daemon->id, peer_id, | ||
6224 | sizeof (struct GNUNET_PeerIdentity))) | ||
6225 | return pg->peers[i].daemon; | ||
6226 | } | ||
6227 | return NULL; | ||
6228 | } | ||
6229 | |||
6230 | /** | ||
6231 | * Prototype of a function that will be called when a | ||
6232 | * particular operation was completed the testing library. | ||
6233 | * | ||
6234 | * @param cls closure (a struct RestartContext) | ||
6235 | * @param id id of the peer that was restarted | ||
6236 | * @param cfg handle to the configuration of the peer | ||
6237 | * @param d handle to the daemon that was restarted | ||
6238 | * @param emsg NULL on success | ||
6239 | */ | ||
6240 | static void | ||
6241 | restart_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
6242 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
6243 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
6244 | { | ||
6245 | struct RestartContext *restart_context = cls; | ||
6246 | |||
6247 | if (emsg == NULL) | ||
6248 | { | ||
6249 | restart_context->peers_restarted++; | ||
6250 | } | ||
6251 | else | ||
6252 | { | ||
6253 | restart_context->peers_restart_failed++; | ||
6254 | } | ||
6255 | |||
6256 | if (restart_context->peers_restarted == restart_context->peer_group->total) | ||
6257 | { | ||
6258 | restart_context->callback (restart_context->callback_cls, NULL); | ||
6259 | GNUNET_free (restart_context); | ||
6260 | } | ||
6261 | else if (restart_context->peers_restart_failed + | ||
6262 | restart_context->peers_restarted == | ||
6263 | restart_context->peer_group->total) | ||
6264 | { | ||
6265 | restart_context->callback (restart_context->callback_cls, | ||
6266 | "Failed to restart peers!"); | ||
6267 | GNUNET_free (restart_context); | ||
6268 | } | ||
6269 | |||
6270 | } | ||
6271 | |||
6272 | /** | ||
6273 | * Callback for informing us about a successful | ||
6274 | * or unsuccessful churn stop call. | ||
6275 | * | ||
6276 | * @param cls a ChurnContext | ||
6277 | * @param emsg NULL on success, non-NULL on failure | ||
6278 | * | ||
6279 | */ | ||
6280 | static void | ||
6281 | churn_stop_callback (void *cls, const char *emsg) | ||
6282 | { | ||
6283 | struct ShutdownContext *shutdown_ctx = cls; | ||
6284 | struct ChurnContext *churn_ctx = shutdown_ctx->cb_cls; | ||
6285 | unsigned int total_left; | ||
6286 | char *error_message; | ||
6287 | |||
6288 | error_message = NULL; | ||
6289 | shutdown_ctx->outstanding--; | ||
6290 | |||
6291 | if (emsg != NULL) | ||
6292 | { | ||
6293 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
6294 | "Churn stop callback failed with error `%s'\n", emsg); | ||
6295 | churn_ctx->num_failed_stop++; | ||
6296 | } | ||
6297 | else | ||
6298 | { | ||
6299 | churn_ctx->num_to_stop--; | ||
6300 | } | ||
6301 | |||
6302 | total_left = | ||
6303 | (churn_ctx->num_to_stop - churn_ctx->num_failed_stop) + | ||
6304 | (churn_ctx->num_to_start - churn_ctx->num_failed_start); | ||
6305 | |||
6306 | if (total_left == 0) | ||
6307 | { | ||
6308 | if ((churn_ctx->num_failed_stop > 0) || (churn_ctx->num_failed_start > 0)) | ||
6309 | { | ||
6310 | GNUNET_asprintf (&error_message, | ||
6311 | "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!", | ||
6312 | churn_ctx->num_failed_start, churn_ctx->num_failed_stop); | ||
6313 | } | ||
6314 | churn_ctx->cb (churn_ctx->cb_cls, error_message); | ||
6315 | GNUNET_free_non_null (error_message); | ||
6316 | GNUNET_free (churn_ctx); | ||
6317 | GNUNET_free (shutdown_ctx); | ||
6318 | } | ||
6319 | } | ||
6320 | |||
6321 | /** | ||
6322 | * Count the number of running peers. | ||
6323 | * | ||
6324 | * @param pg handle for the peer group | ||
6325 | * | ||
6326 | * @return the number of currently running peers in the peer group | ||
6327 | */ | ||
6328 | unsigned int | ||
6329 | GNUNET_TESTING_daemons_running (struct GNUNET_TESTING_PeerGroup *pg) | ||
6330 | { | ||
6331 | unsigned int i; | ||
6332 | unsigned int running = 0; | ||
6333 | |||
6334 | for (i = 0; i < pg->total; i++) | ||
6335 | { | ||
6336 | if (pg->peers[i].daemon->running == GNUNET_YES) | ||
6337 | { | ||
6338 | GNUNET_assert (running != -1); | ||
6339 | running++; | ||
6340 | } | ||
6341 | } | ||
6342 | return running; | ||
6343 | } | ||
6344 | |||
6345 | /** | ||
6346 | * Task to rate limit the number of outstanding peer shutdown | ||
6347 | * requests. This is necessary for making sure we don't do | ||
6348 | * too many ssh connections at once, but is generally nicer | ||
6349 | * to any system as well (graduated task starts, as opposed | ||
6350 | * to calling gnunet-arm N times all at once). | ||
6351 | */ | ||
6352 | static void | ||
6353 | schedule_churn_shutdown_task (void *cls, | ||
6354 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
6355 | { | ||
6356 | struct PeerShutdownContext *peer_shutdown_ctx = cls; | ||
6357 | struct ShutdownContext *shutdown_ctx; | ||
6358 | struct ChurnContext *churn_ctx; | ||
6359 | |||
6360 | GNUNET_assert (peer_shutdown_ctx != NULL); | ||
6361 | shutdown_ctx = peer_shutdown_ctx->shutdown_ctx; | ||
6362 | GNUNET_assert (shutdown_ctx != NULL); | ||
6363 | churn_ctx = (struct ChurnContext *) shutdown_ctx->cb_cls; | ||
6364 | if (shutdown_ctx->outstanding > churn_ctx->pg->max_concurrent_ssh) | ||
6365 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
6366 | (GNUNET_TIME_UNIT_MILLISECONDS, 100), | ||
6367 | &schedule_churn_shutdown_task, | ||
6368 | peer_shutdown_ctx); | ||
6369 | else | ||
6370 | { | ||
6371 | shutdown_ctx->outstanding++; | ||
6372 | if (churn_ctx->service != NULL) | ||
6373 | GNUNET_TESTING_daemon_stop_service (peer_shutdown_ctx->daemon, | ||
6374 | churn_ctx->service, | ||
6375 | shutdown_ctx->timeout, | ||
6376 | shutdown_ctx->cb, shutdown_ctx); | ||
6377 | else | ||
6378 | GNUNET_TESTING_daemon_stop (peer_shutdown_ctx->daemon, | ||
6379 | shutdown_ctx->timeout, shutdown_ctx->cb, | ||
6380 | shutdown_ctx, GNUNET_NO, GNUNET_YES); | ||
6381 | GNUNET_free (peer_shutdown_ctx); | ||
6382 | } | ||
6383 | } | ||
6384 | |||
6385 | |||
6386 | /** | ||
6387 | * Simulate churn by stopping some peers (and possibly | ||
6388 | * re-starting others if churn is called multiple times). This | ||
6389 | * function can only be used to create leave-join churn (peers "never" | ||
6390 | * leave for good). First "voff" random peers that are currently | ||
6391 | * online will be taken offline; then "von" random peers that are then | ||
6392 | * offline will be put back online. No notifications will be | ||
6393 | * generated for any of these operations except for the callback upon | ||
6394 | * completion. | ||
6395 | * | ||
6396 | * @param pg handle for the peer group | ||
6397 | * @param service the service to churn off/on, NULL to churn peer | ||
6398 | * @param voff number of peers that should go offline | ||
6399 | * @param von number of peers that should come back online; | ||
6400 | * must be zero on first call (since "testbed_start" | ||
6401 | * always starts all of the peers) | ||
6402 | * @param timeout how long to wait for operations to finish before | ||
6403 | * giving up | ||
6404 | * @param cb function to call at the end | ||
6405 | * @param cb_cls closure for cb | ||
6406 | */ | ||
6407 | void | ||
6408 | GNUNET_TESTING_daemons_churn (struct GNUNET_TESTING_PeerGroup *pg, | ||
6409 | char *service, unsigned int voff, | ||
6410 | unsigned int von, | ||
6411 | struct GNUNET_TIME_Relative timeout, | ||
6412 | GNUNET_TESTING_NotifyCompletion cb, void *cb_cls) | ||
6413 | { | ||
6414 | struct ChurnContext *churn_ctx; | ||
6415 | struct ShutdownContext *shutdown_ctx; | ||
6416 | struct PeerShutdownContext *peer_shutdown_ctx; | ||
6417 | struct PeerRestartContext *peer_restart_ctx; | ||
6418 | struct ChurnRestartContext *churn_startup_ctx; | ||
6419 | |||
6420 | unsigned int running; | ||
6421 | unsigned int stopped; | ||
6422 | unsigned int total_running; | ||
6423 | unsigned int total_stopped; | ||
6424 | unsigned int i; | ||
6425 | unsigned int *running_arr; | ||
6426 | unsigned int *stopped_arr; | ||
6427 | unsigned int *running_permute; | ||
6428 | unsigned int *stopped_permute; | ||
6429 | char *pos; | ||
6430 | |||
6431 | shutdown_ctx = NULL; | ||
6432 | peer_shutdown_ctx = NULL; | ||
6433 | peer_restart_ctx = NULL; | ||
6434 | churn_startup_ctx = NULL; | ||
6435 | |||
6436 | running = 0; | ||
6437 | stopped = 0; | ||
6438 | |||
6439 | if ((von == 0) && (voff == 0)) /* No peers at all? */ | ||
6440 | { | ||
6441 | cb (cb_cls, NULL); | ||
6442 | return; | ||
6443 | } | ||
6444 | |||
6445 | for (i = 0; i < pg->total; i++) | ||
6446 | { | ||
6447 | if (service == NULL) | ||
6448 | { | ||
6449 | if (pg->peers[i].daemon->running == GNUNET_YES) | ||
6450 | { | ||
6451 | GNUNET_assert (running != -1); | ||
6452 | running++; | ||
6453 | } | ||
6454 | else | ||
6455 | { | ||
6456 | GNUNET_assert (stopped != -1); | ||
6457 | stopped++; | ||
6458 | } | ||
6459 | } | ||
6460 | else | ||
6461 | { | ||
6462 | /* FIXME: make churned services a list! */ | ||
6463 | pos = pg->peers[i].daemon->churned_services; | ||
6464 | /* FIXME: while (pos != NULL) */ | ||
6465 | if (pos != NULL) | ||
6466 | { | ||
6467 | #if FIXME | ||
6468 | if (0 == strcasecmp (pos, service)) | ||
6469 | { | ||
6470 | |||
6471 | break; | ||
6472 | } | ||
6473 | #endif | ||
6474 | GNUNET_assert (stopped != -1); | ||
6475 | stopped++; | ||
6476 | /* FIXME: pos = pos->next; */ | ||
6477 | } | ||
6478 | if (pos == NULL) | ||
6479 | { | ||
6480 | GNUNET_assert (running != -1); | ||
6481 | running++; | ||
6482 | } | ||
6483 | } | ||
6484 | } | ||
6485 | |||
6486 | if (voff > running) | ||
6487 | { | ||
6488 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
6489 | "Trying to stop more peers (%d) than are currently running (%d)!\n", | ||
6490 | voff, running); | ||
6491 | cb (cb_cls, "Trying to stop more peers than are currently running!"); | ||
6492 | return; | ||
6493 | } | ||
6494 | |||
6495 | if (von > stopped) | ||
6496 | { | ||
6497 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
6498 | "Trying to start more peers (%d) than are currently stopped (%d)!\n", | ||
6499 | von, stopped); | ||
6500 | cb (cb_cls, "Trying to start more peers than are currently stopped!"); | ||
6501 | return; | ||
6502 | } | ||
6503 | |||
6504 | churn_ctx = GNUNET_malloc (sizeof (struct ChurnContext)); | ||
6505 | |||
6506 | if (service != NULL) | ||
6507 | churn_ctx->service = GNUNET_strdup (service); | ||
6508 | running_arr = NULL; | ||
6509 | if (running > 0) | ||
6510 | running_arr = GNUNET_malloc (running * sizeof (unsigned int)); | ||
6511 | |||
6512 | stopped_arr = NULL; | ||
6513 | if (stopped > 0) | ||
6514 | stopped_arr = GNUNET_malloc (stopped * sizeof (unsigned int)); | ||
6515 | |||
6516 | running_permute = NULL; | ||
6517 | stopped_permute = NULL; | ||
6518 | |||
6519 | if (running > 0) | ||
6520 | running_permute = | ||
6521 | GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, running); | ||
6522 | if (stopped > 0) | ||
6523 | stopped_permute = | ||
6524 | GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, stopped); | ||
6525 | |||
6526 | total_running = running; | ||
6527 | total_stopped = stopped; | ||
6528 | running = 0; | ||
6529 | stopped = 0; | ||
6530 | |||
6531 | churn_ctx->num_to_start = von; | ||
6532 | churn_ctx->num_to_stop = voff; | ||
6533 | churn_ctx->cb = cb; | ||
6534 | churn_ctx->cb_cls = cb_cls; | ||
6535 | churn_ctx->pg = pg; | ||
6536 | |||
6537 | for (i = 0; i < pg->total; i++) | ||
6538 | { | ||
6539 | if (service == NULL) | ||
6540 | { | ||
6541 | if (pg->peers[i].daemon->running == GNUNET_YES) | ||
6542 | { | ||
6543 | GNUNET_assert ((running_arr != NULL) && (total_running > running)); | ||
6544 | running_arr[running] = i; | ||
6545 | running++; | ||
6546 | } | ||
6547 | else | ||
6548 | { | ||
6549 | GNUNET_assert ((stopped_arr != NULL) && (total_stopped > stopped)); | ||
6550 | stopped_arr[stopped] = i; | ||
6551 | stopped++; | ||
6552 | } | ||
6553 | } | ||
6554 | else | ||
6555 | { | ||
6556 | /* FIXME: make churned services a list! */ | ||
6557 | pos = pg->peers[i].daemon->churned_services; | ||
6558 | /* FIXME: while (pos != NULL) */ | ||
6559 | if (pos != NULL) | ||
6560 | { | ||
6561 | GNUNET_assert ((stopped_arr != NULL) && (total_stopped > stopped)); | ||
6562 | stopped_arr[stopped] = i; | ||
6563 | stopped++; | ||
6564 | /* FIXME: pos = pos->next; */ | ||
6565 | } | ||
6566 | if (pos == NULL) | ||
6567 | { | ||
6568 | GNUNET_assert ((running_arr != NULL) && (total_running > running)); | ||
6569 | running_arr[running] = i; | ||
6570 | running++; | ||
6571 | } | ||
6572 | } | ||
6573 | } | ||
6574 | |||
6575 | GNUNET_assert (running >= voff); | ||
6576 | if (voff > 0) | ||
6577 | { | ||
6578 | shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext)); | ||
6579 | shutdown_ctx->cb = &churn_stop_callback; | ||
6580 | shutdown_ctx->cb_cls = churn_ctx; | ||
6581 | shutdown_ctx->total_peers = voff; | ||
6582 | shutdown_ctx->timeout = timeout; | ||
6583 | } | ||
6584 | |||
6585 | for (i = 0; i < voff; i++) | ||
6586 | { | ||
6587 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peer %d!\n", | ||
6588 | running_arr[running_permute[i]]); | ||
6589 | GNUNET_assert (running_arr != NULL); | ||
6590 | peer_shutdown_ctx = GNUNET_malloc (sizeof (struct PeerShutdownContext)); | ||
6591 | peer_shutdown_ctx->daemon = | ||
6592 | pg->peers[running_arr[running_permute[i]]].daemon; | ||
6593 | peer_shutdown_ctx->shutdown_ctx = shutdown_ctx; | ||
6594 | GNUNET_SCHEDULER_add_now (&schedule_churn_shutdown_task, peer_shutdown_ctx); | ||
6595 | } | ||
6596 | |||
6597 | GNUNET_assert (stopped >= von); | ||
6598 | if (von > 0) | ||
6599 | { | ||
6600 | churn_startup_ctx = GNUNET_malloc (sizeof (struct ChurnRestartContext)); | ||
6601 | churn_startup_ctx->churn_ctx = churn_ctx; | ||
6602 | churn_startup_ctx->timeout = timeout; | ||
6603 | churn_startup_ctx->pg = pg; | ||
6604 | } | ||
6605 | for (i = 0; i < von; i++) | ||
6606 | { | ||
6607 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting up peer %d!\n", | ||
6608 | stopped_arr[stopped_permute[i]]); | ||
6609 | GNUNET_assert (stopped_arr != NULL); | ||
6610 | peer_restart_ctx = GNUNET_malloc (sizeof (struct PeerRestartContext)); | ||
6611 | peer_restart_ctx->churn_restart_ctx = churn_startup_ctx; | ||
6612 | peer_restart_ctx->daemon = | ||
6613 | pg->peers[stopped_arr[stopped_permute[i]]].daemon; | ||
6614 | GNUNET_SCHEDULER_add_now (&schedule_churn_restart, peer_restart_ctx); | ||
6615 | } | ||
6616 | |||
6617 | GNUNET_free_non_null (running_arr); | ||
6618 | GNUNET_free_non_null (stopped_arr); | ||
6619 | GNUNET_free_non_null (running_permute); | ||
6620 | GNUNET_free_non_null (stopped_permute); | ||
6621 | } | ||
6622 | |||
6623 | /* | ||
6624 | * Start a given service for each of the peers in the peer group. | ||
6625 | * | ||
6626 | * @param pg handle for the peer group | ||
6627 | * @param service the service to start | ||
6628 | * @param timeout how long to wait for operations to finish before | ||
6629 | * giving up | ||
6630 | * @param cb function to call once finished | ||
6631 | * @param cb_cls closure for cb | ||
6632 | * | ||
6633 | */ | ||
6634 | void | ||
6635 | GNUNET_TESTING_daemons_start_service (struct GNUNET_TESTING_PeerGroup *pg, | ||
6636 | char *service, | ||
6637 | struct GNUNET_TIME_Relative timeout, | ||
6638 | GNUNET_TESTING_NotifyCompletion cb, | ||
6639 | void *cb_cls) | ||
6640 | { | ||
6641 | struct ServiceStartContext *start_ctx; | ||
6642 | struct PeerServiceStartContext *peer_start_ctx; | ||
6643 | unsigned int i; | ||
6644 | |||
6645 | GNUNET_assert (service != NULL); | ||
6646 | |||
6647 | start_ctx = GNUNET_malloc (sizeof (struct ServiceStartContext)); | ||
6648 | start_ctx->pg = pg; | ||
6649 | start_ctx->remaining = pg->total; | ||
6650 | start_ctx->cb = cb; | ||
6651 | start_ctx->cb_cls = cb_cls; | ||
6652 | start_ctx->service = GNUNET_strdup (service); | ||
6653 | start_ctx->timeout = timeout; | ||
6654 | |||
6655 | for (i = 0; i < pg->total; i++) | ||
6656 | { | ||
6657 | peer_start_ctx = GNUNET_malloc (sizeof (struct PeerServiceStartContext)); | ||
6658 | peer_start_ctx->start_ctx = start_ctx; | ||
6659 | peer_start_ctx->daemon = pg->peers[i].daemon; | ||
6660 | GNUNET_SCHEDULER_add_now (&schedule_service_start, peer_start_ctx); | ||
6661 | } | ||
6662 | } | ||
6663 | |||
6664 | /** | ||
6665 | * Restart all peers in the given group. | ||
6666 | * | ||
6667 | * @param pg the handle to the peer group | ||
6668 | * @param callback function to call on completion (or failure) | ||
6669 | * @param callback_cls closure for the callback function | ||
6670 | */ | ||
6671 | void | ||
6672 | GNUNET_TESTING_daemons_restart (struct GNUNET_TESTING_PeerGroup *pg, | ||
6673 | GNUNET_TESTING_NotifyCompletion callback, | ||
6674 | void *callback_cls) | ||
6675 | { | ||
6676 | struct RestartContext *restart_context; | ||
6677 | unsigned int off; | ||
6678 | |||
6679 | if (pg->total > 0) | ||
6680 | { | ||
6681 | restart_context = GNUNET_malloc (sizeof (struct RestartContext)); | ||
6682 | restart_context->peer_group = pg; | ||
6683 | restart_context->peers_restarted = 0; | ||
6684 | restart_context->callback = callback; | ||
6685 | restart_context->callback_cls = callback_cls; | ||
6686 | |||
6687 | for (off = 0; off < pg->total; off++) | ||
6688 | { | ||
6689 | GNUNET_TESTING_daemon_restart (pg->peers[off].daemon, &restart_callback, | ||
6690 | restart_context); | ||
6691 | } | ||
6692 | } | ||
6693 | } | ||
6694 | |||
6695 | |||
6696 | /** | ||
6697 | * Start or stop an individual peer from the given group. | ||
6698 | * | ||
6699 | * @param pg handle to the peer group | ||
6700 | * @param offset which peer to start or stop | ||
6701 | * @param desired_status GNUNET_YES to have it running, GNUNET_NO to stop it | ||
6702 | * @param timeout how long to wait for shutdown | ||
6703 | * @param cb function to call at the end | ||
6704 | * @param cb_cls closure for cb | ||
6705 | */ | ||
6706 | void | ||
6707 | GNUNET_TESTING_daemons_vary (struct GNUNET_TESTING_PeerGroup *pg, | ||
6708 | unsigned int offset, int desired_status, | ||
6709 | struct GNUNET_TIME_Relative timeout, | ||
6710 | GNUNET_TESTING_NotifyCompletion cb, void *cb_cls) | ||
6711 | { | ||
6712 | struct ShutdownContext *shutdown_ctx; | ||
6713 | struct ChurnRestartContext *startup_ctx; | ||
6714 | struct ChurnContext *churn_ctx; | ||
6715 | |||
6716 | if (GNUNET_NO == desired_status) | ||
6717 | { | ||
6718 | if (NULL != pg->peers[offset].daemon) | ||
6719 | { | ||
6720 | shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext)); | ||
6721 | churn_ctx = GNUNET_malloc (sizeof (struct ChurnContext)); | ||
6722 | churn_ctx->num_to_start = 0; | ||
6723 | churn_ctx->num_to_stop = 1; | ||
6724 | churn_ctx->cb = cb; | ||
6725 | churn_ctx->cb_cls = cb_cls; | ||
6726 | shutdown_ctx->cb_cls = churn_ctx; | ||
6727 | GNUNET_TESTING_daemon_stop (pg->peers[offset].daemon, timeout, | ||
6728 | &churn_stop_callback, shutdown_ctx, GNUNET_NO, | ||
6729 | GNUNET_YES); | ||
6730 | } | ||
6731 | } | ||
6732 | else if (GNUNET_YES == desired_status) | ||
6733 | { | ||
6734 | if (NULL == pg->peers[offset].daemon) | ||
6735 | { | ||
6736 | startup_ctx = GNUNET_malloc (sizeof (struct ChurnRestartContext)); | ||
6737 | churn_ctx = GNUNET_malloc (sizeof (struct ChurnContext)); | ||
6738 | churn_ctx->num_to_start = 1; | ||
6739 | churn_ctx->num_to_stop = 0; | ||
6740 | churn_ctx->cb = cb; | ||
6741 | churn_ctx->cb_cls = cb_cls; | ||
6742 | startup_ctx->churn_ctx = churn_ctx; | ||
6743 | GNUNET_TESTING_daemon_start_stopped (pg->peers[offset].daemon, timeout, | ||
6744 | &churn_start_callback, startup_ctx); | ||
6745 | } | ||
6746 | } | ||
6747 | else | ||
6748 | GNUNET_break (0); | ||
6749 | } | ||
6750 | |||
6751 | |||
6752 | /** | ||
6753 | * Callback for shutting down peers in a peer group. | ||
6754 | * | ||
6755 | * @param cls closure (struct ShutdownContext) | ||
6756 | * @param emsg NULL on success | ||
6757 | */ | ||
6758 | static void | ||
6759 | internal_shutdown_callback (void *cls, const char *emsg) | ||
6760 | { | ||
6761 | struct PeerShutdownContext *peer_shutdown_ctx = cls; | ||
6762 | struct ShutdownContext *shutdown_ctx = peer_shutdown_ctx->shutdown_ctx; | ||
6763 | unsigned int off; | ||
6764 | int i; | ||
6765 | struct OutstandingSSH *ssh_pos; | ||
6766 | |||
6767 | shutdown_ctx->outstanding--; | ||
6768 | if (peer_shutdown_ctx->daemon->hostname != NULL) | ||
6769 | decrement_outstanding_at_host (peer_shutdown_ctx->daemon->hostname, | ||
6770 | shutdown_ctx->pg); | ||
6771 | |||
6772 | if (emsg == NULL) | ||
6773 | { | ||
6774 | shutdown_ctx->peers_down++; | ||
6775 | } | ||
6776 | else | ||
6777 | { | ||
6778 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "internal_shutdown_callback", | ||
6779 | "Failed to stop a peer: %s\n", emsg); | ||
6780 | shutdown_ctx->peers_failed++; | ||
6781 | } | ||
6782 | |||
6783 | if ((shutdown_ctx->cb != NULL) && | ||
6784 | (shutdown_ctx->peers_down + shutdown_ctx->peers_failed == | ||
6785 | shutdown_ctx->total_peers)) | ||
6786 | { | ||
6787 | if (shutdown_ctx->peers_failed > 0) | ||
6788 | shutdown_ctx->cb (shutdown_ctx->cb_cls, | ||
6789 | "Not all peers successfully shut down!"); | ||
6790 | else | ||
6791 | shutdown_ctx->cb (shutdown_ctx->cb_cls, NULL); | ||
6792 | |||
6793 | for (i = 0; i < shutdown_ctx->pg->total; i++) | ||
6794 | { | ||
6795 | if (shutdown_ctx->pg->peers[i].startup_task != GNUNET_SCHEDULER_NO_TASK) | ||
6796 | GNUNET_SCHEDULER_cancel (shutdown_ctx->pg->peers[i].startup_task); | ||
6797 | } | ||
6798 | GNUNET_free (shutdown_ctx->pg->peers); | ||
6799 | GNUNET_free_non_null (shutdown_ctx->pg->hostkey_data); | ||
6800 | for (off = 0; off < shutdown_ctx->pg->num_hosts; off++) | ||
6801 | { | ||
6802 | GNUNET_free (shutdown_ctx->pg->hosts[off].hostname); | ||
6803 | GNUNET_free_non_null (shutdown_ctx->pg->hosts[off].username); | ||
6804 | } | ||
6805 | GNUNET_free_non_null (shutdown_ctx->pg->hosts); | ||
6806 | while (NULL != (ssh_pos = shutdown_ctx->pg->ssh_head)) | ||
6807 | { | ||
6808 | GNUNET_CONTAINER_DLL_remove (shutdown_ctx->pg->ssh_head, | ||
6809 | shutdown_ctx->pg->ssh_tail, ssh_pos); | ||
6810 | GNUNET_free (ssh_pos); | ||
6811 | } | ||
6812 | GNUNET_free (shutdown_ctx->pg); | ||
6813 | GNUNET_free (shutdown_ctx); | ||
6814 | } | ||
6815 | GNUNET_free (peer_shutdown_ctx); | ||
6816 | } | ||
6817 | |||
6818 | |||
6819 | /** | ||
6820 | * Task to rate limit the number of outstanding peer shutdown | ||
6821 | * requests. This is necessary for making sure we don't do | ||
6822 | * too many ssh connections at once, but is generally nicer | ||
6823 | * to any system as well (graduated task starts, as opposed | ||
6824 | * to calling gnunet-arm N times all at once). | ||
6825 | */ | ||
6826 | static void | ||
6827 | schedule_shutdown_task (void *cls, | ||
6828 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
6829 | { | ||
6830 | struct PeerShutdownContext *peer_shutdown_ctx = cls; | ||
6831 | struct ShutdownContext *shutdown_ctx; | ||
6832 | struct GNUNET_TESTING_Daemon *d; | ||
6833 | |||
6834 | GNUNET_assert (peer_shutdown_ctx != NULL); | ||
6835 | d = peer_shutdown_ctx->daemon; | ||
6836 | shutdown_ctx = peer_shutdown_ctx->shutdown_ctx; | ||
6837 | GNUNET_assert (shutdown_ctx != NULL); | ||
6838 | |||
6839 | if ((shutdown_ctx->outstanding < shutdown_ctx->pg->max_concurrent_ssh) || | ||
6840 | ((d->hostname != NULL) && | ||
6841 | (count_outstanding_at_host | ||
6842 | (d->hostname, | ||
6843 | shutdown_ctx->pg) < shutdown_ctx->pg->max_concurrent_ssh))) | ||
6844 | { | ||
6845 | if (d->hostname != NULL) | ||
6846 | increment_outstanding_at_host (d->hostname, | ||
6847 | shutdown_ctx->pg); | ||
6848 | shutdown_ctx->outstanding++; | ||
6849 | GNUNET_TESTING_daemon_stop (d, | ||
6850 | shutdown_ctx->timeout, | ||
6851 | &internal_shutdown_callback, peer_shutdown_ctx, | ||
6852 | shutdown_ctx->delete_files, GNUNET_NO); | ||
6853 | } | ||
6854 | else | ||
6855 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
6856 | (GNUNET_TIME_UNIT_MILLISECONDS, 100), | ||
6857 | &schedule_shutdown_task, peer_shutdown_ctx); | ||
6858 | |||
6859 | } | ||
6860 | |||
6861 | /** | ||
6862 | * Read a testing hosts file based on a configuration. | ||
6863 | * Returns a DLL of hosts (caller must free!) on success | ||
6864 | * or NULL on failure. | ||
6865 | * | ||
6866 | * @param cfg a configuration with a testing section | ||
6867 | * | ||
6868 | * @return DLL of hosts on success, NULL on failure | ||
6869 | */ | ||
6870 | struct GNUNET_TESTING_Host * | ||
6871 | GNUNET_TESTING_hosts_load (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
6872 | { | ||
6873 | struct GNUNET_TESTING_Host *hosts; | ||
6874 | struct GNUNET_TESTING_Host *temphost; | ||
6875 | char *data; | ||
6876 | char *buf; | ||
6877 | char *hostfile; | ||
6878 | struct stat frstat; | ||
6879 | int count; | ||
6880 | int ret; | ||
6881 | |||
6882 | /* Check for a hostfile containing user@host:port triples */ | ||
6883 | if (GNUNET_OK != | ||
6884 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", "hostfile", | ||
6885 | &hostfile)) | ||
6886 | return NULL; | ||
6887 | |||
6888 | hosts = NULL; | ||
6889 | temphost = NULL; | ||
6890 | data = NULL; | ||
6891 | if (hostfile != NULL) | ||
6892 | { | ||
6893 | if (GNUNET_OK != GNUNET_DISK_file_test (hostfile)) | ||
6894 | GNUNET_DISK_fn_write (hostfile, NULL, 0, | ||
6895 | GNUNET_DISK_PERM_USER_READ | | ||
6896 | GNUNET_DISK_PERM_USER_WRITE); | ||
6897 | if ((0 != STAT (hostfile, &frstat)) || (frstat.st_size == 0)) | ||
6898 | { | ||
6899 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
6900 | "Could not open file specified for host list, ending test!"); | ||
6901 | GNUNET_free (hostfile); | ||
6902 | return NULL; | ||
6903 | } | ||
6904 | |||
6905 | data = GNUNET_malloc_large (frstat.st_size); | ||
6906 | GNUNET_assert (data != NULL); | ||
6907 | if (frstat.st_size != GNUNET_DISK_fn_read (hostfile, data, frstat.st_size)) | ||
6908 | { | ||
6909 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
6910 | "Could not read file %s specified for host list, ending test!", | ||
6911 | hostfile); | ||
6912 | GNUNET_free (hostfile); | ||
6913 | GNUNET_free (data); | ||
6914 | return NULL; | ||
6915 | } | ||
6916 | |||
6917 | GNUNET_free_non_null (hostfile); | ||
6918 | |||
6919 | buf = data; | ||
6920 | count = 0; | ||
6921 | while (count < frstat.st_size - 1) | ||
6922 | { | ||
6923 | count++; | ||
6924 | if (((data[count] == '\n')) && (buf != &data[count])) | ||
6925 | { | ||
6926 | data[count] = '\0'; | ||
6927 | temphost = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Host)); | ||
6928 | ret = | ||
6929 | SSCANF (buf, "%a[a-zA-Z0-9_]@%a[a-zA-Z0-9.]:%hd", | ||
6930 | &temphost->username, &temphost->hostname, &temphost->port); | ||
6931 | if (3 == ret) | ||
6932 | { | ||
6933 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
6934 | "Successfully read host %s, port %d and user %s from file\n", | ||
6935 | temphost->hostname, temphost->port, temphost->username); | ||
6936 | } | ||
6937 | else | ||
6938 | { | ||
6939 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
6940 | "Error reading line `%s' in hostfile\n", buf); | ||
6941 | GNUNET_free (temphost); | ||
6942 | buf = &data[count + 1]; | ||
6943 | continue; | ||
6944 | } | ||
6945 | temphost->next = hosts; | ||
6946 | hosts = temphost; | ||
6947 | buf = &data[count + 1]; | ||
6948 | } | ||
6949 | else if ((data[count] == '\n') || (data[count] == '\0')) | ||
6950 | buf = &data[count + 1]; | ||
6951 | } | ||
6952 | } | ||
6953 | GNUNET_free_non_null (data); | ||
6954 | |||
6955 | return hosts; | ||
6956 | } | ||
6957 | |||
6958 | /** | ||
6959 | * Shutdown all peers started in the given group. | ||
6960 | * | ||
6961 | * @param pg handle to the peer group | ||
6962 | * @param timeout how long to wait for shutdown | ||
6963 | * @param cb callback to notify upon success or failure | ||
6964 | * @param cb_cls closure for cb | ||
6965 | */ | ||
6966 | void | ||
6967 | GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg, | ||
6968 | struct GNUNET_TIME_Relative timeout, | ||
6969 | GNUNET_TESTING_NotifyCompletion cb, void *cb_cls) | ||
6970 | { | ||
6971 | unsigned int off; | ||
6972 | struct ShutdownContext *shutdown_ctx; | ||
6973 | struct PeerShutdownContext *peer_shutdown_ctx; | ||
6974 | |||
6975 | #if OLD | ||
6976 | struct PeerConnection *conn_iter; | ||
6977 | struct PeerConnection *temp_conn; | ||
6978 | #endif | ||
6979 | struct ConnectContext *cc; | ||
6980 | |||
6981 | GNUNET_assert (pg->total > 0); | ||
6982 | while (NULL != (cc = pg->cc_head)) | ||
6983 | { | ||
6984 | GNUNET_CONTAINER_DLL_remove (pg->cc_head, pg->cc_tail, cc); | ||
6985 | if (GNUNET_SCHEDULER_NO_TASK != cc->task) | ||
6986 | GNUNET_SCHEDULER_cancel (cc->task); | ||
6987 | if (NULL != cc->cc) | ||
6988 | GNUNET_TESTING_daemons_connect_cancel (cc->cc); | ||
6989 | GNUNET_free (cc); | ||
6990 | } | ||
6991 | |||
6992 | shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext)); | ||
6993 | shutdown_ctx->delete_files = | ||
6994 | GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING_OLD", "DELETE_FILES"); | ||
6995 | shutdown_ctx->cb = cb; | ||
6996 | shutdown_ctx->cb_cls = cb_cls; | ||
6997 | shutdown_ctx->total_peers = pg->total; | ||
6998 | shutdown_ctx->timeout = timeout; | ||
6999 | shutdown_ctx->pg = pg; | ||
7000 | |||
7001 | for (off = 0; off < pg->total; off++) | ||
7002 | { | ||
7003 | GNUNET_assert (NULL != pg->peers[off].daemon); | ||
7004 | peer_shutdown_ctx = GNUNET_malloc (sizeof (struct PeerShutdownContext)); | ||
7005 | peer_shutdown_ctx->daemon = pg->peers[off].daemon; | ||
7006 | peer_shutdown_ctx->shutdown_ctx = shutdown_ctx; | ||
7007 | GNUNET_SCHEDULER_add_now (&schedule_shutdown_task, peer_shutdown_ctx); | ||
7008 | |||
7009 | if (NULL != pg->peers[off].cfg) | ||
7010 | { | ||
7011 | GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg); | ||
7012 | pg->peers[off].cfg = NULL; | ||
7013 | } | ||
7014 | #if OLD | ||
7015 | // FIXME Do DLL remove for all pg->peers[off].LIST | ||
7016 | conn_iter = pg->peers[off].allowed_peers_head; | ||
7017 | while (conn_iter != NULL) | ||
7018 | { | ||
7019 | temp_conn = conn_iter->next; | ||
7020 | GNUNET_free (conn_iter); | ||
7021 | conn_iter = temp_conn; | ||
7022 | } | ||
7023 | pg->peers[off].allowed_peers_head = NULL; | ||
7024 | |||
7025 | conn_iter = pg->peers[off].connect_peers_head; | ||
7026 | while (conn_iter != NULL) | ||
7027 | { | ||
7028 | temp_conn = conn_iter->next; | ||
7029 | GNUNET_free (conn_iter); | ||
7030 | conn_iter = temp_conn; | ||
7031 | } | ||
7032 | pg->peers[off].connect_peers_head = NULL; | ||
7033 | |||
7034 | conn_iter = pg->peers[off].blacklisted_peers_head; | ||
7035 | while (conn_iter != NULL) | ||
7036 | { | ||
7037 | temp_conn = conn_iter->next; | ||
7038 | GNUNET_free (conn_iter); | ||
7039 | conn_iter = temp_conn; | ||
7040 | } | ||
7041 | pg->peers[off].blacklisted_peers_head = NULL; | ||
7042 | |||
7043 | conn_iter = pg->peers[off].connect_peers_working_set_head; | ||
7044 | while (conn_iter != NULL) | ||
7045 | { | ||
7046 | temp_conn = conn_iter->next; | ||
7047 | GNUNET_free (conn_iter); | ||
7048 | conn_iter = temp_conn; | ||
7049 | } | ||
7050 | pg->peers[off].connect_peers_working_set_head = NULL; | ||
7051 | #else | ||
7052 | if (pg->peers[off].allowed_peers != NULL) | ||
7053 | GNUNET_CONTAINER_multihashmap_destroy (pg->peers[off].allowed_peers); | ||
7054 | if (pg->peers[off].connect_peers != NULL) | ||
7055 | GNUNET_CONTAINER_multihashmap_destroy (pg->peers[off].connect_peers); | ||
7056 | if (pg->peers[off].blacklisted_peers != NULL) | ||
7057 | GNUNET_CONTAINER_multihashmap_destroy (pg->peers[off].blacklisted_peers); | ||
7058 | #endif | ||
7059 | } | ||
7060 | } | ||
7061 | |||
7062 | /* end of testing_group.c */ | ||
diff --git a/src/testing_old/testing_old.conf b/src/testing_old/testing_old.conf deleted file mode 100644 index ebba0ad6e..000000000 --- a/src/testing_old/testing_old.conf +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | [TESTING_OLD] | ||
2 | # How long before failing a connection? | ||
3 | CONNECT_TIMEOUT = 30 s | ||
4 | # How many connect attempts should we make? | ||
5 | CONNECT_ATTEMPTS = 3 | ||
6 | # How many connections can happen simultaneously? | ||
7 | MAX_OUTSTANDING_CONNECTIONS = 50 | ||
8 | |||
9 | # Should we clean up the files on peer group shutdown? | ||
10 | DELETE_FILES = YES | ||
11 | |||
diff --git a/src/testing_old/testing_peergroup.c b/src/testing_old/testing_peergroup.c deleted file mode 100644 index acd68dd3c..000000000 --- a/src/testing_old/testing_peergroup.c +++ /dev/null | |||
@@ -1,1017 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | (C) 2008-2011 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testing_old/testing_peergroup.c | ||
23 | * @brief API implementation for easy peer group creation | ||
24 | * @author Nathan Evans | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_constants.h" | ||
30 | #include "gnunet_arm_service.h" | ||
31 | #include "gnunet_testing_lib.h" | ||
32 | #include "gnunet_core_service.h" | ||
33 | #include "gnunet_disk_lib.h" | ||
34 | |||
35 | /** Globals **/ | ||
36 | #define DEFAULT_CONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
37 | |||
38 | #define DEFAULT_CONNECT_ATTEMPTS 2 | ||
39 | |||
40 | /** Struct definitions **/ | ||
41 | |||
42 | struct PeerGroupStartupContext | ||
43 | { | ||
44 | struct GNUNET_TESTING_PeerGroup *pg; | ||
45 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
46 | unsigned int total; | ||
47 | unsigned int peers_left; | ||
48 | unsigned long long max_concurrent_connections; | ||
49 | |||
50 | /** | ||
51 | * Maximum attemps to connect two daemons. | ||
52 | */ | ||
53 | unsigned long long connect_attempts; | ||
54 | |||
55 | /** | ||
56 | * How long to spend trying to establish all the connections? | ||
57 | */ | ||
58 | struct GNUNET_TIME_Relative connect_timeout; | ||
59 | |||
60 | unsigned long long max_concurrent_ssh; | ||
61 | struct GNUNET_TIME_Absolute timeout; | ||
62 | GNUNET_TESTING_NotifyConnection connect_cb; | ||
63 | GNUNET_TESTING_NotifyCompletion peergroup_cb; | ||
64 | |||
65 | /** | ||
66 | * Closure for all peergroup callbacks. | ||
67 | */ | ||
68 | void *cls; | ||
69 | |||
70 | const struct GNUNET_TESTING_Host *hostnames; | ||
71 | |||
72 | /** | ||
73 | * FIXME document | ||
74 | */ | ||
75 | enum GNUNET_TESTING_Topology topology; | ||
76 | |||
77 | float topology_percentage; | ||
78 | |||
79 | float topology_probability; | ||
80 | |||
81 | /** | ||
82 | * FIXME document | ||
83 | */ | ||
84 | enum GNUNET_TESTING_Topology restrict_topology; | ||
85 | |||
86 | /** | ||
87 | * FIXME document | ||
88 | */ | ||
89 | char *restrict_transports; | ||
90 | |||
91 | /** | ||
92 | * Initial connections | ||
93 | */ | ||
94 | enum GNUNET_TESTING_Topology connect_topology; | ||
95 | enum GNUNET_TESTING_TopologyOption connect_topology_option; | ||
96 | double connect_topology_option_modifier; | ||
97 | int verbose; | ||
98 | |||
99 | struct ProgressMeter *hostkey_meter; | ||
100 | struct ProgressMeter *peer_start_meter; | ||
101 | struct ProgressMeter *connect_meter; | ||
102 | |||
103 | /** | ||
104 | * Task used to kill the peergroup. | ||
105 | */ | ||
106 | GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
107 | |||
108 | char *fail_reason; | ||
109 | |||
110 | /** | ||
111 | * Variable used to store the number of connections we should wait for. | ||
112 | */ | ||
113 | unsigned int expected_connections; | ||
114 | |||
115 | /** | ||
116 | * Time when the connecting peers was started. | ||
117 | */ | ||
118 | struct GNUNET_TIME_Absolute connect_start_time; | ||
119 | |||
120 | /** | ||
121 | * The total number of connections that have been created so far. | ||
122 | */ | ||
123 | unsigned int total_connections; | ||
124 | |||
125 | /** | ||
126 | * The total number of connections that have failed so far. | ||
127 | */ | ||
128 | unsigned int failed_connections; | ||
129 | |||
130 | /** | ||
131 | * File handle to write out topology in dot format. | ||
132 | */ | ||
133 | struct GNUNET_DISK_FileHandle *topology_output_file; | ||
134 | }; | ||
135 | |||
136 | struct TopologyOutputContext | ||
137 | { | ||
138 | struct GNUNET_DISK_FileHandle *file; | ||
139 | GNUNET_TESTING_NotifyCompletion notify_cb; | ||
140 | void *notify_cb_cls; | ||
141 | }; | ||
142 | |||
143 | /** | ||
144 | * Simple struct to keep track of progress, and print a | ||
145 | * percentage meter for long running tasks. | ||
146 | */ | ||
147 | struct ProgressMeter | ||
148 | { | ||
149 | /** | ||
150 | * Total number of tasks to complete. | ||
151 | */ | ||
152 | unsigned int total; | ||
153 | |||
154 | /** | ||
155 | * Print percentage done after modnum tasks. | ||
156 | */ | ||
157 | unsigned int modnum; | ||
158 | |||
159 | /** | ||
160 | * Print a . each dotnum tasks. | ||
161 | */ | ||
162 | unsigned int dotnum; | ||
163 | |||
164 | /** | ||
165 | * Total number completed thus far. | ||
166 | */ | ||
167 | unsigned int completed; | ||
168 | |||
169 | /** | ||
170 | * Whether or not to print. | ||
171 | */ | ||
172 | int print; | ||
173 | |||
174 | /** | ||
175 | * Startup string for progress meter. | ||
176 | */ | ||
177 | char *startup_string; | ||
178 | }; | ||
179 | |||
180 | |||
181 | /** Utility functions **/ | ||
182 | |||
183 | /** | ||
184 | * Create a meter to keep track of the progress of some task. | ||
185 | * | ||
186 | * @param total the total number of items to complete | ||
187 | * @param start_string a string to prefix the meter with (if printing) | ||
188 | * @param print GNUNET_YES to print the meter, GNUNET_NO to count | ||
189 | * internally only | ||
190 | * | ||
191 | * @return the progress meter | ||
192 | */ | ||
193 | static struct ProgressMeter * | ||
194 | create_meter (unsigned int total, char *start_string, int print) | ||
195 | { | ||
196 | struct ProgressMeter *ret; | ||
197 | |||
198 | ret = GNUNET_malloc (sizeof (struct ProgressMeter)); | ||
199 | ret->print = print; | ||
200 | ret->total = total; | ||
201 | ret->modnum = (total / 4 == 0) ? 1 : (total / 4); | ||
202 | ret->dotnum = (total / 50) + 1; | ||
203 | if (start_string != NULL) | ||
204 | ret->startup_string = GNUNET_strdup (start_string); | ||
205 | else | ||
206 | ret->startup_string = GNUNET_strdup (""); | ||
207 | |||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | /** | ||
212 | * Update progress meter (increment by one). | ||
213 | * | ||
214 | * @param meter the meter to update and print info for | ||
215 | * | ||
216 | * @return GNUNET_YES if called the total requested, | ||
217 | * GNUNET_NO if more items expected | ||
218 | */ | ||
219 | static int | ||
220 | update_meter (struct ProgressMeter *meter) | ||
221 | { | ||
222 | if (meter->print == GNUNET_YES) | ||
223 | { | ||
224 | if (meter->completed % meter->modnum == 0) | ||
225 | { | ||
226 | if (meter->completed == 0) | ||
227 | { | ||
228 | FPRINTF (stdout, "%sProgress: [0%%", meter->startup_string); | ||
229 | } | ||
230 | else | ||
231 | FPRINTF (stdout, "%d%%", | ||
232 | (int) (((float) meter->completed / meter->total) * 100)); | ||
233 | } | ||
234 | else if (meter->completed % meter->dotnum == 0) | ||
235 | FPRINTF (stdout, "%s", "."); | ||
236 | |||
237 | if (meter->completed + 1 == meter->total) | ||
238 | FPRINTF (stdout, "%d%%]\n", 100); | ||
239 | fflush (stdout); | ||
240 | } | ||
241 | meter->completed++; | ||
242 | |||
243 | if (meter->completed == meter->total) | ||
244 | return GNUNET_YES; | ||
245 | return GNUNET_NO; | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * Reset progress meter. | ||
250 | * | ||
251 | * @param meter the meter to reset | ||
252 | * | ||
253 | * @return GNUNET_YES if meter reset, | ||
254 | * GNUNET_SYSERR on error | ||
255 | */ | ||
256 | static int | ||
257 | reset_meter (struct ProgressMeter *meter) | ||
258 | { | ||
259 | if (meter == NULL) | ||
260 | return GNUNET_SYSERR; | ||
261 | |||
262 | meter->completed = 0; | ||
263 | return GNUNET_YES; | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * Release resources for meter | ||
268 | * | ||
269 | * @param meter the meter to free | ||
270 | */ | ||
271 | static void | ||
272 | free_meter (struct ProgressMeter *meter) | ||
273 | { | ||
274 | GNUNET_free_non_null (meter->startup_string); | ||
275 | GNUNET_free (meter); | ||
276 | } | ||
277 | |||
278 | |||
279 | /** Functions for creating, starting and connecting the peergroup **/ | ||
280 | |||
281 | /** | ||
282 | * Check whether peers successfully shut down. | ||
283 | */ | ||
284 | static void | ||
285 | internal_shutdown_callback (void *cls, const char *emsg) | ||
286 | { | ||
287 | struct PeerGroupStartupContext *pg_start_ctx = cls; | ||
288 | |||
289 | if (emsg != NULL) | ||
290 | pg_start_ctx->peergroup_cb (pg_start_ctx->cls, emsg); | ||
291 | else | ||
292 | pg_start_ctx->peergroup_cb (pg_start_ctx->cls, pg_start_ctx->fail_reason); | ||
293 | } | ||
294 | |||
295 | /** | ||
296 | * Check if the get_handle is being used, if so stop the request. Either | ||
297 | * way, schedule the end_badly_cont function which actually shuts down the | ||
298 | * test. | ||
299 | */ | ||
300 | static void | ||
301 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
302 | { | ||
303 | struct PeerGroupStartupContext *pg_start_ctx = cls; | ||
304 | |||
305 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
306 | "Failing peer group startup with error: `%s'!\n", | ||
307 | pg_start_ctx->fail_reason); | ||
308 | |||
309 | GNUNET_TESTING_daemons_stop (pg_start_ctx->pg, | ||
310 | GNUNET_TIME_absolute_get_remaining | ||
311 | (pg_start_ctx->timeout), | ||
312 | &internal_shutdown_callback, pg_start_ctx); | ||
313 | |||
314 | if (pg_start_ctx->hostkey_meter != NULL) | ||
315 | { | ||
316 | free_meter (pg_start_ctx->hostkey_meter); | ||
317 | pg_start_ctx->hostkey_meter = NULL; | ||
318 | } | ||
319 | if (pg_start_ctx->peer_start_meter != NULL) | ||
320 | { | ||
321 | free_meter (pg_start_ctx->peer_start_meter); | ||
322 | pg_start_ctx->peer_start_meter = NULL; | ||
323 | } | ||
324 | if (pg_start_ctx->connect_meter != NULL) | ||
325 | { | ||
326 | free_meter (pg_start_ctx->connect_meter); | ||
327 | pg_start_ctx->connect_meter = NULL; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | /** | ||
332 | * This function is called whenever a connection attempt is finished between two of | ||
333 | * the started peers (started with GNUNET_TESTING_daemons_start). The total | ||
334 | * number of times this function is called should equal the number returned | ||
335 | * from the GNUNET_TESTING_connect_topology call. | ||
336 | * | ||
337 | * The emsg variable is NULL on success (peers connected), and non-NULL on | ||
338 | * failure (peers failed to connect). | ||
339 | */ | ||
340 | static void | ||
341 | internal_topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, | ||
342 | const struct GNUNET_PeerIdentity *second, | ||
343 | uint32_t distance, | ||
344 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
345 | const struct GNUNET_CONFIGURATION_Handle | ||
346 | *second_cfg, | ||
347 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
348 | struct GNUNET_TESTING_Daemon *second_daemon, | ||
349 | const char *emsg) | ||
350 | { | ||
351 | struct PeerGroupStartupContext *pg_start_ctx = cls; | ||
352 | char *temp_str; | ||
353 | char *second_str; | ||
354 | int temp; | ||
355 | |||
356 | #if TIMING | ||
357 | unsigned long long duration; | ||
358 | unsigned long long total_duration; | ||
359 | unsigned int new_connections; | ||
360 | unsigned int new_failed_connections; | ||
361 | double conns_per_sec_recent; | ||
362 | double conns_per_sec_total; | ||
363 | double failed_conns_per_sec_recent; | ||
364 | double failed_conns_per_sec_total; | ||
365 | #endif | ||
366 | |||
367 | #if TIMING | ||
368 | if (GNUNET_TIME_absolute_get_difference | ||
369 | (connect_last_time, | ||
370 | GNUNET_TIME_absolute_get ()).rel_value > | ||
371 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, | ||
372 | CONN_UPDATE_DURATION).rel_value) | ||
373 | { | ||
374 | /* Get number of new connections */ | ||
375 | new_connections = total_connections - previous_connections; | ||
376 | |||
377 | /* Get number of new FAILED connections */ | ||
378 | new_failed_connections = failed_connections - previous_failed_connections; | ||
379 | |||
380 | /* Get duration in seconds */ | ||
381 | duration = | ||
382 | GNUNET_TIME_absolute_get_difference (connect_last_time, | ||
383 | GNUNET_TIME_absolute_get | ||
384 | ()).rel_value / 1000; | ||
385 | total_duration = | ||
386 | GNUNET_TIME_absolute_get_difference (connect_start_time, | ||
387 | GNUNET_TIME_absolute_get | ||
388 | ()).rel_value / 1000; | ||
389 | |||
390 | failed_conns_per_sec_recent = (double) new_failed_connections / duration; | ||
391 | failed_conns_per_sec_total = (double) failed_connections / total_duration; | ||
392 | conns_per_sec_recent = (double) new_connections / duration; | ||
393 | conns_per_sec_total = (double) total_connections / total_duration; | ||
394 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
395 | "Recent: %.2f/s, Total: %.2f/s, Recent failed: %.2f/s, total failed %.2f/s\n", | ||
396 | conns_per_sec_recent, CONN_UPDATE_DURATION, conns_per_sec_total, | ||
397 | failed_conns_per_sec_recent, failed_conns_per_sec_total); | ||
398 | connect_last_time = GNUNET_TIME_absolute_get (); | ||
399 | previous_connections = total_connections; | ||
400 | previous_failed_connections = failed_connections; | ||
401 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
402 | "have %u total_connections, %u failed\n", total_connections, | ||
403 | failed_connections); | ||
404 | } | ||
405 | #endif | ||
406 | |||
407 | |||
408 | if (emsg == NULL) | ||
409 | { | ||
410 | pg_start_ctx->total_connections++; | ||
411 | #if VERBOSE > 1 | ||
412 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
413 | "connected peer %s to peer %s, distance %u\n", | ||
414 | first_daemon->shortname, second_daemon->shortname, distance); | ||
415 | #endif | ||
416 | if (pg_start_ctx->topology_output_file != NULL) | ||
417 | { | ||
418 | second_str = GNUNET_strdup (GNUNET_i2s (second)); | ||
419 | temp = | ||
420 | GNUNET_asprintf (&temp_str, "\t\"%s\" -- \"%s\"\n", | ||
421 | GNUNET_i2s (first), second_str); | ||
422 | GNUNET_free (second_str); | ||
423 | if (temp > 0) | ||
424 | GNUNET_DISK_file_write (pg_start_ctx->topology_output_file, temp_str, | ||
425 | temp); | ||
426 | GNUNET_free (temp_str); | ||
427 | } | ||
428 | } | ||
429 | else | ||
430 | { | ||
431 | pg_start_ctx->failed_connections++; | ||
432 | #if VERBOSE | ||
433 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
434 | "Failed to connect peer %s to peer %s with error :\n%s\n", | ||
435 | first_daemon->shortname, second_daemon->shortname, emsg); | ||
436 | |||
437 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
438 | "Failed to connect peer %s to peer %s with error :\n%s\n", | ||
439 | first_daemon->shortname, second_daemon->shortname, emsg); | ||
440 | #endif | ||
441 | } | ||
442 | |||
443 | GNUNET_assert (pg_start_ctx->connect_meter != NULL); | ||
444 | if (pg_start_ctx->connect_cb != NULL) | ||
445 | pg_start_ctx->connect_cb (pg_start_ctx->cls, first, second, distance, | ||
446 | first_cfg, second_cfg, first_daemon, | ||
447 | second_daemon, emsg); | ||
448 | if (GNUNET_YES != update_meter (pg_start_ctx->connect_meter)) | ||
449 | { | ||
450 | /* No finished yet */ | ||
451 | return; | ||
452 | } | ||
453 | #if VERBOSE | ||
454 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
455 | "Created %d total connections, which is our target number! Starting next phase of testing.\n", | ||
456 | pg_start_ctx->total_connections); | ||
457 | #endif | ||
458 | |||
459 | #if TIMING | ||
460 | total_duration = | ||
461 | GNUNET_TIME_absolute_get_difference (connect_start_time, | ||
462 | GNUNET_TIME_absolute_get | ||
463 | ()).rel_value / 1000; | ||
464 | failed_conns_per_sec_total = (double) failed_connections / total_duration; | ||
465 | conns_per_sec_total = (double) total_connections / total_duration; | ||
466 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
467 | "Overall connection info --- Total: %u, Total Failed %u/s\n", | ||
468 | total_connections, failed_connections); | ||
469 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
470 | "Overall connection info --- Total: %.2f/s, Total Failed %.2f/s\n", | ||
471 | conns_per_sec_total, failed_conns_per_sec_total); | ||
472 | #endif | ||
473 | |||
474 | GNUNET_assert (pg_start_ctx->die_task != GNUNET_SCHEDULER_NO_TASK); | ||
475 | GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task); | ||
476 | |||
477 | /* Call final callback, signifying that the peer group has been started and connected */ | ||
478 | if (pg_start_ctx->peergroup_cb != NULL) | ||
479 | pg_start_ctx->peergroup_cb (pg_start_ctx->cls, NULL); | ||
480 | |||
481 | if (pg_start_ctx->topology_output_file != NULL) | ||
482 | { | ||
483 | temp = GNUNET_asprintf (&temp_str, "}\n"); | ||
484 | if (temp > 0) | ||
485 | GNUNET_DISK_file_write (pg_start_ctx->topology_output_file, temp_str, | ||
486 | temp); | ||
487 | GNUNET_free (temp_str); | ||
488 | GNUNET_DISK_file_close (pg_start_ctx->topology_output_file); | ||
489 | } | ||
490 | GNUNET_free_non_null (pg_start_ctx->fail_reason); | ||
491 | if (NULL != pg_start_ctx->hostkey_meter) | ||
492 | free_meter(pg_start_ctx->hostkey_meter); | ||
493 | if (NULL != pg_start_ctx->peer_start_meter) | ||
494 | free_meter(pg_start_ctx->peer_start_meter); | ||
495 | if (NULL != pg_start_ctx->connect_meter) | ||
496 | free_meter(pg_start_ctx->connect_meter); | ||
497 | GNUNET_free (pg_start_ctx); | ||
498 | } | ||
499 | |||
500 | |||
501 | /** | ||
502 | * Callback called for each started daemon. | ||
503 | * | ||
504 | * @param cls Clause (PG Context). | ||
505 | * @param id PeerIdentidy of started daemon. | ||
506 | * @param cfg Configuration used by the daemon. | ||
507 | * @param d Handle for the daemon. | ||
508 | * @param emsg Error message, NULL on success. | ||
509 | */ | ||
510 | static void | ||
511 | internal_peers_started_callback (void *cls, | ||
512 | const struct GNUNET_PeerIdentity *id, | ||
513 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
514 | struct GNUNET_TESTING_Daemon *d, | ||
515 | const char *emsg) | ||
516 | { | ||
517 | struct PeerGroupStartupContext *pg_start_ctx = cls; | ||
518 | |||
519 | if (emsg != NULL) | ||
520 | { | ||
521 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
522 | "Failed to start daemon with error: `%s'\n", emsg); | ||
523 | return; | ||
524 | } | ||
525 | GNUNET_assert (id != NULL); | ||
526 | |||
527 | #if VERBOSE > 1 | ||
528 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n", | ||
529 | (pg_start_ctx->total - pg_start_ctx->peers_left) + 1, | ||
530 | pg_start_ctx->total); | ||
531 | #endif | ||
532 | |||
533 | pg_start_ctx->peers_left--; | ||
534 | |||
535 | if (NULL == pg_start_ctx->peer_start_meter) | ||
536 | { | ||
537 | /* Cancelled Ctrl-C or error */ | ||
538 | return; | ||
539 | } | ||
540 | if (GNUNET_YES == update_meter (pg_start_ctx->peer_start_meter)) | ||
541 | { | ||
542 | #if VERBOSE | ||
543 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
544 | "All %d daemons started, now connecting peers!\n", | ||
545 | pg_start_ctx->total); | ||
546 | #endif | ||
547 | GNUNET_assert (pg_start_ctx->die_task != GNUNET_SCHEDULER_NO_TASK); | ||
548 | GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task); | ||
549 | |||
550 | pg_start_ctx->expected_connections = UINT_MAX; | ||
551 | // FIXME: why whould peers_left be != 0?? Or pg NULL? | ||
552 | if ((pg_start_ctx->pg != NULL) && (pg_start_ctx->peers_left == 0)) | ||
553 | { | ||
554 | pg_start_ctx->connect_start_time = GNUNET_TIME_absolute_get (); | ||
555 | pg_start_ctx->expected_connections = | ||
556 | GNUNET_TESTING_connect_topology (pg_start_ctx->pg, | ||
557 | pg_start_ctx->connect_topology, | ||
558 | pg_start_ctx->connect_topology_option, | ||
559 | pg_start_ctx->connect_topology_option_modifier, | ||
560 | pg_start_ctx->connect_timeout, | ||
561 | pg_start_ctx->connect_attempts, NULL, | ||
562 | NULL); | ||
563 | |||
564 | pg_start_ctx->connect_meter = | ||
565 | create_meter (pg_start_ctx->expected_connections, "Peer connection ", | ||
566 | pg_start_ctx->verbose); | ||
567 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n", | ||
568 | pg_start_ctx->expected_connections); | ||
569 | } | ||
570 | |||
571 | if (pg_start_ctx->expected_connections == 0) | ||
572 | { | ||
573 | GNUNET_free_non_null (pg_start_ctx->fail_reason); | ||
574 | pg_start_ctx->fail_reason = | ||
575 | GNUNET_strdup ("from connect topology (bad return)"); | ||
576 | pg_start_ctx->die_task = | ||
577 | GNUNET_SCHEDULER_add_now (&end_badly, pg_start_ctx); | ||
578 | return; | ||
579 | } | ||
580 | |||
581 | GNUNET_free_non_null (pg_start_ctx->fail_reason); | ||
582 | pg_start_ctx->fail_reason = | ||
583 | GNUNET_strdup ("from connect topology (timeout)"); | ||
584 | pg_start_ctx->die_task = | ||
585 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining | ||
586 | (pg_start_ctx->timeout), &end_badly, | ||
587 | pg_start_ctx); | ||
588 | } | ||
589 | } | ||
590 | |||
591 | /** | ||
592 | * Callback indicating that the hostkey was created for a peer. | ||
593 | * | ||
594 | * @param cls NULL | ||
595 | * @param id the peer identity | ||
596 | * @param d the daemon handle (pretty useless at this point, remove?) | ||
597 | * @param emsg non-null on failure | ||
598 | */ | ||
599 | static void | ||
600 | internal_hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
601 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
602 | { | ||
603 | struct PeerGroupStartupContext *pg_start_ctx = cls; | ||
604 | unsigned int create_expected_connections; | ||
605 | |||
606 | if (emsg != NULL) | ||
607 | { | ||
608 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
609 | "Hostkey callback received error: %s\n", emsg); | ||
610 | } | ||
611 | |||
612 | #if VERBOSE > 1 | ||
613 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
614 | "Hostkey (%d/%d) created for peer `%s'\n", | ||
615 | pg_start_ctx->total - pg_start_ctx->peers_left + 1, | ||
616 | pg_start_ctx->total, GNUNET_i2s (id)); | ||
617 | #endif | ||
618 | |||
619 | pg_start_ctx->peers_left--; | ||
620 | if (GNUNET_YES == update_meter (pg_start_ctx->hostkey_meter)) | ||
621 | { | ||
622 | GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task); | ||
623 | GNUNET_free_non_null (pg_start_ctx->fail_reason); | ||
624 | /* Set up task in case topology creation doesn't finish | ||
625 | * within a reasonable amount of time */ | ||
626 | pg_start_ctx->fail_reason = GNUNET_strdup ("from create_topology"); | ||
627 | pg_start_ctx->die_task = | ||
628 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining | ||
629 | (pg_start_ctx->timeout), &end_badly, | ||
630 | pg_start_ctx); | ||
631 | pg_start_ctx->peers_left = pg_start_ctx->total; /* Reset counter */ | ||
632 | create_expected_connections = | ||
633 | GNUNET_TESTING_create_topology (pg_start_ctx->pg, | ||
634 | pg_start_ctx->topology, | ||
635 | pg_start_ctx->restrict_topology, | ||
636 | pg_start_ctx->restrict_transports); | ||
637 | if (create_expected_connections > 0) | ||
638 | { | ||
639 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
640 | "Topology set up, have %u expected connections, now starting peers!\n", | ||
641 | create_expected_connections); | ||
642 | GNUNET_TESTING_daemons_continue_startup (pg_start_ctx->pg); | ||
643 | } | ||
644 | else | ||
645 | { | ||
646 | GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task); | ||
647 | GNUNET_free_non_null (pg_start_ctx->fail_reason); | ||
648 | pg_start_ctx->fail_reason = | ||
649 | GNUNET_strdup ("from create topology (bad return)"); | ||
650 | pg_start_ctx->die_task = | ||
651 | GNUNET_SCHEDULER_add_now (&end_badly, pg_start_ctx); | ||
652 | return; | ||
653 | } | ||
654 | |||
655 | GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task); | ||
656 | GNUNET_free_non_null (pg_start_ctx->fail_reason); | ||
657 | pg_start_ctx->fail_reason = | ||
658 | GNUNET_strdup ("from continue startup (timeout)"); | ||
659 | pg_start_ctx->die_task = | ||
660 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining | ||
661 | (pg_start_ctx->timeout), &end_badly, | ||
662 | pg_start_ctx); | ||
663 | } | ||
664 | } | ||
665 | |||
666 | |||
667 | /** | ||
668 | * Prototype of a callback function indicating that two peers | ||
669 | * are currently connected. | ||
670 | * | ||
671 | * @param cls closure | ||
672 | * @param first peer id for first daemon | ||
673 | * @param second peer id for the second daemon | ||
674 | * @param emsg error message (NULL on success) | ||
675 | */ | ||
676 | void | ||
677 | write_topology_cb (void *cls, const struct GNUNET_PeerIdentity *first, | ||
678 | const struct GNUNET_PeerIdentity *second, const char *emsg) | ||
679 | { | ||
680 | struct TopologyOutputContext *topo_ctx; | ||
681 | int temp; | ||
682 | char *temp_str; | ||
683 | char *temp_pid2; | ||
684 | |||
685 | topo_ctx = (struct TopologyOutputContext *) cls; | ||
686 | GNUNET_assert (topo_ctx->file != NULL); | ||
687 | if ((emsg == NULL) && (first != NULL) && (second != NULL)) | ||
688 | { | ||
689 | GNUNET_assert (first != NULL); | ||
690 | GNUNET_assert (second != NULL); | ||
691 | temp_pid2 = GNUNET_strdup (GNUNET_i2s (second)); | ||
692 | temp = | ||
693 | GNUNET_asprintf (&temp_str, "\t\"%s\" -- \"%s\"\n", GNUNET_i2s (first), | ||
694 | temp_pid2); | ||
695 | GNUNET_free (temp_pid2); | ||
696 | GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp); | ||
697 | } | ||
698 | else if ((emsg == NULL) && (first == NULL) && (second == NULL)) | ||
699 | { | ||
700 | temp = GNUNET_asprintf (&temp_str, "}\n"); | ||
701 | GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp); | ||
702 | GNUNET_DISK_file_close (topo_ctx->file); | ||
703 | topo_ctx->notify_cb (topo_ctx->notify_cb_cls, NULL); | ||
704 | GNUNET_free (topo_ctx); | ||
705 | } | ||
706 | else | ||
707 | { | ||
708 | temp = GNUNET_asprintf (&temp_str, "}\n"); | ||
709 | GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp); | ||
710 | GNUNET_DISK_file_close (topo_ctx->file); | ||
711 | topo_ctx->notify_cb (topo_ctx->notify_cb_cls, emsg); | ||
712 | GNUNET_free (topo_ctx); | ||
713 | } | ||
714 | } | ||
715 | |||
716 | /** | ||
717 | * Print current topology to a graphviz readable file. | ||
718 | * | ||
719 | * @param pg a currently running peergroup to print to file | ||
720 | * @param output_filename the file to write the topology to | ||
721 | * @param notify_cb callback to call upon completion or failure | ||
722 | * @param notify_cb_cls closure for notify_cb | ||
723 | * | ||
724 | */ | ||
725 | void | ||
726 | GNUNET_TESTING_peergroup_topology_to_file (struct GNUNET_TESTING_PeerGroup *pg, | ||
727 | const char *output_filename, | ||
728 | GNUNET_TESTING_NotifyCompletion | ||
729 | notify_cb, void *notify_cb_cls) | ||
730 | { | ||
731 | struct TopologyOutputContext *topo_ctx; | ||
732 | int temp; | ||
733 | char *temp_str; | ||
734 | |||
735 | topo_ctx = GNUNET_malloc (sizeof (struct TopologyOutputContext)); | ||
736 | |||
737 | topo_ctx->notify_cb = notify_cb; | ||
738 | topo_ctx->notify_cb_cls = notify_cb_cls; | ||
739 | topo_ctx->file = | ||
740 | GNUNET_DISK_file_open (output_filename, | ||
741 | GNUNET_DISK_OPEN_READWRITE | | ||
742 | GNUNET_DISK_OPEN_CREATE, | ||
743 | GNUNET_DISK_PERM_USER_READ | | ||
744 | GNUNET_DISK_PERM_USER_WRITE); | ||
745 | if (topo_ctx->file == NULL) | ||
746 | { | ||
747 | notify_cb (notify_cb_cls, "Failed to open output file!"); | ||
748 | GNUNET_free (topo_ctx); | ||
749 | return; | ||
750 | } | ||
751 | |||
752 | temp = GNUNET_asprintf (&temp_str, "strict graph G {\n"); | ||
753 | if (temp > 0) | ||
754 | GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp); | ||
755 | GNUNET_free_non_null (temp_str); | ||
756 | GNUNET_TESTING_get_topology (pg, &write_topology_cb, topo_ctx); | ||
757 | } | ||
758 | |||
759 | /** | ||
760 | * Start a peer group with a given number of peers. Notify | ||
761 | * on completion of peer startup and connection based on given | ||
762 | * topological constraints. Optionally notify on each | ||
763 | * established connection. | ||
764 | * | ||
765 | * @param cfg configuration template to use | ||
766 | * @param total number of daemons to start | ||
767 | * @param timeout total time allowed for peers to start | ||
768 | * @param connect_cb function to call each time two daemons are connected | ||
769 | * @param peergroup_cb function to call once all peers are up and connected | ||
770 | * @param peergroup_cls closure for peergroup callbacks | ||
771 | * @param hostnames linked list of host structs to use to start peers on | ||
772 | * (NULL to run on localhost only) | ||
773 | * | ||
774 | * @return NULL on error, otherwise handle to control peer group | ||
775 | */ | ||
776 | struct GNUNET_TESTING_PeerGroup * | ||
777 | GNUNET_TESTING_peergroup_start (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
778 | unsigned int total, | ||
779 | struct GNUNET_TIME_Relative timeout, | ||
780 | GNUNET_TESTING_NotifyConnection connect_cb, | ||
781 | GNUNET_TESTING_NotifyCompletion peergroup_cb, | ||
782 | void *peergroup_cls, | ||
783 | const struct GNUNET_TESTING_Host *hostnames) | ||
784 | { | ||
785 | struct PeerGroupStartupContext *pg_start_ctx; | ||
786 | char *temp_str; | ||
787 | int temp; | ||
788 | struct GNUNET_TIME_Relative rtimeout; | ||
789 | |||
790 | GNUNET_assert (total > 0); | ||
791 | GNUNET_assert (cfg != NULL); | ||
792 | |||
793 | pg_start_ctx = GNUNET_malloc (sizeof (struct PeerGroupStartupContext)); | ||
794 | |||
795 | if (GNUNET_OK != | ||
796 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "connect_attempts", | ||
797 | &pg_start_ctx->connect_attempts)) | ||
798 | { | ||
799 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
800 | "testing_old", "connect_attempts"); | ||
801 | GNUNET_free (pg_start_ctx); | ||
802 | return NULL; | ||
803 | } | ||
804 | |||
805 | if (GNUNET_OK != | ||
806 | GNUNET_CONFIGURATION_get_value_time (cfg, "testing_old", "CONNECT_TIMEOUT", | ||
807 | &pg_start_ctx->connect_timeout)) | ||
808 | { | ||
809 | pg_start_ctx->connect_timeout = DEFAULT_CONNECT_TIMEOUT; | ||
810 | } | ||
811 | |||
812 | if (GNUNET_OK != | ||
813 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", | ||
814 | "max_outstanding_connections", | ||
815 | &pg_start_ctx->max_concurrent_connections)) | ||
816 | { | ||
817 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
818 | "testing_old", "max_outstanding_connections"); | ||
819 | GNUNET_free (pg_start_ctx); | ||
820 | return NULL; | ||
821 | } | ||
822 | |||
823 | if (GNUNET_OK != | ||
824 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", | ||
825 | "max_concurrent_ssh", | ||
826 | &pg_start_ctx->max_concurrent_ssh)) | ||
827 | { | ||
828 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
829 | "testing_old", "max_concurrent_ssh"); | ||
830 | GNUNET_free (pg_start_ctx); | ||
831 | return NULL; | ||
832 | } | ||
833 | |||
834 | if (GNUNET_SYSERR == | ||
835 | (pg_start_ctx->verbose = | ||
836 | GNUNET_CONFIGURATION_get_value_yesno (cfg, "testing_old", | ||
837 | "use_progressbars"))) | ||
838 | { | ||
839 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
840 | "testing_old", "use_progressbars"); | ||
841 | GNUNET_free (pg_start_ctx); | ||
842 | return NULL; | ||
843 | } | ||
844 | |||
845 | if (GNUNET_OK != | ||
846 | GNUNET_CONFIGURATION_get_value_time (cfg, "testing_old", "PEERGROUP_TIMEOUT", | ||
847 | &rtimeout)) | ||
848 | { | ||
849 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", | ||
850 | "testing_old", "PEERGROUP_TIMEOUT"); | ||
851 | GNUNET_free (pg_start_ctx); | ||
852 | return NULL; | ||
853 | } | ||
854 | pg_start_ctx->timeout = GNUNET_TIME_relative_to_absolute (rtimeout); | ||
855 | |||
856 | |||
857 | /* Read topology related options from the configuration file */ | ||
858 | temp_str = NULL; | ||
859 | if ((GNUNET_YES == | ||
860 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", "topology", | ||
861 | &temp_str)) && | ||
862 | (GNUNET_NO == | ||
863 | GNUNET_TESTING_topology_get (&pg_start_ctx->topology, temp_str))) | ||
864 | { | ||
865 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
866 | "Invalid topology `%s' given for section %s option %s\n", | ||
867 | temp_str, "TESTING_old", "TOPOLOGY"); | ||
868 | pg_start_ctx->topology = GNUNET_TESTING_TOPOLOGY_CLIQUE; /* Defaults to NONE, so set better default here */ | ||
869 | } | ||
870 | GNUNET_free_non_null (temp_str); | ||
871 | |||
872 | if (GNUNET_YES == | ||
873 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", | ||
874 | "topology_output_file", &temp_str)) | ||
875 | { | ||
876 | pg_start_ctx->topology_output_file = | ||
877 | GNUNET_DISK_file_open (temp_str, | ||
878 | GNUNET_DISK_OPEN_READWRITE | | ||
879 | GNUNET_DISK_OPEN_CREATE, | ||
880 | GNUNET_DISK_PERM_USER_READ | | ||
881 | GNUNET_DISK_PERM_USER_WRITE); | ||
882 | if (pg_start_ctx->topology_output_file != NULL) | ||
883 | { | ||
884 | GNUNET_free (temp_str); | ||
885 | temp = GNUNET_asprintf (&temp_str, "strict graph G {\n"); | ||
886 | if (temp > 0) | ||
887 | GNUNET_DISK_file_write (pg_start_ctx->topology_output_file, temp_str, | ||
888 | temp); | ||
889 | } | ||
890 | GNUNET_free (temp_str); | ||
891 | } | ||
892 | |||
893 | if (GNUNET_OK != | ||
894 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", "percentage", | ||
895 | &temp_str)) | ||
896 | pg_start_ctx->topology_percentage = 0.5; | ||
897 | else | ||
898 | { | ||
899 | pg_start_ctx->topology_percentage = atof (temp_str); | ||
900 | GNUNET_free (temp_str); | ||
901 | } | ||
902 | |||
903 | if (GNUNET_OK != | ||
904 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", "probability", | ||
905 | &temp_str)) | ||
906 | pg_start_ctx->topology_probability = 0.5; | ||
907 | else | ||
908 | { | ||
909 | pg_start_ctx->topology_probability = atof (temp_str); | ||
910 | GNUNET_free (temp_str); | ||
911 | } | ||
912 | |||
913 | if ((GNUNET_YES == | ||
914 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", | ||
915 | "connect_topology", &temp_str)) && | ||
916 | (GNUNET_NO == | ||
917 | GNUNET_TESTING_topology_get (&pg_start_ctx->connect_topology, temp_str))) | ||
918 | { | ||
919 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
920 | "Invalid connect topology `%s' given for section %s option %s\n", | ||
921 | temp_str, "TESTING_old", "CONNECT_TOPOLOGY"); | ||
922 | } | ||
923 | GNUNET_free_non_null (temp_str); | ||
924 | |||
925 | if ((GNUNET_YES == | ||
926 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", | ||
927 | "connect_topology_option", | ||
928 | &temp_str)) && | ||
929 | (GNUNET_NO == | ||
930 | GNUNET_TESTING_topology_option_get | ||
931 | (&pg_start_ctx->connect_topology_option, temp_str))) | ||
932 | { | ||
933 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
934 | "Invalid connect topology option `%s' given for section %s option %s\n", | ||
935 | temp_str, "TESTING_old", "CONNECT_TOPOLOGY_OPTION"); | ||
936 | pg_start_ctx->connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Defaults to NONE, set to ALL */ | ||
937 | } | ||
938 | GNUNET_free_non_null (temp_str); | ||
939 | |||
940 | if (GNUNET_YES == | ||
941 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", | ||
942 | "connect_topology_option_modifier", | ||
943 | &temp_str)) | ||
944 | { | ||
945 | if (SSCANF | ||
946 | (temp_str, "%lf", &pg_start_ctx->connect_topology_option_modifier) != 1) | ||
947 | { | ||
948 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
949 | _ | ||
950 | ("Invalid value `%s' for option `%s' in section `%s': expected float\n"), | ||
951 | temp_str, "connect_topology_option_modifier", "TESTING_old"); | ||
952 | GNUNET_free (temp_str); | ||
953 | GNUNET_free (pg_start_ctx); | ||
954 | return NULL; | ||
955 | } | ||
956 | GNUNET_free (temp_str); | ||
957 | } | ||
958 | |||
959 | if (GNUNET_YES != | ||
960 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", | ||
961 | "blacklist_transports", | ||
962 | &pg_start_ctx->restrict_transports)) | ||
963 | pg_start_ctx->restrict_transports = NULL; | ||
964 | |||
965 | pg_start_ctx->restrict_topology = GNUNET_TESTING_TOPOLOGY_NONE; | ||
966 | if ((GNUNET_YES == | ||
967 | GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", | ||
968 | "blacklist_topology", &temp_str)) | ||
969 | && (GNUNET_NO == | ||
970 | GNUNET_TESTING_topology_get (&pg_start_ctx->restrict_topology, | ||
971 | temp_str))) | ||
972 | { | ||
973 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
974 | "Invalid topology `%s' given for section %s option %s\n", | ||
975 | temp_str, "TESTING_OLD", "BLACKLIST_TOPOLOGY"); | ||
976 | } | ||
977 | |||
978 | GNUNET_free_non_null (temp_str); | ||
979 | |||
980 | pg_start_ctx->cfg = cfg; | ||
981 | pg_start_ctx->total = total; | ||
982 | pg_start_ctx->peers_left = total; | ||
983 | pg_start_ctx->connect_cb = connect_cb; | ||
984 | pg_start_ctx->peergroup_cb = peergroup_cb; | ||
985 | pg_start_ctx->cls = peergroup_cls; | ||
986 | pg_start_ctx->hostnames = hostnames; | ||
987 | pg_start_ctx->hostkey_meter = | ||
988 | create_meter (pg_start_ctx->peers_left, "Hostkeys created ", | ||
989 | pg_start_ctx->verbose); | ||
990 | pg_start_ctx->peer_start_meter = | ||
991 | create_meter (pg_start_ctx->peers_left, "Peers started ", | ||
992 | pg_start_ctx->verbose); | ||
993 | /* Make compilers happy */ | ||
994 | reset_meter (pg_start_ctx->peer_start_meter); | ||
995 | pg_start_ctx->fail_reason = | ||
996 | GNUNET_strdup | ||
997 | ("didn't generate all hostkeys within allowed startup time!"); | ||
998 | pg_start_ctx->die_task = | ||
999 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining | ||
1000 | (pg_start_ctx->timeout), &end_badly, | ||
1001 | pg_start_ctx); | ||
1002 | |||
1003 | pg_start_ctx->pg = | ||
1004 | GNUNET_TESTING_daemons_start (pg_start_ctx->cfg, pg_start_ctx->peers_left, | ||
1005 | pg_start_ctx->max_concurrent_connections, | ||
1006 | pg_start_ctx->max_concurrent_ssh, | ||
1007 | GNUNET_TIME_absolute_get_remaining | ||
1008 | (pg_start_ctx->timeout), | ||
1009 | &internal_hostkey_callback, pg_start_ctx, | ||
1010 | &internal_peers_started_callback, | ||
1011 | pg_start_ctx, &internal_topology_callback, | ||
1012 | pg_start_ctx, pg_start_ctx->hostnames); | ||
1013 | |||
1014 | return pg_start_ctx->pg; | ||
1015 | } | ||
1016 | |||
1017 | /* end of testing_peergroup.c */ | ||