diff options
Diffstat (limited to 'src/testbed')
91 files changed, 0 insertions, 34047 deletions
diff --git a/src/testbed/.gitignore b/src/testbed/.gitignore deleted file mode 100644 index f7cfb1e23..000000000 --- a/src/testbed/.gitignore +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | gnunet-testbed-profiler | ||
2 | generate-underlay-topology | ||
3 | gnunet-daemon-latency-logger | ||
4 | gnunet-daemon-testbed-blacklist | ||
5 | gnunet-daemon-testbed-underlay | ||
6 | gnunet-helper-testbed | ||
7 | gnunet-service-testbed | ||
8 | gnunet-service-test-barriers | ||
9 | test_gnunet_helper_testbed | ||
10 | test_testbed_api | ||
11 | test_testbed_api_2peers_1controller | ||
12 | test_testbed_api_3peers_3controllers | ||
13 | test_testbed_api_barriers | ||
14 | test_testbed_api_controllerlink | ||
15 | test_testbed_api_hosts | ||
16 | test_testbed_api_operations | ||
17 | test_testbed_api_peer_reconfiguration | ||
18 | test_testbed_api_peers_manage_services | ||
19 | test_testbed_api_sd | ||
20 | test_testbed_api_statistics | ||
21 | test_testbed_api_test | ||
22 | test_testbed_api_test_timeout | ||
23 | test_testbed_api_testbed_run | ||
24 | test_testbed_api_testbed_run_topology2dtorus | ||
25 | test_testbed_api_testbed_run_topologyclique | ||
26 | test_testbed_api_testbed_run_topologyfromfile | ||
27 | test_testbed_api_testbed_run_topologyline | ||
28 | test_testbed_api_testbed_run_topologyrandom | ||
29 | test_testbed_api_testbed_run_topologyring | ||
30 | test_testbed_api_testbed_run_topologyscalefree | ||
31 | test_testbed_api_testbed_run_topologysmallworld | ||
32 | test_testbed_api_testbed_run_topologysmallworldring | ||
33 | test_testbed_api_testbed_run_topologystar | ||
34 | test_testbed_api_testbed_run_waitforever | ||
35 | test_testbed_api_topology | ||
36 | test_testbed_api_topology_clique | ||
37 | test_testbed_underlay | ||
diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am deleted file mode 100644 index 11399e77c..000000000 --- a/src/testbed/Makefile.am +++ /dev/null | |||
@@ -1,401 +0,0 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | if USE_COVERAGE | ||
5 | AM_CFLAGS = --coverage -O0 | ||
6 | XLIB = -lgcov | ||
7 | endif | ||
8 | |||
9 | plugindir = $(libdir)/gnunet | ||
10 | |||
11 | libexecdir= $(pkglibdir)/libexec/ | ||
12 | |||
13 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
14 | |||
15 | pkgcfg_DATA = \ | ||
16 | testbed.conf | ||
17 | |||
18 | if HAVE_SQLITE | ||
19 | underlay_daemon = gnunet-daemon-testbed-underlay | ||
20 | latency_logger = gnunet-daemon-latency-logger | ||
21 | generate_underlay = generate-underlay-topology | ||
22 | underlay_testcases = test_testbed_underlay | ||
23 | endif | ||
24 | |||
25 | libexec_PROGRAMS = \ | ||
26 | gnunet-service-testbed \ | ||
27 | gnunet-helper-testbed \ | ||
28 | gnunet-daemon-testbed-blacklist \ | ||
29 | $(underlay_daemon) \ | ||
30 | $(latency_logger) | ||
31 | |||
32 | bin_PROGRAMS = \ | ||
33 | gnunet-testbed-profiler | ||
34 | |||
35 | noinst_PROGRAMS = \ | ||
36 | $(generate_underlay) | ||
37 | |||
38 | gnunet_service_testbed_SOURCES = \ | ||
39 | gnunet-service-testbed.c gnunet-service-testbed.h \ | ||
40 | gnunet-service-testbed_links.c gnunet-service-testbed_links.h \ | ||
41 | gnunet-service-testbed_peers.c \ | ||
42 | gnunet-service-testbed_cache.c \ | ||
43 | gnunet-service-testbed_oc.c \ | ||
44 | gnunet-service-testbed_cpustatus.c \ | ||
45 | gnunet-service-testbed_meminfo.c gnunet-service-testbed_meminfo.h \ | ||
46 | gnunet-service-testbed_barriers.c gnunet-service-testbed_barriers.h \ | ||
47 | gnunet-service-testbed_connectionpool.c gnunet-service-testbed_connectionpool.h | ||
48 | gnunet_service_testbed_LDADD = $(XLIB) \ | ||
49 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
50 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
51 | $(top_builddir)/src/hello/libgnunethello.la \ | ||
52 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
53 | $(top_builddir)/src/ats/libgnunetats.la \ | ||
54 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
55 | libgnunettestbed.la \ | ||
56 | $(top_builddir)/src/arm/libgnunetarm.la \ | ||
57 | $(LTLIBINTL) $(Z_LIBS) | ||
58 | |||
59 | gnunet_testbed_profiler_SOURCES = \ | ||
60 | gnunet-testbed-profiler.c | ||
61 | gnunet_testbed_profiler_LDADD = $(XLIB) \ | ||
62 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
63 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
64 | libgnunettestbed.la | ||
65 | gnunet_testbed_profiler_LDFLAGS = \ | ||
66 | $(GN_LIBINTL) | ||
67 | |||
68 | gnunet_helper_testbed_SOURCES = \ | ||
69 | gnunet-helper-testbed.c | ||
70 | gnunet_helper_testbed_LDADD = $(XLIB) \ | ||
71 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
72 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
73 | libgnunettestbed.la \ | ||
74 | $(LTLIBINTL) $(Z_LIBS) | ||
75 | |||
76 | gnunet_daemon_testbed_blacklist_SOURCES = gnunet-daemon-testbed-blacklist.c | ||
77 | gnunet_daemon_testbed_blacklist_LDADD = $(XLIB) \ | ||
78 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
79 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
80 | $(LTLIBINTL) | ||
81 | |||
82 | gnunet_daemon_testbed_underlay_SOURCES = gnunet-daemon-testbed-underlay.c | ||
83 | gnunet_daemon_testbed_underlay_LDADD = $(XLIB) \ | ||
84 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
85 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
86 | $(LTLIBINTL) -lsqlite3 | ||
87 | |||
88 | gnunet_daemon_latency_logger_SOURCES = gnunet-daemon-latency-logger.c | ||
89 | gnunet_daemon_latency_logger_LDADD = $(XLIB) \ | ||
90 | $(top_builddir)/src/ats/libgnunetats.la \ | ||
91 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
92 | $(LTLIBINTL) -lsqlite3 | ||
93 | |||
94 | lib_LTLIBRARIES = \ | ||
95 | libgnunettestbed.la | ||
96 | |||
97 | libgnunettestbed_la_SOURCES = \ | ||
98 | testbed_api.c testbed_api.h testbed.h \ | ||
99 | testbed_api_hosts.c testbed_api_hosts.h testbed_helper.h \ | ||
100 | testbed_api_operations.c testbed_api_operations.h \ | ||
101 | testbed_api_peers.c testbed_api_peers.h \ | ||
102 | testbed_api_services.c \ | ||
103 | testbed_api_statistics.c \ | ||
104 | testbed_api_testbed.c \ | ||
105 | testbed_api_test.c \ | ||
106 | testbed_api_topology.c testbed_api_topology.h \ | ||
107 | testbed_api_sd.c testbed_api_sd.h \ | ||
108 | testbed_api_barriers.c | ||
109 | libgnunettestbed_la_LIBADD = $(XLIB) \ | ||
110 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
111 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
112 | $(top_builddir)/src/hello/libgnunethello.la \ | ||
113 | -lm $(Z_LIBS) \ | ||
114 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
115 | $(top_builddir)/src/arm/libgnunetarm.la \ | ||
116 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
117 | $(LTLIBINTL) | ||
118 | libgnunettestbed_la_LDFLAGS = \ | ||
119 | $(GN_LIB_LDFLAGS) \ | ||
120 | -version-info 0:0:0 | ||
121 | |||
122 | generate_underlay_topology_SOURCES = generate-underlay-topology.c | ||
123 | generate_underlay_topology_LDADD = $(XLIB) \ | ||
124 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
125 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
126 | libgnunettestbed.la \ | ||
127 | $(LTLIBINTL) -lsqlite3 | ||
128 | |||
129 | check_PROGRAMS = \ | ||
130 | test_testbed_api_hosts \ | ||
131 | test_gnunet_helper_testbed \ | ||
132 | test_testbed_api_controllerlink \ | ||
133 | test_testbed_api_2peers_1controller \ | ||
134 | test_testbed_api_3peers_3controllers \ | ||
135 | test_testbed_api \ | ||
136 | test_testbed_api_sd \ | ||
137 | test_testbed_api_operations \ | ||
138 | test_testbed_api_testbed_run \ | ||
139 | test_testbed_api_test \ | ||
140 | test_testbed_api_test_timeout \ | ||
141 | test_testbed_api_peer_reconfiguration \ | ||
142 | test_testbed_api_peers_manage_services \ | ||
143 | test_testbed_api_topology \ | ||
144 | test_testbed_api_topology_clique \ | ||
145 | test_testbed_api_testbed_run_topologyrandom \ | ||
146 | test_testbed_api_testbed_run_topologyline \ | ||
147 | test_testbed_api_testbed_run_topologystar \ | ||
148 | test_testbed_api_testbed_run_topologyclique \ | ||
149 | test_testbed_api_testbed_run_topologyring \ | ||
150 | test_testbed_api_testbed_run_topologysmallworldring \ | ||
151 | test_testbed_api_testbed_run_topology2dtorus \ | ||
152 | test_testbed_api_testbed_run_topologysmallworld \ | ||
153 | test_testbed_api_testbed_run_topologyfromfile \ | ||
154 | test_testbed_api_testbed_run_topologyscalefree \ | ||
155 | test_testbed_api_testbed_run_waitforever \ | ||
156 | test_testbed_api_statistics \ | ||
157 | gnunet-service-test-barriers \ | ||
158 | test_testbed_api_barriers \ | ||
159 | $(underlay_testcases) | ||
160 | |||
161 | if ENABLE_TEST_RUN | ||
162 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
163 | TESTS = \ | ||
164 | test_testbed_api \ | ||
165 | test_testbed_api_sd \ | ||
166 | test_testbed_api_operations \ | ||
167 | test_testbed_api_hosts \ | ||
168 | test_gnunet_helper_testbed \ | ||
169 | test_testbed_api_2peers_1controller \ | ||
170 | test_testbed_api_controllerlink \ | ||
171 | test_testbed_api_3peers_3controllers \ | ||
172 | test_testbed_api_testbed_run \ | ||
173 | test_testbed_api_test \ | ||
174 | test_testbed_api_test_timeout \ | ||
175 | test_testbed_api_statistics \ | ||
176 | test_testbed_api_peer_reconfiguration \ | ||
177 | test_testbed_api_peers_manage_services \ | ||
178 | test_testbed_api_topology \ | ||
179 | test_testbed_api_topology_clique \ | ||
180 | test_testbed_api_testbed_run_topologyrandom \ | ||
181 | test_testbed_api_testbed_run_topologyline \ | ||
182 | test_testbed_api_testbed_run_topologystar \ | ||
183 | test_testbed_api_testbed_run_topologyclique \ | ||
184 | test_testbed_api_testbed_run_topologyring \ | ||
185 | test_testbed_api_testbed_run_topology2dtorus \ | ||
186 | test_testbed_api_testbed_run_topologysmallworld \ | ||
187 | test_testbed_api_testbed_run_topologysmallworldring \ | ||
188 | test_testbed_api_testbed_run_topologyfromfile \ | ||
189 | test_testbed_api_testbed_run_topologyscalefree \ | ||
190 | test_testbed_api_barriers \ | ||
191 | $(underlay_testcases) | ||
192 | endif | ||
193 | |||
194 | test_testbed_api_SOURCES = \ | ||
195 | test_testbed_api.c | ||
196 | test_testbed_api_LDADD = \ | ||
197 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
198 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
199 | $(top_builddir)/src/arm/libgnunetarm.la \ | ||
200 | libgnunettestbed.la | ||
201 | |||
202 | test_testbed_api_sd_SOURCES = \ | ||
203 | test_testbed_api_sd.c | ||
204 | test_testbed_api_sd_LDADD = \ | ||
205 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
206 | libgnunettestbed.la | ||
207 | |||
208 | test_testbed_api_2peers_1controller_SOURCES = \ | ||
209 | test_testbed_api_2peers_1controller.c | ||
210 | test_testbed_api_2peers_1controller_LDADD = \ | ||
211 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
212 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
213 | libgnunettestbed.la | ||
214 | |||
215 | test_testbed_api_3peers_3controllers_SOURCES = \ | ||
216 | test_testbed_api_3peers_3controllers.c | ||
217 | test_testbed_api_3peers_3controllers_LDADD = \ | ||
218 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
219 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
220 | libgnunettestbed.la | ||
221 | |||
222 | test_testbed_api_operations_SOURCES = \ | ||
223 | test_testbed_api_operations.c | ||
224 | test_testbed_api_operations_LDADD = \ | ||
225 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
226 | libgnunettestbed.la | ||
227 | |||
228 | test_testbed_api_hosts_SOURCES = \ | ||
229 | test_testbed_api_hosts.c | ||
230 | test_testbed_api_hosts_LDADD = \ | ||
231 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
232 | libgnunettestbed.la | ||
233 | |||
234 | test_testbed_api_controllerlink_SOURCES = \ | ||
235 | test_testbed_api_controllerlink.c | ||
236 | test_testbed_api_controllerlink_LDADD = \ | ||
237 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
238 | libgnunettestbed.la | ||
239 | |||
240 | test_testbed_api_testbed_run_SOURCES = \ | ||
241 | test_testbed_api_testbed_run.c | ||
242 | test_testbed_api_testbed_run_LDADD = \ | ||
243 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
244 | libgnunettestbed.la | ||
245 | |||
246 | test_testbed_api_test_SOURCES = \ | ||
247 | test_testbed_api_test.c | ||
248 | test_testbed_api_test_LDADD = \ | ||
249 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
250 | libgnunettestbed.la | ||
251 | |||
252 | test_testbed_api_test_timeout_SOURCES = \ | ||
253 | test_testbed_api_test_timeout.c | ||
254 | test_testbed_api_test_timeout_LDADD = \ | ||
255 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
256 | libgnunettestbed.la | ||
257 | |||
258 | test_testbed_api_topology_SOURCES = \ | ||
259 | test_testbed_api_topology.c | ||
260 | test_testbed_api_topology_LDADD = \ | ||
261 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
262 | libgnunettestbed.la | ||
263 | |||
264 | test_testbed_api_topology_clique_SOURCES = \ | ||
265 | test_testbed_api_topology_clique.c | ||
266 | test_testbed_api_topology_clique_LDADD = \ | ||
267 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
268 | libgnunettestbed.la | ||
269 | |||
270 | test_gnunet_helper_testbed_SOURCES = \ | ||
271 | test_gnunet_helper_testbed.c | ||
272 | test_gnunet_helper_testbed_LDADD = \ | ||
273 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
274 | libgnunettestbed.la \ | ||
275 | $(Z_LIBS) | ||
276 | |||
277 | test_testbed_api_testbed_run_topologyrandom_SOURCES = \ | ||
278 | test_testbed_api_testbed_run.c | ||
279 | test_testbed_api_testbed_run_topologyrandom_LDADD = \ | ||
280 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
281 | libgnunettestbed.la | ||
282 | |||
283 | test_testbed_api_testbed_run_topologyline_SOURCES = \ | ||
284 | test_testbed_api_testbed_run.c | ||
285 | test_testbed_api_testbed_run_topologyline_LDADD = \ | ||
286 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
287 | libgnunettestbed.la | ||
288 | |||
289 | test_testbed_api_testbed_run_topologystar_SOURCES = \ | ||
290 | test_testbed_api_testbed_run.c | ||
291 | test_testbed_api_testbed_run_topologystar_LDADD = \ | ||
292 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
293 | libgnunettestbed.la | ||
294 | |||
295 | test_testbed_api_testbed_run_topologyclique_SOURCES = \ | ||
296 | test_testbed_api_testbed_run.c | ||
297 | test_testbed_api_testbed_run_topologyclique_LDADD = \ | ||
298 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
299 | libgnunettestbed.la | ||
300 | |||
301 | test_testbed_api_testbed_run_topologyring_SOURCES = \ | ||
302 | test_testbed_api_testbed_run.c | ||
303 | test_testbed_api_testbed_run_topologyring_LDADD = \ | ||
304 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
305 | libgnunettestbed.la | ||
306 | |||
307 | test_testbed_api_testbed_run_topologysmallworldring_SOURCES = \ | ||
308 | test_testbed_api_testbed_run.c | ||
309 | test_testbed_api_testbed_run_topologysmallworldring_LDADD = \ | ||
310 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
311 | libgnunettestbed.la | ||
312 | |||
313 | test_testbed_api_testbed_run_topology2dtorus_SOURCES = \ | ||
314 | test_testbed_api_testbed_run.c | ||
315 | test_testbed_api_testbed_run_topology2dtorus_LDADD = \ | ||
316 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
317 | libgnunettestbed.la | ||
318 | |||
319 | test_testbed_api_testbed_run_topologysmallworld_SOURCES = \ | ||
320 | test_testbed_api_testbed_run.c | ||
321 | test_testbed_api_testbed_run_topologysmallworld_LDADD = \ | ||
322 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
323 | libgnunettestbed.la | ||
324 | |||
325 | test_testbed_api_testbed_run_topologyfromfile_SOURCES = \ | ||
326 | test_testbed_api_testbed_run.c | ||
327 | test_testbed_api_testbed_run_topologyfromfile_LDADD = \ | ||
328 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
329 | libgnunettestbed.la | ||
330 | |||
331 | test_testbed_api_testbed_run_topologyscalefree_SOURCES = \ | ||
332 | test_testbed_api_testbed_run.c | ||
333 | test_testbed_api_testbed_run_topologyscalefree_LDADD = \ | ||
334 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
335 | libgnunettestbed.la | ||
336 | |||
337 | test_testbed_api_testbed_run_waitforever_SOURCES = \ | ||
338 | test_testbed_api_testbed_run.c | ||
339 | test_testbed_api_testbed_run_waitforever_LDADD = \ | ||
340 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
341 | libgnunettestbed.la | ||
342 | |||
343 | test_testbed_api_statistics_SOURCES = \ | ||
344 | test_testbed_api_statistics.c | ||
345 | test_testbed_api_statistics_LDADD = \ | ||
346 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
347 | libgnunettestbed.la | ||
348 | |||
349 | test_testbed_api_peers_manage_services_SOURCES = \ | ||
350 | test_testbed_api_peers_manage_services.c | ||
351 | test_testbed_api_peers_manage_services_LDADD = \ | ||
352 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
353 | libgnunettestbed.la | ||
354 | |||
355 | test_testbed_api_peer_reconfiguration_SOURCES = \ | ||
356 | test_testbed_api_peer_reconfiguration.c | ||
357 | test_testbed_api_peer_reconfiguration_LDADD = \ | ||
358 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
359 | libgnunettestbed.la | ||
360 | |||
361 | test_testbed_api_barriers_SOURCES = \ | ||
362 | test_testbed_api_barriers.c \ | ||
363 | test_testbed_api_barriers.h | ||
364 | test_testbed_api_barriers_LDADD = \ | ||
365 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
366 | libgnunettestbed.la | ||
367 | |||
368 | gnunet_service_test_barriers_SOURCES = \ | ||
369 | gnunet-service-test-barriers.c \ | ||
370 | test_testbed_api_barriers.h | ||
371 | gnunet_service_test_barriers_LDADD = \ | ||
372 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
373 | libgnunettestbed.la | ||
374 | |||
375 | test_testbed_underlay_SOURCES = \ | ||
376 | test_testbed_underlay.c | ||
377 | test_testbed_underlay_LDADD = \ | ||
378 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
379 | libgnunettestbed.la | ||
380 | |||
381 | EXTRA_DIST = \ | ||
382 | test_testbed_api.conf \ | ||
383 | test_testbed_api_statistics.conf \ | ||
384 | test_testbed_api_test_timeout.conf \ | ||
385 | test_testbed_api_template.conf \ | ||
386 | test_testbed_api_testbed_run_topologyring.conf \ | ||
387 | test_testbed_api_testbed_run_topologystar.conf \ | ||
388 | test_testbed_api_testbed_run_topologyclique.conf \ | ||
389 | test_testbed_api_testbed_run_topologyline.conf \ | ||
390 | test_testbed_api_testbed_run_topologyrandom.conf \ | ||
391 | test_testbed_api_testbed_run_topologysmallworldring.conf \ | ||
392 | test_testbed_api_testbed_run_topology2dtorus.conf \ | ||
393 | test_testbed_api_testbed_run_topologysmallworld.conf \ | ||
394 | test_testbed_api_testbed_run_topologyfromfile.conf \ | ||
395 | test_testbed_api_testbed_run_topologyscalefree.conf \ | ||
396 | test_testbed_api_barriers.conf.in \ | ||
397 | overlay_topology.txt \ | ||
398 | sample_hosts.txt \ | ||
399 | sample.job \ | ||
400 | test_testbed_underlay.conf.in \ | ||
401 | test-underlay.sqlite | ||
diff --git a/src/testbed/barriers.README.org b/src/testbed/barriers.README.org deleted file mode 100644 index 159e1c355..000000000 --- a/src/testbed/barriers.README.org +++ /dev/null | |||
@@ -1,95 +0,0 @@ | |||
1 | * Description | ||
2 | The testbed subsystem's barriers API facilitates coordination among the peers | ||
3 | run by the testbed and the experiment driver. The concept is similar to the | ||
4 | barrier synchronisation mechanism found in parallel programming or | ||
5 | multi-threading paradigms - a peer waits at a barrier upon reaching it until the | ||
6 | barrier is reached by a predefined number of peers. This predefined number of | ||
7 | peers required to cross a barrier is also called quorum. We say a peer has | ||
8 | reached a barrier if the peer is waiting for the barrier to be crossed. | ||
9 | Similarly a barrier is said to be reached if the required quorum of peers reach | ||
10 | the barrier. A barrier which is reached is deemed as crossed after all the | ||
11 | peers waiting on it are notified. | ||
12 | |||
13 | The barriers API provides the following functions: | ||
14 | 1) GNUNET_TESTBED_barrier_init(): function to initialise a barrier in the | ||
15 | experiment | ||
16 | 2) GNUNET_TESTBED_barrier_cancel(): function to cancel a barrier which has been | ||
17 | initialised before | ||
18 | 3) GNUNET_TESTBED_barrier_wait(): function to signal barrier service that the | ||
19 | caller has reached a barrier and is waiting for it to be crossed | ||
20 | 4) GNUNET_TESTBED_barrier_wait_cancel(): function to stop waiting for a barrier | ||
21 | to be crossed | ||
22 | |||
23 | Among the above functions, the first two, namely GNUNET_TESTBED_barrier_init() | ||
24 | and GNUNET_TESTBED_barrier_cacel() are used by experiment drivers. All barriers | ||
25 | should be initialised by the experiment driver by calling | ||
26 | GNUNET_TESTBED_barrier_init(). This function takes a name to identify the | ||
27 | barrier, the quorum required for the barrier to be crossed and a notification | ||
28 | callback for notifying the experiment driver when the barrier is crossed. The | ||
29 | GNUNET_TESTBED_function barrier_cancel() cancels an initialised barrier and | ||
30 | frees the resources allocated for it. This function can be called upon a | ||
31 | initialised barrier before it is crossed. | ||
32 | |||
33 | The remaining two functions GNUNET_TESTBED_barrier_wait() and | ||
34 | GNUNET_TESTBED_barrier_wait_cancel() are used in the peer's processes. | ||
35 | GNUNET_TESTBED_barrier_wait() connects to the local barrier service running on | ||
36 | the same host the peer is running on and registers that the caller has reached | ||
37 | the barrier and is waiting for the barrier to be crossed. Note that this | ||
38 | function can only be used by peers which are started by testbed as this function | ||
39 | tries to access the local barrier service which is part of the testbed | ||
40 | controller service. Calling GNUNET_TESTBED_barrier_wait() on an uninitialised | ||
41 | barrier results in failure. GNUNET_TESTBED_barrier_wait_cancel() cancels the | ||
42 | notification registered by GNUNET_TESTBED_barrier_wait(). | ||
43 | |||
44 | |||
45 | * Implementation | ||
46 | Since barriers involve coordination between experiment driver and peers, the | ||
47 | barrier service in the testbed controller is split into two components. The | ||
48 | first component responds to the message generated by the barrier API used by the | ||
49 | experiment driver (functions GNUNET_TESTBED_barrier_init() and | ||
50 | GNUNET_TESTBED_barrier_cancel()) and the second component to the messages | ||
51 | generated by barrier API used by peers (functions GNUNET_TESTBED_barrier_wait() | ||
52 | and GNUNET_TESTBED_barrier_wait_cancel()). | ||
53 | |||
54 | Calling GNUNET_TESTBED_barrier_init() sends a BARRIER_INIT message to the master | ||
55 | controller. The master controller then registers a barrier and calls | ||
56 | GNUNET_TESTBED_barrier_init() for each its subcontrollers. In this way barrier | ||
57 | initialisation is propagated to the controller hierarchy. While propagating | ||
58 | initialisation, any errors at a subcontroller such as timeout during further | ||
59 | propagation are reported up the hierarchy back to the experiment driver. | ||
60 | |||
61 | Similar to GNUNET_TESTBED_barrier_init(), GNUNET_TESTBED_barrier_cancel() | ||
62 | propagates BARRIER_CANCEL message which causes controllers to remove an | ||
63 | initialised barrier. | ||
64 | |||
65 | The second component is implemented as a separate service in the binary | ||
66 | `gnunet-service-testbed' which already has the testbed controller service. | ||
67 | Although this deviates from the gnunet process architecture of having one | ||
68 | service per binary, it is needed in this case as this component needs access to | ||
69 | barrier data created by the first component. This component responds to | ||
70 | BARRIER_WAIT messages from local peers when they call | ||
71 | GNUNET_TESTBED_barrier_wait(). Upon receiving BARRIER_WAIT message, the service | ||
72 | checks if the requested barrier has been initialised before and if it was not | ||
73 | initialised, an error status is sent through BARRIER_STATUS message to the local | ||
74 | peer and the connection from the peer is terminated. If the barrier is | ||
75 | initialised before, the barrier's counter for reached peers is incremented and a | ||
76 | notification is registered to notify the peer when the barrier is reached. The | ||
77 | connection from the peer is left open. | ||
78 | |||
79 | When enough peers required to attain the quorum send BARRIER_WAIT messages, the | ||
80 | controller sends a BARRIER_STATUS message to its parent informing that the | ||
81 | barrier is crossed. If the controller has started further subcontrollers, it | ||
82 | delays this message until it receives a similar notification from each of those | ||
83 | subcontrollers. Finally, the barriers API at the experiment driver receives the | ||
84 | BARRIER_STATUS when the barrier is reached at all the controllers. | ||
85 | |||
86 | The barriers API at the experiment driver responds to the BARRIER_STATUS message | ||
87 | by echoing it back to the master controller and notifying the experiment | ||
88 | controller through the notification callback that a barrier has been crossed. | ||
89 | The echoed BARRIER_STATUS message is propagated by the master controller to the | ||
90 | controller hierarchy. This propagation triggers the notifications registered by | ||
91 | peers at each of the controllers in the hierarchy. Note the difference between | ||
92 | this downward propagation of the BARRIER_STATUS message from its upward | ||
93 | propagation -- the upward propagation is needed for ensuring that the barrier is | ||
94 | reached by all the controllers and the downward propagation is for triggering | ||
95 | that the barrier is crossed. | ||
diff --git a/src/testbed/buildvars.py.in b/src/testbed/buildvars.py.in deleted file mode 100644 index 3b2f56118..000000000 --- a/src/testbed/buildvars.py.in +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | # This file is part of GNUnet. | ||
2 | # (C) 2008--2013, 2018 Christian Grothoff (and other contributing authors) | ||
3 | # | ||
4 | # GNUnet is free software: you can redistribute it and/or modify it | ||
5 | # under the terms of the GNU Affero General Public License as published | ||
6 | # by the Free Software Foundation, either version 3 of the License, | ||
7 | # or (at your option) any later version. | ||
8 | # | ||
9 | # GNUnet is distributed in the hope that it will be useful, but | ||
10 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # Affero General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU Affero General Public License | ||
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | # | ||
17 | # SPDX-License-Identifier: AGPL3.0-or-later | ||
18 | |||
19 | # file: testbed/buildvars.py | ||
20 | # brief: file for importing variables from build system into python | ||
21 | # author: Sree Harsha Totakura | ||
22 | |||
23 | import os | ||
24 | |||
25 | exec_prefix = '@exec_prefix@' | ||
26 | libexecdir = '@libexecdir@' | ||
27 | |||
28 | if libexecdir.startswith(exec_prefix): | ||
29 | libexecdir = libexecdir[len(exec_prefix):] | ||
30 | |||
31 | gnunet_prefix = os.environ.get('GNUNET_PREFIX', None) | ||
32 | |||
33 | if gnunet_prefix and libexecdir.startswith('/'): | ||
34 | libexecdir = os.path.join(gnunet_prefix, libexecdir[1:]) | ||
diff --git a/src/testbed/generate-underlay-topology.c b/src/testbed/generate-underlay-topology.c deleted file mode 100644 index b7bd8fce9..000000000 --- a/src/testbed/generate-underlay-topology.c +++ /dev/null | |||
@@ -1,407 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2014 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/generate-underlay-topology.c | ||
23 | * @brief Program to generate a database file containing given underlay topology | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | #include "testbed_api_topology.h" | ||
31 | #include "sqlite3.h" | ||
32 | |||
33 | #define LOG(type, ...) GNUNET_log (type, __VA_ARGS__) | ||
34 | |||
35 | |||
36 | #define LOG_ERROR(...) LOG (GNUNET_ERROR_TYPE_ERROR, __VA_ARGS__) | ||
37 | |||
38 | /** | ||
39 | * Log an error message at log-level 'level' that indicates | ||
40 | * a failure of the command 'cmd' on file 'filename' | ||
41 | * with the message given by strerror(errno). | ||
42 | */ | ||
43 | #define LOG_SQLITE(db, msg, level, cmd) \ | ||
44 | do \ | ||
45 | { \ | ||
46 | GNUNET_log_from (level, \ | ||
47 | "sqlite", \ | ||
48 | _ ("`%s' failed at %s:%d with error: %s\n"), \ | ||
49 | cmd, \ | ||
50 | __FILE__, \ | ||
51 | __LINE__, \ | ||
52 | sqlite3_errmsg (db)); \ | ||
53 | if (msg != NULL) \ | ||
54 | GNUNET_asprintf (msg, \ | ||
55 | _ ("`%s' failed at %s:%u with error: %s"), \ | ||
56 | cmd, \ | ||
57 | __FILE__, \ | ||
58 | __LINE__, \ | ||
59 | sqlite3_errmsg (db)); \ | ||
60 | } while (0) | ||
61 | |||
62 | |||
63 | /** | ||
64 | * Handle to the sqlite3 database | ||
65 | */ | ||
66 | static struct sqlite3 *db; | ||
67 | |||
68 | /** | ||
69 | * Prepared statement for inserting link values into db | ||
70 | */ | ||
71 | struct sqlite3_stmt *stmt_insert; | ||
72 | |||
73 | /** | ||
74 | * The topology to generate | ||
75 | */ | ||
76 | enum GNUNET_TESTBED_TopologyOption topology; | ||
77 | |||
78 | /** | ||
79 | * The number of peers to include in the topology | ||
80 | */ | ||
81 | static unsigned int num_peers; | ||
82 | |||
83 | /** | ||
84 | * program result | ||
85 | */ | ||
86 | static int exit_result; | ||
87 | |||
88 | |||
89 | /** | ||
90 | * Functions of this type are called to process underlay link | ||
91 | * | ||
92 | * @param cls closure | ||
93 | * @param A offset of first peer | ||
94 | * @param B offset of second peer | ||
95 | * @param bandwidth the bandwidth of the link in bytes per second | ||
96 | * @param latency the latency of link in milliseconds | ||
97 | * @param loss the percentage of messages dropped on the link | ||
98 | * @return GNUNET_OK to continue processing; GNUNET_SYSERR to abort | ||
99 | */ | ||
100 | static int | ||
101 | link_processor (void *cls, | ||
102 | unsigned int A, | ||
103 | unsigned int B, | ||
104 | unsigned int bandwidth, | ||
105 | unsigned int latency, | ||
106 | unsigned int loss) | ||
107 | { | ||
108 | if ((SQLITE_OK != sqlite3_bind_int (stmt_insert, 1, A)) || | ||
109 | (SQLITE_OK != sqlite3_bind_int (stmt_insert, 2, B)) || | ||
110 | (SQLITE_OK != sqlite3_bind_int (stmt_insert, 3, bandwidth)) || | ||
111 | (SQLITE_OK != sqlite3_bind_int (stmt_insert, 4, latency)) || | ||
112 | (SQLITE_OK != sqlite3_bind_int (stmt_insert, 5, loss))) | ||
113 | { | ||
114 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_int"); | ||
115 | return GNUNET_SYSERR; | ||
116 | } | ||
117 | if (SQLITE_DONE != sqlite3_step (stmt_insert)) | ||
118 | { | ||
119 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_step"); | ||
120 | return GNUNET_SYSERR; | ||
121 | } | ||
122 | fprintf (stdout, "%u -> %u\n", A, B); | ||
123 | GNUNET_break (SQLITE_OK == sqlite3_reset (stmt_insert)); | ||
124 | // GNUNET_break (SQLITE_OK == sqlite3_clear_bindings (stmt_insert)); | ||
125 | if ((SQLITE_OK != sqlite3_bind_int (stmt_insert, 1, B)) || | ||
126 | (SQLITE_OK != sqlite3_bind_int (stmt_insert, 2, A))) | ||
127 | { | ||
128 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_int"); | ||
129 | return GNUNET_SYSERR; | ||
130 | } | ||
131 | if (SQLITE_DONE != sqlite3_step (stmt_insert)) | ||
132 | { | ||
133 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_step"); | ||
134 | return GNUNET_SYSERR; | ||
135 | } | ||
136 | fprintf (stdout, "%u -> %u\n", B, A); | ||
137 | GNUNET_break (SQLITE_OK == sqlite3_reset (stmt_insert)); | ||
138 | return GNUNET_OK; | ||
139 | } | ||
140 | |||
141 | |||
142 | /** | ||
143 | * Open the database file, creating a new database if not existing and setup the | ||
144 | * whitelist table | ||
145 | * | ||
146 | * @param dbfile the database filename | ||
147 | * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure (error message has | ||
148 | * to be printed) | ||
149 | */ | ||
150 | static int | ||
151 | setup_db (const char *dbfile) | ||
152 | { | ||
153 | const char *query_create = "CREATE TABLE whitelist (" | ||
154 | "id INTEGER," | ||
155 | "oid INTEGER," | ||
156 | "bandwidth INTEGER DEFAULT NULL," | ||
157 | "latency INTEGER DEFAULT NULL," | ||
158 | "loss INTEGER DEFAULT NULL," | ||
159 | " UNIQUE (" | ||
160 | " id," | ||
161 | " oid" | ||
162 | " ) ON CONFLICT IGNORE" | ||
163 | ");"; | ||
164 | const char *query_insert = "INSERT INTO whitelist(" | ||
165 | " id," | ||
166 | " oid," | ||
167 | " bandwidth," | ||
168 | " latency," | ||
169 | " loss" | ||
170 | ") VALUES (" | ||
171 | " ?1," | ||
172 | " ?2," | ||
173 | " ?3," | ||
174 | " ?4," | ||
175 | " ?5);"; | ||
176 | int ret; | ||
177 | |||
178 | ret = GNUNET_SYSERR; | ||
179 | if (SQLITE_OK != sqlite3_open (dbfile, &db)) | ||
180 | { | ||
181 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_open"); | ||
182 | goto err_ret; | ||
183 | } | ||
184 | if (0 != sqlite3_exec (db, query_create, NULL, NULL, NULL)) | ||
185 | { | ||
186 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec"); | ||
187 | fprintf (stderr, | ||
188 | "Error: %d. Perhaps the database `%s' already exits.\n", | ||
189 | sqlite3_errcode (db), | ||
190 | dbfile); | ||
191 | goto err_ret; | ||
192 | } | ||
193 | GNUNET_break (0 == | ||
194 | sqlite3_exec (db, "PRAGMA synchronous = 0;", NULL, NULL, NULL)); | ||
195 | if (SQLITE_OK != | ||
196 | sqlite3_prepare_v2 (db, query_insert, -1, &stmt_insert, NULL)) | ||
197 | { | ||
198 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2"); | ||
199 | goto err_ret; | ||
200 | } | ||
201 | ret = GNUNET_OK; | ||
202 | |||
203 | err_ret: | ||
204 | return ret; | ||
205 | } | ||
206 | |||
207 | |||
208 | /** | ||
209 | * Main run function. | ||
210 | * | ||
211 | * @param cls NULL | ||
212 | * @param args arguments passed to GNUNET_PROGRAM_run | ||
213 | * @param cfgfile the path to configuration file | ||
214 | * @param cfg the configuration file handle | ||
215 | */ | ||
216 | static void | ||
217 | run (void *cls, | ||
218 | char *const *args, | ||
219 | const char *cfgfile, | ||
220 | const struct GNUNET_CONFIGURATION_Handle *config) | ||
221 | { | ||
222 | const char *dbfile; | ||
223 | const char *topology_string; | ||
224 | unsigned int arg_uint1; | ||
225 | unsigned int arg_uint2; | ||
226 | const char *arg_str1; | ||
227 | const char *value; | ||
228 | unsigned int argc; | ||
229 | |||
230 | argc = 0; | ||
231 | arg_uint1 = 0; /* make compilers happy */ | ||
232 | arg_uint2 = 0; /* make compilers happy */ | ||
233 | if (NULL == args) | ||
234 | { | ||
235 | LOG_ERROR (_ ("Need at least 2 arguments\n")); | ||
236 | return; | ||
237 | } | ||
238 | if (NULL == (dbfile = args[argc++])) | ||
239 | { | ||
240 | LOG_ERROR (_ ("Database filename missing\n")); | ||
241 | return; | ||
242 | } | ||
243 | if (GNUNET_OK != setup_db (dbfile)) | ||
244 | return; | ||
245 | if (NULL == (topology_string = args[argc++])) | ||
246 | { | ||
247 | LOG_ERROR (_ ("Topology string missing\n")); | ||
248 | return; | ||
249 | } | ||
250 | if (GNUNET_YES != GNUNET_TESTBED_topology_get_ (&topology, topology_string)) | ||
251 | { | ||
252 | LOG_ERROR (_ ("Invalid topology: %s\n"), topology_string); | ||
253 | return; | ||
254 | } | ||
255 | arg_str1 = NULL; | ||
256 | /* parse for first TOPOOPT. This can either be arg_uint1 or arg_str1 */ | ||
257 | switch (topology) | ||
258 | { | ||
259 | case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: | ||
260 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: | ||
261 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: | ||
262 | case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: | ||
263 | if (NULL == (value = args[argc++])) | ||
264 | { | ||
265 | LOG_ERROR (_ ("An argument is missing for given topology `%s'\n"), | ||
266 | topology_string); | ||
267 | return; | ||
268 | } | ||
269 | if (-1 == sscanf (value, "%u", &arg_uint1)) | ||
270 | { | ||
271 | LOG_ERROR (_ ("Invalid argument `%s' given as topology argument\n"), | ||
272 | value); | ||
273 | return; | ||
274 | } | ||
275 | break; | ||
276 | |||
277 | case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: | ||
278 | if (NULL == (arg_str1 = args[argc++])) | ||
279 | { | ||
280 | LOG_ERROR (_ ("Filename argument missing for topology `%s'\n"), | ||
281 | topology_string); | ||
282 | return; | ||
283 | } | ||
284 | break; | ||
285 | |||
286 | default: | ||
287 | break; | ||
288 | } | ||
289 | /* parse for second TOPOOPT. Only required for SCALE_FREE topology */ | ||
290 | switch (topology) | ||
291 | { | ||
292 | case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: | ||
293 | if (NULL == (value = args[argc++])) | ||
294 | { | ||
295 | LOG_ERROR (_ ("Second argument for topology `%s' is missing\n"), | ||
296 | topology_string); | ||
297 | return; | ||
298 | } | ||
299 | if (-1 == sscanf (value, "%u", &arg_uint2)) | ||
300 | { | ||
301 | LOG_ERROR (_ ("Invalid argument `%s'; expecting unsigned int\n"), value); | ||
302 | return; | ||
303 | } | ||
304 | break; | ||
305 | |||
306 | default: | ||
307 | break; | ||
308 | } | ||
309 | /* construct topologies */ | ||
310 | switch (topology) | ||
311 | { | ||
312 | case GNUNET_TESTBED_TOPOLOGY_LINE: | ||
313 | case GNUNET_TESTBED_TOPOLOGY_RING: | ||
314 | case GNUNET_TESTBED_TOPOLOGY_STAR: | ||
315 | case GNUNET_TESTBED_TOPOLOGY_CLIQUE: | ||
316 | case GNUNET_TESTBED_TOPOLOGY_2D_TORUS: | ||
317 | GNUNET_TESTBED_underlay_construct_ (num_peers, | ||
318 | link_processor, | ||
319 | NULL, | ||
320 | topology); | ||
321 | break; | ||
322 | |||
323 | case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: | ||
324 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: | ||
325 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: | ||
326 | GNUNET_TESTBED_underlay_construct_ (num_peers, | ||
327 | link_processor, | ||
328 | NULL, | ||
329 | topology, | ||
330 | arg_uint1); | ||
331 | break; | ||
332 | |||
333 | case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: | ||
334 | GNUNET_TESTBED_underlay_construct_ (num_peers, | ||
335 | link_processor, | ||
336 | NULL, | ||
337 | topology, | ||
338 | arg_str1); | ||
339 | break; | ||
340 | |||
341 | case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: | ||
342 | GNUNET_TESTBED_underlay_construct_ (num_peers, | ||
343 | link_processor, | ||
344 | NULL, | ||
345 | topology, | ||
346 | arg_uint1, | ||
347 | arg_uint2); | ||
348 | break; | ||
349 | |||
350 | default: | ||
351 | GNUNET_assert (0); | ||
352 | } | ||
353 | } | ||
354 | |||
355 | |||
356 | /** | ||
357 | * Main | ||
358 | */ | ||
359 | int | ||
360 | main (int argc, char *const argv[]) | ||
361 | { | ||
362 | struct GNUNET_GETOPT_CommandLineOption option[] = { | ||
363 | GNUNET_GETOPT_option_uint ('p', | ||
364 | "num-peers", | ||
365 | "COUNT", | ||
366 | gettext_noop ("create COUNT number of peers"), | ||
367 | &num_peers), | ||
368 | GNUNET_GETOPT_OPTION_END | ||
369 | }; | ||
370 | |||
371 | int ret; | ||
372 | |||
373 | exit_result = GNUNET_SYSERR; | ||
374 | ret = GNUNET_PROGRAM_run ( | ||
375 | argc, | ||
376 | argv, | ||
377 | "gnunet-underlay-topology", | ||
378 | _ ( | ||
379 | "Generates SQLite3 database representing a given underlay topology.\n" | ||
380 | "Usage: gnunet-underlay-topology [OPTIONS] db-filename TOPO [TOPOOPTS]\n" | ||
381 | "The following options are available for TOPO followed by TOPOOPTS if applicable:\n" | ||
382 | "\t LINE\n" | ||
383 | "\t RING\n" | ||
384 | "\t RANDOM <num_rnd_links>\n" | ||
385 | "\t SMALL_WORLD <num_rnd_links>\n" | ||
386 | "\t SMALL_WORLD_RING <num_rnd_links>\n" | ||
387 | "\t CLIQUE\n" | ||
388 | "\t 2D_TORUS\n" | ||
389 | "\t SCALE_FREE <cap> <m>\n" | ||
390 | "\t FROM_FILE <filename>\n" | ||
391 | "TOPOOPTS:\n" | ||
392 | "\t num_rnd_links: The number of random links\n" | ||
393 | "\t cap: the maximum number of links a node can have\n" | ||
394 | "\t m: the number of links a node should have while joining the network\n" | ||
395 | "\t filename: the path of the file which contains topology information\n" | ||
396 | "NOTE: the format of the above file is described here: https://www.gnunet.org/content/topology-file-format\n"), | ||
397 | option, | ||
398 | &run, | ||
399 | NULL); | ||
400 | if (NULL != stmt_insert) | ||
401 | sqlite3_finalize (stmt_insert); | ||
402 | if (NULL != db) | ||
403 | GNUNET_break (SQLITE_OK == sqlite3_close (db)); | ||
404 | if ((GNUNET_OK != ret) || (GNUNET_OK != exit_result)) | ||
405 | return 1; | ||
406 | return 0; | ||
407 | } | ||
diff --git a/src/testbed/gnunet-daemon-latency-logger.c b/src/testbed/gnunet-daemon-latency-logger.c deleted file mode 100644 index cbc9cfdbf..000000000 --- a/src/testbed/gnunet-daemon-latency-logger.c +++ /dev/null | |||
@@ -1,322 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2014 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-daemon-latency-logger.c | ||
23 | * @brief log latency values from neighbour connections into an SQLite database | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_ats_service.h" | ||
30 | #include <sqlite3.h> | ||
31 | |||
32 | |||
33 | /** | ||
34 | * Logging shorthand | ||
35 | */ | ||
36 | #define LOG(type, ...) \ | ||
37 | GNUNET_log (type, __VA_ARGS__) | ||
38 | |||
39 | /** | ||
40 | * Debug logging shorthand | ||
41 | */ | ||
42 | #define DEBUG(...) \ | ||
43 | LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) | ||
44 | |||
45 | /** | ||
46 | * Log an error message at log-level 'level' that indicates | ||
47 | * a failure of the command 'cmd' on file 'filename' | ||
48 | * with the message given by strerror(errno). | ||
49 | */ | ||
50 | #define LOG_SQLITE(db, msg, level, cmd) \ | ||
51 | do { \ | ||
52 | GNUNET_log_from (level, "sqlite", _ ( \ | ||
53 | "`%s' failed at %s:%d with error: %s\n"), \ | ||
54 | cmd, __FILE__, __LINE__, sqlite3_errmsg (db)); \ | ||
55 | if (msg != NULL) \ | ||
56 | GNUNET_asprintf (msg, _ ("`%s' failed at %s:%u with error: %s"), cmd, \ | ||
57 | __FILE__, __LINE__, sqlite3_errmsg (db)); \ | ||
58 | } while (0) | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Entry type to be used in the map to store old latency values | ||
63 | */ | ||
64 | struct Entry | ||
65 | { | ||
66 | /** | ||
67 | * The peer's identity | ||
68 | */ | ||
69 | struct GNUNET_PeerIdentity id; | ||
70 | |||
71 | /** | ||
72 | * The last known value for latency. | ||
73 | * FIXME: type! | ||
74 | */ | ||
75 | unsigned int latency; | ||
76 | }; | ||
77 | |||
78 | |||
79 | /** | ||
80 | * Handle to the map used to store old latency values for peers | ||
81 | */ | ||
82 | static struct GNUNET_CONTAINER_MultiPeerMap *map; | ||
83 | |||
84 | /** | ||
85 | * The SQLite database handle | ||
86 | */ | ||
87 | static struct sqlite3 *db; | ||
88 | |||
89 | /** | ||
90 | * Handle to the ATS performance subsystem | ||
91 | */ | ||
92 | static struct GNUNET_ATS_PerformanceHandle *ats; | ||
93 | |||
94 | /** | ||
95 | * Prepared statement for inserting values into the database table | ||
96 | */ | ||
97 | static struct sqlite3_stmt *stmt_insert; | ||
98 | |||
99 | |||
100 | /** | ||
101 | * @ingroup hashmap | ||
102 | * Iterator over hash map entries. | ||
103 | * | ||
104 | * @param cls closure | ||
105 | * @param key current public key | ||
106 | * @param value value in the hash map | ||
107 | * @return #GNUNET_YES if we should continue to | ||
108 | * iterate, | ||
109 | * #GNUNET_NO if not. | ||
110 | */ | ||
111 | static int | ||
112 | free_iterator (void *cls, | ||
113 | const struct GNUNET_PeerIdentity *key, | ||
114 | void *value) | ||
115 | { | ||
116 | struct Entry *e = cls; | ||
117 | |||
118 | GNUNET_assert (GNUNET_YES == | ||
119 | GNUNET_CONTAINER_multipeermap_remove (map, key, e)); | ||
120 | GNUNET_free (e); | ||
121 | return GNUNET_YES; | ||
122 | } | ||
123 | |||
124 | |||
125 | /** | ||
126 | * Shutdown | ||
127 | * | ||
128 | * @param cls NULL | ||
129 | * @return | ||
130 | */ | ||
131 | static void | ||
132 | do_shutdown (void *cls) | ||
133 | { | ||
134 | GNUNET_ATS_performance_done (ats); | ||
135 | ats = NULL; | ||
136 | if (NULL != stmt_insert) | ||
137 | { | ||
138 | sqlite3_finalize (stmt_insert); | ||
139 | stmt_insert = NULL; | ||
140 | } | ||
141 | GNUNET_break (SQLITE_OK == sqlite3_close (db)); | ||
142 | db = NULL; | ||
143 | if (NULL != map) | ||
144 | { | ||
145 | GNUNET_assert (GNUNET_SYSERR != | ||
146 | GNUNET_CONTAINER_multipeermap_iterate (map, free_iterator, | ||
147 | NULL)); | ||
148 | GNUNET_CONTAINER_multipeermap_destroy (map); | ||
149 | map = NULL; | ||
150 | } | ||
151 | } | ||
152 | |||
153 | |||
154 | /** | ||
155 | * Signature of a function that is called with QoS information about an address. | ||
156 | * | ||
157 | * @param cls closure | ||
158 | * @param address the address | ||
159 | * @param address_active #GNUNET_YES if this address is actively used | ||
160 | * to maintain a connection to a peer; | ||
161 | * #GNUNET_NO if the address is not actively used; | ||
162 | * #GNUNET_SYSERR if this address is no longer available for ATS | ||
163 | * @param bandwidth_out assigned outbound bandwidth for the connection | ||
164 | * @param bandwidth_in assigned inbound bandwidth for the connection | ||
165 | * @param prop performance data for the address (as far as known) | ||
166 | */ | ||
167 | static void | ||
168 | addr_info_cb (void *cls, | ||
169 | const struct GNUNET_HELLO_Address *address, | ||
170 | int address_active, | ||
171 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, | ||
172 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, | ||
173 | const struct GNUNET_ATS_Properties *prop) | ||
174 | { | ||
175 | static const char *query_insert = | ||
176 | "INSERT INTO ats_info(" | ||
177 | " id," | ||
178 | " val," | ||
179 | " timestamp" | ||
180 | ") VALUES (" | ||
181 | " ?1," | ||
182 | " ?2," | ||
183 | " datetime('now')" | ||
184 | ");"; | ||
185 | struct Entry *entry; | ||
186 | int latency; /* FIXME: type!? */ | ||
187 | |||
188 | if (NULL == address) | ||
189 | { | ||
190 | /* ATS service temporarily disconnected */ | ||
191 | return; | ||
192 | } | ||
193 | |||
194 | GNUNET_assert (NULL != db); | ||
195 | if (GNUNET_YES != address_active) | ||
196 | return; | ||
197 | latency = (int) prop->delay.rel_value_us; | ||
198 | entry = NULL; | ||
199 | if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (map, | ||
200 | &address->peer)) | ||
201 | { | ||
202 | entry = GNUNET_CONTAINER_multipeermap_get (map, &address->peer); | ||
203 | GNUNET_assert (NULL != entry); | ||
204 | if (latency == entry->latency) | ||
205 | return; | ||
206 | } | ||
207 | if (NULL == stmt_insert) | ||
208 | { | ||
209 | if (SQLITE_OK != sqlite3_prepare_v2 (db, query_insert, -1, &stmt_insert, | ||
210 | NULL)) | ||
211 | { | ||
212 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2"); | ||
213 | goto err_shutdown; | ||
214 | } | ||
215 | } | ||
216 | if ((SQLITE_OK != sqlite3_bind_text (stmt_insert, 1, | ||
217 | GNUNET_i2s (&address->peer), -1, | ||
218 | SQLITE_STATIC)) || | ||
219 | (SQLITE_OK != sqlite3_bind_int (stmt_insert, 2, latency))) | ||
220 | { | ||
221 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_text"); | ||
222 | goto err_shutdown; | ||
223 | } | ||
224 | if (SQLITE_DONE != sqlite3_step (stmt_insert)) | ||
225 | { | ||
226 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_step"); | ||
227 | goto err_shutdown; | ||
228 | } | ||
229 | if (SQLITE_OK != sqlite3_reset (stmt_insert)) | ||
230 | { | ||
231 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_insert"); | ||
232 | goto err_shutdown; | ||
233 | } | ||
234 | if (NULL == entry) | ||
235 | { | ||
236 | entry = GNUNET_new (struct Entry); | ||
237 | entry->id = address->peer; | ||
238 | GNUNET_CONTAINER_multipeermap_put (map, | ||
239 | &entry->id, entry, | ||
240 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
241 | } | ||
242 | entry->latency = latency; | ||
243 | return; | ||
244 | |||
245 | err_shutdown: | ||
246 | GNUNET_SCHEDULER_shutdown (); | ||
247 | } | ||
248 | |||
249 | |||
250 | /** | ||
251 | * Main function that will be run. | ||
252 | * | ||
253 | * @param cls closure | ||
254 | * @param args remaining command-line arguments | ||
255 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
256 | * @param c configuration | ||
257 | */ | ||
258 | static void | ||
259 | run (void *cls, char *const *args, const char *cfgfile, | ||
260 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
261 | { | ||
262 | const char *query_create = | ||
263 | "CREATE TABLE ats_info (" | ||
264 | "id TEXT," | ||
265 | "val INTEGER," | ||
266 | "timestamp NUMERIC" | ||
267 | ");"; | ||
268 | char *dbfile; | ||
269 | |||
270 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "LATENCY-LOGGER", | ||
271 | "DBFILE", | ||
272 | &dbfile)) | ||
273 | { | ||
274 | GNUNET_break (0); | ||
275 | return; | ||
276 | } | ||
277 | if (SQLITE_OK != sqlite3_open (dbfile, &db)) | ||
278 | { | ||
279 | if (NULL != db) | ||
280 | { | ||
281 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_open_v2"); | ||
282 | GNUNET_break (SQLITE_OK == sqlite3_close (db)); | ||
283 | } | ||
284 | else | ||
285 | LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot open sqlite file %s\n", dbfile); | ||
286 | GNUNET_free (dbfile); | ||
287 | return; | ||
288 | } | ||
289 | if (0 != sqlite3_exec (db, query_create, NULL, NULL, NULL)) | ||
290 | DEBUG ("SQLite Error: %d. Perhaps the database `%s' already exits.\n", | ||
291 | sqlite3_errcode (db), dbfile); | ||
292 | DEBUG ("Opened database %s\n", dbfile); | ||
293 | GNUNET_free (dbfile); | ||
294 | dbfile = NULL; | ||
295 | ats = GNUNET_ATS_performance_init (c, &addr_info_cb, NULL); | ||
296 | map = GNUNET_CONTAINER_multipeermap_create (30, GNUNET_YES); | ||
297 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
298 | } | ||
299 | |||
300 | |||
301 | /** | ||
302 | * Execution entry point | ||
303 | */ | ||
304 | int | ||
305 | main (int argc, char *const *argv) | ||
306 | { | ||
307 | static const struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
308 | GNUNET_GETOPT_OPTION_END | ||
309 | }; | ||
310 | int ret; | ||
311 | |||
312 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
313 | return 2; | ||
314 | ret = | ||
315 | (GNUNET_OK == | ||
316 | GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-latency-logger", | ||
317 | _ ( | ||
318 | "Daemon to log latency values of connections to neighbours"), | ||
319 | options, &run, NULL)) ? 0 : 1; | ||
320 | GNUNET_free_nz ((void *) argv); | ||
321 | return ret; | ||
322 | } | ||
diff --git a/src/testbed/gnunet-daemon-testbed-blacklist.c b/src/testbed/gnunet-daemon-testbed-blacklist.c deleted file mode 100644 index c82f8075f..000000000 --- a/src/testbed/gnunet-daemon-testbed-blacklist.c +++ /dev/null | |||
@@ -1,254 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | |||
22 | /** | ||
23 | * @file testbed/gnunet-daemon-testbed-blacklist.c | ||
24 | * @brief daemon to restrict incoming connections from other peers at the | ||
25 | * transport layer of a peer | ||
26 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
27 | */ | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_util_lib.h" | ||
31 | #include "gnunet_transport_service.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Logging shorthand | ||
36 | */ | ||
37 | #define LOG(type, ...) \ | ||
38 | GNUNET_log (type, __VA_ARGS__) | ||
39 | |||
40 | /** | ||
41 | * Debug logging shorthand | ||
42 | */ | ||
43 | #define DEBUG(...) \ | ||
44 | LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) | ||
45 | |||
46 | /** | ||
47 | * Allow access from the peers read from the whitelist | ||
48 | */ | ||
49 | #define ACCESS_ALLOW 1 | ||
50 | |||
51 | /** | ||
52 | * Deny access from the peers read from the blacklist | ||
53 | */ | ||
54 | #define ACCESS_DENY 0 | ||
55 | |||
56 | /** | ||
57 | * The map to store the peer identities to allow/deny | ||
58 | */ | ||
59 | static struct GNUNET_CONTAINER_MultiPeerMap *map; | ||
60 | |||
61 | /** | ||
62 | * The array of peer identities we read from whitelist/blacklist | ||
63 | */ | ||
64 | static struct GNUNET_PeerIdentity *ilist; | ||
65 | |||
66 | /** | ||
67 | * The blacklist handle we obtain from transport when we register ourselves for | ||
68 | * access control | ||
69 | */ | ||
70 | static struct GNUNET_TRANSPORT_Blacklist *bh; | ||
71 | |||
72 | /** | ||
73 | * Are we allowing or denying access from peers | ||
74 | */ | ||
75 | static int mode; | ||
76 | |||
77 | |||
78 | /** | ||
79 | * Cleaup and destroy the map | ||
80 | */ | ||
81 | static void | ||
82 | cleanup_map () | ||
83 | { | ||
84 | if (NULL != map) | ||
85 | { | ||
86 | GNUNET_CONTAINER_multipeermap_destroy (map); | ||
87 | map = NULL; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | |||
92 | /** | ||
93 | * Shutdown task to cleanup our resources and exit. | ||
94 | * | ||
95 | * @param cls NULL | ||
96 | */ | ||
97 | static void | ||
98 | do_shutdown (void *cls) | ||
99 | { | ||
100 | cleanup_map (); | ||
101 | if (NULL != bh) | ||
102 | GNUNET_TRANSPORT_blacklist_cancel (bh); | ||
103 | } | ||
104 | |||
105 | |||
106 | /** | ||
107 | * Function that decides if a connection is acceptable or not. | ||
108 | * | ||
109 | * @param cls closure | ||
110 | * @param pid peer to approve or disapproave | ||
111 | * @return GNUNET_OK if the connection is allowed, GNUNET_SYSERR if not | ||
112 | */ | ||
113 | static int | ||
114 | check_access (void *cls, const struct GNUNET_PeerIdentity *pid) | ||
115 | { | ||
116 | int contains; | ||
117 | |||
118 | if (NULL != map) | ||
119 | contains = GNUNET_CONTAINER_multipeermap_contains (map, pid); | ||
120 | else | ||
121 | contains = GNUNET_NO; | ||
122 | if (ACCESS_DENY == mode) | ||
123 | return (contains) ? GNUNET_SYSERR : GNUNET_OK; | ||
124 | return (contains) ? GNUNET_OK : GNUNET_SYSERR; | ||
125 | } | ||
126 | |||
127 | |||
128 | /** | ||
129 | * Setup the access control by reading the given file containing peer identities | ||
130 | * and then establishing blacklist handler with the peer's transport service | ||
131 | * | ||
132 | * @param fname the filename to read the list of peer identities | ||
133 | * @param cfg the configuration for connecting to the peer's transport service | ||
134 | */ | ||
135 | static void | ||
136 | setup_ac (const char *fname, | ||
137 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
138 | { | ||
139 | uint64_t fsize; | ||
140 | unsigned int npeers; | ||
141 | unsigned int cnt; | ||
142 | |||
143 | GNUNET_assert (GNUNET_OK != | ||
144 | GNUNET_DISK_file_size (fname, &fsize, GNUNET_NO, | ||
145 | GNUNET_YES)); | ||
146 | if (0 != (fsize % sizeof(struct GNUNET_PeerIdentity))) | ||
147 | { | ||
148 | GNUNET_break (0); | ||
149 | return; | ||
150 | } | ||
151 | npeers = fsize / sizeof(struct GNUNET_PeerIdentity); | ||
152 | if (0 != npeers) | ||
153 | { | ||
154 | map = GNUNET_CONTAINER_multipeermap_create (npeers, GNUNET_YES); | ||
155 | ilist = GNUNET_malloc_large (fsize); | ||
156 | GNUNET_assert (fsize == GNUNET_DISK_fn_read (fname, ilist, fsize)); | ||
157 | } | ||
158 | for (cnt = 0; cnt < npeers; cnt++) | ||
159 | { | ||
160 | if (GNUNET_SYSERR == | ||
161 | GNUNET_CONTAINER_multipeermap_put (map, &ilist[cnt], | ||
162 | &ilist[cnt], | ||
163 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
164 | { | ||
165 | cleanup_map (); | ||
166 | GNUNET_free (ilist); | ||
167 | return; | ||
168 | } | ||
169 | } | ||
170 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
171 | bh = GNUNET_TRANSPORT_blacklist (cfg, &check_access, NULL); | ||
172 | } | ||
173 | |||
174 | |||
175 | /** | ||
176 | * Main function that will be run. | ||
177 | * | ||
178 | * @param cls closure | ||
179 | * @param args remaining command-line arguments | ||
180 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
181 | * @param c configuration | ||
182 | */ | ||
183 | static void | ||
184 | run (void *cls, | ||
185 | char *const *args, | ||
186 | const char *cfgfile, | ||
187 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
188 | { | ||
189 | char *shome; | ||
190 | char *fname; | ||
191 | |||
192 | if (GNUNET_OK != | ||
193 | GNUNET_CONFIGURATION_get_value_filename (c, | ||
194 | "PATHS", | ||
195 | "GNUNET_HOME", | ||
196 | &shome)) | ||
197 | { | ||
198 | GNUNET_break (0); | ||
199 | return; | ||
200 | } | ||
201 | GNUNET_asprintf (&fname, | ||
202 | "%s/whitelist", | ||
203 | shome); | ||
204 | if (GNUNET_YES == GNUNET_DISK_file_test (fname)) | ||
205 | { | ||
206 | mode = ACCESS_ALLOW; | ||
207 | setup_ac (fname, c); | ||
208 | GNUNET_free (shome); | ||
209 | GNUNET_free (fname); | ||
210 | return; | ||
211 | } | ||
212 | GNUNET_free (fname); | ||
213 | GNUNET_asprintf (&fname, | ||
214 | "%s/blacklist", | ||
215 | shome); | ||
216 | if (GNUNET_YES == GNUNET_DISK_file_test (fname)) | ||
217 | { | ||
218 | mode = ACCESS_DENY; | ||
219 | setup_ac (shome, c); | ||
220 | } | ||
221 | GNUNET_free (shome); | ||
222 | GNUNET_free (fname); | ||
223 | } | ||
224 | |||
225 | |||
226 | /** | ||
227 | * The main function. | ||
228 | * | ||
229 | * @param argc number of arguments from the command line | ||
230 | * @param argv command line arguments | ||
231 | * @return 0 ok, 1 on error | ||
232 | */ | ||
233 | int | ||
234 | main (int argc, char *const *argv) | ||
235 | { | ||
236 | static const struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
237 | GNUNET_GETOPT_OPTION_END | ||
238 | }; | ||
239 | int ret; | ||
240 | |||
241 | if (GNUNET_OK != | ||
242 | GNUNET_STRINGS_get_utf8_args (argc, argv, | ||
243 | &argc, &argv)) | ||
244 | return 2; | ||
245 | ret = | ||
246 | (GNUNET_OK == | ||
247 | GNUNET_PROGRAM_run (argc, argv, | ||
248 | "gnunet-daemon-testbed-blacklist", | ||
249 | _ ( | ||
250 | "Daemon to restrict incoming transport layer connections during testbed deployments"), | ||
251 | options, &run, NULL)) ? 0 : 1; | ||
252 | GNUNET_free_nz ((void *) argv); | ||
253 | return ret; | ||
254 | } | ||
diff --git a/src/testbed/gnunet-daemon-testbed-underlay.c b/src/testbed/gnunet-daemon-testbed-underlay.c deleted file mode 100644 index c3b424c9b..000000000 --- a/src/testbed/gnunet-daemon-testbed-underlay.c +++ /dev/null | |||
@@ -1,481 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | |||
22 | /** | ||
23 | * @file testbed/gnunet-daemon-testbed-blacklist.c | ||
24 | * @brief daemon to restrict incoming connections from other peers at the | ||
25 | * transport layer of a peer | ||
26 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
27 | */ | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_util_lib.h" | ||
31 | #include "gnunet_transport_service.h" | ||
32 | #include "gnunet_transport_manipulation_service.h" | ||
33 | #include "gnunet_ats_service.h" | ||
34 | #include "gnunet_testing_lib.h" | ||
35 | #include <sqlite3.h> | ||
36 | |||
37 | /** | ||
38 | * Logging shorthand | ||
39 | */ | ||
40 | #define LOG(type, ...) \ | ||
41 | GNUNET_log (type, __VA_ARGS__) | ||
42 | |||
43 | /** | ||
44 | * Debug logging shorthand | ||
45 | */ | ||
46 | #define DEBUG(...) \ | ||
47 | LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) | ||
48 | |||
49 | /** | ||
50 | * Log an error message at log-level 'level' that indicates | ||
51 | * a failure of the command 'cmd' on file 'filename' | ||
52 | * with the message given by strerror(errno). | ||
53 | */ | ||
54 | #define LOG_SQLITE(db, msg, level, cmd) \ | ||
55 | do { \ | ||
56 | GNUNET_log_from (level, "sqlite", _ ( \ | ||
57 | "`%s' failed at %s:%d with error: %s\n"), \ | ||
58 | cmd, __FILE__, __LINE__, sqlite3_errmsg (db)); \ | ||
59 | if (msg != NULL) \ | ||
60 | GNUNET_asprintf (msg, _ ("`%s' failed at %s:%u with error: %s"), cmd, \ | ||
61 | __FILE__, __LINE__, sqlite3_errmsg (db)); \ | ||
62 | } while (0) | ||
63 | |||
64 | |||
65 | /** | ||
66 | * The map to store the peer identities to allow/deny | ||
67 | */ | ||
68 | static struct GNUNET_CONTAINER_MultiPeerMap *map; | ||
69 | |||
70 | /** | ||
71 | * The database connection | ||
72 | */ | ||
73 | static struct sqlite3 *db; | ||
74 | |||
75 | /** | ||
76 | * The blacklist handle we obtain from transport when we register ourselves for | ||
77 | * access control | ||
78 | */ | ||
79 | static struct GNUNET_TRANSPORT_Blacklist *bh; | ||
80 | |||
81 | /** | ||
82 | * The hostkeys file | ||
83 | */ | ||
84 | struct GNUNET_DISK_FileHandle *hostkeys_fd; | ||
85 | |||
86 | /** | ||
87 | * The hostkeys map | ||
88 | */ | ||
89 | static struct GNUNET_DISK_MapHandle *hostkeys_map; | ||
90 | |||
91 | /** | ||
92 | * The hostkeys data | ||
93 | */ | ||
94 | static void *hostkeys_data; | ||
95 | |||
96 | /** | ||
97 | * Handle to the transport service. This is used for setting link metrics | ||
98 | */ | ||
99 | static struct GNUNET_TRANSPORT_ManipulationHandle *transport; | ||
100 | |||
101 | /** | ||
102 | * The number of hostkeys in the hostkeys array | ||
103 | */ | ||
104 | static unsigned int num_hostkeys; | ||
105 | |||
106 | |||
107 | /** | ||
108 | * @ingroup hashmap | ||
109 | * Iterator over hash map entries. | ||
110 | * | ||
111 | * @param cls closure | ||
112 | * @param key current key code | ||
113 | * @param value value in the hash map | ||
114 | * @return #GNUNET_YES if we should continue to | ||
115 | * iterate, | ||
116 | * #GNUNET_NO if not. | ||
117 | */ | ||
118 | static int | ||
119 | iterator (void *cls, const struct GNUNET_PeerIdentity *key, void *value) | ||
120 | { | ||
121 | GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (map, key, | ||
122 | value)); | ||
123 | return GNUNET_YES; | ||
124 | } | ||
125 | |||
126 | |||
127 | /** | ||
128 | * Cleaup and destroy the map | ||
129 | */ | ||
130 | static void | ||
131 | cleanup_map () | ||
132 | { | ||
133 | if (NULL != map) | ||
134 | { | ||
135 | GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multipeermap_iterate (map, | ||
136 | & | ||
137 | iterator, | ||
138 | NULL)); | ||
139 | GNUNET_CONTAINER_multipeermap_destroy (map); | ||
140 | map = NULL; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | |||
145 | /** | ||
146 | * Function that decides if a connection is acceptable or not. | ||
147 | * | ||
148 | * @param cls closure | ||
149 | * @param pid peer to approve or disapproave | ||
150 | * @return GNUNET_OK if the connection is allowed, GNUNET_SYSERR if not | ||
151 | */ | ||
152 | static int | ||
153 | check_access (void *cls, const struct GNUNET_PeerIdentity *pid) | ||
154 | { | ||
155 | int contains; | ||
156 | |||
157 | GNUNET_assert (NULL != map); | ||
158 | contains = GNUNET_CONTAINER_multipeermap_contains (map, pid); | ||
159 | if (GNUNET_YES == contains) | ||
160 | { | ||
161 | DEBUG ("Permitting `%s'\n", GNUNET_i2s (pid)); | ||
162 | return GNUNET_OK; | ||
163 | } | ||
164 | DEBUG ("Not permitting `%s'\n", GNUNET_i2s (pid)); | ||
165 | return GNUNET_SYSERR; | ||
166 | } | ||
167 | |||
168 | |||
169 | static int | ||
170 | get_identity (unsigned int offset, | ||
171 | struct GNUNET_PeerIdentity *id) | ||
172 | { | ||
173 | struct GNUNET_CRYPTO_EddsaPrivateKey private_key; | ||
174 | |||
175 | if (offset >= num_hostkeys) | ||
176 | return GNUNET_SYSERR; | ||
177 | GNUNET_memcpy (&private_key, | ||
178 | hostkeys_data + (offset * GNUNET_TESTING_HOSTKEYFILESIZE), | ||
179 | GNUNET_TESTING_HOSTKEYFILESIZE); | ||
180 | GNUNET_CRYPTO_eddsa_key_get_public (&private_key, | ||
181 | &id->public_key); | ||
182 | return GNUNET_OK; | ||
183 | } | ||
184 | |||
185 | |||
186 | /** | ||
187 | * Whilelist entry | ||
188 | */ | ||
189 | struct WhiteListRow | ||
190 | { | ||
191 | /** | ||
192 | * Next ptr | ||
193 | */ | ||
194 | struct WhiteListRow *next; | ||
195 | |||
196 | /** | ||
197 | * The offset where to find the hostkey for the peer | ||
198 | */ | ||
199 | unsigned int id; | ||
200 | |||
201 | /** | ||
202 | * Latency to be assigned to the link | ||
203 | */ | ||
204 | int latency; | ||
205 | }; | ||
206 | |||
207 | |||
208 | /** | ||
209 | * Function to load keys | ||
210 | */ | ||
211 | static int | ||
212 | load_keys (const struct GNUNET_CONFIGURATION_Handle *c) | ||
213 | { | ||
214 | char *data_dir; | ||
215 | char *idfile; | ||
216 | uint64_t fsize; | ||
217 | |||
218 | data_dir = NULL; | ||
219 | idfile = NULL; | ||
220 | fsize = 0; | ||
221 | data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); | ||
222 | GNUNET_asprintf (&idfile, "%s/testing_hostkeys.ecc", data_dir); | ||
223 | GNUNET_free (data_dir); | ||
224 | data_dir = NULL; | ||
225 | if (GNUNET_OK != | ||
226 | GNUNET_DISK_file_size (idfile, &fsize, GNUNET_YES, GNUNET_YES)) | ||
227 | { | ||
228 | GNUNET_free (idfile); | ||
229 | return GNUNET_SYSERR; | ||
230 | } | ||
231 | if (0 != (fsize % GNUNET_TESTING_HOSTKEYFILESIZE)) | ||
232 | { | ||
233 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
234 | _ ("Incorrect hostkey file format: %s\n"), idfile); | ||
235 | GNUNET_free (idfile); | ||
236 | return GNUNET_SYSERR; | ||
237 | } | ||
238 | hostkeys_fd = GNUNET_DISK_file_open (idfile, GNUNET_DISK_OPEN_READ, | ||
239 | GNUNET_DISK_PERM_NONE); | ||
240 | if (NULL == hostkeys_fd) | ||
241 | { | ||
242 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", idfile); | ||
243 | GNUNET_free (idfile); | ||
244 | return GNUNET_SYSERR; | ||
245 | } | ||
246 | GNUNET_free (idfile); | ||
247 | idfile = NULL; | ||
248 | hostkeys_data = GNUNET_DISK_file_map (hostkeys_fd, | ||
249 | &hostkeys_map, | ||
250 | GNUNET_DISK_MAP_TYPE_READ, | ||
251 | fsize); | ||
252 | if (NULL == hostkeys_data) | ||
253 | { | ||
254 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "mmap"); | ||
255 | return GNUNET_SYSERR; | ||
256 | } | ||
257 | num_hostkeys = fsize / GNUNET_TESTING_HOSTKEYFILESIZE; | ||
258 | return GNUNET_OK; | ||
259 | } | ||
260 | |||
261 | |||
262 | /** | ||
263 | * Function to unload keys | ||
264 | */ | ||
265 | static void | ||
266 | unload_keys () | ||
267 | { | ||
268 | if (NULL != hostkeys_map) | ||
269 | { | ||
270 | GNUNET_assert (NULL != hostkeys_data); | ||
271 | GNUNET_DISK_file_unmap (hostkeys_map); | ||
272 | hostkeys_map = NULL; | ||
273 | hostkeys_data = NULL; | ||
274 | } | ||
275 | if (NULL != hostkeys_fd) | ||
276 | { | ||
277 | GNUNET_DISK_file_close (hostkeys_fd); | ||
278 | hostkeys_fd = NULL; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | |||
283 | /** | ||
284 | * Shutdown task to cleanup our resources and exit. | ||
285 | * | ||
286 | * @param cls NULL | ||
287 | */ | ||
288 | static void | ||
289 | do_shutdown (void *cls) | ||
290 | { | ||
291 | if (NULL != transport) | ||
292 | { | ||
293 | GNUNET_TRANSPORT_manipulation_disconnect (transport); | ||
294 | transport = NULL; | ||
295 | } | ||
296 | cleanup_map (); | ||
297 | unload_keys (); | ||
298 | if (NULL != bh) | ||
299 | GNUNET_TRANSPORT_blacklist_cancel (bh); | ||
300 | } | ||
301 | |||
302 | |||
303 | /** | ||
304 | * Function to read whitelist rows from the database | ||
305 | * | ||
306 | * @param db the database connection | ||
307 | * @param pid the identity of this peer | ||
308 | * @param wl_rows where to store the retrieved whitelist rows | ||
309 | * @return GNUNET_SYSERR upon error OR the number of rows retrieved | ||
310 | */ | ||
311 | static int | ||
312 | db_read_whitelist (struct sqlite3 *db, int pid, struct WhiteListRow **wl_rows) | ||
313 | { | ||
314 | static const char *query_wl = | ||
315 | "SELECT oid, latency FROM whitelist WHERE (id == ?);"; | ||
316 | struct sqlite3_stmt *stmt_wl; | ||
317 | struct WhiteListRow *lr; | ||
318 | int nrows; | ||
319 | int ret; | ||
320 | |||
321 | if (SQLITE_OK != (ret = sqlite3_prepare_v2 (db, query_wl, -1, &stmt_wl, | ||
322 | NULL))) | ||
323 | { | ||
324 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2"); | ||
325 | return GNUNET_SYSERR; | ||
326 | } | ||
327 | if (SQLITE_OK != (ret = sqlite3_bind_int (stmt_wl, 1, pid))) | ||
328 | { | ||
329 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_int"); | ||
330 | sqlite3_finalize (stmt_wl); | ||
331 | return GNUNET_SYSERR; | ||
332 | } | ||
333 | nrows = 0; | ||
334 | do | ||
335 | { | ||
336 | ret = sqlite3_step (stmt_wl); | ||
337 | if (SQLITE_ROW != ret) | ||
338 | break; | ||
339 | nrows++; | ||
340 | lr = GNUNET_new (struct WhiteListRow); | ||
341 | lr->id = sqlite3_column_int (stmt_wl, 0); | ||
342 | lr->latency = sqlite3_column_int (stmt_wl, 1); | ||
343 | lr->next = *wl_rows; | ||
344 | *wl_rows = lr; | ||
345 | } | ||
346 | while (1); | ||
347 | sqlite3_finalize (stmt_wl); | ||
348 | return nrows; | ||
349 | } | ||
350 | |||
351 | |||
352 | /** | ||
353 | * Main function that will be run. | ||
354 | * | ||
355 | * @param cls closure | ||
356 | * @param args remaining command-line arguments | ||
357 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
358 | * @param c configuration | ||
359 | */ | ||
360 | static void | ||
361 | run (void *cls, char *const *args, const char *cfgfile, | ||
362 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
363 | { | ||
364 | char *dbfile; | ||
365 | struct WhiteListRow *wl_head; | ||
366 | struct WhiteListRow *wl_entry; | ||
367 | struct GNUNET_PeerIdentity identity; | ||
368 | struct GNUNET_ATS_Properties prop; | ||
369 | struct GNUNET_TIME_Relative delay; | ||
370 | unsigned long long pid; | ||
371 | unsigned int nrows; | ||
372 | int ret; | ||
373 | |||
374 | if (GNUNET_OK != | ||
375 | GNUNET_CONFIGURATION_get_value_number (c, "TESTBED", | ||
376 | "PEERID", &pid)) | ||
377 | { | ||
378 | GNUNET_break (0); | ||
379 | return; | ||
380 | } | ||
381 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, | ||
382 | "TESTBED-UNDERLAY", | ||
383 | "DBFILE", | ||
384 | &dbfile)) | ||
385 | { | ||
386 | GNUNET_break (0); | ||
387 | return; | ||
388 | } | ||
389 | if (SQLITE_OK != (ret = sqlite3_open_v2 (dbfile, &db, SQLITE_OPEN_READONLY, | ||
390 | NULL))) | ||
391 | { | ||
392 | if (NULL != db) | ||
393 | { | ||
394 | LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_open_v2"); | ||
395 | GNUNET_break (SQLITE_OK == sqlite3_close (db)); | ||
396 | } | ||
397 | else | ||
398 | LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot open sqlite file %s\n", dbfile); | ||
399 | GNUNET_free (dbfile); | ||
400 | return; | ||
401 | } | ||
402 | DEBUG ("Opened database %s\n", dbfile); | ||
403 | GNUNET_free (dbfile); | ||
404 | dbfile = NULL; | ||
405 | wl_head = NULL; | ||
406 | if (GNUNET_OK != load_keys (c)) | ||
407 | goto close_db; | ||
408 | |||
409 | transport = GNUNET_TRANSPORT_manipulation_connect (c); | ||
410 | if (NULL == transport) | ||
411 | { | ||
412 | GNUNET_break (0); | ||
413 | return; | ||
414 | } | ||
415 | /* read and process whitelist */ | ||
416 | nrows = 0; | ||
417 | wl_head = NULL; | ||
418 | nrows = db_read_whitelist (db, pid, &wl_head); | ||
419 | if ((GNUNET_SYSERR == nrows) || (0 == nrows)) | ||
420 | { | ||
421 | GNUNET_TRANSPORT_manipulation_disconnect (transport); | ||
422 | goto close_db; | ||
423 | } | ||
424 | map = GNUNET_CONTAINER_multipeermap_create (nrows, GNUNET_NO); | ||
425 | while (NULL != (wl_entry = wl_head)) | ||
426 | { | ||
427 | wl_head = wl_entry->next; | ||
428 | delay.rel_value_us = wl_entry->latency; | ||
429 | memset (&prop, 0, sizeof(prop)); | ||
430 | GNUNET_assert (GNUNET_OK == get_identity (wl_entry->id, &identity)); | ||
431 | GNUNET_break (GNUNET_OK == | ||
432 | GNUNET_CONTAINER_multipeermap_put (map, &identity, &identity, | ||
433 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); | ||
434 | DEBUG ("Setting %u ms latency to peer `%s'\n", | ||
435 | wl_entry->latency, | ||
436 | GNUNET_i2s (&identity)); | ||
437 | GNUNET_TRANSPORT_manipulation_set (transport, | ||
438 | &identity, | ||
439 | &prop, | ||
440 | delay, | ||
441 | delay); | ||
442 | GNUNET_free (wl_entry); | ||
443 | } | ||
444 | bh = GNUNET_TRANSPORT_blacklist (c, &check_access, NULL); | ||
445 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
446 | |||
447 | close_db: | ||
448 | GNUNET_break (SQLITE_OK == sqlite3_close (db)); | ||
449 | } | ||
450 | |||
451 | |||
452 | /** | ||
453 | * The main function. | ||
454 | * | ||
455 | * @param argc number of arguments from the command line | ||
456 | * @param argv command line arguments | ||
457 | * @return 0 ok, 1 on error | ||
458 | */ | ||
459 | int | ||
460 | main (int argc, char *const *argv) | ||
461 | { | ||
462 | static const struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
463 | GNUNET_GETOPT_OPTION_END | ||
464 | }; | ||
465 | int ret; | ||
466 | |||
467 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
468 | return 2; | ||
469 | #ifdef SQLITE_CONFIG_MMAP_SIZE | ||
470 | (void) sqlite3_config (SQLITE_CONFIG_MMAP_SIZE, 512000, 256000000); | ||
471 | #endif | ||
472 | ret = | ||
473 | (GNUNET_OK == | ||
474 | GNUNET_PROGRAM_run (argc, argv, "testbed-underlay", | ||
475 | _ | ||
476 | ( | ||
477 | "Daemon to restrict underlay network in testbed deployments"), | ||
478 | options, &run, NULL)) ? 0 : 1; | ||
479 | GNUNET_free_nz ((void *) argv); | ||
480 | return ret; | ||
481 | } | ||
diff --git a/src/testbed/gnunet-helper-testbed-valgrind.patch b/src/testbed/gnunet-helper-testbed-valgrind.patch deleted file mode 100644 index 1777c30d0..000000000 --- a/src/testbed/gnunet-helper-testbed-valgrind.patch +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | Index: gnunet-helper-testbed.c | ||
2 | =================================================================== | ||
3 | --- gnunet-helper-testbed.c (revision 32320) | ||
4 | +++ gnunet-helper-testbed.c (working copy) | ||
5 | @@ -462,7 +462,15 @@ | ||
6 | testbed = | ||
7 | GNUNET_OS_start_process (PIPE_CONTROL, | ||
8 | GNUNET_OS_INHERIT_STD_ERR /*verbose? */ , NULL, | ||
9 | - NULL, binary, "gnunet-service-testbed", "-c", | ||
10 | + NULL, "valgrind", | ||
11 | + "valgrind", | ||
12 | + "--leak-check=full", | ||
13 | + "--show-reachable=yes", | ||
14 | + "--suppressions=$HOME/gnunet/src/util/util.supp", | ||
15 | + "--suppressions=$HOME/gnunet/src/testbed/misc.supp", | ||
16 | + "--suppressions=$HOME/gnunet/src/testbed/valgrind-zlib.supp", | ||
17 | + "--suppressions=$HOME/gnunet/src/testbed/x64_misc.supp", | ||
18 | + binary, "-c", | ||
19 | config, NULL); | ||
20 | GNUNET_free (binary); | ||
21 | GNUNET_free (config); | ||
diff --git a/src/testbed/gnunet-helper-testbed.c b/src/testbed/gnunet-helper-testbed.c deleted file mode 100644 index 938e50448..000000000 --- a/src/testbed/gnunet-helper-testbed.c +++ /dev/null | |||
@@ -1,613 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-helper-testbed.c | ||
23 | * @brief Helper binary that is started from a remote controller to start | ||
24 | * gnunet-service-testbed. This binary also receives configuration | ||
25 | * from the remove controller which is put in a temporary location | ||
26 | * with ports and paths fixed so that gnunet-service-testbed runs | ||
27 | * without any hurdles. | ||
28 | * | ||
29 | * This helper monitors for three termination events. They are: (1)The | ||
30 | * stdin of the helper is closed for reading; (2)the helper received | ||
31 | * SIGTERM/SIGINT; (3)the testbed crashed. In case of events 1 and 2 | ||
32 | * the helper kills the testbed service. When testbed crashed (event | ||
33 | * 3), the helper should send a SIGTERM to its own process group; this | ||
34 | * behaviour will help terminate any child processes (peers) testbed | ||
35 | * has started and prevents them from leaking and running forever. | ||
36 | * | ||
37 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
38 | */ | ||
39 | |||
40 | |||
41 | #include "platform.h" | ||
42 | #include "gnunet_util_lib.h" | ||
43 | #include "gnunet_testing_lib.h" | ||
44 | #include "gnunet_testbed_service.h" | ||
45 | #include "testbed_helper.h" | ||
46 | #include "testbed_api.h" | ||
47 | #include <zlib.h> | ||
48 | |||
49 | /** | ||
50 | * Generic logging shortcut | ||
51 | */ | ||
52 | #define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__) | ||
53 | |||
54 | /** | ||
55 | * Debug logging shorthand | ||
56 | */ | ||
57 | #define LOG_DEBUG(...) LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) | ||
58 | |||
59 | |||
60 | /** | ||
61 | * Context for a single write on a chunk of memory | ||
62 | */ | ||
63 | struct WriteContext | ||
64 | { | ||
65 | /** | ||
66 | * The data to write | ||
67 | */ | ||
68 | void *data; | ||
69 | |||
70 | /** | ||
71 | * The length of the data | ||
72 | */ | ||
73 | size_t length; | ||
74 | |||
75 | /** | ||
76 | * The current position from where the write operation should begin | ||
77 | */ | ||
78 | size_t pos; | ||
79 | }; | ||
80 | |||
81 | |||
82 | /** | ||
83 | * Handle to the testing system | ||
84 | */ | ||
85 | static struct GNUNET_TESTING_System *test_system; | ||
86 | |||
87 | /** | ||
88 | * Our message stream tokenizer | ||
89 | */ | ||
90 | struct GNUNET_MessageStreamTokenizer *tokenizer; | ||
91 | |||
92 | /** | ||
93 | * Disk handle from stdin | ||
94 | */ | ||
95 | static struct GNUNET_DISK_FileHandle *stdin_fd; | ||
96 | |||
97 | /** | ||
98 | * Disk handle for stdout | ||
99 | */ | ||
100 | static struct GNUNET_DISK_FileHandle *stdout_fd; | ||
101 | |||
102 | /** | ||
103 | * The process handle to the testbed service | ||
104 | */ | ||
105 | static struct GNUNET_OS_Process *testbed; | ||
106 | |||
107 | /** | ||
108 | * Pipe used to communicate shutdown via signal. | ||
109 | */ | ||
110 | static struct GNUNET_DISK_PipeHandle *sigpipe; | ||
111 | |||
112 | /** | ||
113 | * Task identifier for the read task | ||
114 | */ | ||
115 | static struct GNUNET_SCHEDULER_Task *read_task_id; | ||
116 | |||
117 | /** | ||
118 | * Task identifier for the write task | ||
119 | */ | ||
120 | static struct GNUNET_SCHEDULER_Task *write_task_id; | ||
121 | |||
122 | /** | ||
123 | * Task to kill the child | ||
124 | */ | ||
125 | static struct GNUNET_SCHEDULER_Task *child_death_task_id; | ||
126 | |||
127 | /** | ||
128 | * Are we done reading messages from stdin? | ||
129 | */ | ||
130 | static int done_reading; | ||
131 | |||
132 | /** | ||
133 | * Result to return in case we fail | ||
134 | */ | ||
135 | static int status; | ||
136 | |||
137 | |||
138 | /** | ||
139 | * Task to shut down cleanly | ||
140 | * | ||
141 | * @param cls NULL | ||
142 | */ | ||
143 | static void | ||
144 | shutdown_task (void *cls) | ||
145 | { | ||
146 | LOG_DEBUG ("Shutting down\n"); | ||
147 | if (NULL != testbed) | ||
148 | { | ||
149 | LOG_DEBUG ("Killing testbed\n"); | ||
150 | GNUNET_break (0 == GNUNET_OS_process_kill (testbed, GNUNET_TERM_SIG)); | ||
151 | } | ||
152 | if (NULL != read_task_id) | ||
153 | { | ||
154 | GNUNET_SCHEDULER_cancel (read_task_id); | ||
155 | read_task_id = NULL; | ||
156 | } | ||
157 | if (NULL != write_task_id) | ||
158 | { | ||
159 | struct WriteContext *wc; | ||
160 | |||
161 | wc = GNUNET_SCHEDULER_cancel (write_task_id); | ||
162 | write_task_id = NULL; | ||
163 | GNUNET_free (wc->data); | ||
164 | GNUNET_free (wc); | ||
165 | } | ||
166 | if (NULL != child_death_task_id) | ||
167 | { | ||
168 | GNUNET_SCHEDULER_cancel (child_death_task_id); | ||
169 | child_death_task_id = NULL; | ||
170 | } | ||
171 | if (NULL != stdin_fd) | ||
172 | (void) GNUNET_DISK_file_close (stdin_fd); | ||
173 | if (NULL != stdout_fd) | ||
174 | (void) GNUNET_DISK_file_close (stdout_fd); | ||
175 | GNUNET_MST_destroy (tokenizer); | ||
176 | tokenizer = NULL; | ||
177 | if (NULL != testbed) | ||
178 | { | ||
179 | GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (testbed)); | ||
180 | GNUNET_OS_process_destroy (testbed); | ||
181 | testbed = NULL; | ||
182 | } | ||
183 | if (NULL != test_system) | ||
184 | { | ||
185 | GNUNET_TESTING_system_destroy (test_system, GNUNET_YES); | ||
186 | test_system = NULL; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | |||
191 | /** | ||
192 | * Task to write to the standard out | ||
193 | * | ||
194 | * @param cls the WriteContext | ||
195 | */ | ||
196 | static void | ||
197 | write_task (void *cls) | ||
198 | { | ||
199 | struct WriteContext *wc = cls; | ||
200 | ssize_t bytes_wrote; | ||
201 | |||
202 | GNUNET_assert (NULL != wc); | ||
203 | write_task_id = NULL; | ||
204 | bytes_wrote = GNUNET_DISK_file_write (stdout_fd, | ||
205 | wc->data + wc->pos, | ||
206 | wc->length - wc->pos); | ||
207 | if (GNUNET_SYSERR == bytes_wrote) | ||
208 | { | ||
209 | LOG (GNUNET_ERROR_TYPE_WARNING, "Cannot reply back configuration\n"); | ||
210 | GNUNET_free (wc->data); | ||
211 | GNUNET_free (wc); | ||
212 | return; | ||
213 | } | ||
214 | wc->pos += bytes_wrote; | ||
215 | if (wc->pos == wc->length) | ||
216 | { | ||
217 | GNUNET_free (wc->data); | ||
218 | GNUNET_free (wc); | ||
219 | return; | ||
220 | } | ||
221 | write_task_id = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
222 | stdout_fd, | ||
223 | &write_task, | ||
224 | wc); | ||
225 | } | ||
226 | |||
227 | |||
228 | /** | ||
229 | * Task triggered whenever we receive a SIGCHLD (child | ||
230 | * process died). | ||
231 | * | ||
232 | * @param cls closure, NULL if we need to self-restart | ||
233 | */ | ||
234 | static void | ||
235 | child_death_task (void *cls) | ||
236 | { | ||
237 | const struct GNUNET_DISK_FileHandle *pr; | ||
238 | char c[16]; | ||
239 | enum GNUNET_OS_ProcessStatusType type; | ||
240 | unsigned long code; | ||
241 | int ret; | ||
242 | |||
243 | pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); | ||
244 | child_death_task_id = NULL; | ||
245 | /* consume the signal */ | ||
246 | GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof(c))); | ||
247 | LOG_DEBUG ("Got SIGCHLD\n"); | ||
248 | if (NULL == testbed) | ||
249 | { | ||
250 | GNUNET_break (0); | ||
251 | return; | ||
252 | } | ||
253 | GNUNET_break (GNUNET_SYSERR != | ||
254 | (ret = GNUNET_OS_process_status (testbed, &type, &code))); | ||
255 | if (GNUNET_NO != ret) | ||
256 | { | ||
257 | GNUNET_OS_process_destroy (testbed); | ||
258 | testbed = NULL; | ||
259 | /* Send SIGTERM to our process group */ | ||
260 | if (0 != kill (0, GNUNET_TERM_SIG)) | ||
261 | { | ||
262 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "signal"); | ||
263 | GNUNET_SCHEDULER_shutdown (); /* Couldn't send the signal, we shutdown frowning */ | ||
264 | } | ||
265 | return; | ||
266 | } | ||
267 | LOG_DEBUG ("Child hasn't died. Resuming to monitor its status\n"); | ||
268 | child_death_task_id = | ||
269 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
270 | pr, | ||
271 | &child_death_task, | ||
272 | NULL); | ||
273 | } | ||
274 | |||
275 | |||
276 | /** | ||
277 | * Functions with this signature are called whenever a | ||
278 | * complete message is received by the tokenizer. | ||
279 | * | ||
280 | * Do not call #GNUNET_mst_destroy() in this callback | ||
281 | * | ||
282 | * @param cls identification of the client | ||
283 | * @param message the actual message | ||
284 | * @return #GNUNET_OK on success, | ||
285 | * #GNUNET_NO to stop further processing (no error) | ||
286 | * #GNUNET_SYSERR to stop further processing with error | ||
287 | */ | ||
288 | static int | ||
289 | tokenizer_cb (void *cls, const struct GNUNET_MessageHeader *message) | ||
290 | { | ||
291 | const struct GNUNET_TESTBED_HelperInit *msg; | ||
292 | struct GNUNET_TESTBED_HelperReply *reply; | ||
293 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
294 | struct WriteContext *wc; | ||
295 | char *binary; | ||
296 | char *trusted_ip; | ||
297 | char *hostname; | ||
298 | char *config; | ||
299 | char *xconfig; | ||
300 | char *evstr; | ||
301 | // char *str; | ||
302 | size_t config_size; | ||
303 | uLongf ul_config_size; | ||
304 | size_t xconfig_size; | ||
305 | uint16_t trusted_ip_size; | ||
306 | uint16_t hostname_size; | ||
307 | uint16_t msize; | ||
308 | |||
309 | msize = ntohs (message->size); | ||
310 | if ((sizeof(struct GNUNET_TESTBED_HelperInit) >= msize) || | ||
311 | (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT != ntohs (message->type))) | ||
312 | { | ||
313 | LOG (GNUNET_ERROR_TYPE_WARNING, "Received unexpected message -- exiting\n"); | ||
314 | goto error; | ||
315 | } | ||
316 | msg = (const struct GNUNET_TESTBED_HelperInit *) message; | ||
317 | trusted_ip_size = ntohs (msg->trusted_ip_size); | ||
318 | trusted_ip = (char *) &msg[1]; | ||
319 | if ('\0' != trusted_ip[trusted_ip_size]) | ||
320 | { | ||
321 | LOG (GNUNET_ERROR_TYPE_WARNING, "Trusted IP cannot be empty -- exiting\n"); | ||
322 | goto error; | ||
323 | } | ||
324 | hostname_size = ntohs (msg->hostname_size); | ||
325 | if ((sizeof(struct GNUNET_TESTBED_HelperInit) + trusted_ip_size + 1 | ||
326 | + hostname_size) >= msize) | ||
327 | { | ||
328 | GNUNET_break (0); | ||
329 | LOG (GNUNET_ERROR_TYPE_WARNING, "Received unexpected message -- exiting\n"); | ||
330 | goto error; | ||
331 | } | ||
332 | ul_config_size = (uLongf) ntohs (msg->config_size); | ||
333 | config = GNUNET_malloc (ul_config_size); | ||
334 | xconfig_size = msize - (trusted_ip_size + 1 + hostname_size | ||
335 | + sizeof(struct GNUNET_TESTBED_HelperInit)); | ||
336 | int ret = uncompress ((Bytef *) config, | ||
337 | &ul_config_size, | ||
338 | (const Bytef *) (trusted_ip + trusted_ip_size + 1 | ||
339 | + hostname_size), | ||
340 | (uLongf) xconfig_size); | ||
341 | if (Z_OK != ret) | ||
342 | { | ||
343 | switch (ret) | ||
344 | { | ||
345 | case Z_MEM_ERROR: | ||
346 | LOG (GNUNET_ERROR_TYPE_ERROR, "Not enough memory for decompression\n"); | ||
347 | break; | ||
348 | |||
349 | case Z_BUF_ERROR: | ||
350 | LOG (GNUNET_ERROR_TYPE_ERROR, "Output buffer too small\n"); | ||
351 | break; | ||
352 | |||
353 | case Z_DATA_ERROR: | ||
354 | LOG (GNUNET_ERROR_TYPE_ERROR, "Data corrupted/incomplete\n"); | ||
355 | break; | ||
356 | |||
357 | default: | ||
358 | GNUNET_break (0); | ||
359 | } | ||
360 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
361 | "Error while uncompressing config -- exiting\n"); | ||
362 | GNUNET_free (config); | ||
363 | goto error; | ||
364 | } | ||
365 | cfg = GNUNET_CONFIGURATION_create (); | ||
366 | if (GNUNET_OK != | ||
367 | GNUNET_CONFIGURATION_deserialize (cfg, config, ul_config_size, NULL)) | ||
368 | { | ||
369 | LOG (GNUNET_ERROR_TYPE_ERROR, "Unable to deserialize config -- exiting\n"); | ||
370 | GNUNET_free (config); | ||
371 | goto error; | ||
372 | } | ||
373 | GNUNET_free (config); | ||
374 | hostname = NULL; | ||
375 | if (0 != hostname_size) | ||
376 | { | ||
377 | hostname = GNUNET_malloc (hostname_size + 1); | ||
378 | GNUNET_strlcpy (hostname, | ||
379 | ((char *) &msg[1]) + trusted_ip_size + 1, | ||
380 | hostname_size + 1); | ||
381 | } | ||
382 | /* unset GNUNET_TESTING_PREFIX if present as it is more relevant for testbed */ | ||
383 | evstr = getenv (GNUNET_TESTING_PREFIX); | ||
384 | if (NULL != evstr) | ||
385 | { | ||
386 | /* unsetting the variable will invalidate the pointer! */ | ||
387 | evstr = GNUNET_strdup (evstr); | ||
388 | GNUNET_break (0 == unsetenv (GNUNET_TESTING_PREFIX)); | ||
389 | } | ||
390 | test_system = | ||
391 | GNUNET_TESTING_system_create ("testbed-helper", trusted_ip, hostname, NULL); | ||
392 | if (NULL != evstr) | ||
393 | { | ||
394 | char *evar; | ||
395 | |||
396 | GNUNET_asprintf (&evar, GNUNET_TESTING_PREFIX "=%s", evstr); | ||
397 | GNUNET_assert (0 == putenv (evar)); /* consumes 'evar', | ||
398 | see putenv(): becomes part of environment! */ | ||
399 | GNUNET_free (evstr); | ||
400 | evstr = NULL; | ||
401 | } | ||
402 | GNUNET_free (hostname); | ||
403 | hostname = NULL; | ||
404 | GNUNET_assert (NULL != test_system); | ||
405 | GNUNET_assert (GNUNET_OK == | ||
406 | GNUNET_TESTING_configuration_create (test_system, cfg)); | ||
407 | GNUNET_assert (GNUNET_OK == | ||
408 | GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
409 | "PATHS", | ||
410 | "DEFAULTCONFIG", | ||
411 | &config)); | ||
412 | if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config)) | ||
413 | { | ||
414 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
415 | "Unable to write config file: %s -- exiting\n", | ||
416 | config); | ||
417 | GNUNET_CONFIGURATION_destroy (cfg); | ||
418 | GNUNET_free (config); | ||
419 | goto error; | ||
420 | } | ||
421 | LOG_DEBUG ("Staring testbed with config: %s\n", config); | ||
422 | binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-testbed"); | ||
423 | { | ||
424 | char *evar; | ||
425 | |||
426 | /* expose testbed configuration through env variable */ | ||
427 | GNUNET_asprintf (&evar, "%s=%s", ENV_TESTBED_CONFIG, config); | ||
428 | GNUNET_assert (0 == putenv (evar)); /* consumes 'evar', | ||
429 | see putenv(): becomes part of environment! */ | ||
430 | evstr = NULL; | ||
431 | } | ||
432 | testbed = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR /*verbose? */, | ||
433 | NULL, | ||
434 | NULL, | ||
435 | NULL, | ||
436 | binary, | ||
437 | "gnunet-service-testbed", | ||
438 | "-c", | ||
439 | config, | ||
440 | NULL); | ||
441 | GNUNET_free (binary); | ||
442 | GNUNET_free (config); | ||
443 | if (NULL == testbed) | ||
444 | { | ||
445 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
446 | "Error starting gnunet-service-testbed -- exiting\n"); | ||
447 | GNUNET_CONFIGURATION_destroy (cfg); | ||
448 | goto error; | ||
449 | } | ||
450 | done_reading = GNUNET_YES; | ||
451 | config = GNUNET_CONFIGURATION_serialize (cfg, &config_size); | ||
452 | GNUNET_CONFIGURATION_destroy (cfg); | ||
453 | cfg = NULL; | ||
454 | xconfig_size = | ||
455 | GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig); | ||
456 | GNUNET_free (config); | ||
457 | wc = GNUNET_new (struct WriteContext); | ||
458 | wc->length = xconfig_size + sizeof(struct GNUNET_TESTBED_HelperReply); | ||
459 | reply = GNUNET_realloc (xconfig, wc->length); | ||
460 | memmove (&reply[1], reply, xconfig_size); | ||
461 | reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY); | ||
462 | reply->header.size = htons ((uint16_t) wc->length); | ||
463 | reply->config_size = htons ((uint16_t) config_size); | ||
464 | wc->data = reply; | ||
465 | write_task_id = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
466 | stdout_fd, | ||
467 | &write_task, | ||
468 | wc); | ||
469 | child_death_task_id = GNUNET_SCHEDULER_add_read_file ( | ||
470 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
471 | GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ), | ||
472 | &child_death_task, | ||
473 | NULL); | ||
474 | return GNUNET_OK; | ||
475 | |||
476 | error: | ||
477 | status = GNUNET_SYSERR; | ||
478 | GNUNET_SCHEDULER_shutdown (); | ||
479 | return GNUNET_SYSERR; | ||
480 | } | ||
481 | |||
482 | |||
483 | /** | ||
484 | * Task to read from stdin | ||
485 | * | ||
486 | * @param cls NULL | ||
487 | */ | ||
488 | static void | ||
489 | read_task (void *cls) | ||
490 | { | ||
491 | char buf[GNUNET_MAX_MESSAGE_SIZE]; | ||
492 | ssize_t sread; | ||
493 | |||
494 | read_task_id = NULL; | ||
495 | sread = GNUNET_DISK_file_read (stdin_fd, buf, sizeof(buf)); | ||
496 | if ((GNUNET_SYSERR == sread) || (0 == sread)) | ||
497 | { | ||
498 | LOG_DEBUG ("STDIN closed\n"); | ||
499 | GNUNET_SCHEDULER_shutdown (); | ||
500 | return; | ||
501 | } | ||
502 | if (GNUNET_YES == done_reading) | ||
503 | { | ||
504 | /* didn't expect any more data! */ | ||
505 | GNUNET_break_op (0); | ||
506 | GNUNET_SCHEDULER_shutdown (); | ||
507 | return; | ||
508 | } | ||
509 | LOG_DEBUG ("Read %u bytes\n", (unsigned int) sread); | ||
510 | /* FIXME: could introduce a GNUNET_MST_read2 to read | ||
511 | directly from 'stdin_fd' and save a memcpy() here */ | ||
512 | if (GNUNET_OK != | ||
513 | GNUNET_MST_from_buffer (tokenizer, buf, sread, GNUNET_NO, GNUNET_NO)) | ||
514 | { | ||
515 | GNUNET_break (0); | ||
516 | GNUNET_SCHEDULER_shutdown (); | ||
517 | return; | ||
518 | } | ||
519 | read_task_id /* No timeout while reading */ | ||
520 | = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
521 | stdin_fd, | ||
522 | &read_task, | ||
523 | NULL); | ||
524 | } | ||
525 | |||
526 | |||
527 | /** | ||
528 | * Main function that will be run. | ||
529 | * | ||
530 | * @param cls closure | ||
531 | * @param args remaining command-line arguments | ||
532 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
533 | * @param cfg configuration | ||
534 | */ | ||
535 | static void | ||
536 | run (void *cls, | ||
537 | char *const *args, | ||
538 | const char *cfgfile, | ||
539 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
540 | { | ||
541 | LOG_DEBUG ("Starting testbed helper...\n"); | ||
542 | tokenizer = GNUNET_MST_create (&tokenizer_cb, NULL); | ||
543 | stdin_fd = GNUNET_DISK_get_handle_from_native (stdin); | ||
544 | stdout_fd = GNUNET_DISK_get_handle_from_native (stdout); | ||
545 | read_task_id = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
546 | stdin_fd, | ||
547 | &read_task, | ||
548 | NULL); | ||
549 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | ||
550 | } | ||
551 | |||
552 | |||
553 | /** | ||
554 | * Signal handler called for SIGCHLD. | ||
555 | */ | ||
556 | static void | ||
557 | sighandler_child_death () | ||
558 | { | ||
559 | static char c; | ||
560 | int old_errno; /* back-up errno */ | ||
561 | |||
562 | old_errno = errno; | ||
563 | GNUNET_break ( | ||
564 | 1 == | ||
565 | GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe, | ||
566 | GNUNET_DISK_PIPE_END_WRITE), | ||
567 | &c, | ||
568 | sizeof(c))); | ||
569 | errno = old_errno; | ||
570 | } | ||
571 | |||
572 | |||
573 | /** | ||
574 | * Main function | ||
575 | * | ||
576 | * @param argc the number of command line arguments | ||
577 | * @param argv command line arg array | ||
578 | * @return return code | ||
579 | */ | ||
580 | int | ||
581 | main (int argc, char **argv) | ||
582 | { | ||
583 | struct GNUNET_SIGNAL_Context *shc_chld; | ||
584 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
585 | { GNUNET_GETOPT_OPTION_END }; | ||
586 | int ret; | ||
587 | |||
588 | status = GNUNET_OK; | ||
589 | if (NULL == | ||
590 | (sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE))) | ||
591 | { | ||
592 | GNUNET_break (0); | ||
593 | return 1; | ||
594 | } | ||
595 | shc_chld = | ||
596 | GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); | ||
597 | ret = GNUNET_PROGRAM_run (argc, | ||
598 | argv, | ||
599 | "gnunet-helper-testbed", | ||
600 | "Helper for starting gnunet-service-testbed", | ||
601 | options, | ||
602 | &run, | ||
603 | NULL); | ||
604 | GNUNET_SIGNAL_handler_uninstall (shc_chld); | ||
605 | shc_chld = NULL; | ||
606 | GNUNET_DISK_pipe_close (sigpipe); | ||
607 | if (GNUNET_OK != ret) | ||
608 | return 1; | ||
609 | return (GNUNET_OK == status) ? 0 : 1; | ||
610 | } | ||
611 | |||
612 | |||
613 | /* end of gnunet-helper-testbed.c */ | ||
diff --git a/src/testbed/gnunet-service-test-barriers.c b/src/testbed/gnunet-service-test-barriers.c deleted file mode 100644 index e10a28902..000000000 --- a/src/testbed/gnunet-service-test-barriers.c +++ /dev/null | |||
@@ -1,152 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-service-test-barriers.c | ||
23 | * @brief Daemon acting as a service for testing testbed barriers. It is | ||
24 | * started as a peer service and waits for a barrier to be crossed. | ||
25 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
26 | */ | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_testbed_service.h" | ||
31 | #include "test_testbed_api_barriers.h" | ||
32 | |||
33 | /** | ||
34 | * logging short hand | ||
35 | */ | ||
36 | #define LOG(type, ...) \ | ||
37 | GNUNET_log (type, __VA_ARGS__); | ||
38 | |||
39 | /** | ||
40 | * Our barrier wait handle | ||
41 | */ | ||
42 | static struct GNUNET_TESTBED_BarrierWaitHandle *wh; | ||
43 | |||
44 | static struct GNUNET_SCHEDULER_Task *tt; | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Dummy task callback to keep us running forever | ||
49 | * | ||
50 | * @param cls NULL | ||
51 | */ | ||
52 | static void | ||
53 | do_shutdown (void *cls) | ||
54 | { | ||
55 | if (NULL != wh) | ||
56 | { | ||
57 | GNUNET_TESTBED_barrier_wait_cancel (wh); | ||
58 | wh = NULL; | ||
59 | } | ||
60 | if (NULL != tt) | ||
61 | { | ||
62 | GNUNET_SCHEDULER_cancel (tt); | ||
63 | tt = NULL; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | |||
68 | /** | ||
69 | * Functions of this type are to be given as acallback argument to | ||
70 | * GNUNET_TESTBED_barrier_wait(). The callback will be called when the barrier | ||
71 | * corresponding given in GNUNET_TESTBED_barrier_wait() is crossed or cancelled. | ||
72 | * | ||
73 | * @param cls NULL | ||
74 | * @param name the barrier name | ||
75 | * @param status #GNUNET_SYSERR in case of error while waiting for the barrier; | ||
76 | * #GNUNET_OK if the barrier is crossed | ||
77 | */ | ||
78 | static void | ||
79 | barrier_wait_cb (void *cls, | ||
80 | const char *name, | ||
81 | int status) | ||
82 | { | ||
83 | GNUNET_break (NULL == cls); | ||
84 | wh = NULL; | ||
85 | GNUNET_break (GNUNET_OK == status); | ||
86 | } | ||
87 | |||
88 | |||
89 | /** | ||
90 | * Task to wait for the barrier | ||
91 | * | ||
92 | * @param cls NULL | ||
93 | * @return | ||
94 | */ | ||
95 | static void | ||
96 | do_wait (void *cls) | ||
97 | { | ||
98 | tt = NULL; | ||
99 | wh = GNUNET_TESTBED_barrier_wait (TEST_BARRIER_NAME, | ||
100 | &barrier_wait_cb, | ||
101 | NULL); | ||
102 | GNUNET_break (NULL != wh); | ||
103 | } | ||
104 | |||
105 | |||
106 | /** | ||
107 | * Main run function. | ||
108 | * | ||
109 | * @param cls NULL | ||
110 | * @param args arguments passed to GNUNET_PROGRAM_run | ||
111 | * @param cfgfile the path to configuration file | ||
112 | * @param config the configuration file handle | ||
113 | */ | ||
114 | static void | ||
115 | run (void *cls, | ||
116 | char *const *args, | ||
117 | const char *cfgfile, | ||
118 | const struct GNUNET_CONFIGURATION_Handle *config) | ||
119 | { | ||
120 | unsigned int rsec; | ||
121 | |||
122 | rsec = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, | ||
123 | 10); | ||
124 | tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply ( | ||
125 | GNUNET_TIME_UNIT_SECONDS, | ||
126 | rsec), | ||
127 | &do_wait, | ||
128 | NULL); | ||
129 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
130 | } | ||
131 | |||
132 | |||
133 | /** | ||
134 | * Main | ||
135 | */ | ||
136 | int | ||
137 | main (int argc, char **argv) | ||
138 | { | ||
139 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
140 | GNUNET_GETOPT_OPTION_END | ||
141 | }; | ||
142 | int ret; | ||
143 | |||
144 | ret = | ||
145 | GNUNET_PROGRAM_run (argc, argv, | ||
146 | "test-barriers", | ||
147 | "nohelp", | ||
148 | options, | ||
149 | &run, | ||
150 | NULL); | ||
151 | return ret; | ||
152 | } | ||
diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c deleted file mode 100644 index 3ef99ae25..000000000 --- a/src/testbed/gnunet-service-testbed.c +++ /dev/null | |||
@@ -1,985 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2013, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-service-testbed.c | ||
23 | * @brief implementation of the TESTBED service | ||
24 | * @author Sree Harsha Totakura | ||
25 | */ | ||
26 | |||
27 | #include "gnunet-service-testbed.h" | ||
28 | #include "gnunet-service-testbed_barriers.h" | ||
29 | #include "gnunet-service-testbed_connectionpool.h" | ||
30 | |||
31 | /***********/ | ||
32 | /* Globals */ | ||
33 | /***********/ | ||
34 | |||
35 | /** | ||
36 | * Our configuration | ||
37 | */ | ||
38 | struct GNUNET_CONFIGURATION_Handle *GST_config; | ||
39 | |||
40 | /** | ||
41 | * The master context; generated with the first INIT message | ||
42 | */ | ||
43 | struct Context *GST_context; | ||
44 | |||
45 | /** | ||
46 | * Array of hosts | ||
47 | */ | ||
48 | struct GNUNET_TESTBED_Host **GST_host_list; | ||
49 | |||
50 | /** | ||
51 | * DLL head for forwarded operation contexts | ||
52 | */ | ||
53 | struct ForwardedOperationContext *fopcq_head; | ||
54 | |||
55 | /** | ||
56 | * DLL tail for forwarded operation contexts | ||
57 | */ | ||
58 | struct ForwardedOperationContext *fopcq_tail; | ||
59 | |||
60 | /** | ||
61 | * Operation queue for open file descriptors | ||
62 | */ | ||
63 | struct OperationQueue *GST_opq_openfds; | ||
64 | |||
65 | /** | ||
66 | * Timeout for operations which may take some time | ||
67 | */ | ||
68 | struct GNUNET_TIME_Relative GST_timeout; | ||
69 | |||
70 | /** | ||
71 | * The size of the host list | ||
72 | */ | ||
73 | unsigned int GST_host_list_size; | ||
74 | |||
75 | /** | ||
76 | * The size of the peer list | ||
77 | */ | ||
78 | unsigned int GST_peer_list_size; | ||
79 | |||
80 | |||
81 | /***********************************/ | ||
82 | /* Local definitions and variables */ | ||
83 | /***********************************/ | ||
84 | |||
85 | /** | ||
86 | * Our hostname; we give this to all the peers we start | ||
87 | */ | ||
88 | static char *hostname; | ||
89 | |||
90 | |||
91 | /** | ||
92 | * Function to add a host to the current list of known hosts | ||
93 | * | ||
94 | * @param host the host to add | ||
95 | * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure due to host-id | ||
96 | * already in use | ||
97 | */ | ||
98 | static int | ||
99 | host_list_add (struct GNUNET_TESTBED_Host *host) | ||
100 | { | ||
101 | uint32_t host_id; | ||
102 | |||
103 | host_id = GNUNET_TESTBED_host_get_id_ (host); | ||
104 | if (GST_host_list_size <= host_id) | ||
105 | GST_array_grow_large_enough (GST_host_list, GST_host_list_size, host_id); | ||
106 | if (NULL != GST_host_list[host_id]) | ||
107 | { | ||
108 | LOG_DEBUG ("A host with id: %u already exists\n", host_id); | ||
109 | return GNUNET_SYSERR; | ||
110 | } | ||
111 | GST_host_list[host_id] = host; | ||
112 | return GNUNET_OK; | ||
113 | } | ||
114 | |||
115 | |||
116 | /** | ||
117 | * Send operation failure message to client | ||
118 | * | ||
119 | * @param client the client to which the failure message has to be sent to | ||
120 | * @param operation_id the id of the failed operation | ||
121 | * @param emsg the error message; can be NULL | ||
122 | */ | ||
123 | void | ||
124 | GST_send_operation_fail_msg (struct GNUNET_SERVICE_Client *client, | ||
125 | uint64_t operation_id, | ||
126 | const char *emsg) | ||
127 | { | ||
128 | struct GNUNET_MQ_Envelope *env; | ||
129 | struct GNUNET_TESTBED_OperationFailureEventMessage *msg; | ||
130 | uint16_t emsg_len; | ||
131 | |||
132 | emsg_len = (NULL == emsg) ? 0 : strlen (emsg) + 1; | ||
133 | env = GNUNET_MQ_msg_extra (msg, | ||
134 | emsg_len, | ||
135 | GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT); | ||
136 | msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
137 | msg->operation_id = GNUNET_htonll (operation_id); | ||
138 | GNUNET_memcpy (&msg[1], | ||
139 | emsg, | ||
140 | emsg_len); | ||
141 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
142 | env); | ||
143 | } | ||
144 | |||
145 | |||
146 | /** | ||
147 | * Function to send generic operation success message to given client | ||
148 | * | ||
149 | * @param client the client to send the message to | ||
150 | * @param operation_id the id of the operation which was successful | ||
151 | */ | ||
152 | void | ||
153 | GST_send_operation_success_msg (struct GNUNET_SERVICE_Client *client, | ||
154 | uint64_t operation_id) | ||
155 | { | ||
156 | struct GNUNET_MQ_Envelope *env; | ||
157 | struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg; | ||
158 | |||
159 | env = GNUNET_MQ_msg (msg, | ||
160 | GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS); | ||
161 | msg->operation_id = GNUNET_htonll (operation_id); | ||
162 | msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
163 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
164 | env); | ||
165 | } | ||
166 | |||
167 | |||
168 | /** | ||
169 | * Callback which will be called after a host registration succeeded or failed | ||
170 | * | ||
171 | * @param cls the handle to the slave at which the registration is completed | ||
172 | * @param emsg the error message; NULL if host registration is successful | ||
173 | */ | ||
174 | static void | ||
175 | hr_completion (void *cls, | ||
176 | const char *emsg); | ||
177 | |||
178 | |||
179 | /** | ||
180 | * Attempts to register the next host in the host registration queue | ||
181 | * | ||
182 | * @param slave the slave controller whose host registration queue is checked | ||
183 | * for host registrations | ||
184 | */ | ||
185 | static void | ||
186 | register_next_host (struct Slave *slave) | ||
187 | { | ||
188 | struct HostRegistration *hr; | ||
189 | |||
190 | hr = slave->hr_dll_head; | ||
191 | GNUNET_assert (NULL != hr); | ||
192 | GNUNET_assert (NULL == slave->rhandle); | ||
193 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering host %u at %u\n", | ||
194 | GNUNET_TESTBED_host_get_id_ (hr->host), | ||
195 | GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); | ||
196 | slave->rhandle | ||
197 | = GNUNET_TESTBED_register_host (slave->controller, | ||
198 | hr->host, | ||
199 | hr_completion, | ||
200 | slave); | ||
201 | } | ||
202 | |||
203 | |||
204 | /** | ||
205 | * Callback which will be called to after a host registration succeeded or failed | ||
206 | * | ||
207 | * @param cls the handle to the slave at which the registration is completed | ||
208 | * @param emsg the error message; NULL if host registration is successful | ||
209 | */ | ||
210 | static void | ||
211 | hr_completion (void *cls, | ||
212 | const char *emsg) | ||
213 | { | ||
214 | struct Slave *slave = cls; | ||
215 | struct HostRegistration *hr; | ||
216 | |||
217 | slave->rhandle = NULL; | ||
218 | hr = slave->hr_dll_head; | ||
219 | GNUNET_assert (NULL != hr); | ||
220 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
221 | "Registering host %u at %u successful\n", | ||
222 | GNUNET_TESTBED_host_get_id_ (hr->host), | ||
223 | GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); | ||
224 | GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, | ||
225 | slave->hr_dll_tail, | ||
226 | hr); | ||
227 | if (NULL != hr->cb) | ||
228 | hr->cb (hr->cb_cls, | ||
229 | emsg); | ||
230 | GNUNET_free (hr); | ||
231 | if (NULL != slave->hr_dll_head) | ||
232 | register_next_host (slave); | ||
233 | } | ||
234 | |||
235 | |||
236 | /** | ||
237 | * Adds a host registration's request to a slave's registration queue | ||
238 | * | ||
239 | * @param slave the slave controller at which the given host has to be | ||
240 | * registered | ||
241 | * @param cb the host registration completion callback | ||
242 | * @param cb_cls the closure for the host registration completion callback | ||
243 | * @param host the host which has to be registered | ||
244 | */ | ||
245 | void | ||
246 | GST_queue_host_registration (struct Slave *slave, | ||
247 | GNUNET_TESTBED_HostRegistrationCompletion cb, | ||
248 | void *cb_cls, | ||
249 | struct GNUNET_TESTBED_Host *host) | ||
250 | { | ||
251 | struct HostRegistration *hr; | ||
252 | int call_register; | ||
253 | |||
254 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
255 | "Queueing host registration for host %u at %u\n", | ||
256 | GNUNET_TESTBED_host_get_id_ (host), | ||
257 | GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); | ||
258 | hr = GNUNET_new (struct HostRegistration); | ||
259 | hr->cb = cb; | ||
260 | hr->cb_cls = cb_cls; | ||
261 | hr->host = host; | ||
262 | call_register = (NULL == slave->hr_dll_head) ? GNUNET_YES : GNUNET_NO; | ||
263 | GNUNET_CONTAINER_DLL_insert_tail (slave->hr_dll_head, | ||
264 | slave->hr_dll_tail, | ||
265 | hr); | ||
266 | if (GNUNET_YES == call_register) | ||
267 | register_next_host (slave); | ||
268 | } | ||
269 | |||
270 | |||
271 | /** | ||
272 | * Callback to relay the reply msg of a forwarded operation back to the client | ||
273 | * | ||
274 | * @param cls ForwardedOperationContext | ||
275 | * @param msg the message to relay | ||
276 | */ | ||
277 | void | ||
278 | GST_forwarded_operation_reply_relay (void *cls, | ||
279 | const struct GNUNET_MessageHeader *msg) | ||
280 | { | ||
281 | struct ForwardedOperationContext *fopc = cls; | ||
282 | struct GNUNET_MQ_Envelope *env; | ||
283 | |||
284 | LOG_DEBUG ("Relaying message with type: %u, size: %u\n", | ||
285 | ntohs (msg->type), | ||
286 | ntohs (msg->size)); | ||
287 | env = GNUNET_MQ_msg_copy (msg); | ||
288 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (fopc->client), | ||
289 | env); | ||
290 | GNUNET_SCHEDULER_cancel (fopc->timeout_task); | ||
291 | GNUNET_CONTAINER_DLL_remove (fopcq_head, | ||
292 | fopcq_tail, | ||
293 | fopc); | ||
294 | GNUNET_free (fopc); | ||
295 | } | ||
296 | |||
297 | |||
298 | /** | ||
299 | * Task to free resources when forwarded operation has been timed out | ||
300 | * | ||
301 | * @param cls the ForwardedOperationContext | ||
302 | */ | ||
303 | void | ||
304 | GST_forwarded_operation_timeout (void *cls) | ||
305 | { | ||
306 | struct ForwardedOperationContext *fopc = cls; | ||
307 | |||
308 | fopc->timeout_task = NULL; | ||
309 | GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc); | ||
310 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
311 | "A forwarded operation has timed out\n"); | ||
312 | GST_send_operation_fail_msg (fopc->client, | ||
313 | fopc->operation_id, | ||
314 | "A forwarded operation has timed out"); | ||
315 | GNUNET_CONTAINER_DLL_remove (fopcq_head, | ||
316 | fopcq_tail, | ||
317 | fopc); | ||
318 | GNUNET_free (fopc); | ||
319 | } | ||
320 | |||
321 | |||
322 | /** | ||
323 | * Parse service sharing specification line. | ||
324 | * Format is "[<service:share>] [<service:share>] ..." | ||
325 | * | ||
326 | * @param ss_str the spec string to be parsed | ||
327 | * @param cfg the configuration to use for shared services | ||
328 | * @return an array suitable to pass to GNUNET_TESTING_system_create(). NULL | ||
329 | * upon empty service sharing specification. | ||
330 | */ | ||
331 | static struct GNUNET_TESTING_SharedService * | ||
332 | parse_shared_services (char *ss_str, | ||
333 | struct GNUNET_CONFIGURATION_Handle *cfg) | ||
334 | { | ||
335 | struct GNUNET_TESTING_SharedService ss; | ||
336 | struct GNUNET_TESTING_SharedService *slist; | ||
337 | char service[256]; | ||
338 | char *arg; | ||
339 | unsigned int n; | ||
340 | |||
341 | #define GROW_SS \ | ||
342 | do { \ | ||
343 | GNUNET_array_grow (slist, n, n + 1); \ | ||
344 | GNUNET_memcpy (&slist[n - 1], &ss, \ | ||
345 | sizeof(struct GNUNET_TESTING_SharedService)); \ | ||
346 | } while (0) | ||
347 | |||
348 | slist = NULL; | ||
349 | n = 0; | ||
350 | ss.cfg = cfg; | ||
351 | for (; NULL != (arg = strtok (ss_str, " ")); ss_str = NULL) | ||
352 | { | ||
353 | ss.service = NULL; | ||
354 | ss.share = 0; | ||
355 | if (2 != sscanf (arg, "%255[^:]:%u", | ||
356 | service, | ||
357 | &ss.share)) | ||
358 | { | ||
359 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
360 | "Ignoring shared service spec: %s", | ||
361 | arg); | ||
362 | continue; | ||
363 | } | ||
364 | LOG_DEBUG ("Will be sharing %s service among %u peers\n", | ||
365 | service, | ||
366 | ss.share); | ||
367 | ss.service = GNUNET_strdup (service); | ||
368 | GROW_SS; | ||
369 | } | ||
370 | if (NULL != slist) | ||
371 | { | ||
372 | /* Add trailing NULL block */ | ||
373 | (void) memset (&ss, | ||
374 | 0, | ||
375 | sizeof(struct GNUNET_TESTING_SharedService)); | ||
376 | GROW_SS; | ||
377 | } | ||
378 | return slist; | ||
379 | #undef GROW_SS | ||
380 | } | ||
381 | |||
382 | |||
383 | /** | ||
384 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_INIT messages | ||
385 | * | ||
386 | * @param cls identification of the client | ||
387 | * @param message the actual message | ||
388 | * @return #GNUNET_OK if @a message is well-formed | ||
389 | */ | ||
390 | static int | ||
391 | check_init (void *cls, | ||
392 | const struct GNUNET_TESTBED_InitMessage *msg) | ||
393 | { | ||
394 | const char *controller_hostname; | ||
395 | uint16_t msize; | ||
396 | |||
397 | msize = ntohs (msg->header.size) - sizeof(struct GNUNET_TESTBED_InitMessage); | ||
398 | controller_hostname = (const char *) &msg[1]; | ||
399 | if ('\0' != controller_hostname[msize - 1]) | ||
400 | { | ||
401 | GNUNET_break (0); | ||
402 | return GNUNET_SYSERR; | ||
403 | } | ||
404 | return GNUNET_OK; | ||
405 | } | ||
406 | |||
407 | |||
408 | /** | ||
409 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_INIT messages | ||
410 | * | ||
411 | * @param cls identification of the client | ||
412 | * @param message the actual message | ||
413 | */ | ||
414 | static void | ||
415 | handle_init (void *cls, | ||
416 | const struct GNUNET_TESTBED_InitMessage *msg) | ||
417 | { | ||
418 | struct GNUNET_SERVICE_Client *client = cls; | ||
419 | struct GNUNET_TESTBED_Host *host; | ||
420 | const char *controller_hostname; | ||
421 | char *ss_str; | ||
422 | struct GNUNET_TESTING_SharedService *ss; | ||
423 | unsigned int cnt; | ||
424 | |||
425 | if (NULL != GST_context) | ||
426 | { | ||
427 | LOG_DEBUG ("We are being connected to laterally\n"); | ||
428 | GNUNET_SERVICE_client_continue (client); | ||
429 | return; | ||
430 | } | ||
431 | controller_hostname = (const char *) &msg[1]; | ||
432 | ss_str = NULL; | ||
433 | ss = NULL; | ||
434 | if (GNUNET_OK == | ||
435 | GNUNET_CONFIGURATION_get_value_string (GST_config, | ||
436 | "TESTBED", | ||
437 | "SHARED_SERVICES", | ||
438 | &ss_str)) | ||
439 | { | ||
440 | ss = parse_shared_services (ss_str, | ||
441 | GST_config); | ||
442 | GNUNET_free (ss_str); | ||
443 | ss_str = NULL; | ||
444 | } | ||
445 | GST_context = GNUNET_new (struct Context); | ||
446 | GST_context->client = client; | ||
447 | GST_context->host_id = ntohl (msg->host_id); | ||
448 | GST_context->master_ip = GNUNET_strdup (controller_hostname); | ||
449 | LOG_DEBUG ("Our IP: %s\n", | ||
450 | GST_context->master_ip); | ||
451 | GST_context->system | ||
452 | = GNUNET_TESTING_system_create ("testbed", | ||
453 | GST_context->master_ip, | ||
454 | hostname, | ||
455 | ss); | ||
456 | if (NULL != ss) | ||
457 | { | ||
458 | for (cnt = 0; NULL != ss[cnt].service; cnt++) | ||
459 | { | ||
460 | ss_str = (char *) ss[cnt].service; | ||
461 | GNUNET_free (ss_str); | ||
462 | } | ||
463 | GNUNET_free (ss); | ||
464 | ss = NULL; | ||
465 | } | ||
466 | host = | ||
467 | GNUNET_TESTBED_host_create_with_id (GST_context->host_id, | ||
468 | GST_context->master_ip, | ||
469 | NULL, | ||
470 | GST_config, | ||
471 | 0); | ||
472 | host_list_add (host); | ||
473 | LOG_DEBUG ("Created master context with host ID: %u\n", | ||
474 | GST_context->host_id); | ||
475 | GNUNET_SERVICE_client_continue (client); | ||
476 | } | ||
477 | |||
478 | |||
479 | /** | ||
480 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages | ||
481 | * | ||
482 | * @param cls identification of the client | ||
483 | * @param msg the actual message | ||
484 | * @return #GNUNET_OK if @a message is well-formed | ||
485 | */ | ||
486 | static int | ||
487 | check_add_host (void *cls, | ||
488 | const struct GNUNET_TESTBED_AddHostMessage *msg) | ||
489 | { | ||
490 | uint16_t username_length; | ||
491 | uint16_t hostname_length; | ||
492 | uint16_t msize; | ||
493 | |||
494 | msize = ntohs (msg->header.size) - sizeof(struct | ||
495 | GNUNET_TESTBED_AddHostMessage); | ||
496 | username_length = ntohs (msg->username_length); | ||
497 | hostname_length = ntohs (msg->hostname_length); | ||
498 | /* msg must contain hostname */ | ||
499 | if ((msize <= username_length) || | ||
500 | (0 == hostname_length)) | ||
501 | { | ||
502 | GNUNET_break (0); | ||
503 | return GNUNET_SYSERR; | ||
504 | } | ||
505 | /* msg must contain configuration */ | ||
506 | if (msize <= username_length + hostname_length) | ||
507 | { | ||
508 | GNUNET_break (0); | ||
509 | return GNUNET_SYSERR; | ||
510 | } | ||
511 | return GNUNET_OK; | ||
512 | } | ||
513 | |||
514 | |||
515 | /** | ||
516 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages | ||
517 | * | ||
518 | * @param cls identification of the client | ||
519 | * @param msg the actual message | ||
520 | */ | ||
521 | static void | ||
522 | handle_add_host (void *cls, | ||
523 | const struct GNUNET_TESTBED_AddHostMessage *msg) | ||
524 | { | ||
525 | struct GNUNET_SERVICE_Client *client = cls; | ||
526 | struct GNUNET_TESTBED_Host *host; | ||
527 | struct GNUNET_TESTBED_HostConfirmedMessage *reply; | ||
528 | struct GNUNET_CONFIGURATION_Handle *host_cfg; | ||
529 | char *username; | ||
530 | char *hostname; | ||
531 | char *emsg; | ||
532 | const void *ptr; | ||
533 | uint32_t host_id; | ||
534 | uint16_t username_length; | ||
535 | uint16_t hostname_length; | ||
536 | struct GNUNET_MQ_Envelope *env; | ||
537 | |||
538 | username_length = ntohs (msg->username_length); | ||
539 | hostname_length = ntohs (msg->hostname_length); | ||
540 | username = NULL; | ||
541 | hostname = NULL; | ||
542 | ptr = &msg[1]; | ||
543 | if (0 != username_length) | ||
544 | { | ||
545 | username = GNUNET_malloc (username_length + 1); | ||
546 | GNUNET_strlcpy (username, ptr, username_length + 1); | ||
547 | ptr += username_length; | ||
548 | } | ||
549 | hostname = GNUNET_malloc (hostname_length + 1); | ||
550 | GNUNET_strlcpy (hostname, ptr, hostname_length + 1); | ||
551 | if (NULL == (host_cfg = GNUNET_TESTBED_extract_config_ (&msg->header))) | ||
552 | { | ||
553 | GNUNET_free (username); | ||
554 | GNUNET_free (hostname); | ||
555 | GNUNET_break_op (0); | ||
556 | GNUNET_SERVICE_client_drop (client); | ||
557 | return; | ||
558 | } | ||
559 | host_id = ntohl (msg->host_id); | ||
560 | LOG_DEBUG ("Received ADDHOST %u message\n", host_id); | ||
561 | LOG_DEBUG ("-------host id: %u\n", host_id); | ||
562 | LOG_DEBUG ("-------hostname: %s\n", hostname); | ||
563 | if (NULL != username) | ||
564 | LOG_DEBUG ("-------username: %s\n", username); | ||
565 | else | ||
566 | LOG_DEBUG ("-------username: <not given>\n"); | ||
567 | LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port)); | ||
568 | host = GNUNET_TESTBED_host_create_with_id (host_id, | ||
569 | hostname, | ||
570 | username, | ||
571 | host_cfg, | ||
572 | ntohs (msg->ssh_port)); | ||
573 | GNUNET_free (username); | ||
574 | GNUNET_free (hostname); | ||
575 | GNUNET_CONFIGURATION_destroy (host_cfg); | ||
576 | if (NULL == host) | ||
577 | { | ||
578 | GNUNET_break_op (0); | ||
579 | GNUNET_SERVICE_client_drop (client); | ||
580 | return; | ||
581 | } | ||
582 | if (GNUNET_OK != host_list_add (host)) | ||
583 | { | ||
584 | /* We are unable to add a host */ | ||
585 | emsg = "A host exists with given host-id"; | ||
586 | LOG_DEBUG ("%s: %u", | ||
587 | emsg, | ||
588 | host_id); | ||
589 | GNUNET_TESTBED_host_destroy (host); | ||
590 | env = GNUNET_MQ_msg_extra (reply, | ||
591 | strlen (emsg) + 1, | ||
592 | GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS); | ||
593 | GNUNET_memcpy (&reply[1], | ||
594 | emsg, | ||
595 | strlen (emsg) + 1); | ||
596 | } | ||
597 | else | ||
598 | { | ||
599 | LOG_DEBUG ("Added host %u at %u\n", | ||
600 | host_id, | ||
601 | GST_context->host_id); | ||
602 | env = GNUNET_MQ_msg (reply, | ||
603 | GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS); | ||
604 | } | ||
605 | reply->host_id = htonl (host_id); | ||
606 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
607 | env); | ||
608 | GNUNET_SERVICE_client_continue (client); | ||
609 | } | ||
610 | |||
611 | |||
612 | /** | ||
613 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages | ||
614 | * | ||
615 | * @param cls identification of the client | ||
616 | * @param msg the actual message | ||
617 | */ | ||
618 | static void | ||
619 | handle_slave_get_config (void *cls, | ||
620 | const struct | ||
621 | GNUNET_TESTBED_SlaveGetConfigurationMessage *msg) | ||
622 | { | ||
623 | struct GNUNET_SERVICE_Client *client = cls; | ||
624 | struct Slave *slave; | ||
625 | struct GNUNET_TESTBED_SlaveConfiguration *reply; | ||
626 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
627 | struct GNUNET_MQ_Envelope *env; | ||
628 | char *config; | ||
629 | char *xconfig; | ||
630 | size_t config_size; | ||
631 | size_t xconfig_size; | ||
632 | uint64_t op_id; | ||
633 | uint32_t slave_id; | ||
634 | |||
635 | slave_id = ntohl (msg->slave_id); | ||
636 | op_id = GNUNET_ntohll (msg->operation_id); | ||
637 | if ((GST_slave_list_size <= slave_id) || | ||
638 | (NULL == GST_slave_list[slave_id])) | ||
639 | { | ||
640 | /* FIXME: Add forwardings for this type of message here.. */ | ||
641 | GST_send_operation_fail_msg (client, | ||
642 | op_id, | ||
643 | "Slave not found"); | ||
644 | GNUNET_SERVICE_client_continue (client); | ||
645 | return; | ||
646 | } | ||
647 | slave = GST_slave_list[slave_id]; | ||
648 | GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ ( | ||
649 | GST_host_list[slave->host_id]))); | ||
650 | config = GNUNET_CONFIGURATION_serialize (cfg, | ||
651 | &config_size); | ||
652 | /* FIXME: maybe we want to transmit the delta to the default here? */ | ||
653 | xconfig_size = GNUNET_TESTBED_compress_config_ (config, | ||
654 | config_size, | ||
655 | &xconfig); | ||
656 | GNUNET_free (config); | ||
657 | GNUNET_assert (xconfig_size + sizeof(struct | ||
658 | GNUNET_TESTBED_SlaveConfiguration) <= | ||
659 | UINT16_MAX); | ||
660 | GNUNET_assert (xconfig_size <= UINT16_MAX); | ||
661 | env = GNUNET_MQ_msg_extra (reply, | ||
662 | xconfig_size, | ||
663 | GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION); | ||
664 | reply->slave_id = msg->slave_id; | ||
665 | reply->operation_id = msg->operation_id; | ||
666 | reply->config_size = htons ((uint16_t) config_size); | ||
667 | GNUNET_memcpy (&reply[1], | ||
668 | xconfig, | ||
669 | xconfig_size); | ||
670 | GNUNET_free (xconfig); | ||
671 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
672 | env); | ||
673 | GNUNET_SERVICE_client_continue (client); | ||
674 | } | ||
675 | |||
676 | |||
677 | /** | ||
678 | * Clears the forwarded operations queue | ||
679 | */ | ||
680 | void | ||
681 | GST_clear_fopcq () | ||
682 | { | ||
683 | struct ForwardedOperationContext *fopc; | ||
684 | |||
685 | while (NULL != (fopc = fopcq_head)) | ||
686 | { | ||
687 | GNUNET_CONTAINER_DLL_remove (fopcq_head, | ||
688 | fopcq_tail, | ||
689 | fopc); | ||
690 | GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc); | ||
691 | if (NULL != fopc->timeout_task) | ||
692 | GNUNET_SCHEDULER_cancel (fopc->timeout_task); | ||
693 | switch (fopc->type) | ||
694 | { | ||
695 | case OP_PEER_CREATE: | ||
696 | GNUNET_free (fopc->cls); | ||
697 | break; | ||
698 | |||
699 | case OP_SHUTDOWN_PEERS: | ||
700 | { | ||
701 | struct HandlerContext_ShutdownPeers *hc = fopc->cls; | ||
702 | |||
703 | GNUNET_assert (0 < hc->nslaves); | ||
704 | hc->nslaves--; | ||
705 | if (0 == hc->nslaves) | ||
706 | GNUNET_free (hc); | ||
707 | } | ||
708 | break; | ||
709 | |||
710 | case OP_PEER_START: | ||
711 | case OP_PEER_STOP: | ||
712 | case OP_PEER_DESTROY: | ||
713 | case OP_PEER_INFO: | ||
714 | case OP_OVERLAY_CONNECT: | ||
715 | case OP_LINK_CONTROLLERS: | ||
716 | case OP_GET_SLAVE_CONFIG: | ||
717 | case OP_MANAGE_SERVICE: | ||
718 | case OP_PEER_RECONFIGURE: | ||
719 | break; | ||
720 | |||
721 | case OP_FORWARDED: | ||
722 | GNUNET_assert (0); | ||
723 | } | ||
724 | ; | ||
725 | GNUNET_free (fopc); | ||
726 | } | ||
727 | } | ||
728 | |||
729 | |||
730 | /** | ||
731 | * Task to clean up and shutdown nicely | ||
732 | * | ||
733 | * @param cls NULL | ||
734 | */ | ||
735 | static void | ||
736 | shutdown_task (void *cls) | ||
737 | { | ||
738 | uint32_t id; | ||
739 | |||
740 | LOG_DEBUG ("Shutting down testbed service\n"); | ||
741 | /* cleanup any remaining forwarded operations */ | ||
742 | GST_clear_fopcq (); | ||
743 | GST_free_lcf (); | ||
744 | GST_free_mctxq (); | ||
745 | GST_free_occq (); | ||
746 | GST_free_roccq (); | ||
747 | GST_free_nccq (); | ||
748 | GST_neighbour_list_clean (); | ||
749 | GST_free_prcq (); | ||
750 | /* Clear peer list */ | ||
751 | GST_destroy_peers (); | ||
752 | /* Clear route list */ | ||
753 | GST_route_list_clear (); | ||
754 | /* Clear GST_slave_list */ | ||
755 | GST_slave_list_clear (); | ||
756 | /* Clear host list */ | ||
757 | for (id = 0; id < GST_host_list_size; id++) | ||
758 | if (NULL != GST_host_list[id]) | ||
759 | GNUNET_TESTBED_host_destroy (GST_host_list[id]); | ||
760 | GNUNET_free (GST_host_list); | ||
761 | if (NULL != GST_context) | ||
762 | { | ||
763 | GNUNET_free (GST_context->master_ip); | ||
764 | if (NULL != GST_context->system) | ||
765 | GNUNET_TESTING_system_destroy (GST_context->system, | ||
766 | GNUNET_YES); | ||
767 | GNUNET_free (GST_context); | ||
768 | GST_context = NULL; | ||
769 | } | ||
770 | GNUNET_free (hostname); | ||
771 | /* Free hello cache */ | ||
772 | GST_cache_clear (); | ||
773 | GST_connection_pool_destroy (); | ||
774 | GNUNET_TESTBED_operation_queue_destroy_ (GST_opq_openfds); | ||
775 | GST_opq_openfds = NULL; | ||
776 | GST_stats_destroy (); | ||
777 | GST_barriers_destroy (); | ||
778 | GNUNET_CONFIGURATION_destroy (GST_config); | ||
779 | } | ||
780 | |||
781 | |||
782 | /** | ||
783 | * Callback for client connect | ||
784 | * | ||
785 | * @param cls NULL | ||
786 | * @param client the client which has disconnected | ||
787 | * @param mq queue for sending messages to @a client | ||
788 | * @return @a client | ||
789 | */ | ||
790 | static void * | ||
791 | client_connect_cb (void *cls, | ||
792 | struct GNUNET_SERVICE_Client *client, | ||
793 | struct GNUNET_MQ_Handle *mq) | ||
794 | { | ||
795 | return client; | ||
796 | } | ||
797 | |||
798 | |||
799 | /** | ||
800 | * Callback for client disconnect | ||
801 | * | ||
802 | * @param cls NULL | ||
803 | * @param client the client which has disconnected | ||
804 | * @param app_ctx should match @a client | ||
805 | */ | ||
806 | static void | ||
807 | client_disconnect_cb (void *cls, | ||
808 | struct GNUNET_SERVICE_Client *client, | ||
809 | void *app_ctx) | ||
810 | { | ||
811 | struct ForwardedOperationContext *fopc; | ||
812 | struct ForwardedOperationContext *fopcn; | ||
813 | |||
814 | GNUNET_assert (client == app_ctx); | ||
815 | GST_notify_client_disconnect_oc (client); | ||
816 | GST_link_notify_disconnect (client); | ||
817 | GST_notify_client_disconnect_peers (client); | ||
818 | for (fopc = fopcq_head; NULL != fopc; fopc = fopcn) | ||
819 | { | ||
820 | fopcn = fopc->next; | ||
821 | if (fopc->client == client) | ||
822 | { | ||
823 | /* handle as if it were a timeout */ | ||
824 | GNUNET_SCHEDULER_cancel (fopc->timeout_task); | ||
825 | GST_forwarded_operation_timeout (fopc); | ||
826 | } | ||
827 | } | ||
828 | if (NULL == GST_context) | ||
829 | return; | ||
830 | if (client == GST_context->client) | ||
831 | { | ||
832 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
833 | "Master client disconnected\n"); | ||
834 | GST_context->client = NULL; | ||
835 | /* should not be needed as we're terminated by failure to read | ||
836 | * from stdin, but if stdin fails for some reason, this shouldn't | ||
837 | * hurt for now --- might need to revise this later if we ever | ||
838 | * decide that master connections might be temporarily down | ||
839 | * for some reason */// GNUNET_SCHEDULER_shutdown (); | ||
840 | } | ||
841 | } | ||
842 | |||
843 | |||
844 | /** | ||
845 | * Testbed setup | ||
846 | * | ||
847 | * @param cls closure | ||
848 | * @param cfg configuration to use | ||
849 | * @param service the initialized server | ||
850 | */ | ||
851 | static void | ||
852 | testbed_run (void *cls, | ||
853 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
854 | struct GNUNET_SERVICE_Handle *service) | ||
855 | { | ||
856 | char *logfile; | ||
857 | unsigned long long num; | ||
858 | |||
859 | LOG_DEBUG ("Starting testbed\n"); | ||
860 | if (GNUNET_OK == | ||
861 | GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED", "LOG_FILE", | ||
862 | &logfile)) | ||
863 | { | ||
864 | GNUNET_break (GNUNET_OK == | ||
865 | GNUNET_log_setup ("testbed", | ||
866 | "DEBUG", | ||
867 | logfile)); | ||
868 | GNUNET_free (logfile); | ||
869 | } | ||
870 | GNUNET_assert (GNUNET_OK == | ||
871 | GNUNET_CONFIGURATION_get_value_number (cfg, | ||
872 | "testbed", | ||
873 | "CACHE_SIZE", | ||
874 | &num)); | ||
875 | GST_cache_init ((unsigned int) num); | ||
876 | GST_connection_pool_init ((unsigned int) num); | ||
877 | GNUNET_assert (GNUNET_OK == | ||
878 | GNUNET_CONFIGURATION_get_value_number (cfg, | ||
879 | "testbed", | ||
880 | "MAX_OPEN_FDS", | ||
881 | &num)); | ||
882 | GST_opq_openfds = GNUNET_TESTBED_operation_queue_create_ ( | ||
883 | OPERATION_QUEUE_TYPE_FIXED, | ||
884 | (unsigned int) num); | ||
885 | GNUNET_assert (GNUNET_OK == | ||
886 | GNUNET_CONFIGURATION_get_value_time (cfg, | ||
887 | "testbed", | ||
888 | "OPERATION_TIMEOUT", | ||
889 | &GST_timeout)); | ||
890 | GNUNET_assert (GNUNET_OK == | ||
891 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
892 | "testbed", | ||
893 | "HOSTNAME", | ||
894 | &hostname)); | ||
895 | GST_config = GNUNET_CONFIGURATION_dup (cfg); | ||
896 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | ||
897 | NULL); | ||
898 | LOG_DEBUG ("Testbed startup complete\n"); | ||
899 | GST_stats_init (GST_config); | ||
900 | GST_barriers_init (GST_config); | ||
901 | } | ||
902 | |||
903 | |||
904 | /** | ||
905 | * Define "main" method using service macro. | ||
906 | */ | ||
907 | GNUNET_SERVICE_MAIN | ||
908 | ("testbed", | ||
909 | GNUNET_SERVICE_OPTION_NONE, | ||
910 | &testbed_run, | ||
911 | &client_connect_cb, | ||
912 | &client_disconnect_cb, | ||
913 | NULL, | ||
914 | GNUNET_MQ_hd_var_size (init, | ||
915 | GNUNET_MESSAGE_TYPE_TESTBED_INIT, | ||
916 | struct GNUNET_TESTBED_InitMessage, | ||
917 | NULL), | ||
918 | GNUNET_MQ_hd_var_size (add_host, | ||
919 | GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, | ||
920 | struct GNUNET_TESTBED_AddHostMessage, | ||
921 | NULL), | ||
922 | GNUNET_MQ_hd_fixed_size (slave_get_config, | ||
923 | GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION, | ||
924 | struct GNUNET_TESTBED_SlaveGetConfigurationMessage, | ||
925 | NULL), | ||
926 | GNUNET_MQ_hd_fixed_size (link_controllers, | ||
927 | GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, | ||
928 | struct GNUNET_TESTBED_ControllerLinkRequest, | ||
929 | NULL), | ||
930 | GNUNET_MQ_hd_var_size (remote_overlay_connect, | ||
931 | GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT, | ||
932 | struct GNUNET_TESTBED_RemoteOverlayConnectMessage, | ||
933 | NULL), | ||
934 | GNUNET_MQ_hd_fixed_size (overlay_connect, | ||
935 | GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT, | ||
936 | struct GNUNET_TESTBED_OverlayConnectMessage, | ||
937 | NULL), | ||
938 | GNUNET_MQ_hd_var_size (peer_create, | ||
939 | GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER, | ||
940 | struct GNUNET_TESTBED_PeerCreateMessage, | ||
941 | NULL), | ||
942 | GNUNET_MQ_hd_fixed_size (peer_destroy, | ||
943 | GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER, | ||
944 | struct GNUNET_TESTBED_PeerDestroyMessage, | ||
945 | NULL), | ||
946 | GNUNET_MQ_hd_fixed_size (peer_start, | ||
947 | GNUNET_MESSAGE_TYPE_TESTBED_START_PEER, | ||
948 | struct GNUNET_TESTBED_PeerStartMessage, | ||
949 | NULL), | ||
950 | GNUNET_MQ_hd_fixed_size (peer_stop, | ||
951 | GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER, | ||
952 | struct GNUNET_TESTBED_PeerStopMessage, | ||
953 | NULL), | ||
954 | GNUNET_MQ_hd_fixed_size (peer_get_config, | ||
955 | GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION, | ||
956 | struct GNUNET_TESTBED_PeerGetConfigurationMessage, | ||
957 | NULL), | ||
958 | GNUNET_MQ_hd_var_size (manage_peer_service, | ||
959 | GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE, | ||
960 | struct GNUNET_TESTBED_ManagePeerServiceMessage, | ||
961 | NULL), | ||
962 | GNUNET_MQ_hd_fixed_size (shutdown_peers, | ||
963 | GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS, | ||
964 | struct GNUNET_TESTBED_ShutdownPeersMessage, | ||
965 | NULL), | ||
966 | GNUNET_MQ_hd_var_size (peer_reconfigure, | ||
967 | GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER, | ||
968 | struct GNUNET_TESTBED_PeerReconfigureMessage, | ||
969 | NULL), | ||
970 | GNUNET_MQ_hd_var_size (barrier_init, | ||
971 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT, | ||
972 | struct GNUNET_TESTBED_BarrierInit, | ||
973 | NULL), | ||
974 | GNUNET_MQ_hd_var_size (barrier_cancel, | ||
975 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL, | ||
976 | struct GNUNET_TESTBED_BarrierCancel, | ||
977 | NULL), | ||
978 | GNUNET_MQ_hd_var_size (barrier_status, | ||
979 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, | ||
980 | struct GNUNET_TESTBED_BarrierStatusMsg, | ||
981 | NULL), | ||
982 | GNUNET_MQ_handler_end ()); | ||
983 | |||
984 | |||
985 | /* end of gnunet-service-testbed.c */ | ||
diff --git a/src/testbed/gnunet-service-testbed.h b/src/testbed/gnunet-service-testbed.h deleted file mode 100644 index 1c6aadb59..000000000 --- a/src/testbed/gnunet-service-testbed.h +++ /dev/null | |||
@@ -1,900 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-service-testbed.h | ||
23 | * @brief data structures shared amongst components of TESTBED service | ||
24 | * @author Sree Harsha Totakura | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | #include "gnunet_transport_service.h" | ||
31 | #include "gnunet_core_service.h" | ||
32 | |||
33 | #include "testbed.h" | ||
34 | #include "testbed_api.h" | ||
35 | #include "testbed_api_operations.h" | ||
36 | #include "testbed_api_hosts.h" | ||
37 | #include "gnunet_testing_lib.h" | ||
38 | #include "gnunet-service-testbed_links.h" | ||
39 | |||
40 | |||
41 | /** | ||
42 | * Generic logging | ||
43 | */ | ||
44 | #define LOG(kind, ...) \ | ||
45 | GNUNET_log (kind, __VA_ARGS__) | ||
46 | |||
47 | /** | ||
48 | * Debug logging | ||
49 | */ | ||
50 | #define LOG_DEBUG(...) \ | ||
51 | LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) | ||
52 | |||
53 | /** | ||
54 | * By how much should the arrays lists grow | ||
55 | */ | ||
56 | #define LIST_GROW_STEP 10 | ||
57 | |||
58 | |||
59 | /** | ||
60 | * A routing entry | ||
61 | */ | ||
62 | struct Route | ||
63 | { | ||
64 | /** | ||
65 | * destination host | ||
66 | */ | ||
67 | uint32_t dest; | ||
68 | |||
69 | /** | ||
70 | * The destination host is reachable thru | ||
71 | */ | ||
72 | uint32_t thru; | ||
73 | }; | ||
74 | |||
75 | |||
76 | /** | ||
77 | * Context information for operations forwarded to subcontrollers | ||
78 | */ | ||
79 | struct ForwardedOperationContext | ||
80 | { | ||
81 | /** | ||
82 | * The next pointer for DLL | ||
83 | */ | ||
84 | struct ForwardedOperationContext *next; | ||
85 | |||
86 | /** | ||
87 | * The prev pointer for DLL | ||
88 | */ | ||
89 | struct ForwardedOperationContext *prev; | ||
90 | |||
91 | /** | ||
92 | * The generated operation context | ||
93 | */ | ||
94 | struct OperationContext *opc; | ||
95 | |||
96 | /** | ||
97 | * The client to which we have to reply | ||
98 | */ | ||
99 | struct GNUNET_SERVICE_Client *client; | ||
100 | |||
101 | /** | ||
102 | * Closure pointer | ||
103 | */ | ||
104 | void *cls; | ||
105 | |||
106 | /** | ||
107 | * Task ID for the timeout task | ||
108 | */ | ||
109 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
110 | |||
111 | /** | ||
112 | * The id of the operation that has been forwarded | ||
113 | */ | ||
114 | uint64_t operation_id; | ||
115 | |||
116 | /** | ||
117 | * The type of the operation which is forwarded | ||
118 | */ | ||
119 | enum OperationType type; | ||
120 | }; | ||
121 | |||
122 | |||
123 | /** | ||
124 | * A DLL of host registrations to be made | ||
125 | */ | ||
126 | struct HostRegistration | ||
127 | { | ||
128 | /** | ||
129 | * next registration in the DLL | ||
130 | */ | ||
131 | struct HostRegistration *next; | ||
132 | |||
133 | /** | ||
134 | * previous registration in the DLL | ||
135 | */ | ||
136 | struct HostRegistration *prev; | ||
137 | |||
138 | /** | ||
139 | * The callback to call after this registration's status is available | ||
140 | */ | ||
141 | GNUNET_TESTBED_HostRegistrationCompletion cb; | ||
142 | |||
143 | /** | ||
144 | * The closure for the above callback | ||
145 | */ | ||
146 | void *cb_cls; | ||
147 | |||
148 | /** | ||
149 | * The host that has to be registered | ||
150 | */ | ||
151 | struct GNUNET_TESTBED_Host *host; | ||
152 | }; | ||
153 | |||
154 | |||
155 | /** | ||
156 | * Context information used while linking controllers | ||
157 | */ | ||
158 | struct LinkControllersContext | ||
159 | { | ||
160 | /** | ||
161 | * The client which initiated the link controller operation | ||
162 | */ | ||
163 | struct GNUNET_SERVICE_Client *client; | ||
164 | |||
165 | /** | ||
166 | * The ID of the operation | ||
167 | */ | ||
168 | uint64_t operation_id; | ||
169 | }; | ||
170 | |||
171 | |||
172 | /** | ||
173 | * A peer | ||
174 | */ | ||
175 | struct Peer | ||
176 | { | ||
177 | union | ||
178 | { | ||
179 | struct | ||
180 | { | ||
181 | /** | ||
182 | * The peer handle from testing API | ||
183 | */ | ||
184 | struct GNUNET_TESTING_Peer *peer; | ||
185 | |||
186 | /** | ||
187 | * The modified (by GNUNET_TESTING_peer_configure) configuration this | ||
188 | * peer is configured with | ||
189 | */ | ||
190 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
191 | |||
192 | /** | ||
193 | * Is the peer running | ||
194 | */ | ||
195 | int is_running; | ||
196 | } local; | ||
197 | |||
198 | struct | ||
199 | { | ||
200 | /** | ||
201 | * The slave this peer is started through | ||
202 | */ | ||
203 | struct Slave *slave; | ||
204 | |||
205 | /** | ||
206 | * The id of the remote host this peer is running on | ||
207 | */ | ||
208 | uint32_t remote_host_id; | ||
209 | } remote; | ||
210 | } details; | ||
211 | |||
212 | /** | ||
213 | * Is this peer locally created? | ||
214 | */ | ||
215 | int is_remote; | ||
216 | |||
217 | /** | ||
218 | * Our local reference id for this peer | ||
219 | */ | ||
220 | uint32_t id; | ||
221 | |||
222 | /** | ||
223 | * References to peers are using in forwarded overlay contexts and remote | ||
224 | * overlay connect contexts. A peer can only be destroyed after all such | ||
225 | * contexts are destroyed. For this, we maintain a reference counter. When we | ||
226 | * use a peer in any such context, we increment this counter. We decrement it | ||
227 | * when we are destroying these contexts | ||
228 | */ | ||
229 | uint32_t reference_cnt; | ||
230 | |||
231 | /** | ||
232 | * While destroying a peer, due to the fact that there could be references to | ||
233 | * this peer, we delay the peer destroy to a further time. We do this by using | ||
234 | * this flag to destroy the peer while destroying a context in which this peer | ||
235 | * has been used. When the flag is set to 1 and reference_cnt = 0 we destroy | ||
236 | * the peer | ||
237 | */ | ||
238 | uint32_t destroy_flag; | ||
239 | }; | ||
240 | |||
241 | |||
242 | /** | ||
243 | * The main context information associated with the client which started us | ||
244 | */ | ||
245 | struct Context | ||
246 | { | ||
247 | /** | ||
248 | * The client handle associated with this context | ||
249 | */ | ||
250 | struct GNUNET_SERVICE_Client *client; | ||
251 | |||
252 | /** | ||
253 | * The network address of the master controller | ||
254 | */ | ||
255 | char *master_ip; | ||
256 | |||
257 | /** | ||
258 | * The TESTING system handle for starting peers locally | ||
259 | */ | ||
260 | struct GNUNET_TESTING_System *system; | ||
261 | |||
262 | /** | ||
263 | * Our host id according to this context | ||
264 | */ | ||
265 | uint32_t host_id; | ||
266 | }; | ||
267 | |||
268 | |||
269 | /** | ||
270 | * The structure for identifying a shared service | ||
271 | */ | ||
272 | struct SharedService | ||
273 | { | ||
274 | /** | ||
275 | * The name of the shared service | ||
276 | */ | ||
277 | char *name; | ||
278 | |||
279 | /** | ||
280 | * Number of shared peers per instance of the shared service | ||
281 | */ | ||
282 | uint32_t num_shared; | ||
283 | |||
284 | /** | ||
285 | * Number of peers currently sharing the service | ||
286 | */ | ||
287 | uint32_t num_sharing; | ||
288 | }; | ||
289 | |||
290 | |||
291 | struct RegisteredHostContext; | ||
292 | |||
293 | |||
294 | /** | ||
295 | * Context information to used during operations which forward the overlay | ||
296 | * connect message | ||
297 | */ | ||
298 | struct ForwardedOverlayConnectContext | ||
299 | { | ||
300 | /** | ||
301 | * next ForwardedOverlayConnectContext in the DLL | ||
302 | */ | ||
303 | struct ForwardedOverlayConnectContext *next; | ||
304 | |||
305 | /** | ||
306 | * previous ForwardedOverlayConnectContext in the DLL | ||
307 | */ | ||
308 | struct ForwardedOverlayConnectContext *prev; | ||
309 | |||
310 | /** | ||
311 | * Which host does this FOCC belong to? | ||
312 | */ | ||
313 | struct RegisteredHostContext *rhc; | ||
314 | |||
315 | /** | ||
316 | * A copy of the original overlay connect message | ||
317 | */ | ||
318 | struct GNUNET_MessageHeader *orig_msg; | ||
319 | |||
320 | /** | ||
321 | * The client handle | ||
322 | */ | ||
323 | struct GNUNET_SERVICE_Client *client; | ||
324 | |||
325 | /** | ||
326 | * The id of the operation which created this context information | ||
327 | */ | ||
328 | uint64_t operation_id; | ||
329 | |||
330 | /** | ||
331 | * the id of peer 1 | ||
332 | */ | ||
333 | uint32_t peer1; | ||
334 | |||
335 | /** | ||
336 | * The id of peer 2 | ||
337 | */ | ||
338 | uint32_t peer2; | ||
339 | |||
340 | /** | ||
341 | * Id of the host where peer2 is running | ||
342 | */ | ||
343 | uint32_t peer2_host_id; | ||
344 | }; | ||
345 | |||
346 | |||
347 | /** | ||
348 | * This context information will be created for each host that is registered at | ||
349 | * slave controllers during overlay connects. | ||
350 | */ | ||
351 | struct RegisteredHostContext | ||
352 | { | ||
353 | /** | ||
354 | * The host which is being registered | ||
355 | */ | ||
356 | struct GNUNET_TESTBED_Host *reg_host; | ||
357 | |||
358 | /** | ||
359 | * The host of the controller which has to connect to the above rhost | ||
360 | */ | ||
361 | struct GNUNET_TESTBED_Host *host; | ||
362 | |||
363 | /** | ||
364 | * Head of the ForwardedOverlayConnectContext DLL | ||
365 | */ | ||
366 | struct ForwardedOverlayConnectContext *focc_dll_head; | ||
367 | |||
368 | /** | ||
369 | * Tail of the ForwardedOverlayConnectContext DLL | ||
370 | */ | ||
371 | struct ForwardedOverlayConnectContext *focc_dll_tail; | ||
372 | |||
373 | /** | ||
374 | * Enumeration of states for this context | ||
375 | */ | ||
376 | enum RHCState | ||
377 | { | ||
378 | /** | ||
379 | * The initial state | ||
380 | */ | ||
381 | RHC_INIT = 0, | ||
382 | |||
383 | /** | ||
384 | * State where we attempt to do the overlay connection again | ||
385 | */ | ||
386 | RHC_DONE | ||
387 | } state; | ||
388 | }; | ||
389 | |||
390 | |||
391 | /** | ||
392 | * Context data for #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS handler | ||
393 | */ | ||
394 | struct HandlerContext_ShutdownPeers | ||
395 | { | ||
396 | /** | ||
397 | * The number of slave we expect to hear from since we forwarded the | ||
398 | * #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS message to them | ||
399 | */ | ||
400 | unsigned int nslaves; | ||
401 | |||
402 | /** | ||
403 | * Did we observe a timeout with respect to this operation at any of the | ||
404 | * slaves | ||
405 | */ | ||
406 | int timeout; | ||
407 | }; | ||
408 | |||
409 | |||
410 | /** | ||
411 | * Our configuration | ||
412 | */ | ||
413 | extern struct GNUNET_CONFIGURATION_Handle *GST_config; | ||
414 | |||
415 | /** | ||
416 | * The master context; generated with the first INIT message | ||
417 | */ | ||
418 | extern struct Context *GST_context; | ||
419 | |||
420 | /** | ||
421 | * DLL head for forwarded operation contexts | ||
422 | */ | ||
423 | extern struct ForwardedOperationContext *fopcq_head; | ||
424 | |||
425 | /** | ||
426 | * DLL tail for forwarded operation contexts | ||
427 | */ | ||
428 | extern struct ForwardedOperationContext *fopcq_tail; | ||
429 | |||
430 | /** | ||
431 | * A list of peers we know about | ||
432 | */ | ||
433 | extern struct Peer **GST_peer_list; | ||
434 | |||
435 | /** | ||
436 | * Array of hosts | ||
437 | */ | ||
438 | extern struct GNUNET_TESTBED_Host **GST_host_list; | ||
439 | |||
440 | /** | ||
441 | * Operation queue for open file descriptors | ||
442 | */ | ||
443 | extern struct OperationQueue *GST_opq_openfds; | ||
444 | |||
445 | /** | ||
446 | * Timeout for operations which may take some time | ||
447 | */ | ||
448 | extern struct GNUNET_TIME_Relative GST_timeout; | ||
449 | |||
450 | /** | ||
451 | * The size of the peer list | ||
452 | */ | ||
453 | extern unsigned int GST_peer_list_size; | ||
454 | |||
455 | /** | ||
456 | * The current number of peers running locally under this controller | ||
457 | */ | ||
458 | extern unsigned int GST_num_local_peers; | ||
459 | |||
460 | /** | ||
461 | * The size of the host list | ||
462 | */ | ||
463 | extern unsigned int GST_host_list_size; | ||
464 | |||
465 | /** | ||
466 | * The directory where to store load statistics data | ||
467 | */ | ||
468 | extern char *GST_stats_dir; | ||
469 | |||
470 | /** | ||
471 | * Condition to check if host id is valid | ||
472 | */ | ||
473 | #define VALID_HOST_ID(id) \ | ||
474 | (((id) < GST_host_list_size) && (NULL != GST_host_list[id])) | ||
475 | |||
476 | /** | ||
477 | * Condition to check if peer id is valid | ||
478 | */ | ||
479 | #define VALID_PEER_ID(id) \ | ||
480 | (((id) < GST_peer_list_size) && (NULL != GST_peer_list[id])) | ||
481 | |||
482 | |||
483 | /** | ||
484 | * Similar to GNUNET_array_grow(); however instead of calling GNUNET_array_grow() | ||
485 | * several times we call it only once. The array is also made to grow in steps | ||
486 | * of LIST_GROW_STEP. | ||
487 | * | ||
488 | * @param ptr the array pointer to grow | ||
489 | * @param size the size of array | ||
490 | * @param accommodate_size the size which the array has to accommdate; after | ||
491 | * this call the array will be big enough to accommdate sizes up to | ||
492 | * accommodate_size | ||
493 | */ | ||
494 | #define GST_array_grow_large_enough(ptr, size, accommodate_size) \ | ||
495 | do \ | ||
496 | { \ | ||
497 | unsigned int growth_size; \ | ||
498 | GNUNET_assert (size <= accommodate_size); \ | ||
499 | growth_size = size; \ | ||
500 | while (growth_size <= accommodate_size) \ | ||
501 | growth_size += LIST_GROW_STEP; \ | ||
502 | GNUNET_array_grow (ptr, size, growth_size); \ | ||
503 | GNUNET_assert (size > accommodate_size); \ | ||
504 | } while (0) | ||
505 | |||
506 | |||
507 | /** | ||
508 | * Function to destroy a peer | ||
509 | * | ||
510 | * @param peer the peer structure to destroy | ||
511 | */ | ||
512 | void | ||
513 | GST_destroy_peer (struct Peer *peer); | ||
514 | |||
515 | |||
516 | /** | ||
517 | * Stops and destroys all peers | ||
518 | */ | ||
519 | void | ||
520 | GST_destroy_peers (void); | ||
521 | |||
522 | |||
523 | /** | ||
524 | * Finds the route with directly connected host as destination through which | ||
525 | * the destination host can be reached | ||
526 | * | ||
527 | * @param host_id the id of the destination host | ||
528 | * @return the route with directly connected destination host; NULL if no route | ||
529 | * is found | ||
530 | */ | ||
531 | struct Route * | ||
532 | GST_find_dest_route (uint32_t host_id); | ||
533 | |||
534 | |||
535 | /** | ||
536 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages | ||
537 | * | ||
538 | * @param cls identification of the client | ||
539 | * @param msg the actual message | ||
540 | */ | ||
541 | void | ||
542 | handle_overlay_connect (void *cls, | ||
543 | const struct GNUNET_TESTBED_OverlayConnectMessage *msg); | ||
544 | |||
545 | |||
546 | /** | ||
547 | * Adds a host registration's request to a slave's registration queue | ||
548 | * | ||
549 | * @param slave the slave controller at which the given host has to be | ||
550 | * registered | ||
551 | * @param cb the host registration completion callback | ||
552 | * @param cb_cls the closure for the host registration completion callback | ||
553 | * @param host the host which has to be registered | ||
554 | */ | ||
555 | void | ||
556 | GST_queue_host_registration (struct Slave *slave, | ||
557 | GNUNET_TESTBED_HostRegistrationCompletion cb, | ||
558 | void *cb_cls, struct GNUNET_TESTBED_Host *host); | ||
559 | |||
560 | |||
561 | /** | ||
562 | * Callback to relay the reply msg of a forwarded operation back to the client | ||
563 | * | ||
564 | * @param cls ForwardedOperationContext | ||
565 | * @param msg the message to relay | ||
566 | */ | ||
567 | void | ||
568 | GST_forwarded_operation_reply_relay (void *cls, | ||
569 | const struct GNUNET_MessageHeader *msg); | ||
570 | |||
571 | |||
572 | /** | ||
573 | * Task to free resources when forwarded operation has been timedout | ||
574 | * | ||
575 | * @param cls the ForwardedOperationContext | ||
576 | * @param tc the task context from scheduler | ||
577 | */ | ||
578 | void | ||
579 | GST_forwarded_operation_timeout (void *cls); | ||
580 | |||
581 | |||
582 | /** | ||
583 | * Clears the forwarded operations queue | ||
584 | */ | ||
585 | void | ||
586 | GST_clear_fopcq (void); | ||
587 | |||
588 | |||
589 | /** | ||
590 | * Send operation failure message to client | ||
591 | * | ||
592 | * @param client the client to which the failure message has to be sent to | ||
593 | * @param operation_id the id of the failed operation | ||
594 | * @param emsg the error message; can be NULL | ||
595 | */ | ||
596 | void | ||
597 | GST_send_operation_fail_msg (struct GNUNET_SERVICE_Client *client, | ||
598 | uint64_t operation_id, | ||
599 | const char *emsg); | ||
600 | |||
601 | |||
602 | /** | ||
603 | * Notify OC subsystem that @a client disconnected. | ||
604 | * | ||
605 | * @param client the client that disconnected | ||
606 | */ | ||
607 | void | ||
608 | GST_notify_client_disconnect_oc (struct GNUNET_SERVICE_Client *client); | ||
609 | |||
610 | |||
611 | /** | ||
612 | * Notify peers subsystem that @a client disconnected. | ||
613 | * | ||
614 | * @param client the client that disconnected | ||
615 | */ | ||
616 | void | ||
617 | GST_notify_client_disconnect_peers (struct GNUNET_SERVICE_Client *client); | ||
618 | |||
619 | |||
620 | /** | ||
621 | * Function to send generic operation success message to given client | ||
622 | * | ||
623 | * @param client the client to send the message to | ||
624 | * @param operation_id the id of the operation which was successful | ||
625 | */ | ||
626 | void | ||
627 | GST_send_operation_success_msg (struct GNUNET_SERVICE_Client *client, | ||
628 | uint64_t operation_id); | ||
629 | |||
630 | |||
631 | /** | ||
632 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages | ||
633 | * | ||
634 | * @param cls identification of the client | ||
635 | * @param msg the actual message | ||
636 | * @return #GNUNET_OK if @a msg is well-formed | ||
637 | */ | ||
638 | int | ||
639 | check_remote_overlay_connect (void *cls, | ||
640 | const struct | ||
641 | GNUNET_TESTBED_RemoteOverlayConnectMessage *msg); | ||
642 | |||
643 | |||
644 | /** | ||
645 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages | ||
646 | * | ||
647 | * @param cls identification of the client | ||
648 | * @param msg the actual message | ||
649 | */ | ||
650 | void | ||
651 | handle_remote_overlay_connect (void *cls, | ||
652 | const struct | ||
653 | GNUNET_TESTBED_RemoteOverlayConnectMessage *msg); | ||
654 | |||
655 | |||
656 | /** | ||
657 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages | ||
658 | * | ||
659 | * @param cls identification of the client | ||
660 | * @param msg the actual message | ||
661 | * @return #GNUNET_OK if @a msg is well-formed | ||
662 | */ | ||
663 | int | ||
664 | check_peer_create (void *cls, | ||
665 | const struct GNUNET_TESTBED_PeerCreateMessage *msg); | ||
666 | |||
667 | |||
668 | /** | ||
669 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages | ||
670 | * | ||
671 | * @param cls identification of the client | ||
672 | * @param message the actual message | ||
673 | */ | ||
674 | void | ||
675 | handle_peer_create (void *cls, | ||
676 | const struct GNUNET_TESTBED_PeerCreateMessage *msg); | ||
677 | |||
678 | |||
679 | /** | ||
680 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages | ||
681 | * | ||
682 | * @param cls identification of the client | ||
683 | * @param msg the actual message | ||
684 | */ | ||
685 | void | ||
686 | handle_peer_destroy (void *cls, | ||
687 | const struct GNUNET_TESTBED_PeerDestroyMessage *msg); | ||
688 | |||
689 | |||
690 | /** | ||
691 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages | ||
692 | * | ||
693 | * @param cls identification of the client | ||
694 | * @param msg the actual message | ||
695 | */ | ||
696 | void | ||
697 | handle_peer_start (void *cls, | ||
698 | const struct GNUNET_TESTBED_PeerStartMessage *msg); | ||
699 | |||
700 | |||
701 | /** | ||
702 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages | ||
703 | * | ||
704 | * @param cls identification of the client | ||
705 | * @param message the actual message | ||
706 | */ | ||
707 | void | ||
708 | handle_peer_stop (void *cls, | ||
709 | const struct GNUNET_TESTBED_PeerStopMessage *msg); | ||
710 | |||
711 | |||
712 | /** | ||
713 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages | ||
714 | * | ||
715 | * @param cls identification of the client | ||
716 | * @param msg the actual message | ||
717 | */ | ||
718 | void | ||
719 | handle_peer_get_config (void *cls, | ||
720 | const struct | ||
721 | GNUNET_TESTBED_PeerGetConfigurationMessage *msg); | ||
722 | |||
723 | |||
724 | /** | ||
725 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages | ||
726 | * | ||
727 | * @param cls identification of the client | ||
728 | * @param msg the actual message | ||
729 | */ | ||
730 | void | ||
731 | handle_shutdown_peers (void *cls, | ||
732 | const struct GNUNET_TESTBED_ShutdownPeersMessage *msg); | ||
733 | |||
734 | |||
735 | /** | ||
736 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE message | ||
737 | * | ||
738 | * @param cls identification of client | ||
739 | * @param msg the actual message | ||
740 | * @return #GNUNET_OK if @a msg is well-formed | ||
741 | */ | ||
742 | int | ||
743 | check_manage_peer_service (void *cls, | ||
744 | const struct | ||
745 | GNUNET_TESTBED_ManagePeerServiceMessage *msg); | ||
746 | |||
747 | |||
748 | /** | ||
749 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE message | ||
750 | * | ||
751 | * @param cls identification of client | ||
752 | * @param msg the actual message | ||
753 | */ | ||
754 | void | ||
755 | handle_manage_peer_service (void *cls, | ||
756 | const struct | ||
757 | GNUNET_TESTBED_ManagePeerServiceMessage *msg); | ||
758 | |||
759 | |||
760 | /** | ||
761 | * Check #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. | ||
762 | * | ||
763 | * @param cls identification of the client | ||
764 | * @param msg the actual message | ||
765 | * @return #GNUNET_OK if @a msg is well-formed | ||
766 | */ | ||
767 | int | ||
768 | check_peer_reconfigure (void *cls, | ||
769 | const struct | ||
770 | GNUNET_TESTBED_PeerReconfigureMessage *msg); | ||
771 | |||
772 | |||
773 | /** | ||
774 | * Handler for #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. | ||
775 | * Should stop the peer asynchronously, destroy it and create it again with the | ||
776 | * new configuration. | ||
777 | * | ||
778 | * @param cls identification of the client | ||
779 | * @param msg the actual message | ||
780 | */ | ||
781 | void | ||
782 | handle_peer_reconfigure (void *cls, | ||
783 | const struct | ||
784 | GNUNET_TESTBED_PeerReconfigureMessage *msg); | ||
785 | |||
786 | |||
787 | /** | ||
788 | * Frees the ManageServiceContext queue | ||
789 | */ | ||
790 | void | ||
791 | GST_free_mctxq (void); | ||
792 | |||
793 | |||
794 | /** | ||
795 | * Cleans up the queue used for forwarding link controllers requests | ||
796 | */ | ||
797 | void | ||
798 | GST_free_lcf (void); | ||
799 | |||
800 | |||
801 | /** | ||
802 | * Cleans up the route list | ||
803 | */ | ||
804 | void | ||
805 | GST_route_list_clear (void); | ||
806 | |||
807 | |||
808 | /** | ||
809 | * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext | ||
810 | * | ||
811 | * @param rhc the RegisteredHostContext | ||
812 | */ | ||
813 | void | ||
814 | GST_process_next_focc (struct RegisteredHostContext *rhc); | ||
815 | |||
816 | |||
817 | /** | ||
818 | * Cleans up ForwardedOverlayConnectContext | ||
819 | * | ||
820 | * @param focc the ForwardedOverlayConnectContext to cleanup | ||
821 | */ | ||
822 | void | ||
823 | GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc); | ||
824 | |||
825 | |||
826 | /** | ||
827 | * Clears all pending overlay connect contexts in queue | ||
828 | */ | ||
829 | void | ||
830 | GST_free_occq (void); | ||
831 | |||
832 | |||
833 | /** | ||
834 | * Clears all pending remote overlay connect contexts in queue | ||
835 | */ | ||
836 | void | ||
837 | GST_free_roccq (void); | ||
838 | |||
839 | |||
840 | /** | ||
841 | * Cleans up the Peer reconfigure context list | ||
842 | */ | ||
843 | void | ||
844 | GST_free_prcq (void); | ||
845 | |||
846 | |||
847 | /** | ||
848 | * Initializes the cache | ||
849 | * | ||
850 | * @param size the size of the cache | ||
851 | */ | ||
852 | void | ||
853 | GST_cache_init (unsigned int size); | ||
854 | |||
855 | |||
856 | /** | ||
857 | * Clear cache | ||
858 | */ | ||
859 | void | ||
860 | GST_cache_clear (void); | ||
861 | |||
862 | |||
863 | /** | ||
864 | * Looks up in the hello cache and returns the HELLO of the given peer | ||
865 | * | ||
866 | * @param peer_id the index of the peer whose HELLO has to be looked up | ||
867 | * @return the HELLO message; NULL if not found | ||
868 | */ | ||
869 | const struct GNUNET_MessageHeader * | ||
870 | GST_cache_lookup_hello (const unsigned int peer_id); | ||
871 | |||
872 | |||
873 | /** | ||
874 | * Caches the HELLO of the given peer. Updates the HELLO if it was already | ||
875 | * cached before | ||
876 | * | ||
877 | * @param peer_id the peer identity of the peer whose HELLO has to be cached | ||
878 | * @param hello the HELLO message | ||
879 | */ | ||
880 | void | ||
881 | GST_cache_add_hello (const unsigned int peer_id, | ||
882 | const struct GNUNET_MessageHeader *hello); | ||
883 | |||
884 | |||
885 | /** | ||
886 | * Initialize logging CPU and IO statisticfs. Checks the configuration for | ||
887 | * "STATS_DIR" and logs to a file in that directory. The file is name is | ||
888 | * generated from the hostname and the process's PID. | ||
889 | */ | ||
890 | void | ||
891 | GST_stats_init (const struct GNUNET_CONFIGURATION_Handle *cfg); | ||
892 | |||
893 | |||
894 | /** | ||
895 | * Shutdown the status calls module. | ||
896 | */ | ||
897 | void | ||
898 | GST_stats_destroy (void); | ||
899 | |||
900 | /* End of gnunet-service-testbed.h */ | ||
diff --git a/src/testbed/gnunet-service-testbed_barriers.c b/src/testbed/gnunet-service-testbed_barriers.c deleted file mode 100644 index be33bd131..000000000 --- a/src/testbed/gnunet-service-testbed_barriers.c +++ /dev/null | |||
@@ -1,926 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-service-testbed_barriers.c | ||
23 | * @brief barrier handling at the testbed controller | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "gnunet-service-testbed.h" | ||
28 | #include "gnunet-service-testbed_barriers.h" | ||
29 | #include "testbed_api.h" | ||
30 | |||
31 | |||
32 | /** | ||
33 | * timeout for outgoing message transmissions in seconds | ||
34 | */ | ||
35 | #define MESSAGE_SEND_TIMEOUT(s) \ | ||
36 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, s) | ||
37 | |||
38 | |||
39 | /** | ||
40 | * Test to see if local peers have reached the required quorum of a barrier | ||
41 | */ | ||
42 | #define LOCAL_QUORUM_REACHED(barrier) \ | ||
43 | ((barrier->quorum * GST_num_local_peers) <= (barrier->nreached * 100)) | ||
44 | |||
45 | |||
46 | #ifdef LOG | ||
47 | #undef LOG | ||
48 | #endif | ||
49 | |||
50 | /** | ||
51 | * Logging shorthand | ||
52 | */ | ||
53 | #define LOG(kind, ...) \ | ||
54 | GNUNET_log_from (kind, "testbed-barriers", __VA_ARGS__) | ||
55 | |||
56 | |||
57 | /** | ||
58 | * Barrier | ||
59 | */ | ||
60 | struct Barrier; | ||
61 | |||
62 | |||
63 | /** | ||
64 | * Context to be associated with each client | ||
65 | */ | ||
66 | struct ClientCtx | ||
67 | { | ||
68 | /** | ||
69 | * The barrier this client is waiting for | ||
70 | */ | ||
71 | struct Barrier *barrier; | ||
72 | |||
73 | /** | ||
74 | * DLL next ptr | ||
75 | */ | ||
76 | struct ClientCtx *next; | ||
77 | |||
78 | /** | ||
79 | * DLL prev ptr | ||
80 | */ | ||
81 | struct ClientCtx *prev; | ||
82 | |||
83 | /** | ||
84 | * The client handle | ||
85 | */ | ||
86 | struct GNUNET_SERVICE_Client *client; | ||
87 | }; | ||
88 | |||
89 | |||
90 | /** | ||
91 | * Wrapper around Barrier handle | ||
92 | */ | ||
93 | struct WBarrier | ||
94 | { | ||
95 | /** | ||
96 | * DLL next pointer | ||
97 | */ | ||
98 | struct WBarrier *next; | ||
99 | |||
100 | /** | ||
101 | * DLL prev pointer | ||
102 | */ | ||
103 | struct WBarrier *prev; | ||
104 | |||
105 | /** | ||
106 | * The local barrier associated with the creation of this wrapper | ||
107 | */ | ||
108 | struct Barrier *barrier; | ||
109 | |||
110 | /** | ||
111 | * Handle to the slave controller where this wrapper creates a barrier | ||
112 | */ | ||
113 | struct GNUNET_TESTBED_Controller *controller; | ||
114 | |||
115 | /** | ||
116 | * The barrier handle from API | ||
117 | */ | ||
118 | struct GNUNET_TESTBED_Barrier *hbarrier; | ||
119 | |||
120 | /** | ||
121 | * Has this barrier been crossed? | ||
122 | */ | ||
123 | uint8_t reached; | ||
124 | }; | ||
125 | |||
126 | |||
127 | /** | ||
128 | * Barrier | ||
129 | */ | ||
130 | struct Barrier | ||
131 | { | ||
132 | /** | ||
133 | * The hashcode of the barrier name | ||
134 | */ | ||
135 | struct GNUNET_HashCode hash; | ||
136 | |||
137 | /** | ||
138 | * The client handle to the master controller | ||
139 | */ | ||
140 | struct GNUNET_SERVICE_Client *mc; | ||
141 | |||
142 | /** | ||
143 | * The name of the barrier | ||
144 | */ | ||
145 | char *name; | ||
146 | |||
147 | /** | ||
148 | * DLL head for the list of clients waiting for this barrier | ||
149 | */ | ||
150 | struct ClientCtx *head; | ||
151 | |||
152 | /** | ||
153 | * DLL tail for the list of clients waiting for this barrier | ||
154 | */ | ||
155 | struct ClientCtx *tail; | ||
156 | |||
157 | /** | ||
158 | * DLL head for the list of barrier handles | ||
159 | */ | ||
160 | struct WBarrier *whead; | ||
161 | |||
162 | /** | ||
163 | * DLL tail for the list of barrier handles | ||
164 | */ | ||
165 | struct WBarrier *wtail; | ||
166 | |||
167 | /** | ||
168 | * Identifier for the timeout task | ||
169 | */ | ||
170 | struct GNUNET_SCHEDULER_Task *tout_task; | ||
171 | |||
172 | /** | ||
173 | * The status of this barrier | ||
174 | */ | ||
175 | enum GNUNET_TESTBED_BarrierStatus status; | ||
176 | |||
177 | /** | ||
178 | * Number of barriers wrapped in the above DLL | ||
179 | */ | ||
180 | unsigned int num_wbarriers; | ||
181 | |||
182 | /** | ||
183 | * Number of wrapped barriers reached so far | ||
184 | */ | ||
185 | unsigned int num_wbarriers_reached; | ||
186 | |||
187 | /** | ||
188 | * Number of wrapped barrier initialised so far | ||
189 | */ | ||
190 | unsigned int num_wbarriers_inited; | ||
191 | |||
192 | /** | ||
193 | * Number of peers which have reached this barrier | ||
194 | */ | ||
195 | unsigned int nreached; | ||
196 | |||
197 | /** | ||
198 | * Number of slaves we have initialised this barrier | ||
199 | */ | ||
200 | unsigned int nslaves; | ||
201 | |||
202 | /** | ||
203 | * Quorum percentage to be reached | ||
204 | */ | ||
205 | uint8_t quorum; | ||
206 | }; | ||
207 | |||
208 | |||
209 | /** | ||
210 | * Hashtable handle for storing initialised barriers | ||
211 | */ | ||
212 | static struct GNUNET_CONTAINER_MultiHashMap *barrier_map; | ||
213 | |||
214 | /** | ||
215 | * Service context | ||
216 | */ | ||
217 | static struct GNUNET_SERVICE_Handle *ctx; | ||
218 | |||
219 | |||
220 | /** | ||
221 | * Function to remove a barrier from the barrier map and cleanup resources | ||
222 | * occupied by a barrier | ||
223 | * | ||
224 | * @param barrier the barrier handle | ||
225 | */ | ||
226 | static void | ||
227 | remove_barrier (struct Barrier *barrier) | ||
228 | { | ||
229 | struct ClientCtx *ctx; | ||
230 | |||
231 | GNUNET_assert (GNUNET_YES == | ||
232 | GNUNET_CONTAINER_multihashmap_remove (barrier_map, | ||
233 | &barrier->hash, | ||
234 | barrier)); | ||
235 | while (NULL != (ctx = barrier->head)) | ||
236 | { | ||
237 | GNUNET_CONTAINER_DLL_remove (barrier->head, | ||
238 | barrier->tail, | ||
239 | ctx); | ||
240 | ctx->barrier = NULL; | ||
241 | } | ||
242 | GNUNET_free (barrier->name); | ||
243 | GNUNET_free (barrier); | ||
244 | } | ||
245 | |||
246 | |||
247 | /** | ||
248 | * Cancels all subcontroller barrier handles | ||
249 | * | ||
250 | * @param barrier the local barrier | ||
251 | */ | ||
252 | static void | ||
253 | cancel_wrappers (struct Barrier *barrier) | ||
254 | { | ||
255 | struct WBarrier *wrapper; | ||
256 | |||
257 | while (NULL != (wrapper = barrier->whead)) | ||
258 | { | ||
259 | GNUNET_TESTBED_barrier_cancel (wrapper->hbarrier); | ||
260 | GNUNET_CONTAINER_DLL_remove (barrier->whead, | ||
261 | barrier->wtail, | ||
262 | wrapper); | ||
263 | GNUNET_free (wrapper); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | |||
268 | /** | ||
269 | * Send a status message about a barrier to the given client | ||
270 | * | ||
271 | * @param client the client to send the message to | ||
272 | * @param name the barrier name | ||
273 | * @param status the status of the barrier | ||
274 | * @param emsg the error message; should be non-NULL for | ||
275 | * status=GNUNET_TESTBED_BARRIERSTATUS_ERROR | ||
276 | */ | ||
277 | static void | ||
278 | send_client_status_msg (struct GNUNET_SERVICE_Client *client, | ||
279 | const char *name, | ||
280 | enum GNUNET_TESTBED_BarrierStatus status, | ||
281 | const char *emsg) | ||
282 | { | ||
283 | struct GNUNET_MQ_Envelope *env; | ||
284 | struct GNUNET_TESTBED_BarrierStatusMsg *msg; | ||
285 | size_t name_len; | ||
286 | size_t err_len; | ||
287 | |||
288 | GNUNET_assert ((NULL == emsg) || | ||
289 | (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status)); | ||
290 | name_len = strlen (name) + 1; | ||
291 | err_len = ((NULL == emsg) ? 0 : (strlen (emsg) + 1)); | ||
292 | env = GNUNET_MQ_msg_extra (msg, | ||
293 | name_len + err_len, | ||
294 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS); | ||
295 | msg->status = htons (status); | ||
296 | msg->name_len = htons ((uint16_t) name_len - 1); | ||
297 | GNUNET_memcpy (msg->data, | ||
298 | name, | ||
299 | name_len); | ||
300 | GNUNET_memcpy (msg->data + name_len, | ||
301 | emsg, | ||
302 | err_len); | ||
303 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
304 | env); | ||
305 | } | ||
306 | |||
307 | |||
308 | /** | ||
309 | * Sends a barrier failed message | ||
310 | * | ||
311 | * @param barrier the corresponding barrier | ||
312 | * @param emsg the error message; should be non-NULL for | ||
313 | * status=GNUNET_TESTBED_BARRIERSTATUS_ERROR | ||
314 | */ | ||
315 | static void | ||
316 | send_barrier_status_msg (struct Barrier *barrier, | ||
317 | const char *emsg) | ||
318 | { | ||
319 | GNUNET_assert (0 != barrier->status); | ||
320 | send_client_status_msg (barrier->mc, | ||
321 | barrier->name, | ||
322 | barrier->status, | ||
323 | emsg); | ||
324 | } | ||
325 | |||
326 | |||
327 | /** | ||
328 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT messages. | ||
329 | * | ||
330 | * @param cls identification of the client | ||
331 | * @param message the actual message | ||
332 | */ | ||
333 | static int | ||
334 | check_barrier_wait (void *cls, | ||
335 | const struct GNUNET_TESTBED_BarrierWait *msg) | ||
336 | { | ||
337 | return GNUNET_OK; /* always well-formed */ | ||
338 | } | ||
339 | |||
340 | |||
341 | /** | ||
342 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT messages. This | ||
343 | * message should come from peers or a shared helper service using the | ||
344 | * testbed-barrier client API (@see gnunet_testbed_barrier_service.h) | ||
345 | * | ||
346 | * This handler is queued in the main service and will handle the messages sent | ||
347 | * either from the testbed driver or from a high level controller | ||
348 | * | ||
349 | * @param cls identification of the client | ||
350 | * @param message the actual message | ||
351 | */ | ||
352 | static void | ||
353 | handle_barrier_wait (void *cls, | ||
354 | const struct GNUNET_TESTBED_BarrierWait *msg) | ||
355 | { | ||
356 | struct ClientCtx *client_ctx = cls; | ||
357 | struct Barrier *barrier; | ||
358 | char *name; | ||
359 | struct GNUNET_HashCode key; | ||
360 | size_t name_len; | ||
361 | uint16_t msize; | ||
362 | |||
363 | msize = ntohs (msg->header.size); | ||
364 | if (NULL == barrier_map) | ||
365 | { | ||
366 | GNUNET_break (0); | ||
367 | GNUNET_SERVICE_client_drop (client_ctx->client); | ||
368 | return; | ||
369 | } | ||
370 | name_len = msize - sizeof(struct GNUNET_TESTBED_BarrierWait); | ||
371 | name = GNUNET_malloc (name_len + 1); | ||
372 | name[name_len] = '\0'; | ||
373 | GNUNET_memcpy (name, | ||
374 | msg->name, | ||
375 | name_len); | ||
376 | LOG_DEBUG ("Received BARRIER_WAIT for barrier `%s'\n", | ||
377 | name); | ||
378 | GNUNET_CRYPTO_hash (name, | ||
379 | name_len, | ||
380 | &key); | ||
381 | GNUNET_free (name); | ||
382 | if (NULL == (barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, &key))) | ||
383 | { | ||
384 | GNUNET_break (0); | ||
385 | GNUNET_SERVICE_client_drop (client_ctx->client); | ||
386 | return; | ||
387 | } | ||
388 | if (NULL != client_ctx->barrier) | ||
389 | { | ||
390 | GNUNET_break (0); | ||
391 | GNUNET_SERVICE_client_drop (client_ctx->client); | ||
392 | return; | ||
393 | } | ||
394 | client_ctx->barrier = barrier; | ||
395 | GNUNET_CONTAINER_DLL_insert_tail (barrier->head, | ||
396 | barrier->tail, | ||
397 | client_ctx); | ||
398 | barrier->nreached++; | ||
399 | if ((barrier->num_wbarriers_reached == barrier->num_wbarriers) && | ||
400 | (LOCAL_QUORUM_REACHED (barrier))) | ||
401 | { | ||
402 | barrier->status = GNUNET_TESTBED_BARRIERSTATUS_CROSSED; | ||
403 | send_barrier_status_msg (barrier, | ||
404 | NULL); | ||
405 | } | ||
406 | GNUNET_SERVICE_client_continue (client_ctx->client); | ||
407 | } | ||
408 | |||
409 | |||
410 | /** | ||
411 | * Function called when a client connects to the testbed-barrier service. | ||
412 | * | ||
413 | * @param cls NULL | ||
414 | * @param client the connecting client | ||
415 | * @param mq queue to talk to @a client | ||
416 | * @return our `struct ClientCtx` | ||
417 | */ | ||
418 | static void * | ||
419 | connect_cb (void *cls, | ||
420 | struct GNUNET_SERVICE_Client *client, | ||
421 | struct GNUNET_MQ_Handle *mq) | ||
422 | { | ||
423 | struct ClientCtx *client_ctx; | ||
424 | |||
425 | LOG_DEBUG ("Client connected to testbed-barrier service\n"); | ||
426 | client_ctx = GNUNET_new (struct ClientCtx); | ||
427 | client_ctx->client = client; | ||
428 | return client_ctx; | ||
429 | } | ||
430 | |||
431 | |||
432 | /** | ||
433 | * Functions with this signature are called whenever a client | ||
434 | * is disconnected on the network level. | ||
435 | * | ||
436 | * @param cls closure | ||
437 | * @param client identification of the client; NULL | ||
438 | * for the last call when the server is destroyed | ||
439 | */ | ||
440 | static void | ||
441 | disconnect_cb (void *cls, | ||
442 | struct GNUNET_SERVICE_Client *client, | ||
443 | void *app_ctx) | ||
444 | { | ||
445 | struct ClientCtx *client_ctx = app_ctx; | ||
446 | struct Barrier *barrier = client_ctx->barrier; | ||
447 | |||
448 | if (NULL != barrier) | ||
449 | { | ||
450 | GNUNET_CONTAINER_DLL_remove (barrier->head, | ||
451 | barrier->tail, | ||
452 | client_ctx); | ||
453 | client_ctx->barrier = NULL; | ||
454 | } | ||
455 | GNUNET_free (client_ctx); | ||
456 | LOG_DEBUG ("Client disconnected from testbed-barrier service\n"); | ||
457 | } | ||
458 | |||
459 | |||
460 | /** | ||
461 | * Function to initialise barriers component | ||
462 | * | ||
463 | * @param cfg the configuration to use for initialisation | ||
464 | */ | ||
465 | void | ||
466 | GST_barriers_init (struct GNUNET_CONFIGURATION_Handle *cfg) | ||
467 | { | ||
468 | struct GNUNET_MQ_MessageHandler message_handlers[] = { | ||
469 | GNUNET_MQ_hd_var_size (barrier_wait, | ||
470 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT, | ||
471 | struct GNUNET_TESTBED_BarrierWait, | ||
472 | NULL), | ||
473 | GNUNET_MQ_handler_end () | ||
474 | }; | ||
475 | |||
476 | LOG_DEBUG ("Launching testbed-barrier service\n"); | ||
477 | barrier_map = GNUNET_CONTAINER_multihashmap_create (3, | ||
478 | GNUNET_YES); | ||
479 | ctx = GNUNET_SERVICE_start ("testbed-barrier", | ||
480 | cfg, | ||
481 | &connect_cb, | ||
482 | &disconnect_cb, | ||
483 | NULL, | ||
484 | message_handlers); | ||
485 | } | ||
486 | |||
487 | |||
488 | /** | ||
489 | * Iterator over hash map entries. | ||
490 | * | ||
491 | * @param cls closure | ||
492 | * @param key current key code | ||
493 | * @param value value in the hash map | ||
494 | * @return #GNUNET_YES if we should continue to | ||
495 | * iterate, | ||
496 | * #GNUNET_NO if not. | ||
497 | */ | ||
498 | static int | ||
499 | barrier_destroy_iterator (void *cls, | ||
500 | const struct GNUNET_HashCode *key, | ||
501 | void *value) | ||
502 | { | ||
503 | struct Barrier *barrier = value; | ||
504 | |||
505 | GNUNET_assert (NULL != barrier); | ||
506 | cancel_wrappers (barrier); | ||
507 | remove_barrier (barrier); | ||
508 | return GNUNET_YES; | ||
509 | } | ||
510 | |||
511 | |||
512 | /** | ||
513 | * Function to stop the barrier service | ||
514 | */ | ||
515 | void | ||
516 | GST_barriers_destroy () | ||
517 | { | ||
518 | GNUNET_assert (NULL != barrier_map); | ||
519 | GNUNET_assert (GNUNET_SYSERR != | ||
520 | GNUNET_CONTAINER_multihashmap_iterate (barrier_map, | ||
521 | & | ||
522 | barrier_destroy_iterator, | ||
523 | NULL)); | ||
524 | GNUNET_CONTAINER_multihashmap_destroy (barrier_map); | ||
525 | GNUNET_assert (NULL != ctx); | ||
526 | GNUNET_SERVICE_stop (ctx); | ||
527 | } | ||
528 | |||
529 | |||
530 | /** | ||
531 | * Functions of this type are to be given as callback argument to | ||
532 | * GNUNET_TESTBED_barrier_init(). The callback will be called when status | ||
533 | * information is available for the barrier. | ||
534 | * | ||
535 | * @param cls the closure given to GNUNET_TESTBED_barrier_init() | ||
536 | * @param name the name of the barrier | ||
537 | * @param b_ the barrier handle | ||
538 | * @param status status of the barrier; #GNUNET_OK if the barrier is crossed; | ||
539 | * #GNUNET_SYSERR upon error | ||
540 | * @param emsg if the status were to be #GNUNET_SYSERR, this parameter has the | ||
541 | * error message | ||
542 | */ | ||
543 | static void | ||
544 | wbarrier_status_cb (void *cls, | ||
545 | const char *name, | ||
546 | struct GNUNET_TESTBED_Barrier *b_, | ||
547 | enum GNUNET_TESTBED_BarrierStatus status, | ||
548 | const char *emsg) | ||
549 | { | ||
550 | struct WBarrier *wrapper = cls; | ||
551 | struct Barrier *barrier = wrapper->barrier; | ||
552 | |||
553 | GNUNET_assert (b_ == wrapper->hbarrier); | ||
554 | switch (status) | ||
555 | { | ||
556 | case GNUNET_TESTBED_BARRIERSTATUS_ERROR: | ||
557 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
558 | "Initialising barrier `%s' failed at a sub-controller: %s\n", | ||
559 | barrier->name, | ||
560 | (NULL != emsg) ? emsg : "NULL"); | ||
561 | cancel_wrappers (barrier); | ||
562 | if (NULL == emsg) | ||
563 | emsg = "Initialisation failed at a sub-controller"; | ||
564 | barrier->status = GNUNET_TESTBED_BARRIERSTATUS_ERROR; | ||
565 | send_barrier_status_msg (barrier, emsg); | ||
566 | return; | ||
567 | |||
568 | case GNUNET_TESTBED_BARRIERSTATUS_CROSSED: | ||
569 | if (GNUNET_TESTBED_BARRIERSTATUS_INITIALISED != barrier->status) | ||
570 | { | ||
571 | GNUNET_break_op (0); | ||
572 | return; | ||
573 | } | ||
574 | barrier->num_wbarriers_reached++; | ||
575 | if ((barrier->num_wbarriers_reached == barrier->num_wbarriers) | ||
576 | && (LOCAL_QUORUM_REACHED (barrier))) | ||
577 | { | ||
578 | barrier->status = GNUNET_TESTBED_BARRIERSTATUS_CROSSED; | ||
579 | send_barrier_status_msg (barrier, NULL); | ||
580 | } | ||
581 | return; | ||
582 | |||
583 | case GNUNET_TESTBED_BARRIERSTATUS_INITIALISED: | ||
584 | if (0 != barrier->status) | ||
585 | { | ||
586 | GNUNET_break_op (0); | ||
587 | return; | ||
588 | } | ||
589 | barrier->num_wbarriers_inited++; | ||
590 | if (barrier->num_wbarriers_inited == barrier->num_wbarriers) | ||
591 | { | ||
592 | barrier->status = GNUNET_TESTBED_BARRIERSTATUS_INITIALISED; | ||
593 | send_barrier_status_msg (barrier, NULL); | ||
594 | } | ||
595 | return; | ||
596 | } | ||
597 | } | ||
598 | |||
599 | |||
600 | /** | ||
601 | * Function called upon timeout while waiting for a response from the | ||
602 | * subcontrollers to barrier init message | ||
603 | * | ||
604 | * @param cls barrier | ||
605 | */ | ||
606 | static void | ||
607 | fwd_tout_barrier_init (void *cls) | ||
608 | { | ||
609 | struct Barrier *barrier = cls; | ||
610 | |||
611 | cancel_wrappers (barrier); | ||
612 | barrier->status = GNUNET_TESTBED_BARRIERSTATUS_ERROR; | ||
613 | send_barrier_status_msg (barrier, | ||
614 | "Timedout while propagating barrier initialisation\n"); | ||
615 | remove_barrier (barrier); | ||
616 | } | ||
617 | |||
618 | |||
619 | /** | ||
620 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. | ||
621 | * | ||
622 | * @param cls identification of the client | ||
623 | * @param msg the actual message | ||
624 | * @return #GNUNET_OK if @a msg is well-formed | ||
625 | */ | ||
626 | int | ||
627 | check_barrier_init (void *cls, | ||
628 | const struct GNUNET_TESTBED_BarrierInit *msg) | ||
629 | { | ||
630 | return GNUNET_OK; /* always well-formed */ | ||
631 | } | ||
632 | |||
633 | |||
634 | /** | ||
635 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. This | ||
636 | * message should always come from a parent controller or the testbed API if we | ||
637 | * are the root controller. | ||
638 | * | ||
639 | * This handler is queued in the main service and will handle the messages sent | ||
640 | * either from the testbed driver or from a high level controller | ||
641 | * | ||
642 | * @param cls identification of the client | ||
643 | * @param msg the actual message | ||
644 | */ | ||
645 | void | ||
646 | handle_barrier_init (void *cls, | ||
647 | const struct GNUNET_TESTBED_BarrierInit *msg) | ||
648 | { | ||
649 | struct GNUNET_SERVICE_Client *client = cls; | ||
650 | char *name; | ||
651 | struct Barrier *barrier; | ||
652 | struct Slave *slave; | ||
653 | struct WBarrier *wrapper; | ||
654 | struct GNUNET_HashCode hash; | ||
655 | size_t name_len; | ||
656 | unsigned int cnt; | ||
657 | uint16_t msize; | ||
658 | |||
659 | if (NULL == GST_context) | ||
660 | { | ||
661 | GNUNET_break_op (0); | ||
662 | GNUNET_SERVICE_client_drop (client); | ||
663 | return; | ||
664 | } | ||
665 | if (client != GST_context->client) | ||
666 | { | ||
667 | GNUNET_break_op (0); | ||
668 | GNUNET_SERVICE_client_drop (client); | ||
669 | return; | ||
670 | } | ||
671 | msize = ntohs (msg->header.size); | ||
672 | name_len = (size_t) msize - sizeof(struct GNUNET_TESTBED_BarrierInit); | ||
673 | name = GNUNET_malloc (name_len + 1); | ||
674 | GNUNET_memcpy (name, msg->name, name_len); | ||
675 | GNUNET_CRYPTO_hash (name, name_len, &hash); | ||
676 | LOG_DEBUG ("Received BARRIER_INIT for barrier `%s'\n", | ||
677 | name); | ||
678 | if (GNUNET_YES == | ||
679 | GNUNET_CONTAINER_multihashmap_contains (barrier_map, | ||
680 | &hash)) | ||
681 | { | ||
682 | send_client_status_msg (client, | ||
683 | name, | ||
684 | GNUNET_TESTBED_BARRIERSTATUS_ERROR, | ||
685 | "A barrier with the same name already exists"); | ||
686 | GNUNET_free (name); | ||
687 | GNUNET_SERVICE_client_continue (client); | ||
688 | return; | ||
689 | } | ||
690 | barrier = GNUNET_new (struct Barrier); | ||
691 | barrier->hash = hash; | ||
692 | barrier->quorum = msg->quorum; | ||
693 | barrier->name = name; | ||
694 | barrier->mc = client; | ||
695 | GNUNET_assert (GNUNET_OK == | ||
696 | GNUNET_CONTAINER_multihashmap_put (barrier_map, | ||
697 | &barrier->hash, | ||
698 | barrier, | ||
699 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); | ||
700 | GNUNET_SERVICE_client_continue (client); | ||
701 | /* Propagate barrier init to subcontrollers */ | ||
702 | for (cnt = 0; cnt < GST_slave_list_size; cnt++) | ||
703 | { | ||
704 | if (NULL == (slave = GST_slave_list[cnt])) | ||
705 | continue; | ||
706 | if (NULL == slave->controller) | ||
707 | { | ||
708 | GNUNET_break (0); /* May happen when we are connecting to the controller */ | ||
709 | continue; | ||
710 | } | ||
711 | wrapper = GNUNET_new (struct WBarrier); | ||
712 | wrapper->barrier = barrier; | ||
713 | wrapper->controller = slave->controller; | ||
714 | GNUNET_CONTAINER_DLL_insert_tail (barrier->whead, | ||
715 | barrier->wtail, | ||
716 | wrapper); | ||
717 | barrier->num_wbarriers++; | ||
718 | wrapper->hbarrier = GNUNET_TESTBED_barrier_init_ (wrapper->controller, | ||
719 | barrier->name, | ||
720 | barrier->quorum, | ||
721 | &wbarrier_status_cb, | ||
722 | wrapper, | ||
723 | GNUNET_NO); | ||
724 | } | ||
725 | if (NULL == barrier->whead) /* No further propagation */ | ||
726 | { | ||
727 | barrier->status = GNUNET_TESTBED_BARRIERSTATUS_INITIALISED; | ||
728 | LOG_DEBUG ( | ||
729 | "Sending GNUNET_TESTBED_BARRIERSTATUS_INITIALISED for barrier `%s'\n", | ||
730 | barrier->name); | ||
731 | send_barrier_status_msg (barrier, NULL); | ||
732 | } | ||
733 | else | ||
734 | barrier->tout_task = GNUNET_SCHEDULER_add_delayed (MESSAGE_SEND_TIMEOUT ( | ||
735 | 30), | ||
736 | &fwd_tout_barrier_init, | ||
737 | barrier); | ||
738 | } | ||
739 | |||
740 | |||
741 | /** | ||
742 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. | ||
743 | * | ||
744 | * @param cls identification of the client | ||
745 | * @param msg the actual message | ||
746 | * @return #GNUNET_OK if @a msg is well-formed | ||
747 | */ | ||
748 | int | ||
749 | check_barrier_cancel (void *cls, | ||
750 | const struct GNUNET_TESTBED_BarrierCancel *msg) | ||
751 | { | ||
752 | return GNUNET_OK; /* all are well-formed */ | ||
753 | } | ||
754 | |||
755 | |||
756 | /** | ||
757 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. This | ||
758 | * message should always come from a parent controller or the testbed API if we | ||
759 | * are the root controller. | ||
760 | * | ||
761 | * This handler is queued in the main service and will handle the messages sent | ||
762 | * either from the testbed driver or from a high level controller | ||
763 | * | ||
764 | * @param cls identification of the client | ||
765 | * @param msg the actual message | ||
766 | */ | ||
767 | void | ||
768 | handle_barrier_cancel (void *cls, | ||
769 | const struct GNUNET_TESTBED_BarrierCancel *msg) | ||
770 | { | ||
771 | struct GNUNET_SERVICE_Client *client = cls; | ||
772 | char *name; | ||
773 | struct Barrier *barrier; | ||
774 | struct GNUNET_HashCode hash; | ||
775 | size_t name_len; | ||
776 | uint16_t msize; | ||
777 | |||
778 | if (NULL == GST_context) | ||
779 | { | ||
780 | GNUNET_break_op (0); | ||
781 | GNUNET_SERVICE_client_drop (client); | ||
782 | return; | ||
783 | } | ||
784 | if (client != GST_context->client) | ||
785 | { | ||
786 | GNUNET_break_op (0); | ||
787 | GNUNET_SERVICE_client_drop (client); | ||
788 | return; | ||
789 | } | ||
790 | msize = ntohs (msg->header.size); | ||
791 | name_len = msize - sizeof(struct GNUNET_TESTBED_BarrierCancel); | ||
792 | name = GNUNET_malloc (name_len + 1); | ||
793 | GNUNET_memcpy (name, | ||
794 | msg->name, | ||
795 | name_len); | ||
796 | LOG_DEBUG ("Received BARRIER_CANCEL for barrier `%s'\n", | ||
797 | name); | ||
798 | GNUNET_CRYPTO_hash (name, | ||
799 | name_len, | ||
800 | &hash); | ||
801 | if (GNUNET_NO == | ||
802 | GNUNET_CONTAINER_multihashmap_contains (barrier_map, | ||
803 | &hash)) | ||
804 | { | ||
805 | GNUNET_break_op (0); | ||
806 | GNUNET_SERVICE_client_drop (client); | ||
807 | return; | ||
808 | } | ||
809 | barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, | ||
810 | &hash); | ||
811 | GNUNET_assert (NULL != barrier); | ||
812 | cancel_wrappers (barrier); | ||
813 | remove_barrier (barrier); | ||
814 | GNUNET_SERVICE_client_continue (client); | ||
815 | } | ||
816 | |||
817 | |||
818 | /** | ||
819 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. | ||
820 | * | ||
821 | * @param cls identification of the client | ||
822 | * @param msg the actual message | ||
823 | * @return #GNUNET_OK if @a msg is well-formed | ||
824 | */ | ||
825 | int | ||
826 | check_barrier_status (void *cls, | ||
827 | const struct GNUNET_TESTBED_BarrierStatusMsg *msg) | ||
828 | { | ||
829 | uint16_t msize; | ||
830 | uint16_t name_len; | ||
831 | const char *name; | ||
832 | enum GNUNET_TESTBED_BarrierStatus status; | ||
833 | |||
834 | msize = ntohs (msg->header.size) - sizeof(*msg); | ||
835 | status = ntohs (msg->status); | ||
836 | if (GNUNET_TESTBED_BARRIERSTATUS_CROSSED != status) | ||
837 | { | ||
838 | GNUNET_break_op (0); /* current we only expect BARRIER_CROSSED | ||
839 | status message this way */ | ||
840 | return GNUNET_SYSERR; | ||
841 | } | ||
842 | name = msg->data; | ||
843 | name_len = ntohs (msg->name_len); | ||
844 | if ((name_len + 1) != msize) | ||
845 | { | ||
846 | GNUNET_break_op (0); | ||
847 | return GNUNET_SYSERR; | ||
848 | } | ||
849 | if ('\0' != name[name_len]) | ||
850 | { | ||
851 | GNUNET_break_op (0); | ||
852 | return GNUNET_SYSERR; | ||
853 | } | ||
854 | return GNUNET_OK; | ||
855 | } | ||
856 | |||
857 | |||
858 | /** | ||
859 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. | ||
860 | * This handler is queued in the main service and will handle the messages sent | ||
861 | * either from the testbed driver or from a high level controller | ||
862 | * | ||
863 | * @param cls identification of the client | ||
864 | * @param msg the actual message | ||
865 | */ | ||
866 | void | ||
867 | handle_barrier_status (void *cls, | ||
868 | const struct GNUNET_TESTBED_BarrierStatusMsg *msg) | ||
869 | { | ||
870 | struct GNUNET_SERVICE_Client *client = cls; | ||
871 | struct Barrier *barrier; | ||
872 | struct ClientCtx *client_ctx; | ||
873 | struct WBarrier *wrapper; | ||
874 | const char *name; | ||
875 | struct GNUNET_HashCode key; | ||
876 | uint16_t name_len; | ||
877 | struct GNUNET_MQ_Envelope *env; | ||
878 | |||
879 | if (NULL == GST_context) | ||
880 | { | ||
881 | GNUNET_break_op (0); | ||
882 | GNUNET_SERVICE_client_drop (client); | ||
883 | return; | ||
884 | } | ||
885 | if (client != GST_context->client) | ||
886 | { | ||
887 | GNUNET_break_op (0); | ||
888 | GNUNET_SERVICE_client_drop (client); | ||
889 | return; | ||
890 | } | ||
891 | name = msg->data; | ||
892 | name_len = ntohs (msg->name_len); | ||
893 | LOG_DEBUG ("Received BARRIER_STATUS for barrier `%s'\n", | ||
894 | name); | ||
895 | GNUNET_CRYPTO_hash (name, | ||
896 | name_len, | ||
897 | &key); | ||
898 | barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, | ||
899 | &key); | ||
900 | if (NULL == barrier) | ||
901 | { | ||
902 | GNUNET_break_op (0); | ||
903 | GNUNET_SERVICE_client_drop (client); | ||
904 | return; | ||
905 | } | ||
906 | GNUNET_SERVICE_client_continue (client); | ||
907 | for (client_ctx = barrier->head; NULL != client_ctx; client_ctx = | ||
908 | client_ctx->next) /* Notify peers */ | ||
909 | { | ||
910 | env = GNUNET_MQ_msg_copy (&msg->header); | ||
911 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client_ctx->client), | ||
912 | env); | ||
913 | } | ||
914 | /** | ||
915 | * The wrapper barriers do not echo the barrier status, so we have to do it | ||
916 | * here | ||
917 | */ | ||
918 | for (wrapper = barrier->whead; NULL != wrapper; wrapper = wrapper->next) | ||
919 | { | ||
920 | GNUNET_TESTBED_queue_message_ (wrapper->controller, | ||
921 | GNUNET_copy_message (&msg->header)); | ||
922 | } | ||
923 | } | ||
924 | |||
925 | |||
926 | /* end of gnunet-service-testbed_barriers.c */ | ||
diff --git a/src/testbed/gnunet-service-testbed_barriers.h b/src/testbed/gnunet-service-testbed_barriers.h deleted file mode 100644 index aa2718777..000000000 --- a/src/testbed/gnunet-service-testbed_barriers.h +++ /dev/null | |||
@@ -1,128 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-service-testbed_barriers.h | ||
23 | * @brief Interface for the barrier initialisation handler routine | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #ifndef GNUNET_SERVER_TESTBED_BARRIERS_H_ | ||
28 | #define GNUNET_SERVER_TESTBED_BARRIERS_H_ | ||
29 | |||
30 | /** | ||
31 | * Function to initialise barriers component | ||
32 | * | ||
33 | * @param cfg the configuration to use for initialisation | ||
34 | */ | ||
35 | void | ||
36 | GST_barriers_init (struct GNUNET_CONFIGURATION_Handle *cfg); | ||
37 | |||
38 | |||
39 | /** | ||
40 | * Function to stop the barrier service | ||
41 | */ | ||
42 | void | ||
43 | GST_barriers_destroy (void); | ||
44 | |||
45 | |||
46 | /** | ||
47 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. | ||
48 | * | ||
49 | * @param cls identification of the client | ||
50 | * @param msg the actual message | ||
51 | * @return #GNUNET_OK if @a msg is well-formed | ||
52 | */ | ||
53 | int | ||
54 | check_barrier_init (void *cls, | ||
55 | const struct GNUNET_TESTBED_BarrierInit *msg); | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. This | ||
60 | * message should always come from a parent controller or the testbed API if we | ||
61 | * are the root controller. | ||
62 | * | ||
63 | * This handler is queued in the main service and will handle the messages sent | ||
64 | * either from the testbed driver or from a high level controller | ||
65 | * | ||
66 | * @param cls identification of the client | ||
67 | * @param msg the actual message | ||
68 | */ | ||
69 | void | ||
70 | handle_barrier_init (void *cls, | ||
71 | const struct GNUNET_TESTBED_BarrierInit *msg); | ||
72 | |||
73 | |||
74 | /** | ||
75 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. | ||
76 | * | ||
77 | * @param cls identification of the client | ||
78 | * @param msg the actual message | ||
79 | * @return #GNUNET_OK if @a msg is well-formed | ||
80 | */ | ||
81 | int | ||
82 | check_barrier_cancel (void *cls, | ||
83 | const struct GNUNET_TESTBED_BarrierCancel *msg); | ||
84 | |||
85 | |||
86 | /** | ||
87 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. This | ||
88 | * message should always come from a parent controller or the testbed API if we | ||
89 | * are the root controller. | ||
90 | * | ||
91 | * This handler is queued in the main service and will handle the messages sent | ||
92 | * either from the testbed driver or from a high level controller | ||
93 | * | ||
94 | * @param cls identification of the client | ||
95 | * @param msg the actual message | ||
96 | */ | ||
97 | void | ||
98 | handle_barrier_cancel (void *cls, | ||
99 | const struct GNUNET_TESTBED_BarrierCancel *msg); | ||
100 | |||
101 | |||
102 | /** | ||
103 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. | ||
104 | * | ||
105 | * @param cls identification of the client | ||
106 | * @param msg the actual message | ||
107 | * @return #GNUNET_OK if @a msg is well-formed | ||
108 | */ | ||
109 | int | ||
110 | check_barrier_status (void *cls, | ||
111 | const struct GNUNET_TESTBED_BarrierStatusMsg *msg); | ||
112 | |||
113 | |||
114 | /** | ||
115 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. | ||
116 | * This handler is queued in the main service and will handle the messages sent | ||
117 | * either from the testbed driver or from a high level controller | ||
118 | * | ||
119 | * @param cls identification of the client | ||
120 | * @param msg the actual message | ||
121 | */ | ||
122 | void | ||
123 | handle_barrier_status (void *cls, | ||
124 | const struct GNUNET_TESTBED_BarrierStatusMsg *msg); | ||
125 | |||
126 | #endif /* GNUNET_SERVER_TESTBED_BARRIERS_H_ */ | ||
127 | |||
128 | /* end of gnunet-service-testbed_barriers.h */ | ||
diff --git a/src/testbed/gnunet-service-testbed_cache.c b/src/testbed/gnunet-service-testbed_cache.c deleted file mode 100644 index 5e74b865a..000000000 --- a/src/testbed/gnunet-service-testbed_cache.c +++ /dev/null | |||
@@ -1,269 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-service-testbed_cache.c | ||
23 | * @brief testbed cache implementation | ||
24 | * @author Sree Harsha Totakura | ||
25 | */ | ||
26 | #include "gnunet-service-testbed.h" | ||
27 | |||
28 | /** | ||
29 | * Redefine LOG with a changed log component string | ||
30 | */ | ||
31 | #ifdef LOG | ||
32 | #undef LOG | ||
33 | #endif | ||
34 | #define LOG(kind, ...) \ | ||
35 | GNUNET_log_from (kind, "testbed-cache", __VA_ARGS__) | ||
36 | |||
37 | |||
38 | /** | ||
39 | * Cache entry | ||
40 | */ | ||
41 | struct CacheEntry | ||
42 | { | ||
43 | /** | ||
44 | * DLL next ptr for least recently used cache entries | ||
45 | */ | ||
46 | struct CacheEntry *next; | ||
47 | |||
48 | /** | ||
49 | * DLL prev ptr for least recently used cache entries | ||
50 | */ | ||
51 | struct CacheEntry *prev; | ||
52 | |||
53 | /** | ||
54 | * The HELLO message | ||
55 | */ | ||
56 | struct GNUNET_MessageHeader *hello; | ||
57 | |||
58 | /** | ||
59 | * The id of the peer this entry corresponds to | ||
60 | */ | ||
61 | unsigned int peer_id; | ||
62 | }; | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Hashmap to maintain cache | ||
67 | */ | ||
68 | static struct GNUNET_CONTAINER_MultiHashMap32 *cache; | ||
69 | |||
70 | /** | ||
71 | * DLL head for least recently used cache entries; least recently used | ||
72 | * cache items are at the head. The cache enties are added to this queue when | ||
73 | * their demand becomes zero. They are removed from the queue when they are | ||
74 | * needed by any operation. | ||
75 | */ | ||
76 | static struct CacheEntry *cache_head; | ||
77 | |||
78 | /** | ||
79 | * DLL tail for least recently used cache entries; recently used cache | ||
80 | * items are at the tail.The cache enties are added to this queue when | ||
81 | * their demand becomes zero. They are removed from the queue when they are | ||
82 | * needed by any operation. | ||
83 | */ | ||
84 | static struct CacheEntry *cache_tail; | ||
85 | |||
86 | /** | ||
87 | * Maximum number of elements to cache | ||
88 | */ | ||
89 | static unsigned int cache_size; | ||
90 | |||
91 | |||
92 | /** | ||
93 | * Looks up in the cache and returns the entry | ||
94 | * | ||
95 | * @param peer_id the peer identity of the peer whose corresponding entry has to | ||
96 | * be looked up | ||
97 | * @return the HELLO message; NULL if not found | ||
98 | */ | ||
99 | static struct CacheEntry * | ||
100 | cache_lookup (unsigned int peer_id) | ||
101 | { | ||
102 | struct CacheEntry *entry; | ||
103 | |||
104 | GNUNET_assert (NULL != cache); | ||
105 | entry = GNUNET_CONTAINER_multihashmap32_get (cache, peer_id); | ||
106 | if (NULL == entry) | ||
107 | return NULL; | ||
108 | GNUNET_CONTAINER_DLL_remove (cache_head, cache_tail, entry); | ||
109 | GNUNET_CONTAINER_DLL_insert_tail (cache_head, cache_tail, entry); | ||
110 | return entry; | ||
111 | } | ||
112 | |||
113 | |||
114 | /** | ||
115 | * Free the resources occupied by a cache entry | ||
116 | * | ||
117 | * @param entry the cache entry to free | ||
118 | */ | ||
119 | static void | ||
120 | free_entry (struct CacheEntry *entry) | ||
121 | { | ||
122 | GNUNET_CONTAINER_DLL_remove (cache_head, cache_tail, entry); | ||
123 | GNUNET_free (entry->hello); | ||
124 | GNUNET_free (entry); | ||
125 | } | ||
126 | |||
127 | |||
128 | /** | ||
129 | * Creates a new cache entry and then puts it into the cache's hashtable. | ||
130 | * | ||
131 | * @param peer_id the index of the peer to tag the newly created entry | ||
132 | * @return the newly created entry | ||
133 | */ | ||
134 | static struct CacheEntry * | ||
135 | add_entry (unsigned int peer_id) | ||
136 | { | ||
137 | struct CacheEntry *entry; | ||
138 | |||
139 | GNUNET_assert (NULL != cache); | ||
140 | if (cache_size == GNUNET_CONTAINER_multihashmap32_size (cache)) | ||
141 | { | ||
142 | /* remove the LRU head */ | ||
143 | entry = cache_head; | ||
144 | GNUNET_assert (GNUNET_OK == | ||
145 | GNUNET_CONTAINER_multihashmap32_remove (cache, (uint32_t) | ||
146 | entry->peer_id, | ||
147 | entry)); | ||
148 | free_entry (entry); | ||
149 | } | ||
150 | entry = GNUNET_new (struct CacheEntry); | ||
151 | entry->peer_id = peer_id; | ||
152 | GNUNET_assert (GNUNET_OK == | ||
153 | GNUNET_CONTAINER_multihashmap32_put (cache, | ||
154 | (uint32_t) peer_id, | ||
155 | entry, | ||
156 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); | ||
157 | GNUNET_CONTAINER_DLL_insert_tail (cache_head, cache_tail, entry); | ||
158 | return entry; | ||
159 | } | ||
160 | |||
161 | |||
162 | /** | ||
163 | * Iterator over hash map entries. | ||
164 | * | ||
165 | * @param cls closure | ||
166 | * @param key current key | ||
167 | * @param value value in the hash map | ||
168 | * @return GNUNET_YES if we should continue to | ||
169 | * iterate, | ||
170 | * GNUNET_NO if not. | ||
171 | */ | ||
172 | static int | ||
173 | cache_clear_iterator (void *cls, uint32_t key, void *value) | ||
174 | { | ||
175 | struct CacheEntry *entry = value; | ||
176 | |||
177 | GNUNET_assert (NULL != entry); | ||
178 | GNUNET_assert (GNUNET_YES == | ||
179 | GNUNET_CONTAINER_multihashmap32_remove (cache, key, value)); | ||
180 | free_entry (entry); | ||
181 | return GNUNET_YES; | ||
182 | } | ||
183 | |||
184 | |||
185 | /** | ||
186 | * Clear cache | ||
187 | */ | ||
188 | void | ||
189 | GST_cache_clear () | ||
190 | { | ||
191 | if (NULL != cache) | ||
192 | { | ||
193 | GNUNET_CONTAINER_multihashmap32_iterate (cache, &cache_clear_iterator, | ||
194 | NULL); | ||
195 | GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (cache)); | ||
196 | GNUNET_CONTAINER_multihashmap32_destroy (cache); | ||
197 | cache = NULL; | ||
198 | } | ||
199 | cache_size = 0; | ||
200 | cache_head = NULL; | ||
201 | cache_tail = NULL; | ||
202 | } | ||
203 | |||
204 | |||
205 | /** | ||
206 | * Initializes the cache | ||
207 | * | ||
208 | * @param size the size of the cache | ||
209 | */ | ||
210 | void | ||
211 | GST_cache_init (unsigned int size) | ||
212 | { | ||
213 | if (0 == size) | ||
214 | return; | ||
215 | cache_size = size; | ||
216 | cache = GNUNET_CONTAINER_multihashmap32_create (cache_size); | ||
217 | } | ||
218 | |||
219 | |||
220 | /** | ||
221 | * Looks up in the hello cache and returns the HELLO of the given peer | ||
222 | * | ||
223 | * @param peer_id the index of the peer whose HELLO has to be looked up | ||
224 | * @return the HELLO message; NULL if not found | ||
225 | */ | ||
226 | const struct GNUNET_MessageHeader * | ||
227 | GST_cache_lookup_hello (const unsigned int peer_id) | ||
228 | { | ||
229 | struct CacheEntry *entry; | ||
230 | |||
231 | LOG_DEBUG ("Looking up HELLO for peer %u\n", peer_id); | ||
232 | if (NULL == cache) | ||
233 | { | ||
234 | LOG_DEBUG ("Caching disabled\n"); | ||
235 | return NULL; | ||
236 | } | ||
237 | entry = cache_lookup (peer_id); | ||
238 | if (NULL == entry) | ||
239 | return NULL; | ||
240 | if (NULL != entry->hello) | ||
241 | LOG_DEBUG ("HELLO found for peer %u\n", peer_id); | ||
242 | return entry->hello; | ||
243 | } | ||
244 | |||
245 | |||
246 | /** | ||
247 | * Caches the HELLO of the given peer. Updates the HELLO if it was already | ||
248 | * cached before | ||
249 | * | ||
250 | * @param peer_id the peer identity of the peer whose HELLO has to be cached | ||
251 | * @param hello the HELLO message | ||
252 | */ | ||
253 | void | ||
254 | GST_cache_add_hello (const unsigned int peer_id, | ||
255 | const struct GNUNET_MessageHeader *hello) | ||
256 | { | ||
257 | struct CacheEntry *entry; | ||
258 | |||
259 | if (NULL == cache) | ||
260 | return; | ||
261 | entry = cache_lookup (peer_id); | ||
262 | if (NULL == entry) | ||
263 | entry = add_entry (peer_id); | ||
264 | GNUNET_free (entry->hello); | ||
265 | entry->hello = GNUNET_copy_message (hello); | ||
266 | } | ||
267 | |||
268 | |||
269 | /* end of gnunet-service-testbed_hc.c */ | ||
diff --git a/src/testbed/gnunet-service-testbed_connectionpool.c b/src/testbed/gnunet-service-testbed_connectionpool.c deleted file mode 100644 index 7318971b3..000000000 --- a/src/testbed/gnunet-service-testbed_connectionpool.c +++ /dev/null | |||
@@ -1,1031 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-service-testbed_connectionpool.c | ||
23 | * @brief connection pooling for connections to peers' services | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "gnunet-service-testbed.h" | ||
28 | #include "gnunet-service-testbed_connectionpool.h" | ||
29 | #include "testbed_api_operations.h" | ||
30 | #include "gnunet_transport_service.h" | ||
31 | |||
32 | /** | ||
33 | * Redefine LOG with a changed log component string | ||
34 | */ | ||
35 | #ifdef LOG | ||
36 | #undef LOG | ||
37 | #endif | ||
38 | #define LOG(kind, ...) \ | ||
39 | GNUNET_log_from (kind, "testbed-connectionpool", __VA_ARGS__) | ||
40 | |||
41 | |||
42 | /** | ||
43 | * Time to expire a cache entry | ||
44 | */ | ||
45 | #define CACHE_EXPIRY \ | ||
46 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) | ||
47 | |||
48 | |||
49 | /** | ||
50 | * The request handle for obtaining a pooled connection | ||
51 | */ | ||
52 | struct GST_ConnectionPool_GetHandle; | ||
53 | |||
54 | |||
55 | /** | ||
56 | * A pooled connection | ||
57 | */ | ||
58 | struct PooledConnection | ||
59 | { | ||
60 | /** | ||
61 | * Next ptr for placing this object in the DLL of least recently used pooled | ||
62 | * connections | ||
63 | */ | ||
64 | struct PooledConnection *next; | ||
65 | |||
66 | /** | ||
67 | * Prev ptr for placing this object in the DLL of the least recently used | ||
68 | * pooled connections | ||
69 | */ | ||
70 | struct PooledConnection *prev; | ||
71 | |||
72 | /** | ||
73 | * The transport handle to the peer corresponding to this entry; can be NULL | ||
74 | */ | ||
75 | struct GNUNET_TRANSPORT_CoreHandle *handle_transport; | ||
76 | |||
77 | /** | ||
78 | * The core handle to the peer corresponding to this entry; can be NULL | ||
79 | */ | ||
80 | struct GNUNET_CORE_Handle *handle_core; | ||
81 | |||
82 | /** | ||
83 | * The ATS handle to the peer correspondign to this entry; can be NULL. | ||
84 | */ | ||
85 | struct GNUNET_ATS_ConnectivityHandle *handle_ats_connectivity; | ||
86 | |||
87 | /** | ||
88 | * The operation handle for transport handle | ||
89 | */ | ||
90 | struct GNUNET_TESTBED_Operation *op_transport; | ||
91 | |||
92 | /** | ||
93 | * The operation handle for core handle | ||
94 | */ | ||
95 | struct GNUNET_TESTBED_Operation *op_core; | ||
96 | |||
97 | /** | ||
98 | * The operation handle for ATS handle | ||
99 | */ | ||
100 | struct GNUNET_TESTBED_Operation *op_ats_connectivity; | ||
101 | |||
102 | /** | ||
103 | * The peer identity of this peer. Will be set upon opening a connection to | ||
104 | * the peers CORE service. Will be NULL until then and after the CORE | ||
105 | * connection is closed | ||
106 | */ | ||
107 | struct GNUNET_PeerIdentity *peer_identity; | ||
108 | |||
109 | /** | ||
110 | * The configuration of the peer. Should be not NULL as long as the | ||
111 | * core_handle or transport_handle are valid | ||
112 | */ | ||
113 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
114 | |||
115 | /** | ||
116 | * DLL head for the queue to serve notifications when a peer is connected | ||
117 | */ | ||
118 | struct GST_ConnectionPool_GetHandle *head_notify; | ||
119 | |||
120 | /** | ||
121 | * DLL tail for the queue to serve notifications when a peer is connected | ||
122 | */ | ||
123 | struct GST_ConnectionPool_GetHandle *tail_notify; | ||
124 | |||
125 | /** | ||
126 | * DLL head for the queue of #GST_ConnectionPool_GetHandle requests that are | ||
127 | * waiting for this connection to be opened | ||
128 | */ | ||
129 | struct GST_ConnectionPool_GetHandle *head_waiting; | ||
130 | |||
131 | /** | ||
132 | * DLL tail for the queue of #GST_ConnectionPool_GetHandle requests that are | ||
133 | * waiting for this connection to be opened | ||
134 | */ | ||
135 | struct GST_ConnectionPool_GetHandle *tail_waiting; | ||
136 | |||
137 | /** | ||
138 | * The task to expire this connection from the connection pool | ||
139 | */ | ||
140 | struct GNUNET_SCHEDULER_Task *expire_task; | ||
141 | |||
142 | /** | ||
143 | * The task to notify a waiting #GST_ConnectionPool_GetHandle object | ||
144 | */ | ||
145 | struct GNUNET_SCHEDULER_Task *notify_task; | ||
146 | |||
147 | /** | ||
148 | * Number of active requests using this pooled connection | ||
149 | */ | ||
150 | unsigned int demand; | ||
151 | |||
152 | /** | ||
153 | * Is this entry in LRU | ||
154 | */ | ||
155 | int in_lru; | ||
156 | |||
157 | /** | ||
158 | * Is this entry present in the connection pool | ||
159 | */ | ||
160 | int in_pool; | ||
161 | |||
162 | /** | ||
163 | * The index of this peer | ||
164 | */ | ||
165 | uint32_t index; | ||
166 | }; | ||
167 | |||
168 | |||
169 | /** | ||
170 | * The request handle for obtaining a pooled connection | ||
171 | */ | ||
172 | struct GST_ConnectionPool_GetHandle | ||
173 | { | ||
174 | /** | ||
175 | * The next ptr for inclusion in the notification DLLs. At first the object | ||
176 | * is placed in the waiting DLL of the corresponding #PooledConnection | ||
177 | * object. After the handle is opened it is moved to the notification DLL if | ||
178 | * @p connect_notify_cb and @p target are not NULL | ||
179 | */ | ||
180 | struct GST_ConnectionPool_GetHandle *next; | ||
181 | |||
182 | /** | ||
183 | * The prev ptr for inclusion in the notification DLLs | ||
184 | */ | ||
185 | struct GST_ConnectionPool_GetHandle *prev; | ||
186 | |||
187 | /** | ||
188 | * The pooled connection object this handle corresponds to | ||
189 | */ | ||
190 | struct PooledConnection *entry; | ||
191 | |||
192 | /** | ||
193 | * The cache callback to call when a handle is available | ||
194 | */ | ||
195 | GST_connection_pool_connection_ready_cb cb; | ||
196 | |||
197 | /** | ||
198 | * The closure for the above callback | ||
199 | */ | ||
200 | void *cb_cls; | ||
201 | |||
202 | /** | ||
203 | * The peer identity of the target peer. When this target peer is connected, | ||
204 | * call the notify callback | ||
205 | */ | ||
206 | const struct GNUNET_PeerIdentity *target; | ||
207 | |||
208 | /** | ||
209 | * The callback to be called for serving notification that the target peer is | ||
210 | * connected | ||
211 | */ | ||
212 | GST_connection_pool_peer_connect_notify connect_notify_cb; | ||
213 | |||
214 | /** | ||
215 | * The closure for the notify callback | ||
216 | */ | ||
217 | void *connect_notify_cb_cls; | ||
218 | |||
219 | /** | ||
220 | * The service we want to connect to | ||
221 | */ | ||
222 | enum GST_ConnectionPool_Service service; | ||
223 | |||
224 | /** | ||
225 | * Did we call the pool_connection_ready_cb already? | ||
226 | */ | ||
227 | int connection_ready_called; | ||
228 | |||
229 | /** | ||
230 | * Are we waiting for any peer connect notifications? | ||
231 | */ | ||
232 | int notify_waiting; | ||
233 | }; | ||
234 | |||
235 | |||
236 | /** | ||
237 | * A hashmap for quickly finding connections in the connection pool | ||
238 | */ | ||
239 | static struct GNUNET_CONTAINER_MultiHashMap32 *map; | ||
240 | |||
241 | /** | ||
242 | * DLL head for maitaining the least recently used #PooledConnection objects. | ||
243 | * The head is the least recently used object. | ||
244 | */ | ||
245 | static struct PooledConnection *head_lru; | ||
246 | |||
247 | /** | ||
248 | * DLL tail for maitaining the least recently used #PooledConnection objects | ||
249 | */ | ||
250 | static struct PooledConnection *tail_lru; | ||
251 | |||
252 | /** | ||
253 | * DLL head for maintaining #PooledConnection objects that are not added into | ||
254 | * the connection pool as it was full at the time the object's creation | ||
255 | * FIXME | ||
256 | */ | ||
257 | static struct PooledConnection *head_not_pooled; | ||
258 | |||
259 | /** | ||
260 | * DLL tail for maintaining #PooledConnection objects that are not added into | ||
261 | * the connection pool as it was full at the time the object's creation | ||
262 | */ | ||
263 | static struct PooledConnection *tail_not_pooled; | ||
264 | |||
265 | /** | ||
266 | * The maximum number of entries that can be present in the connection pool | ||
267 | */ | ||
268 | static unsigned int max_size; | ||
269 | |||
270 | |||
271 | /** | ||
272 | * Cancel the expiration task of the give #PooledConnection object | ||
273 | * | ||
274 | * @param entry the #PooledConnection object | ||
275 | */ | ||
276 | static void | ||
277 | expire_task_cancel (struct PooledConnection *entry); | ||
278 | |||
279 | |||
280 | /** | ||
281 | * Destroy a #PooledConnection object | ||
282 | * | ||
283 | * @param entry the #PooledConnection object | ||
284 | */ | ||
285 | static void | ||
286 | destroy_pooled_connection (struct PooledConnection *entry) | ||
287 | { | ||
288 | GNUNET_assert ((NULL == entry->head_notify) && (NULL == entry->tail_notify)); | ||
289 | GNUNET_assert ((NULL == entry->head_waiting) && | ||
290 | (NULL == entry->tail_waiting)); | ||
291 | GNUNET_assert (0 == entry->demand); | ||
292 | expire_task_cancel (entry); | ||
293 | if (entry->in_lru) | ||
294 | GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry); | ||
295 | if (entry->in_pool) | ||
296 | GNUNET_assert ( | ||
297 | GNUNET_OK == | ||
298 | GNUNET_CONTAINER_multihashmap32_remove (map, entry->index, entry)); | ||
299 | if (NULL != entry->notify_task) | ||
300 | { | ||
301 | GNUNET_SCHEDULER_cancel (entry->notify_task); | ||
302 | entry->notify_task = NULL; | ||
303 | } | ||
304 | LOG_DEBUG ("Cleaning up handles of a pooled connection\n"); | ||
305 | if (NULL != entry->handle_transport) | ||
306 | GNUNET_assert (NULL != entry->op_transport); | ||
307 | if (NULL != entry->op_transport) | ||
308 | { | ||
309 | GNUNET_TESTBED_operation_done (entry->op_transport); | ||
310 | entry->op_transport = NULL; | ||
311 | } | ||
312 | if (NULL != entry->handle_ats_connectivity) | ||
313 | GNUNET_assert (NULL != entry->op_ats_connectivity); | ||
314 | if (NULL != entry->op_ats_connectivity) | ||
315 | { | ||
316 | GNUNET_TESTBED_operation_done (entry->op_ats_connectivity); | ||
317 | entry->op_ats_connectivity = NULL; | ||
318 | } | ||
319 | if (NULL != entry->op_core) | ||
320 | { | ||
321 | GNUNET_TESTBED_operation_done (entry->op_core); | ||
322 | entry->op_core = NULL; | ||
323 | } | ||
324 | GNUNET_assert (NULL == entry->handle_core); | ||
325 | GNUNET_assert (NULL == entry->handle_ats_connectivity); | ||
326 | GNUNET_assert (NULL == entry->handle_transport); | ||
327 | GNUNET_CONFIGURATION_destroy (entry->cfg); | ||
328 | GNUNET_free (entry); | ||
329 | } | ||
330 | |||
331 | |||
332 | /** | ||
333 | * Expire a #PooledConnection object | ||
334 | * | ||
335 | * @param cls the #PooledConnection object | ||
336 | */ | ||
337 | static void | ||
338 | expire (void *cls) | ||
339 | { | ||
340 | struct PooledConnection *entry = cls; | ||
341 | |||
342 | entry->expire_task = NULL; | ||
343 | destroy_pooled_connection (entry); | ||
344 | } | ||
345 | |||
346 | |||
347 | /** | ||
348 | * Cancel the expiration task of the give #PooledConnection object | ||
349 | * | ||
350 | * @param entry the #PooledConnection object | ||
351 | */ | ||
352 | static void | ||
353 | expire_task_cancel (struct PooledConnection *entry) | ||
354 | { | ||
355 | if (NULL != entry->expire_task) | ||
356 | { | ||
357 | GNUNET_SCHEDULER_cancel (entry->expire_task); | ||
358 | entry->expire_task = NULL; | ||
359 | } | ||
360 | } | ||
361 | |||
362 | |||
363 | /** | ||
364 | * Function to add a #PooledConnection object into LRU and begin the expiry task | ||
365 | * | ||
366 | * @param entry the #PooledConnection object | ||
367 | */ | ||
368 | static void | ||
369 | add_to_lru (struct PooledConnection *entry) | ||
370 | { | ||
371 | GNUNET_assert (0 == entry->demand); | ||
372 | GNUNET_assert (! entry->in_lru); | ||
373 | GNUNET_CONTAINER_DLL_insert_tail (head_lru, tail_lru, entry); | ||
374 | entry->in_lru = GNUNET_YES; | ||
375 | GNUNET_assert (NULL == entry->expire_task); | ||
376 | entry->expire_task = | ||
377 | GNUNET_SCHEDULER_add_delayed (CACHE_EXPIRY, &expire, entry); | ||
378 | } | ||
379 | |||
380 | |||
381 | /** | ||
382 | * Function to find a #GST_ConnectionPool_GetHandle which is waiting for one of | ||
383 | * the handles in given entry which are now available. | ||
384 | * | ||
385 | * @param entry the pooled connection whose active list has to be searched | ||
386 | * @param head the starting list element in the GSTCacheGetHandle where the | ||
387 | * search has to be begin | ||
388 | * @return a suitable GSTCacheGetHandle whose handle ready notify callback | ||
389 | * hasn't been called yet. NULL if no such suitable GSTCacheGetHandle | ||
390 | * is found | ||
391 | */ | ||
392 | static struct GST_ConnectionPool_GetHandle * | ||
393 | search_waiting (const struct PooledConnection *entry, | ||
394 | struct GST_ConnectionPool_GetHandle *head) | ||
395 | { | ||
396 | struct GST_ConnectionPool_GetHandle *gh; | ||
397 | |||
398 | for (gh = head; NULL != gh; gh = gh->next) | ||
399 | { | ||
400 | switch (gh->service) | ||
401 | { | ||
402 | case GST_CONNECTIONPOOL_SERVICE_CORE: | ||
403 | if (NULL == entry->handle_core) | ||
404 | continue; | ||
405 | if (NULL == entry->peer_identity) | ||
406 | continue; /* CORE connection isn't ready yet */ | ||
407 | break; | ||
408 | |||
409 | case GST_CONNECTIONPOOL_SERVICE_TRANSPORT: | ||
410 | if (NULL == entry->handle_transport) | ||
411 | continue; | ||
412 | break; | ||
413 | |||
414 | case GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY: | ||
415 | if (NULL == entry->handle_ats_connectivity) | ||
416 | continue; | ||
417 | break; | ||
418 | } | ||
419 | break; | ||
420 | } | ||
421 | return gh; | ||
422 | } | ||
423 | |||
424 | |||
425 | /** | ||
426 | * A handle in the #PooledConnection object pointed by @a cls is ready and there | ||
427 | * is a #GST_ConnectionPool_GetHandle object waiting in the waiting list. This | ||
428 | * function retrieves that object and calls the handle ready callback. It | ||
429 | * further schedules itself if there are similar waiting objects which can be | ||
430 | * notified. | ||
431 | * | ||
432 | * @param cls the #PooledConnection object | ||
433 | */ | ||
434 | static void | ||
435 | connection_ready (void *cls) | ||
436 | { | ||
437 | struct PooledConnection *entry = cls; | ||
438 | struct GST_ConnectionPool_GetHandle *gh; | ||
439 | struct GST_ConnectionPool_GetHandle *gh_next; | ||
440 | |||
441 | GNUNET_assert (NULL != entry->notify_task); | ||
442 | entry->notify_task = NULL; | ||
443 | gh = search_waiting (entry, entry->head_waiting); | ||
444 | GNUNET_assert (NULL != gh); | ||
445 | gh_next = NULL; | ||
446 | if (NULL != gh->next) | ||
447 | gh_next = search_waiting (entry, gh->next); | ||
448 | GNUNET_CONTAINER_DLL_remove (entry->head_waiting, entry->tail_waiting, gh); | ||
449 | gh->connection_ready_called = 1; | ||
450 | if (NULL != gh_next) | ||
451 | entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready, entry); | ||
452 | if ((NULL != gh->target) && (NULL != gh->connect_notify_cb)) | ||
453 | { | ||
454 | GNUNET_CONTAINER_DLL_insert_tail (entry->head_notify, | ||
455 | entry->tail_notify, | ||
456 | gh); | ||
457 | gh->notify_waiting = 1; | ||
458 | } | ||
459 | LOG_DEBUG ("Connection ready for handle type %u\n", gh->service); | ||
460 | gh->cb (gh->cb_cls, | ||
461 | entry->handle_core, | ||
462 | entry->handle_transport, | ||
463 | entry->handle_ats_connectivity, | ||
464 | entry->peer_identity, | ||
465 | entry->cfg); | ||
466 | } | ||
467 | |||
468 | |||
469 | /** | ||
470 | * Function called from peer connect notify callbacks from CORE and TRANSPORT | ||
471 | * connections. This function calls the pending peer connect notify callbacks | ||
472 | * which are queued in an entry. | ||
473 | * | ||
474 | * @param cls the #PooledConnection object | ||
475 | * @param peer the peer that connected | ||
476 | * @param service the service where this notification has originated | ||
477 | */ | ||
478 | static void | ||
479 | peer_connect_notify_cb (void *cls, | ||
480 | const struct GNUNET_PeerIdentity *peer, | ||
481 | const enum GST_ConnectionPool_Service service) | ||
482 | { | ||
483 | struct PooledConnection *entry = cls; | ||
484 | struct GST_ConnectionPool_GetHandle *gh; | ||
485 | struct GST_ConnectionPool_GetHandle *gh_next; | ||
486 | GST_connection_pool_peer_connect_notify cb; | ||
487 | void *cb_cls; | ||
488 | |||
489 | for (gh = entry->head_notify; NULL != gh;) | ||
490 | { | ||
491 | GNUNET_assert (NULL != gh->target); | ||
492 | GNUNET_assert (NULL != gh->connect_notify_cb); | ||
493 | GNUNET_assert (gh->connection_ready_called); | ||
494 | if (service != gh->service) | ||
495 | { | ||
496 | gh = gh->next; | ||
497 | continue; | ||
498 | } | ||
499 | if (0 != memcmp (gh->target, peer, sizeof(struct GNUNET_PeerIdentity))) | ||
500 | { | ||
501 | gh = gh->next; | ||
502 | continue; | ||
503 | } | ||
504 | cb = gh->connect_notify_cb; | ||
505 | cb_cls = gh->connect_notify_cb_cls; | ||
506 | gh_next = gh->next; | ||
507 | GNUNET_CONTAINER_DLL_remove (entry->head_notify, entry->tail_notify, gh); | ||
508 | gh->notify_waiting = 0; | ||
509 | LOG_DEBUG ("Peer connected to peer %u at service %u\n", | ||
510 | entry->index, | ||
511 | gh->service); | ||
512 | gh = gh_next; | ||
513 | cb (cb_cls, peer); | ||
514 | } | ||
515 | } | ||
516 | |||
517 | |||
518 | /** | ||
519 | * Function called to notify transport users that another | ||
520 | * peer connected to us. | ||
521 | * | ||
522 | * @param cls the #PooledConnection object | ||
523 | * @param peer the peer that connected | ||
524 | * @param mq queue for sending data to @a peer | ||
525 | * @return NULL | ||
526 | */ | ||
527 | static void * | ||
528 | transport_peer_connect_notify_cb (void *cls, | ||
529 | const struct GNUNET_PeerIdentity *peer, | ||
530 | struct GNUNET_MQ_Handle *mq) | ||
531 | { | ||
532 | struct PooledConnection *entry = cls; | ||
533 | |||
534 | peer_connect_notify_cb (entry, peer, GST_CONNECTIONPOOL_SERVICE_TRANSPORT); | ||
535 | return NULL; | ||
536 | } | ||
537 | |||
538 | |||
539 | /** | ||
540 | * Function called when resources for opening a connection to TRANSPORT are | ||
541 | * available. | ||
542 | * | ||
543 | * @param cls the #PooledConnection object | ||
544 | */ | ||
545 | static void | ||
546 | opstart_get_handle_transport (void *cls) | ||
547 | { | ||
548 | struct PooledConnection *entry = cls; | ||
549 | |||
550 | GNUNET_assert (NULL != entry); | ||
551 | LOG_DEBUG ("Opening a transport connection to peer %u\n", entry->index); | ||
552 | entry->handle_transport = | ||
553 | GNUNET_TRANSPORT_core_connect (entry->cfg, | ||
554 | NULL, | ||
555 | NULL, | ||
556 | entry, | ||
557 | &transport_peer_connect_notify_cb, | ||
558 | NULL, | ||
559 | NULL); | ||
560 | if (NULL == entry->handle_transport) | ||
561 | { | ||
562 | GNUNET_break (0); | ||
563 | return; | ||
564 | } | ||
565 | if (0 == entry->demand) | ||
566 | return; | ||
567 | if (NULL != entry->notify_task) | ||
568 | return; | ||
569 | if (NULL != search_waiting (entry, entry->head_waiting)) | ||
570 | { | ||
571 | entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready, entry); | ||
572 | return; | ||
573 | } | ||
574 | } | ||
575 | |||
576 | |||
577 | /** | ||
578 | * Function called when the operation responsible for opening a TRANSPORT | ||
579 | * connection is marked as done. | ||
580 | * | ||
581 | * @param cls the cache entry | ||
582 | */ | ||
583 | static void | ||
584 | oprelease_get_handle_transport (void *cls) | ||
585 | { | ||
586 | struct PooledConnection *entry = cls; | ||
587 | |||
588 | if (NULL == entry->handle_transport) | ||
589 | return; | ||
590 | GNUNET_TRANSPORT_core_disconnect (entry->handle_transport); | ||
591 | entry->handle_transport = NULL; | ||
592 | } | ||
593 | |||
594 | |||
595 | /** | ||
596 | * Method called whenever a given peer connects at CORE level | ||
597 | * | ||
598 | * @param cls the #PooledConnection object | ||
599 | * @param peer peer identity this notification is about | ||
600 | * @param mq message queue for talking to @a peer | ||
601 | * @return peer | ||
602 | */ | ||
603 | static void * | ||
604 | core_peer_connect_cb (void *cls, | ||
605 | const struct GNUNET_PeerIdentity *peer, | ||
606 | struct GNUNET_MQ_Handle *mq) | ||
607 | { | ||
608 | struct PooledConnection *entry = cls; | ||
609 | |||
610 | peer_connect_notify_cb (entry, peer, GST_CONNECTIONPOOL_SERVICE_CORE); | ||
611 | return (void *) peer; | ||
612 | } | ||
613 | |||
614 | |||
615 | /** | ||
616 | * Function called after #GNUNET_CORE_connect() has succeeded (or failed | ||
617 | * for good). Note that the private key of the peer is intentionally | ||
618 | * not exposed here; if you need it, your process should try to read | ||
619 | * the private key file directly (which should work if you are | ||
620 | * authorized...). Implementations of this function must not call | ||
621 | * #GNUNET_CORE_disconnect() (other than by scheduling a new task to | ||
622 | * do this later). | ||
623 | * | ||
624 | * @param cls the #PooledConnection object | ||
625 | * @param my_identity ID of this peer, NULL if we failed | ||
626 | */ | ||
627 | static void | ||
628 | core_startup_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity) | ||
629 | { | ||
630 | struct PooledConnection *entry = cls; | ||
631 | |||
632 | if (NULL == my_identity) | ||
633 | { | ||
634 | GNUNET_break (0); | ||
635 | return; | ||
636 | } | ||
637 | GNUNET_assert (NULL == entry->peer_identity); | ||
638 | entry->peer_identity = GNUNET_new (struct GNUNET_PeerIdentity); | ||
639 | *entry->peer_identity = *my_identity; | ||
640 | if (0 == entry->demand) | ||
641 | return; | ||
642 | if (NULL != entry->notify_task) | ||
643 | return; | ||
644 | if (NULL != search_waiting (entry, entry->head_waiting)) | ||
645 | { | ||
646 | entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready, entry); | ||
647 | return; | ||
648 | } | ||
649 | } | ||
650 | |||
651 | |||
652 | /** | ||
653 | * Function called when resources for opening a connection to CORE are | ||
654 | * available. | ||
655 | * | ||
656 | * @param cls the #PooledConnection object | ||
657 | */ | ||
658 | static void | ||
659 | opstart_get_handle_core (void *cls) | ||
660 | { | ||
661 | struct PooledConnection *entry = cls; | ||
662 | |||
663 | GNUNET_assert (NULL != entry); | ||
664 | LOG_DEBUG ("Opening a CORE connection to peer %u\n", entry->index); | ||
665 | entry->handle_core = | ||
666 | GNUNET_CORE_connect (entry->cfg, | ||
667 | entry, /* closure */ | ||
668 | &core_startup_cb, /* core startup notify */ | ||
669 | &core_peer_connect_cb, /* peer connect notify */ | ||
670 | NULL, /* peer disconnect notify */ | ||
671 | NULL); | ||
672 | } | ||
673 | |||
674 | |||
675 | /** | ||
676 | * Function called when the operation responsible for opening a CORE | ||
677 | * connection is marked as done. | ||
678 | * | ||
679 | * @param cls the #PooledConnection object | ||
680 | */ | ||
681 | static void | ||
682 | oprelease_get_handle_core (void *cls) | ||
683 | { | ||
684 | struct PooledConnection *entry = cls; | ||
685 | |||
686 | if (NULL == entry->handle_core) | ||
687 | return; | ||
688 | GNUNET_CORE_disconnect (entry->handle_core); | ||
689 | entry->handle_core = NULL; | ||
690 | GNUNET_free (entry->peer_identity); | ||
691 | entry->peer_identity = NULL; | ||
692 | } | ||
693 | |||
694 | |||
695 | /** | ||
696 | * Function called when resources for opening a connection to ATS are | ||
697 | * available. | ||
698 | * | ||
699 | * @param cls the #PooledConnection object | ||
700 | */ | ||
701 | static void | ||
702 | opstart_get_handle_ats_connectivity (void *cls) | ||
703 | { | ||
704 | struct PooledConnection *entry = cls; | ||
705 | |||
706 | entry->handle_ats_connectivity = GNUNET_ATS_connectivity_init (entry->cfg); | ||
707 | } | ||
708 | |||
709 | |||
710 | /** | ||
711 | * Function called when the operation responsible for opening a ATS | ||
712 | * connection is marked as done. | ||
713 | * | ||
714 | * @param cls the #PooledConnection object | ||
715 | */ | ||
716 | static void | ||
717 | oprelease_get_handle_ats_connectivity (void *cls) | ||
718 | { | ||
719 | struct PooledConnection *entry = cls; | ||
720 | |||
721 | if (NULL == entry->handle_ats_connectivity) | ||
722 | return; | ||
723 | GNUNET_ATS_connectivity_done (entry->handle_ats_connectivity); | ||
724 | entry->handle_ats_connectivity = NULL; | ||
725 | } | ||
726 | |||
727 | |||
728 | /** | ||
729 | * This function will be called for every #PooledConnection object in @p map | ||
730 | * | ||
731 | * @param cls NULL | ||
732 | * @param key current key code | ||
733 | * @param value the #PooledConnection object | ||
734 | * @return #GNUNET_YES if we should continue to | ||
735 | * iterate, | ||
736 | * #GNUNET_NO if not. | ||
737 | */ | ||
738 | static int | ||
739 | cleanup_iterator (void *cls, uint32_t key, void *value) | ||
740 | { | ||
741 | struct PooledConnection *entry = value; | ||
742 | |||
743 | GNUNET_assert (NULL != entry); | ||
744 | destroy_pooled_connection (entry); | ||
745 | return GNUNET_YES; | ||
746 | } | ||
747 | |||
748 | |||
749 | /** | ||
750 | * Initialise the connection pool. | ||
751 | * | ||
752 | * @param size the size of the connection pool. Each entry in the connection | ||
753 | * pool can handle a connection to each of the services enumerated in | ||
754 | * #GST_ConnectionPool_Service | ||
755 | */ | ||
756 | void | ||
757 | GST_connection_pool_init (unsigned int size) | ||
758 | { | ||
759 | max_size = size; | ||
760 | if (0 == max_size) | ||
761 | return; | ||
762 | GNUNET_assert (NULL == map); | ||
763 | map = GNUNET_CONTAINER_multihashmap32_create (((size * 3) / 4) + 1); | ||
764 | } | ||
765 | |||
766 | |||
767 | /** | ||
768 | * Cleanup the connection pool | ||
769 | */ | ||
770 | void | ||
771 | GST_connection_pool_destroy () | ||
772 | { | ||
773 | struct PooledConnection *entry; | ||
774 | |||
775 | if (NULL != map) | ||
776 | { | ||
777 | GNUNET_assert ( | ||
778 | GNUNET_SYSERR != | ||
779 | GNUNET_CONTAINER_multihashmap32_iterate (map, &cleanup_iterator, NULL)); | ||
780 | GNUNET_CONTAINER_multihashmap32_destroy (map); | ||
781 | map = NULL; | ||
782 | } | ||
783 | while (NULL != (entry = head_lru)) | ||
784 | { | ||
785 | GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry); | ||
786 | destroy_pooled_connection (entry); | ||
787 | } | ||
788 | GNUNET_assert (NULL == head_not_pooled); | ||
789 | } | ||
790 | |||
791 | |||
792 | /** | ||
793 | * Get a connection handle to @a service. If the connection is opened before | ||
794 | * and the connection handle is present in the connection pool, it is returned | ||
795 | * through @a cb. @a peer_id is used for the lookup in the connection pool. If | ||
796 | * the connection handle is not present in the connection pool, a new connection | ||
797 | * handle is opened for the @a service using @a cfg. Additionally, @a target, | ||
798 | * @a connect_notify_cb can be specified to get notified when @a target is | ||
799 | * connected at @a service. | ||
800 | * | ||
801 | * @note @a connect_notify_cb will not be called if @a target is | ||
802 | * already connected @a service level. Use | ||
803 | * GNUNET_TRANSPORT_check_peer_connected() or a similar function from the | ||
804 | * respective @a service's API to check if the target peer is already connected | ||
805 | * or not. @a connect_notify_cb will be called only once or never (in case @a | ||
806 | * target cannot be connected or is already connected). | ||
807 | * | ||
808 | * @param peer_id the index of the peer | ||
809 | * @param cfg the configuration with which the transport handle has to be | ||
810 | * created if it was not present in the cache | ||
811 | * @param service the service of interest | ||
812 | * @param cb the callback to notify when the transport handle is available | ||
813 | * @param cb_cls the closure for @a cb | ||
814 | * @param target the peer identify of the peer whose connection to our TRANSPORT | ||
815 | * subsystem will be notified through the @a connect_notify_cb. Can be | ||
816 | * NULL | ||
817 | * @param connect_notify_cb the callback to call when the @a target peer is | ||
818 | * connected. This callback will only be called once or never again (in | ||
819 | * case the target peer cannot be connected). Can be NULL | ||
820 | * @param connect_notify_cb_cls the closure for @a connect_notify_cb | ||
821 | * @return the handle which can be used cancel or mark that the handle is no | ||
822 | * longer being used | ||
823 | */ | ||
824 | struct GST_ConnectionPool_GetHandle * | ||
825 | GST_connection_pool_get_handle ( | ||
826 | unsigned int peer_id, | ||
827 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
828 | enum GST_ConnectionPool_Service service, | ||
829 | GST_connection_pool_connection_ready_cb cb, | ||
830 | void *cb_cls, | ||
831 | const struct GNUNET_PeerIdentity *target, | ||
832 | GST_connection_pool_peer_connect_notify connect_notify_cb, | ||
833 | void *connect_notify_cb_cls) | ||
834 | { | ||
835 | struct GST_ConnectionPool_GetHandle *gh; | ||
836 | struct PooledConnection *entry; | ||
837 | struct GNUNET_TESTBED_Operation *op; | ||
838 | void *handle; | ||
839 | uint32_t peer_id32; | ||
840 | |||
841 | peer_id32 = (uint32_t) peer_id; | ||
842 | handle = NULL; | ||
843 | entry = NULL; | ||
844 | if (NULL != map) | ||
845 | entry = GNUNET_CONTAINER_multihashmap32_get (map, peer_id32); | ||
846 | if (NULL != entry) | ||
847 | { | ||
848 | if (entry->in_lru) | ||
849 | { | ||
850 | GNUNET_assert (0 == entry->demand); | ||
851 | expire_task_cancel (entry); | ||
852 | GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry); | ||
853 | entry->in_lru = GNUNET_NO; | ||
854 | } | ||
855 | switch (service) | ||
856 | { | ||
857 | case GST_CONNECTIONPOOL_SERVICE_TRANSPORT: | ||
858 | handle = entry->handle_transport; | ||
859 | if (NULL != handle) | ||
860 | LOG_DEBUG ("Found TRANSPORT handle for peer %u\n", entry->index); | ||
861 | break; | ||
862 | |||
863 | case GST_CONNECTIONPOOL_SERVICE_CORE: | ||
864 | handle = entry->handle_core; | ||
865 | if (NULL != handle) | ||
866 | LOG_DEBUG ("Found CORE handle for peer %u\n", entry->index); | ||
867 | break; | ||
868 | |||
869 | case GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY: | ||
870 | handle = entry->handle_ats_connectivity; | ||
871 | if (NULL != handle) | ||
872 | LOG_DEBUG ("Found ATS CONNECTIVITY handle for peer %u\n", entry->index); | ||
873 | break; | ||
874 | } | ||
875 | } | ||
876 | else | ||
877 | { | ||
878 | entry = GNUNET_new (struct PooledConnection); | ||
879 | entry->index = peer_id32; | ||
880 | if ((NULL != map) && | ||
881 | (GNUNET_CONTAINER_multihashmap32_size (map) < max_size)) | ||
882 | { | ||
883 | GNUNET_assert (GNUNET_OK == | ||
884 | GNUNET_CONTAINER_multihashmap32_put ( | ||
885 | map, | ||
886 | entry->index, | ||
887 | entry, | ||
888 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); | ||
889 | entry->in_pool = GNUNET_YES; | ||
890 | } | ||
891 | else | ||
892 | { | ||
893 | GNUNET_CONTAINER_DLL_insert_tail (head_not_pooled, | ||
894 | tail_not_pooled, | ||
895 | entry); | ||
896 | } | ||
897 | entry->cfg = GNUNET_CONFIGURATION_dup (cfg); | ||
898 | } | ||
899 | entry->demand++; | ||
900 | gh = GNUNET_new (struct GST_ConnectionPool_GetHandle); | ||
901 | gh->entry = entry; | ||
902 | gh->cb = cb; | ||
903 | gh->cb_cls = cb_cls; | ||
904 | gh->target = target; | ||
905 | gh->connect_notify_cb = connect_notify_cb; | ||
906 | gh->connect_notify_cb_cls = connect_notify_cb_cls; | ||
907 | gh->service = service; | ||
908 | GNUNET_CONTAINER_DLL_insert (entry->head_waiting, entry->tail_waiting, gh); | ||
909 | if (NULL != handle) | ||
910 | { | ||
911 | if (NULL == entry->notify_task) | ||
912 | { | ||
913 | if (NULL != search_waiting (entry, entry->head_waiting)) | ||
914 | entry->notify_task = | ||
915 | GNUNET_SCHEDULER_add_now (&connection_ready, entry); | ||
916 | } | ||
917 | return gh; | ||
918 | } | ||
919 | op = NULL; | ||
920 | switch (gh->service) | ||
921 | { | ||
922 | case GST_CONNECTIONPOOL_SERVICE_TRANSPORT: | ||
923 | if (NULL != entry->op_transport) | ||
924 | return gh; /* Operation pending */ | ||
925 | op = GNUNET_TESTBED_operation_create_ (entry, | ||
926 | &opstart_get_handle_transport, | ||
927 | &oprelease_get_handle_transport); | ||
928 | entry->op_transport = op; | ||
929 | break; | ||
930 | |||
931 | case GST_CONNECTIONPOOL_SERVICE_CORE: | ||
932 | if (NULL != entry->op_core) | ||
933 | return gh; /* Operation pending */ | ||
934 | op = GNUNET_TESTBED_operation_create_ (entry, | ||
935 | &opstart_get_handle_core, | ||
936 | &oprelease_get_handle_core); | ||
937 | entry->op_core = op; | ||
938 | break; | ||
939 | |||
940 | case GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY: | ||
941 | if (NULL != entry->op_ats_connectivity) | ||
942 | return gh; /* Operation pending */ | ||
943 | op = | ||
944 | GNUNET_TESTBED_operation_create_ (entry, | ||
945 | &opstart_get_handle_ats_connectivity, | ||
946 | &oprelease_get_handle_ats_connectivity); | ||
947 | entry->op_ats_connectivity = op; | ||
948 | break; | ||
949 | } | ||
950 | GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, op); | ||
951 | GNUNET_TESTBED_operation_begin_wait_ (op); | ||
952 | return gh; | ||
953 | } | ||
954 | |||
955 | |||
956 | /** | ||
957 | * Relinquish a #GST_ConnectionPool_GetHandle object. If the connection | ||
958 | * associated with the object is currently being used by other | ||
959 | * #GST_ConnectionPool_GetHandle objects, it is left in the connection pool. If | ||
960 | * no other objects are using the connection and the connection pool is not full | ||
961 | * then it is placed in a LRU queue. If the connection pool is full, then | ||
962 | * connections from the LRU queue are evicted and closed to create place for | ||
963 | * this connection. If the connection pool if full and the LRU queue is empty, | ||
964 | * then the connection is closed. | ||
965 | * | ||
966 | * @param gh the handle | ||
967 | */ | ||
968 | void | ||
969 | GST_connection_pool_get_handle_done (struct GST_ConnectionPool_GetHandle *gh) | ||
970 | { | ||
971 | struct PooledConnection *entry; | ||
972 | |||
973 | if (NULL == gh) | ||
974 | return; | ||
975 | entry = gh->entry; | ||
976 | LOG_DEBUG ("Cleaning up get handle %p for service %u, peer %u\n", | ||
977 | gh, | ||
978 | gh->service, | ||
979 | entry->index); | ||
980 | if (! gh->connection_ready_called) | ||
981 | { | ||
982 | GNUNET_CONTAINER_DLL_remove (entry->head_waiting, entry->tail_waiting, gh); | ||
983 | if ((NULL == search_waiting (entry, entry->head_waiting)) && | ||
984 | (NULL != entry->notify_task)) | ||
985 | { | ||
986 | GNUNET_SCHEDULER_cancel (entry->notify_task); | ||
987 | entry->notify_task = NULL; | ||
988 | } | ||
989 | } | ||
990 | if (gh->notify_waiting) | ||
991 | { | ||
992 | GNUNET_CONTAINER_DLL_remove (entry->head_notify, entry->tail_notify, gh); | ||
993 | gh->notify_waiting = 0; | ||
994 | } | ||
995 | GNUNET_free (gh); | ||
996 | gh = NULL; | ||
997 | GNUNET_assert (! entry->in_lru); | ||
998 | if (! entry->in_pool) | ||
999 | GNUNET_CONTAINER_DLL_remove (head_not_pooled, tail_not_pooled, entry); | ||
1000 | if (NULL != map) | ||
1001 | { | ||
1002 | if (GNUNET_YES == | ||
1003 | GNUNET_CONTAINER_multihashmap32_contains (map, entry->index)) | ||
1004 | goto unallocate; | ||
1005 | if (GNUNET_CONTAINER_multihashmap32_size (map) == max_size) | ||
1006 | { | ||
1007 | if (NULL == head_lru) | ||
1008 | goto unallocate; | ||
1009 | destroy_pooled_connection (head_lru); | ||
1010 | } | ||
1011 | GNUNET_assert (GNUNET_OK == | ||
1012 | GNUNET_CONTAINER_multihashmap32_put ( | ||
1013 | map, | ||
1014 | entry->index, | ||
1015 | entry, | ||
1016 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1017 | entry->in_pool = GNUNET_YES; | ||
1018 | } | ||
1019 | |||
1020 | unallocate: | ||
1021 | GNUNET_assert (0 < entry->demand); | ||
1022 | entry->demand--; | ||
1023 | if (0 != entry->demand) | ||
1024 | return; | ||
1025 | if (entry->in_pool) | ||
1026 | { | ||
1027 | add_to_lru (entry); | ||
1028 | return; | ||
1029 | } | ||
1030 | destroy_pooled_connection (entry); | ||
1031 | } | ||
diff --git a/src/testbed/gnunet-service-testbed_connectionpool.h b/src/testbed/gnunet-service-testbed_connectionpool.h deleted file mode 100644 index cbab151be..000000000 --- a/src/testbed/gnunet-service-testbed_connectionpool.h +++ /dev/null | |||
@@ -1,172 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-service-testbed_connectionpool.h | ||
23 | * @brief Interface for connection pooling subroutines | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | #include "gnunet_ats_service.h" | ||
27 | #include "gnunet_core_service.h" | ||
28 | #include "gnunet_transport_service.h" | ||
29 | |||
30 | /** | ||
31 | * The request handle for obtaining a pooled connection | ||
32 | */ | ||
33 | struct GST_ConnectionPool_GetHandle; | ||
34 | |||
35 | |||
36 | /** | ||
37 | * The type of service | ||
38 | */ | ||
39 | enum GST_ConnectionPool_Service | ||
40 | { | ||
41 | /** | ||
42 | * Transport service | ||
43 | */ | ||
44 | GST_CONNECTIONPOOL_SERVICE_TRANSPORT = 1, | ||
45 | |||
46 | /** | ||
47 | * Core service | ||
48 | */ | ||
49 | GST_CONNECTIONPOOL_SERVICE_CORE, | ||
50 | |||
51 | /** | ||
52 | * ATS service | ||
53 | */ | ||
54 | GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY | ||
55 | }; | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Initialise the connection pool. | ||
60 | * | ||
61 | * @param size the size of the connection pool. Each entry in the connection | ||
62 | * pool can handle a connection to each of the services enumerated in | ||
63 | * #GST_ConnectionPool_Service | ||
64 | */ | ||
65 | void | ||
66 | GST_connection_pool_init (unsigned int size); | ||
67 | |||
68 | |||
69 | /** | ||
70 | * Cleanup the connection pool | ||
71 | */ | ||
72 | void | ||
73 | GST_connection_pool_destroy (void); | ||
74 | |||
75 | /** | ||
76 | * Functions of this type are called when the needed handle is available for | ||
77 | * usage. These functions are to be registered with the function | ||
78 | * GST_connection_pool_get_handle(). The corresponding handles will be set upon | ||
79 | * success. If they are not set, then it signals an error while opening the | ||
80 | * handles. | ||
81 | * | ||
82 | * @param cls the closure passed to GST_connection_pool_get_handle() | ||
83 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
84 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
85 | * @param ac the handle to ATS, can be NULL if it is not requested | ||
86 | * @param peer_id the identity of the peer. Will be NULL if ch is NULL. In other | ||
87 | * cases, its value being NULL means that CORE connection has failed. | ||
88 | * @param cfg configuration of the peer | ||
89 | */ | ||
90 | typedef void (*GST_connection_pool_connection_ready_cb) ( | ||
91 | void *cls, | ||
92 | struct GNUNET_CORE_Handle *ch, | ||
93 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
94 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
95 | const struct GNUNET_PeerIdentity *peer_id, | ||
96 | const struct GNUNET_CONFIGURATION_Handle *cfg); | ||
97 | |||
98 | |||
99 | /** | ||
100 | * Callback to notify when the target peer given to | ||
101 | * GST_connection_pool_get_handle() is connected. | ||
102 | * | ||
103 | * @param cls the closure given to GST_connection_pool_get_handle() for this | ||
104 | * callback | ||
105 | * @param target the peer identity of the target peer | ||
106 | */ | ||
107 | typedef void (*GST_connection_pool_peer_connect_notify) ( | ||
108 | void *cls, | ||
109 | const struct GNUNET_PeerIdentity *target); | ||
110 | |||
111 | |||
112 | /** | ||
113 | * Get a connection handle to @a service. If the connection is opened before | ||
114 | * and the connection handle is present in the connection pool, it is returned | ||
115 | * through @a cb. @a peer_id is used for the lookup in the connection pool. If | ||
116 | * the connection handle is not present in the connection pool, a new connection | ||
117 | * handle is opened for the @a service using @a cfg. Additionally, @a target, | ||
118 | * @a connect_notify_cb can be specified to get notified when @a target is | ||
119 | * connected at @a service. | ||
120 | * | ||
121 | * @note @a connect_notify_cb will not be called if @a target is | ||
122 | * already connected @a service level. Use | ||
123 | * GNUNET_TRANSPORT_check_peer_connected() or a similar function from the | ||
124 | * respective @a service's API to check if the target peer is already connected | ||
125 | * or not. @a connect_notify_cb will be called only once or never (in case @a | ||
126 | * target cannot be connected or is already connected). | ||
127 | * | ||
128 | * @param peer_id the index of the peer | ||
129 | * @param cfg the configuration with which the transport handle has to be | ||
130 | * created if it was not present in the cache | ||
131 | * @param service the service of interest | ||
132 | * @param cb the callback to notify when the transport handle is available | ||
133 | * @param cb_cls the closure for @a cb | ||
134 | * @param target the peer identify of the peer whose connection to our TRANSPORT | ||
135 | * subsystem will be notified through the @a connect_notify_cb. Can be | ||
136 | * NULL | ||
137 | * @param connect_notify_cb the callback to call when the @a target peer is | ||
138 | * connected. This callback will only be called once or never again (in | ||
139 | * case the target peer cannot be connected). Can be NULL | ||
140 | * @param connect_notify_cb_cls the closure for @a connect_notify_cb | ||
141 | * @return the handle which can be used cancel or mark that the handle is no | ||
142 | * longer being used | ||
143 | */ | ||
144 | struct GST_ConnectionPool_GetHandle * | ||
145 | GST_connection_pool_get_handle ( | ||
146 | unsigned int peer_id, | ||
147 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
148 | enum GST_ConnectionPool_Service service, | ||
149 | GST_connection_pool_connection_ready_cb cb, | ||
150 | void *cb_cls, | ||
151 | const struct GNUNET_PeerIdentity *target, | ||
152 | GST_connection_pool_peer_connect_notify connect_notify_cb, | ||
153 | void *connect_notify_cb_cls); | ||
154 | |||
155 | |||
156 | /** | ||
157 | * Relinquish a #GST_ConnectionPool_GetHandle object. If the connection | ||
158 | * associated with the object is currently being used by other | ||
159 | * #GST_ConnectionPool_GetHandle objects, it is left in the connection pool. If | ||
160 | * no other objects are using the connection and the connection pool is not full | ||
161 | * then it is placed in a LRU queue. If the connection pool is full, then | ||
162 | * connections from the LRU queue are evicted and closed to create place for | ||
163 | * this connection. If the connection pool if full and the LRU queue is empty, | ||
164 | * then the connection is closed. | ||
165 | * | ||
166 | * @param gh the handle | ||
167 | */ | ||
168 | void | ||
169 | GST_connection_pool_get_handle_done (struct GST_ConnectionPool_GetHandle *gh); | ||
170 | |||
171 | |||
172 | /* End of gnunet-service-testbed_connectionpool.h */ | ||
diff --git a/src/testbed/gnunet-service-testbed_cpustatus.c b/src/testbed/gnunet-service-testbed_cpustatus.c deleted file mode 100644 index 5b9528ba3..000000000 --- a/src/testbed/gnunet-service-testbed_cpustatus.c +++ /dev/null | |||
@@ -1,664 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-service-testbed_cpustatus.c | ||
23 | * @brief calls to determine current CPU load | ||
24 | * @author Tzvetan Horozov | ||
25 | * @author Christian Grothoff | ||
26 | * @author Igor Wronsky | ||
27 | * @author Alex Harper (OS X portion) | ||
28 | * @author Sree Harsha Totakura | ||
29 | */ | ||
30 | |||
31 | #include "platform.h" | ||
32 | #include "gnunet_util_lib.h" | ||
33 | #include "gnunet-service-testbed_meminfo.h" | ||
34 | |||
35 | #if SOLARIS | ||
36 | #if HAVE_KSTAT_H | ||
37 | #include <kstat.h> | ||
38 | #endif | ||
39 | #if HAVE_SYS_SYSINFO_H | ||
40 | #include <sys/sysinfo.h> | ||
41 | #endif | ||
42 | #if HAVE_KVM_H | ||
43 | #include <kvm.h> | ||
44 | #endif | ||
45 | #endif | ||
46 | #ifdef BSD | ||
47 | #if HAVE_KVM_H | ||
48 | #include <kvm.h> | ||
49 | #endif | ||
50 | #endif | ||
51 | |||
52 | #ifdef OSX | ||
53 | #include <mach/mach.h> | ||
54 | |||
55 | static processor_cpu_load_info_t prev_cpu_load; | ||
56 | #endif | ||
57 | |||
58 | #define DEBUG_STATUSCALLS GNUNET_NO | ||
59 | |||
60 | #ifdef __linux__ | ||
61 | static FILE *proc_stat; | ||
62 | #endif | ||
63 | |||
64 | /** | ||
65 | * Current CPU load, as percentage of CPU cycles not idle or | ||
66 | * blocked on IO. | ||
67 | */ | ||
68 | static int currentCPULoad; | ||
69 | |||
70 | static double agedCPULoad = -1; | ||
71 | |||
72 | /** | ||
73 | * Current IO load, as percentage of CPU cycles blocked on IO. | ||
74 | */ | ||
75 | static int currentIOLoad; | ||
76 | |||
77 | static double agedIOLoad = -1; | ||
78 | |||
79 | |||
80 | /** | ||
81 | * handle to the file to write the load statistics to | ||
82 | */ | ||
83 | struct GNUNET_BIO_WriteHandle *bw; | ||
84 | |||
85 | struct GNUNET_SCHEDULER_Task *sample_load_task_id; | ||
86 | |||
87 | |||
88 | #ifdef OSX | ||
89 | static int | ||
90 | initMachCpuStats () | ||
91 | { | ||
92 | unsigned int cpu_count; | ||
93 | processor_cpu_load_info_t cpu_load; | ||
94 | mach_msg_type_number_t cpu_msg_count; | ||
95 | kern_return_t kret; | ||
96 | int i, j; | ||
97 | |||
98 | kret = host_processor_info (mach_host_self (), | ||
99 | PROCESSOR_CPU_LOAD_INFO, | ||
100 | &cpu_count, | ||
101 | (processor_info_array_t *) &cpu_load, | ||
102 | &cpu_msg_count); | ||
103 | if (kret != KERN_SUCCESS) | ||
104 | { | ||
105 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "host_processor_info failed."); | ||
106 | return GNUNET_SYSERR; | ||
107 | } | ||
108 | prev_cpu_load = GNUNET_malloc (cpu_count * sizeof(*prev_cpu_load)); | ||
109 | for (i = 0; i < cpu_count; i++) | ||
110 | { | ||
111 | for (j = 0; j < CPU_STATE_MAX; j++) | ||
112 | { | ||
113 | prev_cpu_load[i].cpu_ticks[j] = cpu_load[i].cpu_ticks[j]; | ||
114 | } | ||
115 | } | ||
116 | vm_deallocate (mach_task_self (), | ||
117 | (vm_address_t) cpu_load, | ||
118 | (vm_size_t) (cpu_msg_count * sizeof(*cpu_load))); | ||
119 | return GNUNET_OK; | ||
120 | } | ||
121 | |||
122 | |||
123 | #endif | ||
124 | |||
125 | /** | ||
126 | * Update the currentCPU and currentIO load (and on Linux, memory) values. | ||
127 | * | ||
128 | * Before its first invocation the method initStatusCalls() must be called. | ||
129 | * If there is an error the method returns -1. | ||
130 | */ | ||
131 | static int | ||
132 | updateUsage () | ||
133 | { | ||
134 | currentIOLoad = -1; | ||
135 | currentCPULoad = -1; | ||
136 | #ifdef __linux__ | ||
137 | /* under linux, first try %idle/usage using /proc/stat; | ||
138 | if that does not work, disable /proc/stat for the future | ||
139 | by closing the file and use the next-best method. */ | ||
140 | if (proc_stat != NULL) | ||
141 | { | ||
142 | static unsigned long long last_cpu_results[5] = { 0, 0, 0, 0, 0 }; | ||
143 | static int have_last_cpu = GNUNET_NO; | ||
144 | int ret; | ||
145 | char line[256]; | ||
146 | unsigned long long user_read, system_read, nice_read, idle_read, | ||
147 | iowait_read; | ||
148 | unsigned long long user, system, nice, idle, iowait; | ||
149 | unsigned long long usage_time = 0, total_time = 1; | ||
150 | |||
151 | /* Get the first line with the data */ | ||
152 | rewind (proc_stat); | ||
153 | fflush (proc_stat); | ||
154 | if (NULL == fgets (line, 256, proc_stat)) | ||
155 | { | ||
156 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | ||
157 | "fgets", "/proc/stat"); | ||
158 | proc_stat = NULL; /* don't try again */ | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | iowait_read = 0; | ||
163 | ret = sscanf (line, "%*s %llu %llu %llu %llu %llu", | ||
164 | &user_read, | ||
165 | &system_read, &nice_read, &idle_read, &iowait_read); | ||
166 | if (ret < 4) | ||
167 | { | ||
168 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | ||
169 | "fgets-sscanf", "/proc/stat"); | ||
170 | fclose (proc_stat); | ||
171 | proc_stat = NULL; /* don't try again */ | ||
172 | have_last_cpu = GNUNET_NO; | ||
173 | } | ||
174 | else | ||
175 | { | ||
176 | /* Store the current usage */ | ||
177 | user = user_read - last_cpu_results[0]; | ||
178 | system = system_read - last_cpu_results[1]; | ||
179 | nice = nice_read - last_cpu_results[2]; | ||
180 | idle = idle_read - last_cpu_results[3]; | ||
181 | iowait = iowait_read - last_cpu_results[4]; | ||
182 | /* Calculate the % usage */ | ||
183 | usage_time = user + system + nice; | ||
184 | total_time = usage_time + idle + iowait; | ||
185 | if ((total_time > 0) && (have_last_cpu == GNUNET_YES)) | ||
186 | { | ||
187 | currentCPULoad = (int) (100L * usage_time / total_time); | ||
188 | if (ret > 4) | ||
189 | currentIOLoad = (int) (100L * iowait / total_time); | ||
190 | else | ||
191 | currentIOLoad = -1; /* 2.4 kernel */ | ||
192 | } | ||
193 | /* Store the values for the next calculation */ | ||
194 | last_cpu_results[0] = user_read; | ||
195 | last_cpu_results[1] = system_read; | ||
196 | last_cpu_results[2] = nice_read; | ||
197 | last_cpu_results[3] = idle_read; | ||
198 | last_cpu_results[4] = iowait_read; | ||
199 | have_last_cpu = GNUNET_YES; | ||
200 | return GNUNET_OK; | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | #endif | ||
205 | |||
206 | #ifdef OSX | ||
207 | { | ||
208 | unsigned int cpu_count; | ||
209 | processor_cpu_load_info_t cpu_load; | ||
210 | mach_msg_type_number_t cpu_msg_count; | ||
211 | unsigned long long t_sys, t_user, t_nice, t_idle, t_total; | ||
212 | unsigned long long t_idle_all, t_total_all; | ||
213 | kern_return_t kret; | ||
214 | int i, j; | ||
215 | |||
216 | t_idle_all = t_total_all = 0; | ||
217 | kret = host_processor_info (mach_host_self (), PROCESSOR_CPU_LOAD_INFO, | ||
218 | &cpu_count, | ||
219 | (processor_info_array_t *) &cpu_load, | ||
220 | &cpu_msg_count); | ||
221 | if (kret == KERN_SUCCESS) | ||
222 | { | ||
223 | for (i = 0; i < cpu_count; i++) | ||
224 | { | ||
225 | if (cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM] >= | ||
226 | prev_cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM]) | ||
227 | { | ||
228 | t_sys = cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM] | ||
229 | - prev_cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM]; | ||
230 | } | ||
231 | else | ||
232 | { | ||
233 | t_sys = cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM] | ||
234 | + (ULONG_MAX - prev_cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM] | ||
235 | + 1); | ||
236 | } | ||
237 | |||
238 | if (cpu_load[i].cpu_ticks[CPU_STATE_USER] >= | ||
239 | prev_cpu_load[i].cpu_ticks[CPU_STATE_USER]) | ||
240 | { | ||
241 | t_user = cpu_load[i].cpu_ticks[CPU_STATE_USER] | ||
242 | - prev_cpu_load[i].cpu_ticks[CPU_STATE_USER]; | ||
243 | } | ||
244 | else | ||
245 | { | ||
246 | t_user = cpu_load[i].cpu_ticks[CPU_STATE_USER] | ||
247 | + (ULONG_MAX - prev_cpu_load[i].cpu_ticks[CPU_STATE_USER] | ||
248 | + 1); | ||
249 | } | ||
250 | |||
251 | if (cpu_load[i].cpu_ticks[CPU_STATE_NICE] >= | ||
252 | prev_cpu_load[i].cpu_ticks[CPU_STATE_NICE]) | ||
253 | { | ||
254 | t_nice = cpu_load[i].cpu_ticks[CPU_STATE_NICE] | ||
255 | - prev_cpu_load[i].cpu_ticks[CPU_STATE_NICE]; | ||
256 | } | ||
257 | else | ||
258 | { | ||
259 | t_nice = cpu_load[i].cpu_ticks[CPU_STATE_NICE] | ||
260 | + (ULONG_MAX - prev_cpu_load[i].cpu_ticks[CPU_STATE_NICE] | ||
261 | + 1); | ||
262 | } | ||
263 | |||
264 | if (cpu_load[i].cpu_ticks[CPU_STATE_IDLE] >= | ||
265 | prev_cpu_load[i].cpu_ticks[CPU_STATE_IDLE]) | ||
266 | { | ||
267 | t_idle = cpu_load[i].cpu_ticks[CPU_STATE_IDLE] | ||
268 | - prev_cpu_load[i].cpu_ticks[CPU_STATE_IDLE]; | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | t_idle = cpu_load[i].cpu_ticks[CPU_STATE_IDLE] | ||
273 | + (ULONG_MAX - prev_cpu_load[i].cpu_ticks[CPU_STATE_IDLE] | ||
274 | + 1); | ||
275 | } | ||
276 | t_total = t_sys + t_user + t_nice + t_idle; | ||
277 | t_idle_all += t_idle; | ||
278 | t_total_all += t_total; | ||
279 | } | ||
280 | for (i = 0; i < cpu_count; i++) | ||
281 | { | ||
282 | for (j = 0; j < CPU_STATE_MAX; j++) | ||
283 | { | ||
284 | prev_cpu_load[i].cpu_ticks[j] = cpu_load[i].cpu_ticks[j]; | ||
285 | } | ||
286 | } | ||
287 | if (t_total_all > 0) | ||
288 | currentCPULoad = 100 - (100 * t_idle_all) / t_total_all; | ||
289 | else | ||
290 | currentCPULoad = -1; | ||
291 | vm_deallocate (mach_task_self (), | ||
292 | (vm_address_t) cpu_load, | ||
293 | (vm_size_t) (cpu_msg_count * sizeof(*cpu_load))); | ||
294 | currentIOLoad = -1; /* FIXME-OSX! */ | ||
295 | return GNUNET_OK; | ||
296 | } | ||
297 | else | ||
298 | { | ||
299 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "host_processor_info failed."); | ||
300 | return GNUNET_SYSERR; | ||
301 | } | ||
302 | } | ||
303 | #endif | ||
304 | /* try kstat (Solaris only) */ | ||
305 | #if SOLARIS && HAVE_KSTAT_H && HAVE_SYS_SYSINFO_H | ||
306 | { | ||
307 | static long long last_idlecount; | ||
308 | static long long last_totalcount; | ||
309 | static int kstat_once; /* if open fails, don't keep | ||
310 | trying */ | ||
311 | kstat_ctl_t *kc; | ||
312 | kstat_t *khelper; | ||
313 | long long idlecount; | ||
314 | long long totalcount; | ||
315 | long long deltaidle; | ||
316 | long long deltatotal; | ||
317 | |||
318 | if (kstat_once == 1) | ||
319 | goto ABORT_KSTAT; | ||
320 | kc = kstat_open (); | ||
321 | if (kc == NULL) | ||
322 | { | ||
323 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kstat_close"); | ||
324 | goto ABORT_KSTAT; | ||
325 | } | ||
326 | |||
327 | idlecount = 0; | ||
328 | totalcount = 0; | ||
329 | for (khelper = kc->kc_chain; khelper != NULL; khelper = khelper->ks_next) | ||
330 | { | ||
331 | cpu_stat_t stats; | ||
332 | |||
333 | if (0 != strncmp (khelper->ks_name, "cpu_stat", strlen ("cpu_stat"))) | ||
334 | continue; | ||
335 | if (khelper->ks_data_size > sizeof(cpu_stat_t)) | ||
336 | continue; /* better save then sorry! */ | ||
337 | if (-1 != kstat_read (kc, khelper, &stats)) | ||
338 | { | ||
339 | idlecount += stats.cpu_sysinfo.cpu[CPU_IDLE]; | ||
340 | totalcount | ||
341 | += stats.cpu_sysinfo.cpu[CPU_IDLE] | ||
342 | + stats.cpu_sysinfo.cpu[CPU_USER] | ||
343 | + stats.cpu_sysinfo.cpu[CPU_KERNEL] | ||
344 | + stats.cpu_sysinfo.cpu[CPU_WAIT]; | ||
345 | } | ||
346 | } | ||
347 | if (0 != kstat_close (kc)) | ||
348 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kstat_close"); | ||
349 | if ((idlecount == 0) && (totalcount == 0)) | ||
350 | goto ABORT_KSTAT; /* no stats found => abort */ | ||
351 | deltaidle = idlecount - last_idlecount; | ||
352 | deltatotal = totalcount - last_totalcount; | ||
353 | if ((deltatotal > 0) && (last_totalcount > 0)) | ||
354 | { | ||
355 | currentCPULoad = (unsigned int) (100.0 * deltaidle / deltatotal); | ||
356 | if (currentCPULoad > 100) | ||
357 | currentCPULoad = 100; /* odd */ | ||
358 | if (currentCPULoad < 0) | ||
359 | currentCPULoad = 0; /* odd */ | ||
360 | currentCPULoad = 100 - currentCPULoad; /* computed idle-load before! */ | ||
361 | } | ||
362 | else | ||
363 | currentCPULoad = -1; | ||
364 | currentIOLoad = -1; /* FIXME-SOLARIS! */ | ||
365 | last_idlecount = idlecount; | ||
366 | last_totalcount = totalcount; | ||
367 | return GNUNET_OK; | ||
368 | ABORT_KSTAT: | ||
369 | kstat_once = 1; /* failed, don't try again */ | ||
370 | return GNUNET_SYSERR; | ||
371 | } | ||
372 | #endif | ||
373 | |||
374 | /* insert methods better than getloadavg for | ||
375 | other platforms HERE! */ | ||
376 | |||
377 | /* ok, maybe we have getloadavg on this platform */ | ||
378 | #if HAVE_GETLOADAVG | ||
379 | { | ||
380 | static int warnOnce = 0; | ||
381 | double loadavg; | ||
382 | if (1 != getloadavg (&loadavg, 1)) | ||
383 | { | ||
384 | /* only warn once, if there is a problem with | ||
385 | getloadavg, we're going to hit it frequently... */ | ||
386 | if (warnOnce == 0) | ||
387 | { | ||
388 | warnOnce = 1; | ||
389 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "getloadavg"); | ||
390 | } | ||
391 | return GNUNET_SYSERR; | ||
392 | } | ||
393 | else | ||
394 | { | ||
395 | /* success with getloadavg */ | ||
396 | currentCPULoad = (int) (100 * loadavg); | ||
397 | currentIOLoad = -1; /* FIXME */ | ||
398 | return GNUNET_OK; | ||
399 | } | ||
400 | } | ||
401 | #endif | ||
402 | |||
403 | /* loadaverage not defined and no platform | ||
404 | specific alternative defined | ||
405 | => default: error | ||
406 | */ | ||
407 | return GNUNET_SYSERR; | ||
408 | } | ||
409 | |||
410 | |||
411 | /** | ||
412 | * Update load values (if enough time has expired), | ||
413 | * including computation of averages. Code assumes | ||
414 | * that lock has already been obtained. | ||
415 | */ | ||
416 | static void | ||
417 | updateAgedLoad () | ||
418 | { | ||
419 | static struct GNUNET_TIME_Absolute lastCall; | ||
420 | struct GNUNET_TIME_Relative age; | ||
421 | |||
422 | age = GNUNET_TIME_absolute_get_duration (lastCall); | ||
423 | if ((agedCPULoad == -1) | ||
424 | || (age.rel_value_us > 500000)) | ||
425 | { | ||
426 | /* use smoothing, but do NOT update lastRet at frequencies higher | ||
427 | than 500ms; this makes the smoothing (mostly) independent from | ||
428 | the frequency at which getCPULoad is called (and we don't spend | ||
429 | more time measuring CPU than actually computing something). */ | ||
430 | lastCall = GNUNET_TIME_absolute_get (); | ||
431 | updateUsage (); | ||
432 | if (currentCPULoad == -1) | ||
433 | { | ||
434 | agedCPULoad = -1; | ||
435 | } | ||
436 | else | ||
437 | { | ||
438 | if (agedCPULoad == -1) | ||
439 | { | ||
440 | agedCPULoad = currentCPULoad; | ||
441 | } | ||
442 | else | ||
443 | { | ||
444 | /* for CPU, we don't do the 'fast increase' since CPU is much | ||
445 | more jitterish to begin with */ | ||
446 | agedCPULoad = (agedCPULoad * 31 + currentCPULoad) / 32; | ||
447 | } | ||
448 | } | ||
449 | if (currentIOLoad == -1) | ||
450 | { | ||
451 | agedIOLoad = -1; | ||
452 | } | ||
453 | else | ||
454 | { | ||
455 | if (agedIOLoad == -1) | ||
456 | { | ||
457 | agedIOLoad = currentIOLoad; | ||
458 | } | ||
459 | else | ||
460 | { | ||
461 | /* for IO, we don't do the 'fast increase' since IO is much | ||
462 | more jitterish to begin with */ | ||
463 | agedIOLoad = (agedIOLoad * 31 + currentIOLoad) / 32; | ||
464 | } | ||
465 | } | ||
466 | } | ||
467 | } | ||
468 | |||
469 | |||
470 | /** | ||
471 | * Get the load of the CPU relative to what is allowed. | ||
472 | * @return the CPU load as a percentage of allowed | ||
473 | * (100 is equivalent to full load) | ||
474 | */ | ||
475 | static int | ||
476 | cpu_get_load () | ||
477 | { | ||
478 | updateAgedLoad (); | ||
479 | return (int) agedCPULoad; | ||
480 | } | ||
481 | |||
482 | |||
483 | /** | ||
484 | * Get the load of the CPU relative to what is allowed. | ||
485 | * @return the CPU load as a percentage of allowed | ||
486 | * (100 is equivalent to full load) | ||
487 | */ | ||
488 | static int | ||
489 | disk_get_load () | ||
490 | { | ||
491 | updateAgedLoad (); | ||
492 | return (int) agedIOLoad; | ||
493 | } | ||
494 | |||
495 | |||
496 | /** | ||
497 | * Get the percentage of memory used | ||
498 | * | ||
499 | * @return the percentage of memory used | ||
500 | */ | ||
501 | static unsigned int | ||
502 | mem_get_usage () | ||
503 | { | ||
504 | double percentage; | ||
505 | |||
506 | meminfo (); | ||
507 | percentage = (((double) kb_main_used) / ((double) kb_main_total) * 100.0); | ||
508 | return (unsigned int) percentage; | ||
509 | } | ||
510 | |||
511 | |||
512 | #ifdef __linux__ | ||
513 | #include <dirent.h> | ||
514 | /** | ||
515 | * Returns the number of processes | ||
516 | * | ||
517 | * @return the number of processes | ||
518 | */ | ||
519 | static unsigned int | ||
520 | get_nproc () | ||
521 | { | ||
522 | DIR *dir; | ||
523 | struct dirent *ent; | ||
524 | unsigned int nproc; | ||
525 | |||
526 | dir = opendir ("/proc"); | ||
527 | if (NULL == dir) | ||
528 | return 0; | ||
529 | nproc = 0; | ||
530 | while (NULL != (ent = readdir (dir))) | ||
531 | { | ||
532 | if ((*ent->d_name > '0') && (*ent->d_name <= '9')) | ||
533 | nproc++; | ||
534 | } | ||
535 | closedir (dir); | ||
536 | return nproc; | ||
537 | } | ||
538 | |||
539 | |||
540 | #endif | ||
541 | |||
542 | |||
543 | static void | ||
544 | sample_load_task (void *cls) | ||
545 | { | ||
546 | struct GNUNET_TIME_Absolute now; | ||
547 | char *str; | ||
548 | int nbs; | ||
549 | int ld_cpu; | ||
550 | int ld_disk; | ||
551 | unsigned int mem_usage; | ||
552 | unsigned int nproc; | ||
553 | |||
554 | sample_load_task_id = NULL; | ||
555 | ld_cpu = cpu_get_load (); | ||
556 | ld_disk = disk_get_load (); | ||
557 | if ((-1 == ld_cpu) || (-1 == ld_disk)) | ||
558 | goto reschedule; | ||
559 | mem_usage = mem_get_usage (); | ||
560 | #ifdef __linux__ | ||
561 | nproc = get_nproc (); | ||
562 | #else | ||
563 | nproc = 0; | ||
564 | #endif | ||
565 | now = GNUNET_TIME_absolute_get (); | ||
566 | nbs = GNUNET_asprintf (&str, "%llu %d %d %u %u\n", now.abs_value_us / 1000LL | ||
567 | / 1000LL, | ||
568 | ld_cpu, ld_disk, mem_usage, nproc); | ||
569 | if (0 < nbs) | ||
570 | { | ||
571 | GNUNET_BIO_write (bw, "sample load task", str, nbs); | ||
572 | } | ||
573 | else | ||
574 | GNUNET_break (0); | ||
575 | GNUNET_free (str); | ||
576 | |||
577 | reschedule: | ||
578 | sample_load_task_id = | ||
579 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
580 | &sample_load_task, NULL); | ||
581 | } | ||
582 | |||
583 | |||
584 | /** | ||
585 | * Initialize logging CPU and IO statisticfs. Checks the configuration for | ||
586 | * "STATS_DIR" and logs to a file in that directory. The file is name is | ||
587 | * generated from the hostname and the process's PID. | ||
588 | */ | ||
589 | void | ||
590 | GST_stats_init (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
591 | { | ||
592 | char *hostname; | ||
593 | char *stats_dir; | ||
594 | char *fn; | ||
595 | size_t len; | ||
596 | |||
597 | if (GNUNET_OK != | ||
598 | GNUNET_CONFIGURATION_get_value_filename (cfg, "testbed", | ||
599 | "STATS_DIR", &stats_dir)) | ||
600 | return; | ||
601 | len = GNUNET_OS_get_hostname_max_length (); | ||
602 | hostname = GNUNET_malloc (len); | ||
603 | if (0 != gethostname (hostname, len)) | ||
604 | { | ||
605 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "gethostname"); | ||
606 | GNUNET_free (stats_dir); | ||
607 | GNUNET_free (hostname); | ||
608 | return; | ||
609 | } | ||
610 | fn = NULL; | ||
611 | (void) GNUNET_asprintf (&fn, "%s/%.*s-%jd.dat", stats_dir, (int)len, | ||
612 | hostname, (intmax_t) getpid ()); | ||
613 | GNUNET_free (stats_dir); | ||
614 | GNUNET_free (hostname); | ||
615 | if (NULL == (bw = GNUNET_BIO_write_open_file (fn))) | ||
616 | { | ||
617 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
618 | _ ("Cannot open %s for writing load statistics. " | ||
619 | "Not logging load statistics\n"), fn); | ||
620 | GNUNET_free (fn); | ||
621 | return; | ||
622 | } | ||
623 | GNUNET_free (fn); | ||
624 | sample_load_task_id = GNUNET_SCHEDULER_add_now (&sample_load_task, NULL); | ||
625 | #ifdef __linux__ | ||
626 | proc_stat = fopen ("/proc/stat", "r"); | ||
627 | if (NULL == proc_stat) | ||
628 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | ||
629 | "fopen", "/proc/stat"); | ||
630 | #elif OSX | ||
631 | initMachCpuStats (); | ||
632 | #endif | ||
633 | updateUsage (); /* initialize */ | ||
634 | } | ||
635 | |||
636 | |||
637 | /** | ||
638 | * Shutdown the status calls module. | ||
639 | */ | ||
640 | void | ||
641 | GST_stats_destroy () | ||
642 | { | ||
643 | if (NULL == bw) | ||
644 | return; | ||
645 | #ifdef __linux__ | ||
646 | if (proc_stat != NULL) | ||
647 | { | ||
648 | fclose (proc_stat); | ||
649 | proc_stat = NULL; | ||
650 | } | ||
651 | #elif OSX | ||
652 | GNUNET_free (prev_cpu_load); | ||
653 | #endif | ||
654 | if (NULL != sample_load_task_id) | ||
655 | { | ||
656 | GNUNET_SCHEDULER_cancel (sample_load_task_id); | ||
657 | sample_load_task_id = NULL; | ||
658 | } | ||
659 | GNUNET_break (GNUNET_OK == GNUNET_BIO_write_close (bw, NULL)); | ||
660 | bw = NULL; | ||
661 | } | ||
662 | |||
663 | |||
664 | /* end of cpustatus.c */ | ||
diff --git a/src/testbed/gnunet-service-testbed_links.c b/src/testbed/gnunet-service-testbed_links.c deleted file mode 100644 index fe87d64ea..000000000 --- a/src/testbed/gnunet-service-testbed_links.c +++ /dev/null | |||
@@ -1,1467 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-service-testbed_links.c | ||
23 | * @brief TESTBED service components that deals with starting slave controllers | ||
24 | * and establishing lateral links between controllers | ||
25 | * @author Sree Harsha Totakura | ||
26 | */ | ||
27 | |||
28 | #include "gnunet-service-testbed.h" | ||
29 | |||
30 | /** | ||
31 | * Redefine LOG with a changed log component string | ||
32 | */ | ||
33 | #ifdef LOG | ||
34 | #undef LOG | ||
35 | #endif | ||
36 | #define LOG(kind, ...) \ | ||
37 | GNUNET_log_from (kind, "testbed-links", __VA_ARGS__) | ||
38 | |||
39 | /** | ||
40 | * The event mask for the events we listen from sub-controllers | ||
41 | */ | ||
42 | #define EVENT_MASK (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED) | ||
43 | |||
44 | |||
45 | /** | ||
46 | * States of LCFContext | ||
47 | */ | ||
48 | enum LCFContextState | ||
49 | { | ||
50 | /** | ||
51 | * The Context has been initialized; Nothing has been done on it | ||
52 | */ | ||
53 | INIT, | ||
54 | |||
55 | /** | ||
56 | * Delegated host has been registered at the forwarding controller | ||
57 | */ | ||
58 | DELEGATED_HOST_REGISTERED, | ||
59 | |||
60 | /** | ||
61 | * The slave host has been registered at the forwarding controller | ||
62 | */ | ||
63 | SLAVE_HOST_REGISTERED, | ||
64 | |||
65 | /** | ||
66 | * The context has been finished (may have error) | ||
67 | */ | ||
68 | FINISHED | ||
69 | }; | ||
70 | |||
71 | |||
72 | /** | ||
73 | * Link controllers request forwarding context | ||
74 | */ | ||
75 | struct LCFContext | ||
76 | { | ||
77 | /** | ||
78 | * The LCFContext | ||
79 | */ | ||
80 | struct LCFContext *next; | ||
81 | |||
82 | /** | ||
83 | * The LCFContext | ||
84 | */ | ||
85 | struct LCFContext *prev; | ||
86 | |||
87 | /** | ||
88 | * The gateway which will pass the link message to delegated host | ||
89 | */ | ||
90 | struct Slave *gateway; | ||
91 | |||
92 | /** | ||
93 | * The client which has asked to perform this operation | ||
94 | */ | ||
95 | struct GNUNET_SERVICE_Client *client; | ||
96 | |||
97 | /** | ||
98 | * Handle for operations which are forwarded while linking controllers | ||
99 | */ | ||
100 | struct GNUNET_TESTBED_Operation *op; | ||
101 | |||
102 | /** | ||
103 | * The timeout task | ||
104 | */ | ||
105 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
106 | |||
107 | /** | ||
108 | * The id of the operation which created this context | ||
109 | */ | ||
110 | uint64_t operation_id; | ||
111 | |||
112 | /** | ||
113 | * should the slave controller start the delegated controller? | ||
114 | */ | ||
115 | int is_subordinate; | ||
116 | |||
117 | /** | ||
118 | * The state of this context | ||
119 | */ | ||
120 | enum LCFContextState state; | ||
121 | |||
122 | /** | ||
123 | * The delegated host | ||
124 | */ | ||
125 | uint32_t delegated_host_id; | ||
126 | |||
127 | /** | ||
128 | * The slave host | ||
129 | */ | ||
130 | uint32_t slave_host_id; | ||
131 | }; | ||
132 | |||
133 | |||
134 | /** | ||
135 | * Notification context to be used to notify when connection to the neighbour's | ||
136 | * controller is opened | ||
137 | */ | ||
138 | struct NeighbourConnectNotification | ||
139 | { | ||
140 | /** | ||
141 | * DLL next for inclusion in neighbour's list of notification requests | ||
142 | */ | ||
143 | struct NeighbourConnectNotification *next; | ||
144 | |||
145 | /** | ||
146 | * DLL prev | ||
147 | */ | ||
148 | struct NeighbourConnectNotification *prev; | ||
149 | |||
150 | /** | ||
151 | * The neighbour | ||
152 | */ | ||
153 | struct Neighbour *n; | ||
154 | |||
155 | /** | ||
156 | * The notification callback to call when we are connect to neighbour | ||
157 | */ | ||
158 | GST_NeighbourConnectNotifyCallback cb; | ||
159 | |||
160 | /** | ||
161 | * The closure for the above callback | ||
162 | */ | ||
163 | void *cb_cls; | ||
164 | }; | ||
165 | |||
166 | |||
167 | /** | ||
168 | * A connected controller which is not our child | ||
169 | */ | ||
170 | struct Neighbour | ||
171 | { | ||
172 | /** | ||
173 | * The controller handle | ||
174 | */ | ||
175 | struct GNUNET_TESTBED_Controller *controller; | ||
176 | |||
177 | /** | ||
178 | * Operation handle for opening a lateral connection to another controller. | ||
179 | * Will be NULL if the slave controller is started by this controller | ||
180 | */ | ||
181 | struct GNUNET_TESTBED_Operation *conn_op; | ||
182 | |||
183 | /** | ||
184 | * DLL head for the list of notification requests | ||
185 | */ | ||
186 | struct NeighbourConnectNotification *nl_head; | ||
187 | |||
188 | /** | ||
189 | * DLL tail for the list of notification requests | ||
190 | */ | ||
191 | struct NeighbourConnectNotification *nl_tail; | ||
192 | |||
193 | /** | ||
194 | * Task id for the task to call notifications from the notification list | ||
195 | */ | ||
196 | struct GNUNET_SCHEDULER_Task *notify_task; | ||
197 | |||
198 | /** | ||
199 | * How many references are present currently to this neighbour's connection | ||
200 | */ | ||
201 | unsigned int reference_cnt; | ||
202 | |||
203 | /** | ||
204 | * Is the conn_op inactivated? | ||
205 | */ | ||
206 | unsigned int inactive; | ||
207 | |||
208 | /** | ||
209 | * The id of the host this controller is running on | ||
210 | */ | ||
211 | uint32_t host_id; | ||
212 | }; | ||
213 | |||
214 | |||
215 | /** | ||
216 | * The neighbour list | ||
217 | */ | ||
218 | static struct Neighbour **neighbour_list; | ||
219 | |||
220 | /** | ||
221 | * The size of the neighbour list | ||
222 | */ | ||
223 | static unsigned int neighbour_list_size; | ||
224 | |||
225 | |||
226 | /** | ||
227 | * Context information for establishing a link to neighbour (Used is | ||
228 | * GST_handle_link_controllers() | ||
229 | */ | ||
230 | struct NeighbourConnectCtxt | ||
231 | { | ||
232 | /** | ||
233 | * DLL next for inclusion in the corresponding context list | ||
234 | */ | ||
235 | struct NeighbourConnectCtxt *next; | ||
236 | |||
237 | /** | ||
238 | * DLL tail | ||
239 | */ | ||
240 | struct NeighbourConnectCtxt *prev; | ||
241 | |||
242 | /** | ||
243 | * The neighbour to whom connection should be made | ||
244 | */ | ||
245 | struct Neighbour *n; | ||
246 | |||
247 | /** | ||
248 | * The client requesting the connection | ||
249 | */ | ||
250 | struct GNUNET_SERVICE_Client *client; | ||
251 | |||
252 | /** | ||
253 | * Task to be run upon timeout | ||
254 | */ | ||
255 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
256 | |||
257 | /** | ||
258 | * The notification handle associated with the neighbour's connection request | ||
259 | */ | ||
260 | struct NeighbourConnectNotification *nh; | ||
261 | |||
262 | /** | ||
263 | * The id of the link-controllers operation responsible for creating this | ||
264 | * context | ||
265 | */ | ||
266 | uint64_t op_id; | ||
267 | }; | ||
268 | |||
269 | /** | ||
270 | * DLL head for the list of neighbour connect contexts | ||
271 | */ | ||
272 | struct NeighbourConnectCtxt *ncc_head; | ||
273 | |||
274 | /** | ||
275 | * DLL tail for the list of neighbour connect contexts | ||
276 | */ | ||
277 | struct NeighbourConnectCtxt *ncc_tail; | ||
278 | |||
279 | /** | ||
280 | * A list of directly linked neighbours | ||
281 | */ | ||
282 | struct Slave **GST_slave_list; | ||
283 | |||
284 | /** | ||
285 | * The size of directly linked neighbours list | ||
286 | */ | ||
287 | unsigned int GST_slave_list_size; | ||
288 | |||
289 | /** | ||
290 | * A list of routes | ||
291 | */ | ||
292 | static struct Route **route_list; | ||
293 | |||
294 | /** | ||
295 | * The LCF queue | ||
296 | */ | ||
297 | static struct LCFContext *lcf_head; | ||
298 | |||
299 | /** | ||
300 | * The tail for the LCF queue | ||
301 | */ | ||
302 | static struct LCFContext *lcf_tail; | ||
303 | |||
304 | /** | ||
305 | * The lcf_task handle | ||
306 | */ | ||
307 | static struct GNUNET_SCHEDULER_Task *lcf_proc_task_id; | ||
308 | |||
309 | /** | ||
310 | * The size of the route list | ||
311 | */ | ||
312 | static unsigned int route_list_size; | ||
313 | |||
314 | |||
315 | /** | ||
316 | * Adds a slave to the slave array | ||
317 | * | ||
318 | * @param slave the slave controller to add | ||
319 | */ | ||
320 | static void | ||
321 | slave_list_add (struct Slave *slave) | ||
322 | { | ||
323 | if (slave->host_id >= GST_slave_list_size) | ||
324 | GST_array_grow_large_enough (GST_slave_list, | ||
325 | GST_slave_list_size, | ||
326 | slave->host_id); | ||
327 | GNUNET_assert (NULL == GST_slave_list[slave->host_id]); | ||
328 | GST_slave_list[slave->host_id] = slave; | ||
329 | } | ||
330 | |||
331 | |||
332 | /** | ||
333 | * Clean up all forwarded operation overlay context matching the | ||
334 | * client given in @a cls. | ||
335 | * | ||
336 | * @param cls a `struct GNUNET_SERVICE_Client *` to match | ||
337 | * @param key unused | ||
338 | * @param value the `struct RegisteredHostContext` to search for @a cls | ||
339 | * @return #GNUNET_OK (continue iterating) | ||
340 | */ | ||
341 | static int | ||
342 | drop_client_entries (void *cls, | ||
343 | const struct GNUNET_HashCode *key, | ||
344 | void *value) | ||
345 | { | ||
346 | struct GNUNET_SERVICE_Client *client = cls; | ||
347 | struct RegisteredHostContext *rhc = value; | ||
348 | struct ForwardedOverlayConnectContext *focc; | ||
349 | struct ForwardedOverlayConnectContext *foccn; | ||
350 | |||
351 | for (focc = rhc->focc_dll_head; NULL != focc; focc = foccn) | ||
352 | { | ||
353 | foccn = focc->next; | ||
354 | if (focc->client == client) | ||
355 | GST_cleanup_focc (focc); | ||
356 | } | ||
357 | return GNUNET_OK; | ||
358 | } | ||
359 | |||
360 | |||
361 | /** | ||
362 | * Adds a route to the route list | ||
363 | * | ||
364 | * @param route the route to add | ||
365 | */ | ||
366 | static void | ||
367 | route_list_add (struct Route *route) | ||
368 | { | ||
369 | if (route->dest >= route_list_size) | ||
370 | GST_array_grow_large_enough (route_list, route_list_size, route->dest); | ||
371 | GNUNET_assert (NULL == route_list[route->dest]); | ||
372 | route_list[route->dest] = route; | ||
373 | } | ||
374 | |||
375 | |||
376 | /** | ||
377 | * Add a neighbour to the neighbour list. Grows the neighbour list | ||
378 | * automatically. | ||
379 | * | ||
380 | * @param n the neighbour to add | ||
381 | */ | ||
382 | static void | ||
383 | neighbour_list_add (struct Neighbour *n) | ||
384 | { | ||
385 | if (n->host_id >= neighbour_list_size) | ||
386 | GST_array_grow_large_enough (neighbour_list, neighbour_list_size, | ||
387 | n->host_id); | ||
388 | GNUNET_assert (NULL == neighbour_list[n->host_id]); | ||
389 | neighbour_list[n->host_id] = n; | ||
390 | } | ||
391 | |||
392 | |||
393 | /** | ||
394 | * Cleans up the route list | ||
395 | */ | ||
396 | void | ||
397 | GST_route_list_clear () | ||
398 | { | ||
399 | unsigned int id; | ||
400 | |||
401 | for (id = 0; id < route_list_size; id++) | ||
402 | if (NULL != route_list[id]) | ||
403 | GNUNET_free (route_list[id]); | ||
404 | GNUNET_free (route_list); | ||
405 | route_list = NULL; | ||
406 | } | ||
407 | |||
408 | |||
409 | /** | ||
410 | * Iterator for freeing hash map entries in a slave's reghost_map | ||
411 | * | ||
412 | * @param cls handle to the slave | ||
413 | * @param key current key code | ||
414 | * @param value value in the hash map | ||
415 | * @return #GNUNET_YES if we should continue to iterate, | ||
416 | * #GNUNET_NO if not. | ||
417 | */ | ||
418 | static int | ||
419 | reghost_free_iterator (void *cls, | ||
420 | const struct GNUNET_HashCode *key, | ||
421 | void *value) | ||
422 | { | ||
423 | struct Slave *slave = cls; | ||
424 | struct RegisteredHostContext *rhc = value; | ||
425 | struct ForwardedOverlayConnectContext *focc; | ||
426 | |||
427 | GNUNET_assert (GNUNET_YES == | ||
428 | GNUNET_CONTAINER_multihashmap_remove (slave->reghost_map, key, | ||
429 | value)); | ||
430 | while (NULL != (focc = rhc->focc_dll_head)) | ||
431 | GST_cleanup_focc (focc); | ||
432 | GNUNET_free (value); | ||
433 | return GNUNET_YES; | ||
434 | } | ||
435 | |||
436 | |||
437 | /** | ||
438 | * Kill a #Slave object | ||
439 | * | ||
440 | * @param slave the #Slave object | ||
441 | */ | ||
442 | static void | ||
443 | kill_slave (struct Slave *slave) | ||
444 | { | ||
445 | struct HostRegistration *hr_entry; | ||
446 | |||
447 | while (NULL != (hr_entry = slave->hr_dll_head)) | ||
448 | { | ||
449 | GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, slave->hr_dll_tail, | ||
450 | hr_entry); | ||
451 | GNUNET_free (hr_entry); | ||
452 | } | ||
453 | if (NULL != slave->rhandle) | ||
454 | GNUNET_TESTBED_cancel_registration (slave->rhandle); | ||
455 | GNUNET_assert (GNUNET_SYSERR != | ||
456 | GNUNET_CONTAINER_multihashmap_iterate (slave->reghost_map, | ||
457 | reghost_free_iterator, | ||
458 | slave)); | ||
459 | GNUNET_CONTAINER_multihashmap_destroy (slave->reghost_map); | ||
460 | if (NULL != slave->controller) | ||
461 | GNUNET_TESTBED_controller_disconnect (slave->controller); | ||
462 | if (NULL != slave->controller_proc) | ||
463 | { | ||
464 | LOG_DEBUG ("Stopping a slave\n"); | ||
465 | GNUNET_TESTBED_controller_kill_ (slave->controller_proc); | ||
466 | } | ||
467 | } | ||
468 | |||
469 | |||
470 | /** | ||
471 | * Destroy a #Slave object | ||
472 | * | ||
473 | * @param slave the #Slave object | ||
474 | */ | ||
475 | static void | ||
476 | destroy_slave (struct Slave *slave) | ||
477 | { | ||
478 | if (NULL != slave->controller_proc) | ||
479 | { | ||
480 | GNUNET_TESTBED_controller_destroy_ (slave->controller_proc); | ||
481 | LOG_DEBUG ("Slave stopped\n"); | ||
482 | } | ||
483 | GST_slave_list[slave->host_id] = NULL; | ||
484 | GNUNET_free (slave); | ||
485 | } | ||
486 | |||
487 | |||
488 | /** | ||
489 | * Cleans up the slave list | ||
490 | */ | ||
491 | void | ||
492 | GST_slave_list_clear () | ||
493 | { | ||
494 | struct Slave *slave; | ||
495 | unsigned int id; | ||
496 | |||
497 | for (id = 0; id < GST_slave_list_size; id++) | ||
498 | { | ||
499 | slave = GST_slave_list[id]; | ||
500 | if (NULL == slave) | ||
501 | continue; | ||
502 | kill_slave (slave); | ||
503 | } | ||
504 | for (id = 0; id < GST_slave_list_size; id++) | ||
505 | { | ||
506 | slave = GST_slave_list[id]; | ||
507 | if (NULL == slave) | ||
508 | continue; | ||
509 | destroy_slave (slave); | ||
510 | } | ||
511 | GNUNET_free (GST_slave_list); | ||
512 | GST_slave_list = NULL; | ||
513 | } | ||
514 | |||
515 | |||
516 | /** | ||
517 | * Finds the route with directly connected host as destination through which | ||
518 | * the destination host can be reached | ||
519 | * | ||
520 | * @param host_id the id of the destination host | ||
521 | * @return the route with directly connected destination host; NULL if no route | ||
522 | * is found | ||
523 | */ | ||
524 | struct Route * | ||
525 | GST_find_dest_route (uint32_t host_id) | ||
526 | { | ||
527 | struct Route *route; | ||
528 | |||
529 | if (route_list_size <= host_id) | ||
530 | return NULL; | ||
531 | while (NULL != (route = route_list[host_id])) | ||
532 | { | ||
533 | if (route->thru == GST_context->host_id) | ||
534 | break; | ||
535 | host_id = route->thru; | ||
536 | } | ||
537 | return route; | ||
538 | } | ||
539 | |||
540 | |||
541 | /** | ||
542 | * Function to send a failure response for controller link operation | ||
543 | * | ||
544 | * @param client the client to send the message to | ||
545 | * @param operation_id the operation ID of the controller link request | ||
546 | * @param cfg the configuration with which the delegated controller is started. | ||
547 | * Can be NULL if the delegated controller is not started but just | ||
548 | * linked to. | ||
549 | * @param emsg set to an error message explaining why the controller link | ||
550 | * failed. Setting this to NULL signifies success. !This should be | ||
551 | * NULL if cfg is set! | ||
552 | */ | ||
553 | static void | ||
554 | send_controller_link_response (struct GNUNET_SERVICE_Client *client, | ||
555 | uint64_t operation_id, | ||
556 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
557 | const char *emsg) | ||
558 | { | ||
559 | struct GNUNET_MQ_Envelope *env; | ||
560 | struct GNUNET_TESTBED_ControllerLinkResponse *msg; | ||
561 | char *xconfig; | ||
562 | size_t config_size; | ||
563 | size_t xconfig_size; | ||
564 | uint16_t msize; | ||
565 | |||
566 | GNUNET_assert ((NULL == cfg) || (NULL == emsg)); | ||
567 | xconfig = NULL; | ||
568 | xconfig_size = 0; | ||
569 | config_size = 0; | ||
570 | msize = 0; | ||
571 | if (NULL != cfg) | ||
572 | { | ||
573 | xconfig = GNUNET_TESTBED_compress_cfg_ (cfg, | ||
574 | &config_size, | ||
575 | &xconfig_size); | ||
576 | msize += xconfig_size; | ||
577 | } | ||
578 | if (NULL != emsg) | ||
579 | msize += strlen (emsg); | ||
580 | env = GNUNET_MQ_msg_extra (msg, | ||
581 | msize, | ||
582 | GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT); | ||
583 | if (NULL == emsg) | ||
584 | msg->success = htons (GNUNET_YES); | ||
585 | msg->operation_id = GNUNET_htonll (operation_id); | ||
586 | msg->config_size = htons ((uint16_t) config_size); | ||
587 | if (NULL != xconfig) | ||
588 | { | ||
589 | GNUNET_memcpy (&msg[1], | ||
590 | xconfig, | ||
591 | xconfig_size); | ||
592 | GNUNET_free (xconfig); | ||
593 | } | ||
594 | if (NULL != emsg) | ||
595 | GNUNET_memcpy (&msg[1], | ||
596 | emsg, | ||
597 | strlen (emsg)); | ||
598 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
599 | env); | ||
600 | } | ||
601 | |||
602 | |||
603 | /** | ||
604 | * The Link Controller forwarding task | ||
605 | * | ||
606 | * @param cls the LCFContext | ||
607 | */ | ||
608 | static void | ||
609 | lcf_proc_task (void *cls); | ||
610 | |||
611 | |||
612 | /** | ||
613 | * Completion callback for host registrations while forwarding Link Controller messages | ||
614 | * | ||
615 | * @param cls the LCFContext | ||
616 | * @param emsg the error message; NULL if host registration is successful | ||
617 | */ | ||
618 | static void | ||
619 | lcf_proc_cc (void *cls, | ||
620 | const char *emsg) | ||
621 | { | ||
622 | struct LCFContext *lcf = cls; | ||
623 | |||
624 | GNUNET_assert (NULL == lcf_proc_task_id); | ||
625 | switch (lcf->state) | ||
626 | { | ||
627 | case INIT: | ||
628 | if (NULL != emsg) | ||
629 | goto registration_error; | ||
630 | lcf->state = DELEGATED_HOST_REGISTERED; | ||
631 | lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); | ||
632 | break; | ||
633 | |||
634 | case DELEGATED_HOST_REGISTERED: | ||
635 | if (NULL != emsg) | ||
636 | goto registration_error; | ||
637 | lcf->state = SLAVE_HOST_REGISTERED; | ||
638 | lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); | ||
639 | break; | ||
640 | |||
641 | default: | ||
642 | GNUNET_assert (0); /* Shouldn't reach here */ | ||
643 | } | ||
644 | return; | ||
645 | |||
646 | registration_error: | ||
647 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
648 | "Host registration failed with message: %s\n", | ||
649 | emsg); | ||
650 | lcf->state = FINISHED; | ||
651 | lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, | ||
652 | lcf); | ||
653 | } | ||
654 | |||
655 | |||
656 | /** | ||
657 | * The Link Controller forwarding task | ||
658 | * | ||
659 | * @param cls the LCFContext | ||
660 | */ | ||
661 | static void | ||
662 | lcf_proc_task (void *cls); | ||
663 | |||
664 | |||
665 | /** | ||
666 | * Task to free resources when forwarded link controllers has been timedout | ||
667 | * | ||
668 | * @param cls the LCFContext | ||
669 | */ | ||
670 | static void | ||
671 | lcf_forwarded_operation_timeout (void *cls) | ||
672 | { | ||
673 | struct LCFContext *lcf = cls; | ||
674 | |||
675 | lcf->timeout_task = NULL; | ||
676 | // GST_forwarded_operation_timeout (lcf->fopc, tc); | ||
677 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
678 | "A forwarded controller link operation has timed out\n"); | ||
679 | send_controller_link_response (lcf->client, | ||
680 | lcf->operation_id, | ||
681 | NULL, | ||
682 | "A forwarded controller link operation has timed out\n"); | ||
683 | GNUNET_assert (NULL == lcf_proc_task_id); | ||
684 | lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, | ||
685 | lcf); | ||
686 | } | ||
687 | |||
688 | |||
689 | /** | ||
690 | * The Link Controller forwarding task | ||
691 | * | ||
692 | * @param cls the LCFContext | ||
693 | */ | ||
694 | static void | ||
695 | lcf_proc_task (void *cls) | ||
696 | { | ||
697 | struct LCFContext *lcf = cls; | ||
698 | |||
699 | lcf_proc_task_id = NULL; | ||
700 | switch (lcf->state) | ||
701 | { | ||
702 | case INIT: | ||
703 | if (GNUNET_NO == | ||
704 | GNUNET_TESTBED_is_host_registered_ (GST_host_list | ||
705 | [lcf->delegated_host_id], | ||
706 | lcf->gateway->controller)) | ||
707 | { | ||
708 | GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf, | ||
709 | GST_host_list[lcf->delegated_host_id]); | ||
710 | } | ||
711 | else | ||
712 | { | ||
713 | lcf->state = DELEGATED_HOST_REGISTERED; | ||
714 | lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); | ||
715 | } | ||
716 | break; | ||
717 | |||
718 | case DELEGATED_HOST_REGISTERED: | ||
719 | if (GNUNET_NO == | ||
720 | GNUNET_TESTBED_is_host_registered_ (GST_host_list[lcf->slave_host_id], | ||
721 | lcf->gateway->controller)) | ||
722 | { | ||
723 | GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf, | ||
724 | GST_host_list[lcf->slave_host_id]); | ||
725 | } | ||
726 | else | ||
727 | { | ||
728 | lcf->state = SLAVE_HOST_REGISTERED; | ||
729 | lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); | ||
730 | } | ||
731 | break; | ||
732 | |||
733 | case SLAVE_HOST_REGISTERED: | ||
734 | lcf->op = GNUNET_TESTBED_controller_link (lcf, | ||
735 | lcf->gateway->controller, | ||
736 | GST_host_list[lcf-> | ||
737 | delegated_host_id], | ||
738 | GST_host_list[lcf->slave_host_id], | ||
739 | lcf->is_subordinate); | ||
740 | lcf->timeout_task = | ||
741 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
742 | &lcf_forwarded_operation_timeout, | ||
743 | lcf); | ||
744 | lcf->state = FINISHED; | ||
745 | break; | ||
746 | |||
747 | case FINISHED: | ||
748 | if (NULL != lcf->op) | ||
749 | GNUNET_TESTBED_operation_done (lcf->op); | ||
750 | GNUNET_CONTAINER_DLL_remove (lcf_head, | ||
751 | lcf_tail, | ||
752 | lcf); | ||
753 | GNUNET_free (lcf); | ||
754 | if (NULL != lcf_head) | ||
755 | lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, | ||
756 | lcf_head); | ||
757 | } | ||
758 | } | ||
759 | |||
760 | |||
761 | /** | ||
762 | * Callback for event from slave controllers | ||
763 | * | ||
764 | * @param cls NULL | ||
765 | * @param event information about the event | ||
766 | */ | ||
767 | static void | ||
768 | slave_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) | ||
769 | { | ||
770 | struct LCFContext *lcf; | ||
771 | |||
772 | /* We currently only get here when working on LCFContexts */ | ||
773 | GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type); | ||
774 | lcf = event->op_cls; | ||
775 | GNUNET_assert (lcf->op == event->op); | ||
776 | GNUNET_TESTBED_operation_done (lcf->op); | ||
777 | lcf->op = NULL; | ||
778 | GNUNET_assert (FINISHED == lcf->state); | ||
779 | GNUNET_assert (NULL != lcf->timeout_task); | ||
780 | GNUNET_SCHEDULER_cancel (lcf->timeout_task); | ||
781 | if (NULL == event->details.operation_finished.emsg) | ||
782 | send_controller_link_response (lcf->client, lcf->operation_id, | ||
783 | GNUNET_TESTBED_host_get_cfg_ | ||
784 | (GST_host_list[lcf->delegated_host_id]), | ||
785 | NULL); | ||
786 | else | ||
787 | send_controller_link_response (lcf->client, lcf->operation_id, | ||
788 | NULL, | ||
789 | event->details.operation_finished.emsg); | ||
790 | GNUNET_assert (NULL == lcf_proc_task_id); | ||
791 | lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); | ||
792 | return; | ||
793 | } | ||
794 | |||
795 | |||
796 | /** | ||
797 | * Callback to signal successful startup of the controller process | ||
798 | * | ||
799 | * @param cls the handle to the slave whose status is to be found here | ||
800 | * @param cfg the configuration with which the controller has been started; | ||
801 | * NULL if status is not #GNUNET_OK | ||
802 | * @param status #GNUNET_OK if the startup is successful; #GNUNET_SYSERR if not, | ||
803 | * GNUNET_TESTBED_controller_stop() shouldn't be called in this case | ||
804 | */ | ||
805 | static void | ||
806 | slave_status_cb (void *cls, | ||
807 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
808 | int status) | ||
809 | { | ||
810 | struct Slave *slave = cls; | ||
811 | struct LinkControllersContext *lcc; | ||
812 | |||
813 | lcc = slave->lcc; | ||
814 | if (GNUNET_SYSERR == status) | ||
815 | { | ||
816 | slave->controller_proc = NULL; | ||
817 | /* Stop all link controller forwarding tasks since we shutdown here anyway | ||
818 | and as these tasks they depend on the operation queues which are created | ||
819 | through GNUNET_TESTBED_controller_connect() and in kill_slave() we call | ||
820 | the destructor function GNUNET_TESTBED_controller_disconnect() */ | ||
821 | GST_free_lcf (); | ||
822 | kill_slave (slave); | ||
823 | destroy_slave (slave); | ||
824 | slave = NULL; | ||
825 | LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected slave shutdown\n"); | ||
826 | GNUNET_SCHEDULER_shutdown (); /* We too shutdown */ | ||
827 | goto clean_lcc; | ||
828 | } | ||
829 | slave->controller = | ||
830 | GNUNET_TESTBED_controller_connect (GST_host_list[slave->host_id], | ||
831 | EVENT_MASK, &slave_event_cb, | ||
832 | slave); | ||
833 | if (NULL != slave->controller) | ||
834 | { | ||
835 | send_controller_link_response (lcc->client, lcc->operation_id, cfg, NULL); | ||
836 | } | ||
837 | else | ||
838 | { | ||
839 | send_controller_link_response (lcc->client, lcc->operation_id, NULL, | ||
840 | "Could not connect to delegated controller"); | ||
841 | kill_slave (slave); | ||
842 | destroy_slave (slave); | ||
843 | slave = NULL; | ||
844 | } | ||
845 | |||
846 | clean_lcc: | ||
847 | if (NULL != lcc) | ||
848 | { | ||
849 | if (NULL != lcc->client) | ||
850 | { | ||
851 | GNUNET_SERVICE_client_continue (lcc->client); | ||
852 | lcc->client = NULL; | ||
853 | } | ||
854 | GNUNET_free (lcc); | ||
855 | } | ||
856 | if (NULL != slave) | ||
857 | slave->lcc = NULL; | ||
858 | } | ||
859 | |||
860 | |||
861 | /** | ||
862 | * Trigger notification task if there are notification requests currently | ||
863 | * waiting in the given neighbour. Also activates the neighbour connect operation | ||
864 | * if it was previously inactivated so that the connection to the neighbour can | ||
865 | * be re-used | ||
866 | * | ||
867 | * @param n the neighbour | ||
868 | */ | ||
869 | static void | ||
870 | trigger_notifications (struct Neighbour *n); | ||
871 | |||
872 | |||
873 | /** | ||
874 | * Task to call the notification queued in the notifications list of the given | ||
875 | * neighbour | ||
876 | * | ||
877 | * @param cls the neighbour | ||
878 | */ | ||
879 | static void | ||
880 | neighbour_connect_notify_task (void *cls) | ||
881 | { | ||
882 | struct Neighbour *n = cls; | ||
883 | struct NeighbourConnectNotification *h; | ||
884 | |||
885 | GNUNET_assert (NULL != (h = n->nl_head)); | ||
886 | GNUNET_assert (NULL != n->notify_task); | ||
887 | n->notify_task = NULL; | ||
888 | GNUNET_assert (NULL != n->controller); | ||
889 | GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h); | ||
890 | trigger_notifications (n); | ||
891 | h->cb (h->cb_cls, n->controller); | ||
892 | GNUNET_free (h); | ||
893 | } | ||
894 | |||
895 | |||
896 | /** | ||
897 | * Trigger notification task if there are notification requests currently | ||
898 | * waiting in the given neighbour. Also activates the neighbour connect operation | ||
899 | * if it was previously inactivated so that the connection to the neighbour can | ||
900 | * be re-used | ||
901 | * | ||
902 | * @param n the neighbour | ||
903 | */ | ||
904 | static void | ||
905 | trigger_notifications (struct Neighbour *n) | ||
906 | { | ||
907 | GNUNET_assert (NULL != n->conn_op); | ||
908 | if (NULL == n->nl_head) | ||
909 | return; | ||
910 | if (NULL == n->controller) | ||
911 | return; | ||
912 | if (NULL != n->notify_task) | ||
913 | return; | ||
914 | if (1 == n->inactive) | ||
915 | { | ||
916 | GNUNET_assert (0 == n->reference_cnt); | ||
917 | GNUNET_TESTBED_operation_activate_ (n->conn_op); | ||
918 | n->inactive = 0; | ||
919 | } | ||
920 | n->reference_cnt++; | ||
921 | n->notify_task = | ||
922 | GNUNET_SCHEDULER_add_now (&neighbour_connect_notify_task, n); | ||
923 | } | ||
924 | |||
925 | |||
926 | /** | ||
927 | * Callback to be called when the neighbour connect operation is started. The | ||
928 | * connection to the neighbour is opened here and any pending notifications are | ||
929 | * trigger. | ||
930 | * | ||
931 | * @param cls the neighbour | ||
932 | */ | ||
933 | static void | ||
934 | opstart_neighbour_conn (void *cls) | ||
935 | { | ||
936 | struct Neighbour *n = cls; | ||
937 | |||
938 | GNUNET_assert (NULL != n->conn_op); | ||
939 | GNUNET_assert (NULL == n->controller); | ||
940 | LOG_DEBUG ("Opening connection to controller on host %u\n", n->host_id); | ||
941 | n->controller = GNUNET_TESTBED_controller_connect (GST_host_list[n->host_id], | ||
942 | EVENT_MASK, | ||
943 | &slave_event_cb, | ||
944 | NULL); | ||
945 | trigger_notifications (n); | ||
946 | } | ||
947 | |||
948 | |||
949 | /** | ||
950 | * Callback to be called when the neighbour connect operation is released | ||
951 | * | ||
952 | * @param cls the neighbour | ||
953 | */ | ||
954 | static void | ||
955 | oprelease_neighbour_conn (void *cls) | ||
956 | { | ||
957 | struct Neighbour *n = cls; | ||
958 | |||
959 | GNUNET_assert (0 == n->reference_cnt); | ||
960 | GNUNET_assert (NULL == n->notify_task); | ||
961 | GNUNET_assert (NULL == n->nl_head); | ||
962 | if (NULL != n->controller) | ||
963 | { | ||
964 | LOG_DEBUG ("Closing connection to controller on host %u\n", n->host_id); | ||
965 | GNUNET_TESTBED_controller_disconnect (n->controller); | ||
966 | n->controller = NULL; | ||
967 | } | ||
968 | n->conn_op = NULL; | ||
969 | n->inactive = 0; | ||
970 | } | ||
971 | |||
972 | |||
973 | /** | ||
974 | * Try to open a connection to the given neighbour. If the connection is open | ||
975 | * already, then it is re-used. If not, the request is queued in the operation | ||
976 | * queues responsible for bounding the total number of file descriptors. The | ||
977 | * actual connection will happen when the operation queue marks the | ||
978 | * corresponding operation as active. | ||
979 | * | ||
980 | * @param n the neighbour to open a connection to | ||
981 | * @param cb the notification callback to call when the connection is opened | ||
982 | * @param cb_cls the closure for the above callback | ||
983 | */ | ||
984 | struct NeighbourConnectNotification * | ||
985 | GST_neighbour_get_connection (struct Neighbour *n, | ||
986 | GST_NeighbourConnectNotifyCallback cb, | ||
987 | void *cb_cls) | ||
988 | { | ||
989 | struct NeighbourConnectNotification *h; | ||
990 | |||
991 | GNUNET_assert (NULL != cb); | ||
992 | LOG_DEBUG ("Attempting to get connection to controller on host %u\n", | ||
993 | n->host_id); | ||
994 | h = GNUNET_new (struct NeighbourConnectNotification); | ||
995 | h->n = n; | ||
996 | h->cb = cb; | ||
997 | h->cb_cls = cb_cls; | ||
998 | GNUNET_CONTAINER_DLL_insert_tail (n->nl_head, n->nl_tail, h); | ||
999 | if (NULL == n->conn_op) | ||
1000 | { | ||
1001 | GNUNET_assert (NULL == n->controller); | ||
1002 | n->conn_op = GNUNET_TESTBED_operation_create_ (n, &opstart_neighbour_conn, | ||
1003 | &oprelease_neighbour_conn); | ||
1004 | GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, n->conn_op); | ||
1005 | GNUNET_TESTBED_operation_begin_wait_ (n->conn_op); | ||
1006 | return h; | ||
1007 | } | ||
1008 | trigger_notifications (n); | ||
1009 | return h; | ||
1010 | } | ||
1011 | |||
1012 | |||
1013 | /** | ||
1014 | * Cancel the request for opening a connection to the neighbour | ||
1015 | * | ||
1016 | * @param h the notification handle | ||
1017 | */ | ||
1018 | void | ||
1019 | GST_neighbour_get_connection_cancel (struct NeighbourConnectNotification *h) | ||
1020 | { | ||
1021 | struct Neighbour *n; | ||
1022 | int cleanup_task; | ||
1023 | |||
1024 | n = h->n; | ||
1025 | cleanup_task = (h == n->nl_head) ? GNUNET_YES : GNUNET_NO; | ||
1026 | GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h); | ||
1027 | GNUNET_free (h); | ||
1028 | if (GNUNET_NO == cleanup_task) | ||
1029 | return; | ||
1030 | if (NULL == n->notify_task) | ||
1031 | return; | ||
1032 | GNUNET_assert (0 < n->reference_cnt); | ||
1033 | n->reference_cnt--; | ||
1034 | GNUNET_SCHEDULER_cancel (n->notify_task); | ||
1035 | n->notify_task = NULL; | ||
1036 | if (NULL == n->nl_head) | ||
1037 | { | ||
1038 | if ((0 == n->reference_cnt) && (0 == n->inactive)) | ||
1039 | { | ||
1040 | n->inactive = 1; | ||
1041 | GNUNET_TESTBED_operation_inactivate_ (n->conn_op); | ||
1042 | } | ||
1043 | return; | ||
1044 | } | ||
1045 | trigger_notifications (n); | ||
1046 | } | ||
1047 | |||
1048 | |||
1049 | /** | ||
1050 | * Release the connection to the neighbour. The actual connection will be | ||
1051 | * closed if connections to other neighbour are waiting (to maintain a bound on | ||
1052 | * the total number of connections that are open). | ||
1053 | * | ||
1054 | * @param n the neighbour whose connection can be closed | ||
1055 | */ | ||
1056 | void | ||
1057 | GST_neighbour_release_connection (struct Neighbour *n) | ||
1058 | { | ||
1059 | GNUNET_assert (0 == n->inactive); | ||
1060 | GNUNET_assert (0 < n->reference_cnt); | ||
1061 | n->reference_cnt--; | ||
1062 | if (0 == n->reference_cnt) | ||
1063 | { | ||
1064 | n->inactive = 1; | ||
1065 | GNUNET_TESTBED_operation_inactivate_ (n->conn_op); | ||
1066 | } | ||
1067 | } | ||
1068 | |||
1069 | |||
1070 | /** | ||
1071 | * Cleanup neighbour connect contexts | ||
1072 | * | ||
1073 | * @param ncc the neighbour connect context to cleanup | ||
1074 | */ | ||
1075 | static void | ||
1076 | cleanup_ncc (struct NeighbourConnectCtxt *ncc) | ||
1077 | { | ||
1078 | if (NULL != ncc->nh) | ||
1079 | GST_neighbour_get_connection_cancel (ncc->nh); | ||
1080 | if (NULL != ncc->timeout_task) | ||
1081 | GNUNET_SCHEDULER_cancel (ncc->timeout_task); | ||
1082 | GNUNET_CONTAINER_DLL_remove (ncc_head, | ||
1083 | ncc_tail, | ||
1084 | ncc); | ||
1085 | GNUNET_free (ncc); | ||
1086 | } | ||
1087 | |||
1088 | |||
1089 | /** | ||
1090 | * Cleans up the neighbour list | ||
1091 | */ | ||
1092 | void | ||
1093 | GST_neighbour_list_clean () | ||
1094 | { | ||
1095 | struct Neighbour *n; | ||
1096 | unsigned int id; | ||
1097 | |||
1098 | for (id = 0; id < neighbour_list_size; id++) | ||
1099 | { | ||
1100 | if (NULL == (n = neighbour_list[id])) | ||
1101 | continue; | ||
1102 | if (NULL != n->conn_op) | ||
1103 | GNUNET_TESTBED_operation_release_ (n->conn_op); | ||
1104 | GNUNET_free (n); | ||
1105 | neighbour_list[id] = NULL; | ||
1106 | } | ||
1107 | GNUNET_free (neighbour_list); | ||
1108 | } | ||
1109 | |||
1110 | |||
1111 | /** | ||
1112 | * Get a neighbour from the neighbour list | ||
1113 | * | ||
1114 | * @param id the index of the neighbour in the neighbour list | ||
1115 | * @return the Neighbour; NULL if the given index in invalid (index greater than | ||
1116 | * the list size or neighbour at that index is NULL) | ||
1117 | */ | ||
1118 | struct Neighbour * | ||
1119 | GST_get_neighbour (uint32_t id) | ||
1120 | { | ||
1121 | if (neighbour_list_size <= id) | ||
1122 | return NULL; | ||
1123 | return neighbour_list[id]; | ||
1124 | } | ||
1125 | |||
1126 | |||
1127 | /** | ||
1128 | * Function to cleanup the neighbour connect contexts | ||
1129 | */ | ||
1130 | void | ||
1131 | GST_free_nccq () | ||
1132 | { | ||
1133 | while (NULL != ncc_head) | ||
1134 | cleanup_ncc (ncc_head); | ||
1135 | } | ||
1136 | |||
1137 | |||
1138 | /** | ||
1139 | * Task to be run upon timeout while attempting to connect to the neighbour | ||
1140 | * | ||
1141 | * @param cls the NeighbourConnectCtxt created in GST_handle_link_controllers() | ||
1142 | */ | ||
1143 | static void | ||
1144 | timeout_neighbour_connect (void *cls) | ||
1145 | { | ||
1146 | struct NeighbourConnectCtxt *ncc = cls; | ||
1147 | |||
1148 | ncc->timeout_task = NULL; | ||
1149 | send_controller_link_response (ncc->client, | ||
1150 | ncc->op_id, | ||
1151 | NULL, | ||
1152 | "Could not connect to delegated controller"); | ||
1153 | cleanup_ncc (ncc); | ||
1154 | } | ||
1155 | |||
1156 | |||
1157 | /** | ||
1158 | * Callback called when a connection to the neighbour is made | ||
1159 | * | ||
1160 | * @param cls the NeighbourConnectCtxt created in GST_handle_link_controllers() | ||
1161 | * @param c the handle the neighbour's controller | ||
1162 | */ | ||
1163 | static void | ||
1164 | neighbour_connect_cb (void *cls, | ||
1165 | struct GNUNET_TESTBED_Controller *c) | ||
1166 | { | ||
1167 | struct NeighbourConnectCtxt *ncc = cls; | ||
1168 | |||
1169 | GNUNET_SCHEDULER_cancel (ncc->timeout_task); | ||
1170 | ncc->timeout_task = NULL; | ||
1171 | ncc->nh = NULL; | ||
1172 | GST_neighbour_release_connection (ncc->n); | ||
1173 | send_controller_link_response (ncc->client, | ||
1174 | ncc->op_id, | ||
1175 | NULL, | ||
1176 | NULL); | ||
1177 | cleanup_ncc (ncc); | ||
1178 | } | ||
1179 | |||
1180 | |||
1181 | /** | ||
1182 | * Function to create a neighbour and add it into the neighbour list | ||
1183 | * | ||
1184 | * @param host the host of the neighbour | ||
1185 | */ | ||
1186 | struct Neighbour * | ||
1187 | GST_create_neighbour (struct GNUNET_TESTBED_Host *host) | ||
1188 | { | ||
1189 | struct Neighbour *n; | ||
1190 | |||
1191 | n = GNUNET_new (struct Neighbour); | ||
1192 | n->host_id = GNUNET_TESTBED_host_get_id_ (host); | ||
1193 | neighbour_list_add (n); /* just add; connect on-demand */ | ||
1194 | return n; | ||
1195 | } | ||
1196 | |||
1197 | |||
1198 | /** | ||
1199 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message | ||
1200 | * | ||
1201 | * @param cls identification of the client | ||
1202 | * @param msg the actual message | ||
1203 | */ | ||
1204 | void | ||
1205 | handle_link_controllers (void *cls, | ||
1206 | const struct GNUNET_TESTBED_ControllerLinkRequest *msg) | ||
1207 | { | ||
1208 | struct GNUNET_SERVICE_Client *client = cls; | ||
1209 | struct LCFContext *lcf; | ||
1210 | struct Route *route; | ||
1211 | struct Route *new_route; | ||
1212 | uint64_t op_id; | ||
1213 | uint32_t delegated_host_id; | ||
1214 | uint32_t slave_host_id; | ||
1215 | |||
1216 | if (NULL == GST_context) | ||
1217 | { | ||
1218 | GNUNET_break (0); | ||
1219 | GNUNET_SERVICE_client_drop (client); | ||
1220 | return; | ||
1221 | } | ||
1222 | delegated_host_id = ntohl (msg->delegated_host_id); | ||
1223 | if (delegated_host_id == GST_context->host_id) | ||
1224 | { | ||
1225 | GNUNET_break (0); | ||
1226 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1227 | "Trying to link ourselves\n"); | ||
1228 | GNUNET_SERVICE_client_drop (client); | ||
1229 | return; | ||
1230 | } | ||
1231 | if ((delegated_host_id >= GST_host_list_size) || | ||
1232 | (NULL == GST_host_list[delegated_host_id])) | ||
1233 | { | ||
1234 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1235 | "Delegated host %u not registered with us\n", | ||
1236 | delegated_host_id); | ||
1237 | GNUNET_SERVICE_client_drop (client); | ||
1238 | return; | ||
1239 | } | ||
1240 | slave_host_id = ntohl (msg->slave_host_id); | ||
1241 | if ((slave_host_id >= GST_host_list_size) || | ||
1242 | (NULL == GST_host_list[slave_host_id])) | ||
1243 | { | ||
1244 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1245 | "Slave host %u not registered with us\n", | ||
1246 | slave_host_id); | ||
1247 | GNUNET_SERVICE_client_drop (client); | ||
1248 | return; | ||
1249 | } | ||
1250 | if (slave_host_id == delegated_host_id) | ||
1251 | { | ||
1252 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1253 | "Slave and delegated host are same\n"); | ||
1254 | GNUNET_SERVICE_client_drop (client); | ||
1255 | return; | ||
1256 | } | ||
1257 | op_id = GNUNET_ntohll (msg->operation_id); | ||
1258 | if (slave_host_id == GST_context->host_id) /* Link from us */ | ||
1259 | { | ||
1260 | struct Slave *slave; | ||
1261 | struct LinkControllersContext *lcc; | ||
1262 | |||
1263 | if (1 != msg->is_subordinate) | ||
1264 | { | ||
1265 | struct Neighbour *n; | ||
1266 | struct NeighbourConnectCtxt *ncc; | ||
1267 | |||
1268 | if ((delegated_host_id < neighbour_list_size) && | ||
1269 | (NULL != neighbour_list[delegated_host_id])) | ||
1270 | { | ||
1271 | GNUNET_break (0); | ||
1272 | GNUNET_SERVICE_client_drop (client); | ||
1273 | return; | ||
1274 | } | ||
1275 | LOG_DEBUG ("Received request to establish a link to host %u\n", | ||
1276 | delegated_host_id); | ||
1277 | n = GST_create_neighbour (GST_host_list[delegated_host_id]); | ||
1278 | ncc = GNUNET_new (struct NeighbourConnectCtxt); | ||
1279 | ncc->n = n; | ||
1280 | ncc->op_id = op_id; | ||
1281 | ncc->client = client; | ||
1282 | ncc->nh = GST_neighbour_get_connection (n, | ||
1283 | &neighbour_connect_cb, | ||
1284 | ncc); | ||
1285 | ncc->timeout_task | ||
1286 | = GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
1287 | &timeout_neighbour_connect, | ||
1288 | ncc); | ||
1289 | GNUNET_CONTAINER_DLL_insert_tail (ncc_head, | ||
1290 | ncc_tail, | ||
1291 | ncc); | ||
1292 | GNUNET_SERVICE_client_continue (client); | ||
1293 | return; | ||
1294 | } | ||
1295 | if ((delegated_host_id < GST_slave_list_size) && | ||
1296 | (NULL != GST_slave_list[delegated_host_id])) | ||
1297 | { | ||
1298 | GNUNET_break (0); | ||
1299 | GNUNET_SERVICE_client_drop (client); | ||
1300 | return; | ||
1301 | } | ||
1302 | LOG_DEBUG ("Received request to start and establish a link to host %u\n", | ||
1303 | delegated_host_id); | ||
1304 | slave = GNUNET_new (struct Slave); | ||
1305 | slave->host_id = delegated_host_id; | ||
1306 | slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100, | ||
1307 | GNUNET_NO); | ||
1308 | slave_list_add (slave); | ||
1309 | lcc = GNUNET_new (struct LinkControllersContext); | ||
1310 | lcc->operation_id = op_id; | ||
1311 | lcc->client = client; | ||
1312 | slave->lcc = lcc; | ||
1313 | slave->controller_proc | ||
1314 | = GNUNET_TESTBED_controller_start (GST_context->master_ip, | ||
1315 | GST_host_list[slave->host_id], | ||
1316 | &slave_status_cb, | ||
1317 | slave); | ||
1318 | new_route = GNUNET_new (struct Route); | ||
1319 | new_route->dest = delegated_host_id; | ||
1320 | new_route->thru = GST_context->host_id; | ||
1321 | route_list_add (new_route); | ||
1322 | return; | ||
1323 | } | ||
1324 | |||
1325 | /* Route the request */ | ||
1326 | if (slave_host_id >= route_list_size) | ||
1327 | { | ||
1328 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1329 | "No route towards slave host"); | ||
1330 | GNUNET_SERVICE_client_drop (client); | ||
1331 | return; | ||
1332 | } | ||
1333 | lcf = GNUNET_new (struct LCFContext); | ||
1334 | lcf->delegated_host_id = delegated_host_id; | ||
1335 | lcf->slave_host_id = slave_host_id; | ||
1336 | route = GST_find_dest_route (slave_host_id); | ||
1337 | GNUNET_assert (NULL != route); /* because we add routes carefully */ | ||
1338 | GNUNET_assert (route->dest < GST_slave_list_size); | ||
1339 | GNUNET_assert (NULL != GST_slave_list[route->dest]); | ||
1340 | lcf->is_subordinate = msg->is_subordinate; | ||
1341 | lcf->state = INIT; | ||
1342 | lcf->operation_id = op_id; | ||
1343 | lcf->gateway = GST_slave_list[route->dest]; | ||
1344 | lcf->client = client; | ||
1345 | if (NULL == lcf_head) | ||
1346 | { | ||
1347 | GNUNET_assert (NULL == lcf_proc_task_id); | ||
1348 | GNUNET_CONTAINER_DLL_insert_tail (lcf_head, | ||
1349 | lcf_tail, | ||
1350 | lcf); | ||
1351 | lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, | ||
1352 | lcf); | ||
1353 | } | ||
1354 | else | ||
1355 | { | ||
1356 | GNUNET_CONTAINER_DLL_insert_tail (lcf_head, | ||
1357 | lcf_tail, | ||
1358 | lcf); | ||
1359 | } | ||
1360 | /* FIXME: Adding a new route should happen after the controllers are linked | ||
1361 | * successfully */ | ||
1362 | if (1 != msg->is_subordinate) | ||
1363 | { | ||
1364 | GNUNET_SERVICE_client_continue (client); | ||
1365 | return; | ||
1366 | } | ||
1367 | if ((delegated_host_id < route_list_size) && | ||
1368 | (NULL != route_list[delegated_host_id])) | ||
1369 | { | ||
1370 | GNUNET_break_op (0); /* Are you trying to link delegated host twice | ||
1371 | * with is subordinate flag set to GNUNET_YES? */ | ||
1372 | GNUNET_SERVICE_client_drop (client); | ||
1373 | return; | ||
1374 | } | ||
1375 | new_route = GNUNET_new (struct Route); | ||
1376 | new_route->dest = delegated_host_id; | ||
1377 | new_route->thru = route->dest; | ||
1378 | route_list_add (new_route); | ||
1379 | GNUNET_SERVICE_client_continue (client); | ||
1380 | } | ||
1381 | |||
1382 | |||
1383 | /** | ||
1384 | * Clean up @a client handle if we stored any via #handle_link_controllers(), | ||
1385 | * the given client disconnected. | ||
1386 | * | ||
1387 | * @param client the client that is history | ||
1388 | */ | ||
1389 | void | ||
1390 | GST_link_notify_disconnect (struct GNUNET_SERVICE_Client *client) | ||
1391 | { | ||
1392 | struct NeighbourConnectCtxt *ncc; | ||
1393 | struct NeighbourConnectCtxt *nccn; | ||
1394 | struct LCFContext *lcf; | ||
1395 | struct LCFContext *lcfn; | ||
1396 | |||
1397 | for (ncc = ncc_head; NULL != ncc; ncc = nccn) | ||
1398 | { | ||
1399 | nccn = ncc->next; | ||
1400 | if (ncc->client == client) | ||
1401 | cleanup_ncc (ncc); | ||
1402 | } | ||
1403 | for (unsigned int i = 0; i < GST_slave_list_size; i++) | ||
1404 | { | ||
1405 | struct Slave *slave = GST_slave_list[i]; | ||
1406 | struct LinkControllersContext *lcc; | ||
1407 | |||
1408 | if (NULL == slave) | ||
1409 | continue; | ||
1410 | GNUNET_CONTAINER_multihashmap_iterate (slave->reghost_map, | ||
1411 | &drop_client_entries, | ||
1412 | client); | ||
1413 | lcc = slave->lcc; | ||
1414 | if (NULL == lcc) | ||
1415 | continue; | ||
1416 | if (lcc->client == client) | ||
1417 | { | ||
1418 | slave->lcc = NULL; | ||
1419 | GNUNET_free (lcc); | ||
1420 | } | ||
1421 | } | ||
1422 | for (lcf = lcf_head; NULL != lcf; lcf = lcfn) | ||
1423 | { | ||
1424 | lcfn = lcf->next; | ||
1425 | if ((NULL != lcf) && | ||
1426 | (client == lcf->client)) | ||
1427 | { | ||
1428 | if (NULL != lcf->op) | ||
1429 | GNUNET_TESTBED_operation_done (lcf->op); | ||
1430 | GNUNET_CONTAINER_DLL_remove (lcf_head, | ||
1431 | lcf_tail, | ||
1432 | lcf); | ||
1433 | GNUNET_free (lcf); | ||
1434 | } | ||
1435 | } | ||
1436 | } | ||
1437 | |||
1438 | |||
1439 | /** | ||
1440 | * Cleans up the queue used for forwarding link controllers requests | ||
1441 | */ | ||
1442 | void | ||
1443 | GST_free_lcf () | ||
1444 | { | ||
1445 | struct LCFContext *lcf; | ||
1446 | |||
1447 | if (NULL != lcf_head) | ||
1448 | { | ||
1449 | if (NULL != lcf_proc_task_id) | ||
1450 | { | ||
1451 | GNUNET_SCHEDULER_cancel (lcf_proc_task_id); | ||
1452 | lcf_proc_task_id = NULL; | ||
1453 | } | ||
1454 | } | ||
1455 | GNUNET_assert (NULL == lcf_proc_task_id); | ||
1456 | for (lcf = lcf_head; NULL != lcf; lcf = lcf_head) | ||
1457 | { | ||
1458 | if (NULL != lcf->op) | ||
1459 | GNUNET_TESTBED_operation_done (lcf->op); | ||
1460 | if (NULL != lcf->timeout_task) | ||
1461 | GNUNET_SCHEDULER_cancel (lcf->timeout_task); | ||
1462 | GNUNET_CONTAINER_DLL_remove (lcf_head, | ||
1463 | lcf_tail, | ||
1464 | lcf); | ||
1465 | GNUNET_free (lcf); | ||
1466 | } | ||
1467 | } | ||
diff --git a/src/testbed/gnunet-service-testbed_links.h b/src/testbed/gnunet-service-testbed_links.h deleted file mode 100644 index 74db0bd47..000000000 --- a/src/testbed/gnunet-service-testbed_links.h +++ /dev/null | |||
@@ -1,209 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-service-testbed_links.h | ||
23 | * @brief TESTBED service components that deals with starting slave controllers | ||
24 | * and establishing lateral links between controllers | ||
25 | * @author Sree Harsha Totakura | ||
26 | */ | ||
27 | |||
28 | |||
29 | /** | ||
30 | * A connected controller which is not our child | ||
31 | */ | ||
32 | struct Neighbour; | ||
33 | |||
34 | |||
35 | /** | ||
36 | * Structure representing a connected(directly-linked) controller | ||
37 | */ | ||
38 | struct Slave | ||
39 | { | ||
40 | /** | ||
41 | * The controller process handle if we had started the controller | ||
42 | */ | ||
43 | struct GNUNET_TESTBED_ControllerProc *controller_proc; | ||
44 | |||
45 | /** | ||
46 | * The controller handle | ||
47 | */ | ||
48 | struct GNUNET_TESTBED_Controller *controller; | ||
49 | |||
50 | /** | ||
51 | * handle to lcc which is associated with this slave startup. Should be set to | ||
52 | * NULL when the slave has successfully started up | ||
53 | */ | ||
54 | struct LinkControllersContext *lcc; | ||
55 | |||
56 | /** | ||
57 | * Head of the host registration DLL | ||
58 | */ | ||
59 | struct HostRegistration *hr_dll_head; | ||
60 | |||
61 | /** | ||
62 | * Tail of the host registration DLL | ||
63 | */ | ||
64 | struct HostRegistration *hr_dll_tail; | ||
65 | |||
66 | /** | ||
67 | * The current host registration handle | ||
68 | */ | ||
69 | struct GNUNET_TESTBED_HostRegistrationHandle *rhandle; | ||
70 | |||
71 | /** | ||
72 | * Hashmap to hold Registered host contexts | ||
73 | */ | ||
74 | struct GNUNET_CONTAINER_MultiHashMap *reghost_map; | ||
75 | |||
76 | /** | ||
77 | * The id of the host this controller is running on | ||
78 | */ | ||
79 | uint32_t host_id; | ||
80 | }; | ||
81 | |||
82 | /** | ||
83 | * A list of directly linked neighbours | ||
84 | */ | ||
85 | extern struct Slave **GST_slave_list; | ||
86 | |||
87 | /** | ||
88 | * The size of directly linked neighbours list | ||
89 | */ | ||
90 | extern unsigned int GST_slave_list_size; | ||
91 | |||
92 | |||
93 | /** | ||
94 | * Cleans up the neighbour list | ||
95 | */ | ||
96 | void | ||
97 | GST_neighbour_list_clean (void); | ||
98 | |||
99 | |||
100 | /** | ||
101 | * Get a neighbour from the neighbour list | ||
102 | * | ||
103 | * @param id the index of the neighbour in the neighbour list | ||
104 | * @return the Neighbour; NULL if the given index in invalid (index greater than | ||
105 | * the list size or neighbour at that index is NULL) | ||
106 | */ | ||
107 | struct Neighbour * | ||
108 | GST_get_neighbour (uint32_t id); | ||
109 | |||
110 | |||
111 | /** | ||
112 | * Function to cleanup the neighbour connect contexts | ||
113 | */ | ||
114 | void | ||
115 | GST_free_nccq (void); | ||
116 | |||
117 | |||
118 | /** | ||
119 | * Notification context to be used to notify when connection to the neighbour's | ||
120 | * controller is opened | ||
121 | */ | ||
122 | struct NeighbourConnectNotification; | ||
123 | |||
124 | |||
125 | /** | ||
126 | * The notification callback to call when we are connect to neighbour | ||
127 | * | ||
128 | * @param cls the closure given to GST_neighbour_get_connection() | ||
129 | * @param controller the controller handle to the neighbour | ||
130 | */ | ||
131 | typedef void | ||
132 | (*GST_NeighbourConnectNotifyCallback) (void *cls, | ||
133 | struct GNUNET_TESTBED_Controller * | ||
134 | controller); | ||
135 | |||
136 | |||
137 | /** | ||
138 | * Try to open a connection to the given neighbour. If the connection is open | ||
139 | * already, then it is re-used. If not, the request is queued in the operation | ||
140 | * queues responsible for bounding the total number of file descriptors. The | ||
141 | * actual connection will happen when the operation queue marks the | ||
142 | * corresponding operation as active. | ||
143 | * | ||
144 | * @param n the neighbour to open a connection to | ||
145 | * @param cb the notification callback to call when the connection is opened | ||
146 | * @param cb_cls the closure for the above callback | ||
147 | */ | ||
148 | struct NeighbourConnectNotification * | ||
149 | GST_neighbour_get_connection (struct Neighbour *n, | ||
150 | GST_NeighbourConnectNotifyCallback cb, | ||
151 | void *cb_cls); | ||
152 | |||
153 | |||
154 | /** | ||
155 | * Cancel the request for opening a connection to the neighbour | ||
156 | * | ||
157 | * @param h the notification handle | ||
158 | */ | ||
159 | void | ||
160 | GST_neighbour_get_connection_cancel (struct NeighbourConnectNotification *h); | ||
161 | |||
162 | |||
163 | /** | ||
164 | * Release the connection to the neighbour. The actual connection will be | ||
165 | * closed if connections to other neighbour are waiting (to maintain a bound on | ||
166 | * the total number of connections that are open). | ||
167 | * | ||
168 | * @param n the neighbour whose connection can be closed | ||
169 | */ | ||
170 | void | ||
171 | GST_neighbour_release_connection (struct Neighbour *n); | ||
172 | |||
173 | |||
174 | /** | ||
175 | * Function to create a neighbour and add it into the neighbour list | ||
176 | * | ||
177 | * @param host the host of the neighbour | ||
178 | */ | ||
179 | struct Neighbour * | ||
180 | GST_create_neighbour (struct GNUNET_TESTBED_Host *host); | ||
181 | |||
182 | |||
183 | /** | ||
184 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message | ||
185 | * | ||
186 | * @param cls identification of the client | ||
187 | * @param msg the actual message | ||
188 | */ | ||
189 | void | ||
190 | handle_link_controllers (void *cls, | ||
191 | const struct | ||
192 | GNUNET_TESTBED_ControllerLinkRequest *msg); | ||
193 | |||
194 | |||
195 | /** | ||
196 | * Clean up @a client handle if we stored any via #handle_link_controllers(), | ||
197 | * the given client disconnected. | ||
198 | * | ||
199 | * @param client the client that is history | ||
200 | */ | ||
201 | void | ||
202 | GST_link_notify_disconnect (struct GNUNET_SERVICE_Client *client); | ||
203 | |||
204 | |||
205 | /** | ||
206 | * Cleans up the slave list | ||
207 | */ | ||
208 | void | ||
209 | GST_slave_list_clear (void); | ||
diff --git a/src/testbed/gnunet-service-testbed_meminfo.c b/src/testbed/gnunet-service-testbed_meminfo.c deleted file mode 100644 index 1646b8d19..000000000 --- a/src/testbed/gnunet-service-testbed_meminfo.c +++ /dev/null | |||
@@ -1,279 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | #include "platform.h" | ||
22 | #include "gnunet_util_lib.h" | ||
23 | |||
24 | /* | ||
25 | * File for parsing top-level /proc entities. | ||
26 | * Copyright Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com | ||
27 | * Copyright 1998-2003 Albert Cahalan | ||
28 | * June 2003, Fabian Frederick, disk and slab info | ||
29 | * | ||
30 | * This library is free software; you can redistribute it and/or | ||
31 | * modify it under the terms of the GNU Lesser General Public | ||
32 | * License as published by the Free Software Foundation; either | ||
33 | * version 2.1 of the License, or (at your option) any later version. | ||
34 | * | ||
35 | * This library is distributed in the hope that it will be useful, | ||
36 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
37 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
38 | * Lesser General Public License for more details. | ||
39 | * | ||
40 | * You should have received a copy of the GNU Lesser General Public | ||
41 | * License along with this library; if not, write to the Free Software | ||
42 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
43 | */ | ||
44 | |||
45 | #define BAD_OPEN_MESSAGE \ | ||
46 | "Error: /proc must be mounted\n" \ | ||
47 | " To mount /proc at boot you need an /etc/fstab line like:\n" \ | ||
48 | " proc /proc proc defaults\n" \ | ||
49 | " In the meantime, run \"mount proc /proc -t proc\"\n" | ||
50 | |||
51 | #define STAT_FILE "/proc/stat" | ||
52 | // static int stat_fd = -1; | ||
53 | #define UPTIME_FILE "/proc/uptime" | ||
54 | // static int uptime_fd = -1; | ||
55 | #define LOADAVG_FILE "/proc/loadavg" | ||
56 | // static int loadavg_fd = -1; | ||
57 | #define MEMINFO_FILE "/proc/meminfo" | ||
58 | static int meminfo_fd = -1; | ||
59 | #define VMINFO_FILE "/proc/vmstat" | ||
60 | // static int vminfo_fd = -1; | ||
61 | |||
62 | // As of 2.6.24 /proc/meminfo seems to need 888 on 64-bit, | ||
63 | // and would need 1258 if the obsolete fields were there. | ||
64 | static char buf[2048]; | ||
65 | |||
66 | /* This macro opens filename only if necessary and seeks to 0 so | ||
67 | * that successive calls to the functions are more efficient. | ||
68 | * It also reads the current contents of the file into the global buf. | ||
69 | */ | ||
70 | #define FILE_TO_BUF(filename, fd) do { \ | ||
71 | static int local_n; \ | ||
72 | if (fd == -1 && (fd = open (filename, O_RDONLY)) == -1) { \ | ||
73 | fputs (BAD_OPEN_MESSAGE, stderr); \ | ||
74 | fflush (NULL); \ | ||
75 | _exit (102); \ | ||
76 | } \ | ||
77 | lseek (fd, 0L, SEEK_SET); \ | ||
78 | if ((local_n = read (fd, buf, sizeof buf - 1)) < 0) { \ | ||
79 | perror (filename); \ | ||
80 | fflush (NULL); \ | ||
81 | _exit (103); \ | ||
82 | } \ | ||
83 | buf[local_n] = '\0'; \ | ||
84 | } while (0) | ||
85 | |||
86 | |||
87 | /***********************************************************************/ | ||
88 | /* | ||
89 | * Copyright 1999 by Albert Cahalan; all rights reserved. | ||
90 | * This file may be used subject to the terms and conditions of the | ||
91 | * GNU Library General Public License Version 2, or any later version | ||
92 | * at your option, as published by the Free Software Foundation. | ||
93 | * This program is distributed in the hope that it will be useful, | ||
94 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
95 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
96 | * GNU Library General Public License for more details. | ||
97 | */ | ||
98 | |||
99 | typedef struct mem_table_struct | ||
100 | { | ||
101 | const char *name; /* memory type name */ | ||
102 | unsigned long *slot; /* slot in return struct */ | ||
103 | } mem_table_struct; | ||
104 | |||
105 | static int | ||
106 | compare_mem_table_structs (const void *a, const void *b) | ||
107 | { | ||
108 | return strcmp (((const mem_table_struct *) a)->name, ((const | ||
109 | mem_table_struct *) b) | ||
110 | -> | ||
111 | name); | ||
112 | } | ||
113 | |||
114 | |||
115 | /* example data, following junk, with comments added: | ||
116 | * | ||
117 | * MemTotal: 61768 kB old | ||
118 | * MemFree: 1436 kB old | ||
119 | * MemShared: 0 kB old (now always zero; not calculated) | ||
120 | * Buffers: 1312 kB old | ||
121 | * Cached: 20932 kB old | ||
122 | * Active: 12464 kB new | ||
123 | * Inact_dirty: 7772 kB new | ||
124 | * Inact_clean: 2008 kB new | ||
125 | * Inact_target: 0 kB new | ||
126 | * Inact_laundry: 0 kB new, and might be missing too | ||
127 | * HighTotal: 0 kB | ||
128 | * HighFree: 0 kB | ||
129 | * LowTotal: 61768 kB | ||
130 | * LowFree: 1436 kB | ||
131 | * SwapTotal: 122580 kB old | ||
132 | * SwapFree: 60352 kB old | ||
133 | * Inactive: 20420 kB 2.5.41+ | ||
134 | * Dirty: 0 kB 2.5.41+ | ||
135 | * Writeback: 0 kB 2.5.41+ | ||
136 | * Mapped: 9792 kB 2.5.41+ | ||
137 | * Slab: 4564 kB 2.5.41+ | ||
138 | * Committed_AS: 8440 kB 2.5.41+ | ||
139 | * PageTables: 304 kB 2.5.41+ | ||
140 | * ReverseMaps: 5738 2.5.41+ | ||
141 | * SwapCached: 0 kB 2.5.??+ | ||
142 | * HugePages_Total: 220 2.5.??+ | ||
143 | * HugePages_Free: 138 2.5.??+ | ||
144 | * Hugepagesize: 4096 kB 2.5.??+ | ||
145 | */ | ||
146 | |||
147 | /* obsolete */ | ||
148 | unsigned long kb_main_shared; | ||
149 | /* old but still kicking -- the important stuff */ | ||
150 | unsigned long kb_main_buffers; | ||
151 | unsigned long kb_main_cached; | ||
152 | unsigned long kb_main_free; | ||
153 | unsigned long kb_main_total; | ||
154 | unsigned long kb_swap_free; | ||
155 | unsigned long kb_swap_total; | ||
156 | /* recently introduced */ | ||
157 | unsigned long kb_high_free; | ||
158 | unsigned long kb_high_total; | ||
159 | unsigned long kb_low_free; | ||
160 | unsigned long kb_low_total; | ||
161 | /* 2.4.xx era */ | ||
162 | unsigned long kb_active; | ||
163 | unsigned long kb_inact_laundry; | ||
164 | unsigned long kb_inact_dirty; | ||
165 | unsigned long kb_inact_clean; | ||
166 | unsigned long kb_inact_target; | ||
167 | unsigned long kb_swap_cached; /* late 2.4 and 2.6+ only */ | ||
168 | /* derived values */ | ||
169 | unsigned long kb_swap_used; | ||
170 | unsigned long kb_main_used; | ||
171 | /* 2.5.41+ */ | ||
172 | unsigned long kb_writeback; | ||
173 | unsigned long kb_slab; | ||
174 | unsigned long nr_reversemaps; | ||
175 | unsigned long kb_committed_as; | ||
176 | unsigned long kb_dirty; | ||
177 | unsigned long kb_inactive; | ||
178 | unsigned long kb_mapped; | ||
179 | unsigned long kb_pagetables; | ||
180 | // seen on a 2.6.x kernel: | ||
181 | static unsigned long kb_vmalloc_chunk; | ||
182 | static unsigned long kb_vmalloc_total; | ||
183 | static unsigned long kb_vmalloc_used; | ||
184 | // seen on 2.6.24-rc6-git12 | ||
185 | static unsigned long kb_anon_pages; | ||
186 | static unsigned long kb_bounce; | ||
187 | static unsigned long kb_commit_limit; | ||
188 | static unsigned long kb_nfs_unstable; | ||
189 | static unsigned long kb_swap_reclaimable; | ||
190 | static unsigned long kb_swap_unreclaimable; | ||
191 | |||
192 | void | ||
193 | meminfo (void) | ||
194 | { | ||
195 | char namebuf[16]; /* big enough to hold any row name */ | ||
196 | mem_table_struct findme = { namebuf, NULL }; | ||
197 | mem_table_struct *found; | ||
198 | char *head; | ||
199 | char *tail; | ||
200 | static const mem_table_struct mem_table[] = { | ||
201 | { "Active", &kb_active }, // important | ||
202 | { "AnonPages", &kb_anon_pages }, | ||
203 | { "Bounce", &kb_bounce }, | ||
204 | { "Buffers", &kb_main_buffers }, // important | ||
205 | { "Cached", &kb_main_cached }, // important | ||
206 | { "CommitLimit", &kb_commit_limit }, | ||
207 | { "Committed_AS", &kb_committed_as }, | ||
208 | { "Dirty", &kb_dirty }, // kB version of vmstat nr_dirty | ||
209 | { "HighFree", &kb_high_free }, | ||
210 | { "HighTotal", &kb_high_total }, | ||
211 | { "Inact_clean", &kb_inact_clean }, | ||
212 | { "Inact_dirty", &kb_inact_dirty }, | ||
213 | { "Inact_laundry", &kb_inact_laundry }, | ||
214 | { "Inact_target", &kb_inact_target }, | ||
215 | { "Inactive", &kb_inactive }, // important | ||
216 | { "LowFree", &kb_low_free }, | ||
217 | { "LowTotal", &kb_low_total }, | ||
218 | { "Mapped", &kb_mapped }, // kB version of vmstat nr_mapped | ||
219 | { "MemFree", &kb_main_free }, // important | ||
220 | { "MemShared", &kb_main_shared }, // important, but now gone! | ||
221 | { "MemTotal", &kb_main_total }, // important | ||
222 | { "NFS_Unstable", &kb_nfs_unstable }, | ||
223 | { "PageTables", &kb_pagetables }, // kB version of vmstat nr_page_table_pages | ||
224 | { "ReverseMaps", &nr_reversemaps }, // same as vmstat nr_page_table_pages | ||
225 | { "SReclaimable", &kb_swap_reclaimable }, // "swap reclaimable" (dentry and inode structures) | ||
226 | { "SUnreclaim", &kb_swap_unreclaimable }, | ||
227 | { "Slab", &kb_slab }, // kB version of vmstat nr_slab | ||
228 | { "SwapCached", &kb_swap_cached }, | ||
229 | { "SwapFree", &kb_swap_free }, // important | ||
230 | { "SwapTotal", &kb_swap_total }, // important | ||
231 | { "VmallocChunk", &kb_vmalloc_chunk }, | ||
232 | { "VmallocTotal", &kb_vmalloc_total }, | ||
233 | { "VmallocUsed", &kb_vmalloc_used }, | ||
234 | { "Writeback", &kb_writeback }, // kB version of vmstat nr_writeback | ||
235 | }; | ||
236 | const int mem_table_count = sizeof(mem_table) / sizeof(mem_table_struct); | ||
237 | |||
238 | FILE_TO_BUF (MEMINFO_FILE, meminfo_fd); | ||
239 | |||
240 | kb_inactive = ~0UL; | ||
241 | |||
242 | head = buf; | ||
243 | for (;;) | ||
244 | { | ||
245 | tail = strchr (head, ':'); | ||
246 | if (! tail) | ||
247 | break; | ||
248 | *tail = '\0'; | ||
249 | if (strlen (head) >= sizeof(namebuf)) | ||
250 | { | ||
251 | head = tail + 1; | ||
252 | goto nextline; | ||
253 | } | ||
254 | strcpy (namebuf, head); | ||
255 | found = bsearch (&findme, mem_table, mem_table_count, | ||
256 | sizeof(mem_table_struct), compare_mem_table_structs | ||
257 | ); | ||
258 | head = tail + 1; | ||
259 | if (! found) | ||
260 | goto nextline; | ||
261 | *(found->slot) = (unsigned long) strtoull (head, &tail, 10); | ||
262 | nextline: | ||
263 | tail = strchr (head, '\n'); | ||
264 | if (! tail) | ||
265 | break; | ||
266 | head = tail + 1; | ||
267 | } | ||
268 | if (! kb_low_total) /* low==main except with large-memory support */ | ||
269 | { | ||
270 | kb_low_total = kb_main_total; | ||
271 | kb_low_free = kb_main_free; | ||
272 | } | ||
273 | if (kb_inactive == ~0UL) | ||
274 | { | ||
275 | kb_inactive = kb_inact_dirty + kb_inact_clean + kb_inact_laundry; | ||
276 | } | ||
277 | kb_swap_used = kb_swap_total - kb_swap_free; | ||
278 | kb_main_used = kb_main_total - kb_main_free; | ||
279 | } | ||
diff --git a/src/testbed/gnunet-service-testbed_meminfo.h b/src/testbed/gnunet-service-testbed_meminfo.h deleted file mode 100644 index b993a8a97..000000000 --- a/src/testbed/gnunet-service-testbed_meminfo.h +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /* obsolete */ | ||
22 | extern unsigned long kb_main_shared; | ||
23 | /* old but still kicking -- the important stuff */ | ||
24 | extern unsigned long kb_main_buffers; | ||
25 | extern unsigned long kb_main_cached; | ||
26 | extern unsigned long kb_main_free; | ||
27 | extern unsigned long kb_main_total; | ||
28 | extern unsigned long kb_swap_free; | ||
29 | extern unsigned long kb_swap_total; | ||
30 | /* recently introduced */ | ||
31 | extern unsigned long kb_high_free; | ||
32 | extern unsigned long kb_high_total; | ||
33 | extern unsigned long kb_low_free; | ||
34 | extern unsigned long kb_low_total; | ||
35 | /* 2.4.xx era */ | ||
36 | extern unsigned long kb_active; | ||
37 | extern unsigned long kb_inact_laundry; // grrr... | ||
38 | extern unsigned long kb_inact_dirty; | ||
39 | extern unsigned long kb_inact_clean; | ||
40 | extern unsigned long kb_inact_target; | ||
41 | extern unsigned long kb_swap_cached; /* late 2.4+ */ | ||
42 | /* derived values */ | ||
43 | extern unsigned long kb_swap_used; | ||
44 | extern unsigned long kb_main_used; | ||
45 | /* 2.5.41+ */ | ||
46 | extern unsigned long kb_writeback; | ||
47 | extern unsigned long kb_slab; | ||
48 | extern unsigned long nr_reversemaps; | ||
49 | extern unsigned long kb_committed_as; | ||
50 | extern unsigned long kb_dirty; | ||
51 | extern unsigned long kb_inactive; | ||
52 | extern unsigned long kb_mapped; | ||
53 | extern unsigned long kb_pagetables; | ||
54 | |||
55 | extern void meminfo (void); | ||
diff --git a/src/testbed/gnunet-service-testbed_oc.c b/src/testbed/gnunet-service-testbed_oc.c deleted file mode 100644 index 4fe7c20b3..000000000 --- a/src/testbed/gnunet-service-testbed_oc.c +++ /dev/null | |||
@@ -1,1978 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-service-testbed_oc.c | ||
23 | * @brief code for handling overlay connect operations | ||
24 | * @author Sree Harsha Totakura | ||
25 | */ | ||
26 | |||
27 | #include "gnunet-service-testbed.h" | ||
28 | #include "gnunet-service-testbed_connectionpool.h" | ||
29 | #include "gnunet_transport_hello_service.h" | ||
30 | |||
31 | /** | ||
32 | * Redefine LOG with a changed log component string | ||
33 | */ | ||
34 | #ifdef LOG | ||
35 | #undef LOG | ||
36 | #endif | ||
37 | #define LOG(kind, ...) \ | ||
38 | GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__) | ||
39 | |||
40 | |||
41 | /** | ||
42 | * Context information for requesting ATS to connect to a peer | ||
43 | */ | ||
44 | struct ConnectivitySuggestContext | ||
45 | { | ||
46 | /** | ||
47 | * The transport handle obtained from cache. Do NOT close/disconnect. | ||
48 | */ | ||
49 | struct GNUNET_TRANSPORT_CoreHandle *th_; | ||
50 | |||
51 | /** | ||
52 | * Configuration of the peer from cache. Do not free! | ||
53 | */ | ||
54 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
55 | |||
56 | /** | ||
57 | * The GetCacheHandle for the peer2's transport handle | ||
58 | * (used to offer the HELLO to the peer). | ||
59 | */ | ||
60 | struct GST_ConnectionPool_GetHandle *cgh_p2_th; | ||
61 | |||
62 | /** | ||
63 | * The GetCacheHandle for the peer2's ATS handle. | ||
64 | */ | ||
65 | struct GST_ConnectionPool_GetHandle *cgh_p2_ats; | ||
66 | |||
67 | /** | ||
68 | * The ATS handle for the connectivity suggestion. | ||
69 | */ | ||
70 | struct GNUNET_ATS_ConnectivitySuggestHandle *csh; | ||
71 | }; | ||
72 | |||
73 | |||
74 | /** | ||
75 | * Types for context information we create for overlay connect requests | ||
76 | */ | ||
77 | enum OverlayConnectContextType | ||
78 | { | ||
79 | /** | ||
80 | * This type is used if the overlay connection is local i.e. the connection | ||
81 | * has to be made between local peers | ||
82 | */ | ||
83 | OCC_TYPE_LOCAL, | ||
84 | |||
85 | /** | ||
86 | * Type to be used when the first peer is local and the other peer is on a slave | ||
87 | * controller started by us | ||
88 | */ | ||
89 | OCC_TYPE_REMOTE_SLAVE, | ||
90 | |||
91 | /** | ||
92 | * Type to be used when the first peer is local and the other peer is on a | ||
93 | * controller which is not started by us. | ||
94 | */ | ||
95 | OCC_TYPE_REMOTE_LATERAL | ||
96 | }; | ||
97 | |||
98 | |||
99 | /** | ||
100 | * Context data for operations on second peer in local overlay connection | ||
101 | * contexts | ||
102 | */ | ||
103 | struct LocalPeer2Context | ||
104 | { | ||
105 | /** | ||
106 | * The handle for offering the HELLO of the first peer to the second | ||
107 | * peer. | ||
108 | */ | ||
109 | struct GNUNET_TRANSPORT_OfferHelloHandle *ohh; | ||
110 | |||
111 | /** | ||
112 | * The transport ConnectivitySuggestContext | ||
113 | */ | ||
114 | struct ConnectivitySuggestContext tcc; | ||
115 | }; | ||
116 | |||
117 | |||
118 | /** | ||
119 | * Context data for operations on second peer in remote overlay connection | ||
120 | * contexts | ||
121 | */ | ||
122 | struct RemotePeer2Context | ||
123 | { | ||
124 | /** | ||
125 | * Controller of peer 2; If #OCC_TYPE_REMOTE_LATERAL is the type of overlay | ||
126 | * connection then this can be NULL until the connection to the controller is | ||
127 | * established | ||
128 | */ | ||
129 | struct GNUNET_TESTBED_Controller *p2c; | ||
130 | |||
131 | /** | ||
132 | * Operation context for the suboperation we start to get the identity of the | ||
133 | * second peer | ||
134 | */ | ||
135 | struct OperationContext *opc; | ||
136 | |||
137 | /** | ||
138 | * Notification handle acquire to connect to a remote controller. Only used | ||
139 | * if the type of overlay connection is #OCC_TYPE_REMOTE_LATERAL. | ||
140 | */ | ||
141 | struct NeighbourConnectNotification *ncn; | ||
142 | |||
143 | /** | ||
144 | * The neighbour handle. Only used if the type of overlay connection is | ||
145 | * #OCC_TYPE_REMOTE_LATERAL. | ||
146 | */ | ||
147 | struct Neighbour *p2n; | ||
148 | }; | ||
149 | |||
150 | /** | ||
151 | * Context information for connecting 2 peers in overlay. | ||
152 | */ | ||
153 | struct OverlayConnectContext | ||
154 | { | ||
155 | /** | ||
156 | * The next pointer for maintaining a DLL of all OverlayConnectContexts | ||
157 | */ | ||
158 | struct OverlayConnectContext *next; | ||
159 | |||
160 | /** | ||
161 | * The prev pointer for maintaining a DLL of all OverlayConnectContexts | ||
162 | */ | ||
163 | struct OverlayConnectContext *prev; | ||
164 | |||
165 | /** | ||
166 | * The client which has requested for overlay connection. This is used to send | ||
167 | * either a success of failure message | ||
168 | */ | ||
169 | struct GNUNET_SERVICE_Client *client; | ||
170 | |||
171 | /** | ||
172 | * the first peer which is to expect an overlay connection from the second peer. | ||
173 | */ | ||
174 | struct Peer *peer; | ||
175 | |||
176 | /** | ||
177 | * Transport handle of the first peer obtained from cache to get its HELLO. Do | ||
178 | * NOT close/disconnect. | ||
179 | */ | ||
180 | struct GNUNET_TRANSPORT_CoreHandle *p1th_; | ||
181 | |||
182 | /** | ||
183 | * The #GST_ConnectionPool_GetHandle for the peer1's transport handle | ||
184 | */ | ||
185 | struct GST_ConnectionPool_GetHandle *cgh_p1th; | ||
186 | |||
187 | /** | ||
188 | * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE | ||
189 | * level peer connects and to get our identity. | ||
190 | */ | ||
191 | struct GST_ConnectionPool_GetHandle *cgh_ch; | ||
192 | |||
193 | /** | ||
194 | * HELLO of the first peer. This should be sent to the second peer. | ||
195 | */ | ||
196 | struct GNUNET_MessageHeader *hello; | ||
197 | |||
198 | /** | ||
199 | * Get GetHelloHandle to acquire a HELLO of the first peer | ||
200 | */ | ||
201 | struct GNUNET_TRANSPORT_HelloGetHandle *ghh; | ||
202 | |||
203 | /** | ||
204 | * The error message we send if this overlay connect operation has timed out | ||
205 | */ | ||
206 | char *emsg; | ||
207 | |||
208 | /** | ||
209 | * Context information for operations on the second peer | ||
210 | */ | ||
211 | union | ||
212 | { | ||
213 | /** | ||
214 | * Context information to be used if the second peer is local | ||
215 | */ | ||
216 | struct LocalPeer2Context local; | ||
217 | |||
218 | /** | ||
219 | * Context information to be used if the second peer is remote | ||
220 | */ | ||
221 | struct RemotePeer2Context remote; | ||
222 | } p2ctx; | ||
223 | |||
224 | /** | ||
225 | * The peer identity of the first peer | ||
226 | */ | ||
227 | struct GNUNET_PeerIdentity peer_identity; | ||
228 | |||
229 | /** | ||
230 | * The peer identity of the other peer | ||
231 | */ | ||
232 | struct GNUNET_PeerIdentity other_peer_identity; | ||
233 | |||
234 | /** | ||
235 | * The id of the operation responsible for creating this context | ||
236 | */ | ||
237 | uint64_t op_id; | ||
238 | |||
239 | /** | ||
240 | * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to | ||
241 | * connect to peer 2 | ||
242 | */ | ||
243 | struct GNUNET_SCHEDULER_Task *send_hello_task; | ||
244 | |||
245 | /** | ||
246 | * The id of the overlay connect timeout task | ||
247 | */ | ||
248 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
249 | |||
250 | /** | ||
251 | * The id of the cleanup task | ||
252 | */ | ||
253 | struct GNUNET_SCHEDULER_Task *cleanup_task; | ||
254 | |||
255 | /** | ||
256 | * The type of this context information | ||
257 | */ | ||
258 | enum OverlayConnectContextType type; | ||
259 | |||
260 | /** | ||
261 | * The id of the second peer which has to connect to the first peer | ||
262 | */ | ||
263 | uint32_t other_peer_id; | ||
264 | }; | ||
265 | |||
266 | |||
267 | /** | ||
268 | * Context information for remote overlay connect operations. Remote overlay | ||
269 | * connections are used when peers A and B reside on different hosts. In these | ||
270 | * operations the host controller for peer B is asked by the host controller of | ||
271 | * peer A to make peer B connect to peer A by sending the controller of peer B | ||
272 | * the HELLO of peer A. | ||
273 | */ | ||
274 | struct RemoteOverlayConnectCtx | ||
275 | { | ||
276 | /** | ||
277 | * the next pointer for DLL | ||
278 | */ | ||
279 | struct RemoteOverlayConnectCtx *next; | ||
280 | |||
281 | /** | ||
282 | * the prev pointer for DLL | ||
283 | */ | ||
284 | struct RemoteOverlayConnectCtx *prev; | ||
285 | |||
286 | /** | ||
287 | * The peer handle of peer B | ||
288 | */ | ||
289 | struct Peer *peer; | ||
290 | |||
291 | /** | ||
292 | * Peer A's HELLO | ||
293 | */ | ||
294 | struct GNUNET_MessageHeader *hello; | ||
295 | |||
296 | /** | ||
297 | * The handle for offering HELLO | ||
298 | */ | ||
299 | struct GNUNET_TRANSPORT_OfferHelloHandle *ohh; | ||
300 | |||
301 | /** | ||
302 | * The transport try connect context | ||
303 | */ | ||
304 | struct ConnectivitySuggestContext tcc; | ||
305 | |||
306 | /** | ||
307 | * The peer identity of peer A | ||
308 | */ | ||
309 | struct GNUNET_PeerIdentity a_id; | ||
310 | |||
311 | /** | ||
312 | * Task for offering HELLO of A to B and doing try_connect | ||
313 | */ | ||
314 | struct GNUNET_SCHEDULER_Task *attempt_connect_task_id; | ||
315 | |||
316 | /** | ||
317 | * Task to timeout RequestOverlayConnect | ||
318 | */ | ||
319 | struct GNUNET_SCHEDULER_Task *timeout_rocc_task_id; | ||
320 | |||
321 | /** | ||
322 | * The id of the operation responsible for creating this context | ||
323 | */ | ||
324 | uint64_t op_id; | ||
325 | }; | ||
326 | |||
327 | |||
328 | /** | ||
329 | * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown | ||
330 | */ | ||
331 | static struct OverlayConnectContext *occq_head; | ||
332 | |||
333 | /** | ||
334 | * DLL tail for OverlayConnectContext DLL | ||
335 | */ | ||
336 | static struct OverlayConnectContext *occq_tail; | ||
337 | |||
338 | /** | ||
339 | * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during | ||
340 | * shutdown | ||
341 | */ | ||
342 | static struct RemoteOverlayConnectCtx *roccq_head; | ||
343 | |||
344 | /** | ||
345 | * DLL tail for RequectOverlayConnectContext DLL | ||
346 | */ | ||
347 | static struct RemoteOverlayConnectCtx *roccq_tail; | ||
348 | |||
349 | |||
350 | /** | ||
351 | * Cleans up ForwardedOverlayConnectContext | ||
352 | * | ||
353 | * @param focc the ForwardedOverlayConnectContext to cleanup | ||
354 | */ | ||
355 | void | ||
356 | GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc) | ||
357 | { | ||
358 | struct RegisteredHostContext *rhc = focc->rhc; | ||
359 | |||
360 | GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, | ||
361 | rhc->focc_dll_tail, | ||
362 | focc); | ||
363 | GNUNET_free (focc->orig_msg); | ||
364 | GNUNET_free (focc); | ||
365 | } | ||
366 | |||
367 | |||
368 | /** | ||
369 | * Timeout task for cancelling a forwarded overlay connect connect | ||
370 | * | ||
371 | * @param cls the `struct ForwardedOperationContext` | ||
372 | */ | ||
373 | static void | ||
374 | forwarded_overlay_connect_timeout (void *cls) | ||
375 | { | ||
376 | struct ForwardedOperationContext *fopc = cls; | ||
377 | struct RegisteredHostContext *rhc; | ||
378 | struct ForwardedOverlayConnectContext *focc; | ||
379 | |||
380 | fopc->timeout_task = NULL; | ||
381 | rhc = fopc->cls; | ||
382 | focc = rhc->focc_dll_head; | ||
383 | LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", | ||
384 | focc->peer1, | ||
385 | focc->peer2); | ||
386 | GST_cleanup_focc (focc); | ||
387 | GST_forwarded_operation_timeout (fopc); | ||
388 | if (NULL != rhc->focc_dll_head) | ||
389 | GST_process_next_focc (rhc); | ||
390 | } | ||
391 | |||
392 | |||
393 | /** | ||
394 | * Callback to be called when forwarded overlay connection operation has a reply | ||
395 | * from the sub-controller successful. We have to relay the reply msg back to | ||
396 | * the client | ||
397 | * | ||
398 | * @param cls ForwardedOperationContext | ||
399 | * @param msg the peer create success message | ||
400 | */ | ||
401 | static void | ||
402 | forwarded_overlay_connect_listener (void *cls, | ||
403 | const struct GNUNET_MessageHeader *msg) | ||
404 | { | ||
405 | struct ForwardedOperationContext *fopc = cls; | ||
406 | struct RegisteredHostContext *rhc; | ||
407 | struct ForwardedOverlayConnectContext *focc; | ||
408 | |||
409 | rhc = fopc->cls; | ||
410 | GST_forwarded_operation_reply_relay (cls, msg); | ||
411 | focc = rhc->focc_dll_head; | ||
412 | GST_cleanup_focc (focc); | ||
413 | if (NULL != rhc->focc_dll_head) | ||
414 | GST_process_next_focc (rhc); | ||
415 | } | ||
416 | |||
417 | |||
418 | /** | ||
419 | * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext | ||
420 | * | ||
421 | * @param rhc the RegisteredHostContext | ||
422 | */ | ||
423 | void | ||
424 | GST_process_next_focc (struct RegisteredHostContext *rhc) | ||
425 | { | ||
426 | struct ForwardedOperationContext *fopc; | ||
427 | struct ForwardedOverlayConnectContext *focc; | ||
428 | struct Peer *peer; | ||
429 | struct Slave *slave; | ||
430 | |||
431 | focc = rhc->focc_dll_head; | ||
432 | GNUNET_assert (NULL != focc); | ||
433 | GNUNET_assert (RHC_DONE == rhc->state); | ||
434 | GNUNET_assert (VALID_PEER_ID (focc->peer1)); | ||
435 | peer = GST_peer_list[focc->peer1]; | ||
436 | GNUNET_assert (GNUNET_YES == peer->is_remote); | ||
437 | GNUNET_assert (NULL != (slave = peer->details.remote.slave)); | ||
438 | fopc = GNUNET_new (struct ForwardedOperationContext); | ||
439 | fopc->client = focc->client; | ||
440 | fopc->operation_id = focc->operation_id; | ||
441 | fopc->cls = rhc; | ||
442 | fopc->type = OP_OVERLAY_CONNECT; | ||
443 | fopc->opc = | ||
444 | GNUNET_TESTBED_forward_operation_msg_ (slave->controller, | ||
445 | focc->operation_id, | ||
446 | focc->orig_msg, | ||
447 | &forwarded_overlay_connect_listener, | ||
448 | fopc); | ||
449 | GNUNET_free (focc->orig_msg); | ||
450 | focc->orig_msg = NULL; | ||
451 | fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
452 | & | ||
453 | forwarded_overlay_connect_timeout, | ||
454 | fopc); | ||
455 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, | ||
456 | fopcq_tail, | ||
457 | fopc); | ||
458 | } | ||
459 | |||
460 | |||
461 | /** | ||
462 | * Cleans up any used handles in local peer2 context | ||
463 | * | ||
464 | * @param lp2c the local peer2 context information | ||
465 | */ | ||
466 | static void | ||
467 | cleanup_occ_lp2c (struct LocalPeer2Context *lp2c) | ||
468 | { | ||
469 | if (NULL != lp2c->ohh) | ||
470 | { | ||
471 | GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh); | ||
472 | lp2c->ohh = NULL; | ||
473 | } | ||
474 | if (NULL != lp2c->tcc.cgh_p2_th) | ||
475 | { | ||
476 | GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_th); | ||
477 | lp2c->tcc.cgh_p2_th = NULL; | ||
478 | } | ||
479 | if (NULL != lp2c->tcc.cgh_p2_ats) | ||
480 | { | ||
481 | GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_ats); | ||
482 | lp2c->tcc.cgh_p2_ats = NULL; | ||
483 | } | ||
484 | if (NULL != lp2c->tcc.csh) | ||
485 | { | ||
486 | GNUNET_ATS_connectivity_suggest_cancel (lp2c->tcc.csh); | ||
487 | lp2c->tcc.csh = NULL; | ||
488 | } | ||
489 | } | ||
490 | |||
491 | |||
492 | /** | ||
493 | * Cleans up any used handles in remote peer2 context. Relinquishes the | ||
494 | * remote controller connection if it has been established on-demand. | ||
495 | * | ||
496 | * @param rp2c the remote peer2 context information | ||
497 | */ | ||
498 | static void | ||
499 | cleanup_occ_rp2c (struct RemotePeer2Context *rp2c) | ||
500 | { | ||
501 | if (NULL != rp2c->opc) | ||
502 | { | ||
503 | GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc); | ||
504 | rp2c->opc = NULL; | ||
505 | } | ||
506 | if (NULL != rp2c->ncn) | ||
507 | { | ||
508 | GST_neighbour_get_connection_cancel (rp2c->ncn); | ||
509 | rp2c->ncn = NULL; | ||
510 | } | ||
511 | if ((NULL != rp2c->p2c) && (NULL != rp2c->p2n)) | ||
512 | { | ||
513 | GST_neighbour_release_connection (rp2c->p2n); | ||
514 | rp2c->p2n = NULL; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | |||
519 | /** | ||
520 | * Condition for checking if given peer is ready to be destroyed | ||
521 | * | ||
522 | * @param peer the peer to check | ||
523 | */ | ||
524 | #define PEER_EXPIRED(peer) \ | ||
525 | ((GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt)) | ||
526 | |||
527 | /** | ||
528 | * Cleanup overlay connect context structure | ||
529 | * | ||
530 | * @param occ the overlay connect context | ||
531 | */ | ||
532 | static void | ||
533 | cleanup_occ (struct OverlayConnectContext *occ) | ||
534 | { | ||
535 | struct Peer *peer2; | ||
536 | |||
537 | LOG_DEBUG ("0x%llx: Cleaning up occ\n", | ||
538 | (unsigned long long) occ->op_id); | ||
539 | GNUNET_free (occ->emsg); | ||
540 | GNUNET_free (occ->hello); | ||
541 | if (NULL != occ->send_hello_task) | ||
542 | GNUNET_SCHEDULER_cancel (occ->send_hello_task); | ||
543 | if (NULL != occ->cleanup_task) | ||
544 | GNUNET_SCHEDULER_cancel (occ->cleanup_task); | ||
545 | if (NULL != occ->timeout_task) | ||
546 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
547 | if (NULL != occ->cgh_ch) | ||
548 | GST_connection_pool_get_handle_done (occ->cgh_ch); | ||
549 | if (NULL != occ->ghh) | ||
550 | GNUNET_TRANSPORT_hello_get_cancel (occ->ghh); | ||
551 | GST_connection_pool_get_handle_done (occ->cgh_p1th); | ||
552 | GNUNET_assert (NULL != GST_peer_list); | ||
553 | GNUNET_assert (occ->peer->reference_cnt > 0); | ||
554 | occ->peer->reference_cnt--; | ||
555 | if (PEER_EXPIRED (occ->peer)) | ||
556 | GST_destroy_peer (occ->peer); | ||
557 | switch (occ->type) | ||
558 | { | ||
559 | case OCC_TYPE_LOCAL: | ||
560 | peer2 = GST_peer_list[occ->other_peer_id]; | ||
561 | GNUNET_assert (peer2->reference_cnt > 0); | ||
562 | peer2->reference_cnt--; | ||
563 | if (PEER_EXPIRED (peer2)) | ||
564 | GST_destroy_peer (peer2); | ||
565 | cleanup_occ_lp2c (&occ->p2ctx.local); | ||
566 | break; | ||
567 | |||
568 | case OCC_TYPE_REMOTE_SLAVE: | ||
569 | case OCC_TYPE_REMOTE_LATERAL: | ||
570 | cleanup_occ_rp2c (&occ->p2ctx.remote); | ||
571 | break; | ||
572 | } | ||
573 | GNUNET_CONTAINER_DLL_remove (occq_head, | ||
574 | occq_tail, | ||
575 | occ); | ||
576 | GNUNET_free (occ); | ||
577 | } | ||
578 | |||
579 | |||
580 | /** | ||
581 | * Task for cleaning up overlay connect context structure | ||
582 | * | ||
583 | * @param cls the overlay connect context | ||
584 | */ | ||
585 | static void | ||
586 | do_cleanup_occ (void *cls) | ||
587 | { | ||
588 | struct OverlayConnectContext *occ = cls; | ||
589 | |||
590 | occ->cleanup_task = NULL; | ||
591 | cleanup_occ (occ); | ||
592 | } | ||
593 | |||
594 | |||
595 | /** | ||
596 | * Task which will be run when overlay connect request has been timed out | ||
597 | * | ||
598 | * @param cls the OverlayConnectContext | ||
599 | */ | ||
600 | static void | ||
601 | timeout_overlay_connect (void *cls) | ||
602 | { | ||
603 | struct OverlayConnectContext *occ = cls; | ||
604 | |||
605 | GNUNET_assert (NULL != occ->timeout_task); | ||
606 | occ->timeout_task = NULL; | ||
607 | /* LOG (GNUNET_ERROR_TYPE_WARNING, */ | ||
608 | /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */ | ||
609 | /* occ->peer->id, occ->other_peer_id, occ->emsg); */ | ||
610 | GST_send_operation_fail_msg (occ->client, | ||
611 | occ->op_id, | ||
612 | occ->emsg); | ||
613 | cleanup_occ (occ); | ||
614 | } | ||
615 | |||
616 | |||
617 | /** | ||
618 | * Notify OC subsystem that @a client disconnected. | ||
619 | * | ||
620 | * @param client the client that disconnected | ||
621 | */ | ||
622 | void | ||
623 | GST_notify_client_disconnect_oc (struct GNUNET_SERVICE_Client *client) | ||
624 | { | ||
625 | struct ForwardedOperationContext *fopc; | ||
626 | struct ForwardedOperationContext *fopcn; | ||
627 | struct OverlayConnectContext *occ; | ||
628 | struct OverlayConnectContext *occn; | ||
629 | |||
630 | for (fopc = fopcq_head; NULL != fopc; fopc = fopcn) | ||
631 | { | ||
632 | fopcn = fopc->next; | ||
633 | if (fopc->client == client) | ||
634 | { | ||
635 | GNUNET_SCHEDULER_cancel (fopc->timeout_task); | ||
636 | GST_forwarded_operation_timeout (fopc); | ||
637 | } | ||
638 | } | ||
639 | for (occ = occq_head; NULL != occ; occ = occn) | ||
640 | { | ||
641 | occn = occ->next; | ||
642 | if (occ->client == client) | ||
643 | cleanup_occ (occ); | ||
644 | } | ||
645 | // FIXME: implement clean up for client_keep replacements! | ||
646 | } | ||
647 | |||
648 | |||
649 | /** | ||
650 | * FIXME. | ||
651 | */ | ||
652 | static void | ||
653 | send_overlay_connect_success_msg (struct OverlayConnectContext *occ) | ||
654 | { | ||
655 | struct GNUNET_MQ_Envelope *env; | ||
656 | struct GNUNET_TESTBED_ConnectionEventMessage *msg; | ||
657 | |||
658 | LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n", | ||
659 | (unsigned long long) occ->op_id); | ||
660 | env = GNUNET_MQ_msg (msg, | ||
661 | GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT); | ||
662 | msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT); | ||
663 | msg->peer1 = htonl (occ->peer->id); | ||
664 | msg->peer2 = htonl (occ->other_peer_id); | ||
665 | msg->operation_id = GNUNET_htonll (occ->op_id); | ||
666 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (occ->client), | ||
667 | env); | ||
668 | } | ||
669 | |||
670 | |||
671 | /** | ||
672 | * Function called to notify transport users that another | ||
673 | * peer connected to us. | ||
674 | * | ||
675 | * @param cls closure | ||
676 | * @param new_peer the peer that connected | ||
677 | */ | ||
678 | static void | ||
679 | overlay_connect_notify (void *cls, | ||
680 | const struct GNUNET_PeerIdentity *new_peer) | ||
681 | { | ||
682 | struct OverlayConnectContext *occ = cls; | ||
683 | char *new_peer_str; | ||
684 | char *other_peer_str; | ||
685 | |||
686 | LOG_DEBUG ("Overlay connect notify\n"); | ||
687 | if (0 == | ||
688 | memcmp (new_peer, &occ->peer_identity, | ||
689 | sizeof(struct GNUNET_PeerIdentity))) | ||
690 | return; | ||
691 | new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer)); | ||
692 | other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); | ||
693 | if (0 != | ||
694 | memcmp (new_peer, | ||
695 | &occ->other_peer_identity, | ||
696 | sizeof(struct GNUNET_PeerIdentity))) | ||
697 | { | ||
698 | LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n", | ||
699 | new_peer_str, | ||
700 | other_peer_str); | ||
701 | GNUNET_free (new_peer_str); | ||
702 | GNUNET_free (other_peer_str); | ||
703 | return; | ||
704 | } | ||
705 | GNUNET_free (new_peer_str); | ||
706 | LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n", | ||
707 | (unsigned long long) occ->op_id, | ||
708 | other_peer_str, | ||
709 | GNUNET_i2s (&occ->peer_identity)); | ||
710 | GNUNET_free (other_peer_str); | ||
711 | if (NULL != occ->send_hello_task) | ||
712 | { | ||
713 | GNUNET_SCHEDULER_cancel (occ->send_hello_task); | ||
714 | occ->send_hello_task = NULL; | ||
715 | } | ||
716 | GNUNET_assert (NULL != occ->timeout_task); | ||
717 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
718 | occ->timeout_task = NULL; | ||
719 | switch (occ->type) | ||
720 | { | ||
721 | case OCC_TYPE_LOCAL: | ||
722 | cleanup_occ_lp2c (&occ->p2ctx.local); | ||
723 | break; | ||
724 | |||
725 | case OCC_TYPE_REMOTE_SLAVE: | ||
726 | case OCC_TYPE_REMOTE_LATERAL: | ||
727 | cleanup_occ_rp2c (&occ->p2ctx.remote); | ||
728 | break; | ||
729 | } | ||
730 | GNUNET_free (occ->emsg); | ||
731 | occ->emsg = NULL; | ||
732 | send_overlay_connect_success_msg (occ); | ||
733 | occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, | ||
734 | occ); | ||
735 | } | ||
736 | |||
737 | |||
738 | /** | ||
739 | * Callback from cache with needed ATS handle set | ||
740 | * | ||
741 | * @param cls a `struct OverlayConnectCtx *` | ||
742 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
743 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
744 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
745 | * @param my_identity the identity of our peer | ||
746 | * @param cfg configuration of the peer | ||
747 | */ | ||
748 | static void | ||
749 | occ_cache_get_handle_ats_occ_cb (void *cls, | ||
750 | struct GNUNET_CORE_Handle *ch, | ||
751 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
752 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
753 | const struct GNUNET_PeerIdentity *my_identity, | ||
754 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
755 | { | ||
756 | struct OverlayConnectContext *occ = cls; | ||
757 | struct LocalPeer2Context *lp2c; | ||
758 | |||
759 | GNUNET_assert (OCC_TYPE_LOCAL == occ->type); | ||
760 | GNUNET_assert (NULL != occ->timeout_task); | ||
761 | GNUNET_free (occ->emsg); | ||
762 | if (NULL == ac) | ||
763 | { | ||
764 | GNUNET_asprintf (&occ->emsg, | ||
765 | "0x%llx: Failed to connect to ATS of peer with id: %u", | ||
766 | (unsigned long long) occ->op_id, | ||
767 | occ->peer->id); | ||
768 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
769 | occ->timeout_task = | ||
770 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, | ||
771 | occ); | ||
772 | return; | ||
773 | } | ||
774 | occ->emsg = NULL; | ||
775 | |||
776 | GNUNET_asprintf (&occ->emsg, | ||
777 | "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s", | ||
778 | (unsigned long long) occ->op_id, | ||
779 | GNUNET_i2s (&occ->other_peer_identity)); | ||
780 | |||
781 | lp2c = &occ->p2ctx.local; | ||
782 | lp2c->tcc.csh = | ||
783 | GNUNET_ATS_connectivity_suggest (ac, | ||
784 | &occ->peer_identity, | ||
785 | 1); | ||
786 | } | ||
787 | |||
788 | |||
789 | /** | ||
790 | * Callback from cache with needed ATS handle set | ||
791 | * | ||
792 | * @param cls a `struct RemoteOverlayConnectCtx *` | ||
793 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
794 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
795 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
796 | * @param my_identity the identity of our peer | ||
797 | */ | ||
798 | static void | ||
799 | occ_cache_get_handle_ats_rocc_cb (void *cls, | ||
800 | struct GNUNET_CORE_Handle *ch, | ||
801 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
802 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
803 | const struct GNUNET_PeerIdentity *my_identity, | ||
804 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
805 | { | ||
806 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
807 | |||
808 | rocc->tcc.csh = | ||
809 | GNUNET_ATS_connectivity_suggest (ac, | ||
810 | &rocc->a_id, | ||
811 | 1); | ||
812 | } | ||
813 | |||
814 | |||
815 | /** | ||
816 | * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to | ||
817 | * peer 1. | ||
818 | * | ||
819 | * @param cls the OverlayConnectContext | ||
820 | */ | ||
821 | static void | ||
822 | send_hello (void *cls); | ||
823 | |||
824 | |||
825 | /** | ||
826 | * Task that is run when hello has been sent If tc->reason = | ||
827 | * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if | ||
828 | * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded | ||
829 | * | ||
830 | * @param cls the overlay connect context | ||
831 | */ | ||
832 | static void | ||
833 | occ_hello_sent_cb (void *cls) | ||
834 | { | ||
835 | struct OverlayConnectContext *occ = cls; | ||
836 | struct LocalPeer2Context *lp2c; | ||
837 | struct Peer *peer2; | ||
838 | |||
839 | GNUNET_assert (OCC_TYPE_LOCAL == occ->type); | ||
840 | GNUNET_assert (NULL != occ->timeout_task); | ||
841 | lp2c = &occ->p2ctx.local; | ||
842 | lp2c->ohh = NULL; | ||
843 | |||
844 | GNUNET_assert (NULL == occ->send_hello_task); | ||
845 | GNUNET_free (occ->emsg); | ||
846 | |||
847 | GNUNET_asprintf (&occ->emsg, | ||
848 | "0x%llx: Timeout while acquiring ATS of %s from cache", | ||
849 | (unsigned long long) occ->op_id, | ||
850 | GNUNET_i2s (&occ->other_peer_identity)); | ||
851 | GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id])); | ||
852 | lp2c->tcc.cgh_p2_ats = | ||
853 | GST_connection_pool_get_handle (occ->other_peer_id, | ||
854 | peer2->details.local.cfg, | ||
855 | GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY, | ||
856 | &occ_cache_get_handle_ats_occ_cb, | ||
857 | occ, NULL, NULL, NULL); | ||
858 | } | ||
859 | |||
860 | |||
861 | /** | ||
862 | * Sends the HELLO of peer1 to peer2's controller through remote overlay connect | ||
863 | * request. | ||
864 | * | ||
865 | * @param occ the overlay connect context. Its type must be either | ||
866 | * #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL | ||
867 | */ | ||
868 | static void | ||
869 | send_hello_thru_rocc (struct OverlayConnectContext *occ) | ||
870 | { | ||
871 | struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg; | ||
872 | char *other_peer_str; | ||
873 | uint16_t msize; | ||
874 | uint16_t hello_size; | ||
875 | |||
876 | GNUNET_assert (OCC_TYPE_LOCAL != occ->type); | ||
877 | GNUNET_assert (NULL != occ->hello); | ||
878 | other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); | ||
879 | LOG_DEBUG ( | ||
880 | "0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n", | ||
881 | (unsigned long long) occ->op_id, | ||
882 | GNUNET_i2s (&occ->peer_identity), | ||
883 | ntohs (occ->hello->size), | ||
884 | other_peer_str); | ||
885 | GNUNET_free (other_peer_str); | ||
886 | hello_size = ntohs (occ->hello->size); | ||
887 | msize = sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage) | ||
888 | + hello_size; | ||
889 | msg = GNUNET_malloc (msize); | ||
890 | msg->header.type = | ||
891 | htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT); | ||
892 | msg->header.size = htons (msize); | ||
893 | msg->peer = htonl (occ->other_peer_id); | ||
894 | msg->operation_id = GNUNET_htonll (occ->op_id); | ||
895 | msg->peer_identity = occ->peer_identity; | ||
896 | GNUNET_memcpy (msg->hello, | ||
897 | occ->hello, | ||
898 | hello_size); | ||
899 | GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c, | ||
900 | &msg->header); | ||
901 | } | ||
902 | |||
903 | |||
904 | /** | ||
905 | * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered | ||
906 | * using its TRANSPORT connection; if remote the HELLO is sent remotely by using | ||
907 | * send_hello_thru_rocc() | ||
908 | * | ||
909 | * @param cls the OverlayConnectContext | ||
910 | */ | ||
911 | static void | ||
912 | send_hello (void *cls) | ||
913 | { | ||
914 | struct OverlayConnectContext *occ = cls; | ||
915 | struct LocalPeer2Context *lp2c; | ||
916 | char *other_peer_str; | ||
917 | |||
918 | occ->send_hello_task = NULL; | ||
919 | GNUNET_assert (NULL != occ->timeout_task); | ||
920 | GNUNET_assert (NULL != occ->hello); | ||
921 | if (OCC_TYPE_LOCAL != occ->type) | ||
922 | { | ||
923 | send_hello_thru_rocc (occ); | ||
924 | return; | ||
925 | } | ||
926 | lp2c = &occ->p2ctx.local; | ||
927 | other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); | ||
928 | LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n", | ||
929 | (unsigned long long) occ->op_id, | ||
930 | GNUNET_i2s (&occ->peer_identity), | ||
931 | other_peer_str); | ||
932 | GNUNET_free (other_peer_str); | ||
933 | lp2c->ohh = | ||
934 | GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg, | ||
935 | occ->hello, | ||
936 | &occ_hello_sent_cb, | ||
937 | occ); | ||
938 | if (NULL == lp2c->ohh) | ||
939 | { | ||
940 | GNUNET_break (0); | ||
941 | occ->send_hello_task = | ||
942 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
943 | (GNUNET_TIME_UNIT_MILLISECONDS, | ||
944 | 100 | ||
945 | + GNUNET_CRYPTO_random_u32 | ||
946 | (GNUNET_CRYPTO_QUALITY_WEAK, 500)), | ||
947 | &send_hello, occ); | ||
948 | } | ||
949 | } | ||
950 | |||
951 | |||
952 | /** | ||
953 | * Callback from cache with needed handles set | ||
954 | * | ||
955 | * @param cls the closure passed to GST_cache_get_handle_transport() | ||
956 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
957 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
958 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
959 | * @param ignore_ peer identity which is ignored in this callback | ||
960 | * @param cfg configuration of the peer | ||
961 | */ | ||
962 | static void | ||
963 | p2_transport_connect_cache_callback (void *cls, | ||
964 | struct GNUNET_CORE_Handle *ch, | ||
965 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
966 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
967 | const struct GNUNET_PeerIdentity *ignore_, | ||
968 | const struct | ||
969 | GNUNET_CONFIGURATION_Handle *cfg) | ||
970 | { | ||
971 | struct OverlayConnectContext *occ = cls; | ||
972 | |||
973 | GNUNET_assert (OCC_TYPE_LOCAL == occ->type); | ||
974 | if (NULL == th) | ||
975 | { | ||
976 | GNUNET_asprintf (&occ->emsg, | ||
977 | "0x%llx: Cannot connect to TRANSPORT of %s", | ||
978 | (unsigned long long) occ->op_id, | ||
979 | GNUNET_i2s (&occ->other_peer_identity)); | ||
980 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
981 | occ->timeout_task = | ||
982 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); | ||
983 | return; | ||
984 | } | ||
985 | occ->p2ctx.local.tcc.th_ = th; | ||
986 | occ->p2ctx.local.tcc.cfg = cfg; | ||
987 | GNUNET_asprintf (&occ->emsg, | ||
988 | "0x%llx: Timeout while offering HELLO to %s", | ||
989 | (unsigned long long) occ->op_id, | ||
990 | GNUNET_i2s (&occ->other_peer_identity)); | ||
991 | occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ); | ||
992 | } | ||
993 | |||
994 | |||
995 | /** | ||
996 | * Connects to the transport of the other peer if it is a local peer and | ||
997 | * schedules the send hello task | ||
998 | * | ||
999 | * @param occ the overlay connect context | ||
1000 | */ | ||
1001 | static void | ||
1002 | p2_transport_connect (struct OverlayConnectContext *occ) | ||
1003 | { | ||
1004 | struct Peer *peer2; | ||
1005 | |||
1006 | /* HUH? Why to *obtain* HELLO? Seems we use this to *SEND* the | ||
1007 | HELLO! */ | ||
1008 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1009 | "Connecting to transport of peer %s to obtain HELLO\n", | ||
1010 | GNUNET_i2s (&occ->other_peer_identity)); | ||
1011 | GNUNET_assert (NULL == occ->emsg); | ||
1012 | GNUNET_assert (NULL != occ->hello); | ||
1013 | GNUNET_assert (NULL == occ->ghh); | ||
1014 | GNUNET_assert (NULL == occ->p1th_); | ||
1015 | GNUNET_assert (NULL == occ->cgh_p1th); | ||
1016 | if (OCC_TYPE_LOCAL == occ->type) | ||
1017 | { | ||
1018 | GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id])); | ||
1019 | occ->p2ctx.local.tcc.cgh_p2_th = | ||
1020 | GST_connection_pool_get_handle (occ->other_peer_id, | ||
1021 | peer2->details.local.cfg, | ||
1022 | GST_CONNECTIONPOOL_SERVICE_TRANSPORT, | ||
1023 | &p2_transport_connect_cache_callback, | ||
1024 | occ, NULL, NULL, NULL); | ||
1025 | return; | ||
1026 | } | ||
1027 | GNUNET_asprintf (&occ->emsg, | ||
1028 | "0x%llx: Timeout while offering HELLO to %s", | ||
1029 | (unsigned long long) occ->op_id, | ||
1030 | GNUNET_i2s (&occ->other_peer_identity)); | ||
1031 | occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ); | ||
1032 | } | ||
1033 | |||
1034 | |||
1035 | /** | ||
1036 | * Test for checking whether HELLO message is empty | ||
1037 | * | ||
1038 | * @param cls empty flag to set | ||
1039 | * @param address the HELLO | ||
1040 | * @param expiration expiration of the HELLO | ||
1041 | * @return #GNUNET_OK | ||
1042 | */ | ||
1043 | static int | ||
1044 | test_address (void *cls, | ||
1045 | const struct GNUNET_HELLO_Address *address, | ||
1046 | struct GNUNET_TIME_Absolute expiration) | ||
1047 | { | ||
1048 | int *empty = cls; | ||
1049 | |||
1050 | *empty = GNUNET_NO; | ||
1051 | return GNUNET_OK; | ||
1052 | } | ||
1053 | |||
1054 | |||
1055 | /** | ||
1056 | * Function called whenever there is an update to the HELLO of peers in the | ||
1057 | * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's | ||
1058 | * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1 | ||
1059 | * | ||
1060 | * @param cls closure | ||
1061 | * @param hello our updated HELLO | ||
1062 | */ | ||
1063 | static void | ||
1064 | hello_update_cb (void *cls, | ||
1065 | const struct GNUNET_MessageHeader *hello) | ||
1066 | { | ||
1067 | struct OverlayConnectContext *occ = cls; | ||
1068 | int empty; | ||
1069 | uint16_t msize; | ||
1070 | |||
1071 | msize = ntohs (hello->size); | ||
1072 | empty = GNUNET_YES; | ||
1073 | (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *) | ||
1074 | hello, GNUNET_NO, | ||
1075 | &test_address, | ||
1076 | &empty); | ||
1077 | if (GNUNET_YES == empty) | ||
1078 | { | ||
1079 | LOG_DEBUG ("0x%llx: HELLO of %s is empty\n", | ||
1080 | (unsigned long long) occ->op_id, | ||
1081 | GNUNET_i2s (&occ->peer_identity)); | ||
1082 | return; | ||
1083 | } | ||
1084 | LOG_DEBUG ("0x%llx: Received HELLO of %s\n", | ||
1085 | (unsigned long long) occ->op_id, | ||
1086 | GNUNET_i2s (&occ->peer_identity)); | ||
1087 | occ->hello = GNUNET_malloc (msize); | ||
1088 | GST_cache_add_hello (occ->peer->id, hello); | ||
1089 | GNUNET_memcpy (occ->hello, hello, msize); | ||
1090 | GNUNET_TRANSPORT_hello_get_cancel (occ->ghh); | ||
1091 | occ->ghh = NULL; | ||
1092 | GST_connection_pool_get_handle_done (occ->cgh_p1th); | ||
1093 | occ->cgh_p1th = NULL; | ||
1094 | occ->p1th_ = NULL; | ||
1095 | GNUNET_free (occ->emsg); | ||
1096 | occ->emsg = NULL; | ||
1097 | p2_transport_connect (occ); | ||
1098 | } | ||
1099 | |||
1100 | |||
1101 | /** | ||
1102 | * Callback from cache with needed handles set | ||
1103 | * | ||
1104 | * @param cls the closure passed to GST_cache_get_handle_transport() | ||
1105 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
1106 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
1107 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
1108 | * @param ignore_ peer identity which is ignored in this callback | ||
1109 | */ | ||
1110 | static void | ||
1111 | p1_transport_connect_cache_callback (void *cls, | ||
1112 | struct GNUNET_CORE_Handle *ch, | ||
1113 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
1114 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
1115 | const struct GNUNET_PeerIdentity *ignore_, | ||
1116 | const struct | ||
1117 | GNUNET_CONFIGURATION_Handle *cfg) | ||
1118 | { | ||
1119 | struct OverlayConnectContext *occ = cls; | ||
1120 | |||
1121 | GNUNET_free (occ->emsg); | ||
1122 | occ->emsg = NULL; | ||
1123 | if (NULL == th) | ||
1124 | { | ||
1125 | GNUNET_asprintf (&occ->emsg, | ||
1126 | "0x%llx: Cannot connect to TRANSPORT of %s", | ||
1127 | (unsigned long long) occ->op_id, | ||
1128 | GNUNET_i2s (&occ->peer_identity)); | ||
1129 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
1130 | occ->timeout_task = | ||
1131 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); | ||
1132 | return; | ||
1133 | } | ||
1134 | GNUNET_assert (NULL == occ->p1th_); | ||
1135 | GNUNET_assert (NULL != occ->cgh_p1th); | ||
1136 | occ->p1th_ = th; | ||
1137 | GNUNET_asprintf (&occ->emsg, | ||
1138 | "0x%llx: Timeout while acquiring HELLO of peer %s", | ||
1139 | (unsigned long long) occ->op_id, | ||
1140 | GNUNET_i2s (&occ->peer_identity)); | ||
1141 | occ->ghh = GNUNET_TRANSPORT_hello_get (cfg, | ||
1142 | GNUNET_TRANSPORT_AC_ANY, | ||
1143 | &hello_update_cb, | ||
1144 | occ); | ||
1145 | } | ||
1146 | |||
1147 | |||
1148 | /** | ||
1149 | * Callback from cache with needed CORE handle set | ||
1150 | * | ||
1151 | * @param cls the closure passed to GST_cache_get_handle_transport() | ||
1152 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
1153 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
1154 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
1155 | * @param my_identity the identity of our peer | ||
1156 | */ | ||
1157 | static void | ||
1158 | occ_cache_get_handle_core_cb (void *cls, | ||
1159 | struct GNUNET_CORE_Handle *ch, | ||
1160 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
1161 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
1162 | const struct GNUNET_PeerIdentity *my_identity, | ||
1163 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
1164 | { | ||
1165 | struct OverlayConnectContext *occ = cls; | ||
1166 | const struct GNUNET_MessageHeader *hello; | ||
1167 | |||
1168 | GNUNET_assert (NULL != occ->timeout_task); | ||
1169 | GNUNET_free (occ->emsg); | ||
1170 | if ((NULL == ch) || (NULL == my_identity)) | ||
1171 | { | ||
1172 | GNUNET_asprintf (&occ->emsg, | ||
1173 | "0x%llx: Failed to connect to CORE of peer with " | ||
1174 | "id: %u", | ||
1175 | (unsigned long long) occ->op_id, | ||
1176 | occ->peer->id); | ||
1177 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
1178 | occ->timeout_task = | ||
1179 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); | ||
1180 | return; | ||
1181 | } | ||
1182 | occ->emsg = NULL; | ||
1183 | if (NULL != | ||
1184 | GNUNET_CORE_get_mq (ch, | ||
1185 | &occ->other_peer_identity)) | ||
1186 | { | ||
1187 | LOG_DEBUG ("0x%llx: Target peer already connected\n", | ||
1188 | (unsigned long long) occ->op_id); | ||
1189 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
1190 | occ->timeout_task = NULL; | ||
1191 | send_overlay_connect_success_msg (occ); | ||
1192 | occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ); | ||
1193 | return; | ||
1194 | } | ||
1195 | occ->peer_identity = *my_identity; | ||
1196 | LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", | ||
1197 | (unsigned long long) occ->op_id, | ||
1198 | GNUNET_i2s (&occ->peer_identity)); | ||
1199 | /* Lookup for HELLO in hello cache */ | ||
1200 | if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id))) | ||
1201 | { | ||
1202 | LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", | ||
1203 | (unsigned long long) occ->op_id, | ||
1204 | GNUNET_i2s (&occ->peer_identity)); | ||
1205 | occ->hello = GNUNET_copy_message (hello); | ||
1206 | p2_transport_connect (occ); | ||
1207 | return; | ||
1208 | } | ||
1209 | GNUNET_asprintf (&occ->emsg, | ||
1210 | "0x%llx: Timeout while acquiring TRANSPORT of %s from cache", | ||
1211 | (unsigned long long) occ->op_id, | ||
1212 | GNUNET_i2s (&occ->peer_identity)); | ||
1213 | occ->cgh_p1th = | ||
1214 | GST_connection_pool_get_handle (occ->peer->id, | ||
1215 | occ->peer->details.local.cfg, | ||
1216 | GST_CONNECTIONPOOL_SERVICE_TRANSPORT, | ||
1217 | p1_transport_connect_cache_callback, | ||
1218 | occ, | ||
1219 | NULL, NULL, NULL); | ||
1220 | } | ||
1221 | |||
1222 | |||
1223 | /** | ||
1224 | * Callback to be called when forwarded get peer config operation as part of | ||
1225 | * overlay connect is successful. Connection to Peer 1's core is made and is | ||
1226 | * checked for new connection from peer 2 | ||
1227 | * | ||
1228 | * @param cls ForwardedOperationContext | ||
1229 | * @param msg the peer create success message | ||
1230 | */ | ||
1231 | static void | ||
1232 | overlay_connect_get_config (void *cls, | ||
1233 | const struct GNUNET_MessageHeader *msg) | ||
1234 | { | ||
1235 | struct OverlayConnectContext *occ = cls; | ||
1236 | struct RemotePeer2Context *rp2c; | ||
1237 | const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg; | ||
1238 | |||
1239 | GNUNET_assert (OCC_TYPE_LOCAL != occ->type); | ||
1240 | rp2c = &occ->p2ctx.remote; | ||
1241 | rp2c->opc = NULL; | ||
1242 | GNUNET_assert (NULL != occ->timeout_task); | ||
1243 | if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type)) | ||
1244 | { | ||
1245 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
1246 | occ->timeout_task = | ||
1247 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); | ||
1248 | } | ||
1249 | cmsg = | ||
1250 | (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg; | ||
1251 | occ->other_peer_identity = cmsg->peer_identity; | ||
1252 | GNUNET_free (occ->emsg); | ||
1253 | GNUNET_asprintf (&occ->emsg, | ||
1254 | "0x%llx: Timeout while connecting to CORE of peer with " | ||
1255 | "id: %u", | ||
1256 | (unsigned long long) occ->op_id, | ||
1257 | occ->peer->id); | ||
1258 | occ->cgh_ch = | ||
1259 | GST_connection_pool_get_handle (occ->peer->id, | ||
1260 | occ->peer->details.local.cfg, | ||
1261 | GST_CONNECTIONPOOL_SERVICE_CORE, | ||
1262 | occ_cache_get_handle_core_cb, | ||
1263 | occ, | ||
1264 | &occ->other_peer_identity, | ||
1265 | &overlay_connect_notify, | ||
1266 | occ); | ||
1267 | return; | ||
1268 | } | ||
1269 | |||
1270 | |||
1271 | /** | ||
1272 | * Callback which will be called after a host registration succeeded or failed | ||
1273 | * | ||
1274 | * @param cls the RegisteredHostContext | ||
1275 | * @param emsg the error message; NULL if host registration is successful | ||
1276 | */ | ||
1277 | static void | ||
1278 | host_registration_comp (void *cls, const char *emsg) | ||
1279 | { | ||
1280 | struct RegisteredHostContext *rhc = cls; | ||
1281 | |||
1282 | rhc->state = RHC_DONE; | ||
1283 | GST_process_next_focc (rhc); | ||
1284 | } | ||
1285 | |||
1286 | |||
1287 | /** | ||
1288 | * Iterator to match a registered host context | ||
1289 | * | ||
1290 | * @param cls pointer 2 pointer of RegisteredHostContext | ||
1291 | * @param key current key code | ||
1292 | * @param value value in the hash map | ||
1293 | * @return #GNUNET_YES if we should continue to | ||
1294 | * iterate, | ||
1295 | * #GNUNET_NO if not. | ||
1296 | */ | ||
1297 | static int | ||
1298 | reghost_match_iterator (void *cls, | ||
1299 | const struct GNUNET_HashCode *key, | ||
1300 | void *value) | ||
1301 | { | ||
1302 | struct RegisteredHostContext **rh = cls; | ||
1303 | struct RegisteredHostContext *rh_val = value; | ||
1304 | |||
1305 | if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host)) | ||
1306 | { | ||
1307 | GNUNET_free (*rh); | ||
1308 | *rh = rh_val; | ||
1309 | return GNUNET_NO; | ||
1310 | } | ||
1311 | return GNUNET_YES; | ||
1312 | } | ||
1313 | |||
1314 | |||
1315 | /** | ||
1316 | * Function to generate the hashcode corresponding to a RegisteredHostContext | ||
1317 | * | ||
1318 | * @param reg_host the host which is being registered in RegisteredHostContext | ||
1319 | * @param host the host of the controller which has to connect to the above rhost | ||
1320 | * @return the hashcode | ||
1321 | */ | ||
1322 | static struct GNUNET_HashCode | ||
1323 | hash_hosts (struct GNUNET_TESTBED_Host *reg_host, | ||
1324 | struct GNUNET_TESTBED_Host *host) | ||
1325 | { | ||
1326 | struct GNUNET_HashCode hash; | ||
1327 | uint32_t host_ids[2]; | ||
1328 | |||
1329 | host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host); | ||
1330 | host_ids[1] = GNUNET_TESTBED_host_get_id_ (host); | ||
1331 | GNUNET_CRYPTO_hash (host_ids, sizeof(host_ids), &hash); | ||
1332 | return hash; | ||
1333 | } | ||
1334 | |||
1335 | |||
1336 | /** | ||
1337 | * Checks if the given host is registered at the given slave. | ||
1338 | * | ||
1339 | * @param slave the slave where registration has to be checked. The check is | ||
1340 | * actually done through a locally maintained hashmap. No | ||
1341 | * communication with the slave is involved. | ||
1342 | * @param host the host to register | ||
1343 | * @return If the given host is not registered already or the registration is | ||
1344 | * pending, it returns the registration context. Any overlay connects | ||
1345 | * to be forwarded should be queued in the context so that they can be | ||
1346 | * executed when the registration is completed. If the given host is | ||
1347 | * already registered, NULL is returned. | ||
1348 | */ | ||
1349 | static struct RegisteredHostContext * | ||
1350 | register_host (struct Slave *slave, | ||
1351 | struct GNUNET_TESTBED_Host *host) | ||
1352 | { | ||
1353 | struct GNUNET_HashCode hash; | ||
1354 | struct RegisteredHostContext *rhc; | ||
1355 | |||
1356 | rhc = GNUNET_new (struct RegisteredHostContext); | ||
1357 | rhc->reg_host = host; | ||
1358 | rhc->host = GST_host_list[slave->host_id]; | ||
1359 | GNUNET_assert (NULL != rhc->reg_host); | ||
1360 | GNUNET_assert (NULL != rhc->host); | ||
1361 | rhc->state = RHC_INIT; | ||
1362 | hash = hash_hosts (rhc->reg_host, rhc->host); | ||
1363 | if ((GNUNET_NO == | ||
1364 | GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map, | ||
1365 | &hash)) || | ||
1366 | (GNUNET_SYSERR != | ||
1367 | GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map, | ||
1368 | &hash, | ||
1369 | reghost_match_iterator, | ||
1370 | &rhc))) | ||
1371 | { | ||
1372 | /* create and add a new registered host context */ | ||
1373 | /* add the focc to its queue */ | ||
1374 | GNUNET_CONTAINER_multihashmap_put (slave->reghost_map, | ||
1375 | &hash, | ||
1376 | rhc, | ||
1377 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
1378 | GST_queue_host_registration (slave, | ||
1379 | host_registration_comp, | ||
1380 | rhc, | ||
1381 | rhc->reg_host); | ||
1382 | } | ||
1383 | else | ||
1384 | { | ||
1385 | /* rhc is now set to the existing one from the hash map by | ||
1386 | * reghost_match_iterator() */ | ||
1387 | /* if queue is empty then ignore creating focc and proceed with normal | ||
1388 | * forwarding */ | ||
1389 | if (RHC_DONE == rhc->state) | ||
1390 | return NULL; | ||
1391 | } | ||
1392 | return rhc; | ||
1393 | } | ||
1394 | |||
1395 | |||
1396 | /** | ||
1397 | * Forwards the overlay connect request to a slave controller. Before | ||
1398 | * forwarding, any hosts which are needed to be known by the slave controller to | ||
1399 | * execute the overlay connect request are registered at slave. | ||
1400 | * | ||
1401 | * @param msg the overlay connect request message to be forwarded | ||
1402 | * @param client the client to which the status of the forwarded request has to | ||
1403 | * be notified | ||
1404 | */ | ||
1405 | static void | ||
1406 | forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg, | ||
1407 | struct GNUNET_SERVICE_Client *client) | ||
1408 | { | ||
1409 | struct ForwardedOperationContext *fopc; | ||
1410 | struct Route *route_to_peer2_host; | ||
1411 | struct Route *route_to_peer1_host; | ||
1412 | struct Peer *peer; | ||
1413 | struct RegisteredHostContext *rhc; | ||
1414 | struct ForwardedOverlayConnectContext *focc; | ||
1415 | uint64_t op_id; | ||
1416 | uint32_t peer2_host_id; | ||
1417 | uint32_t p1; | ||
1418 | uint32_t p2; | ||
1419 | |||
1420 | p1 = ntohl (msg->peer1); | ||
1421 | p2 = ntohl (msg->peer2); | ||
1422 | op_id = GNUNET_ntohll (msg->operation_id); | ||
1423 | peer2_host_id = ntohl (msg->peer2_host_id); | ||
1424 | GNUNET_assert (VALID_PEER_ID (p1)); | ||
1425 | GNUNET_assert (VALID_HOST_ID (peer2_host_id)); | ||
1426 | peer = GST_peer_list[p1]; | ||
1427 | GNUNET_assert (GNUNET_YES == peer->is_remote); | ||
1428 | LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", | ||
1429 | (unsigned long long) op_id); | ||
1430 | route_to_peer2_host = GST_find_dest_route (peer2_host_id); | ||
1431 | route_to_peer1_host = GST_find_dest_route | ||
1432 | (peer->details.remote.remote_host_id); | ||
1433 | GNUNET_assert (NULL != route_to_peer1_host); | ||
1434 | if ((NULL != route_to_peer2_host) && | ||
1435 | (route_to_peer1_host->dest == route_to_peer2_host->dest)) | ||
1436 | goto forward; | ||
1437 | /* Peer2 is either with us OR peer1 and peer2 can be reached through | ||
1438 | different subtrees OR peer2 is on a subtree unknown to us */ | ||
1439 | if (NULL != (rhc = register_host (peer->details.remote.slave, | ||
1440 | GST_host_list[peer2_host_id]))) | ||
1441 | { | ||
1442 | LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, | ||
1443 | p2); | ||
1444 | focc = GNUNET_new (struct ForwardedOverlayConnectContext); | ||
1445 | focc->rhc = rhc; | ||
1446 | focc->peer1 = p1; | ||
1447 | focc->peer2 = p2; | ||
1448 | focc->peer2_host_id = peer2_host_id; | ||
1449 | focc->orig_msg = GNUNET_copy_message (&msg->header); | ||
1450 | focc->operation_id = op_id; | ||
1451 | focc->client = client; | ||
1452 | GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head, | ||
1453 | rhc->focc_dll_tail, | ||
1454 | focc); | ||
1455 | return; | ||
1456 | } | ||
1457 | |||
1458 | forward: | ||
1459 | LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, | ||
1460 | p2); | ||
1461 | fopc = GNUNET_new (struct ForwardedOperationContext); | ||
1462 | fopc->client = client; | ||
1463 | fopc->operation_id = op_id; | ||
1464 | fopc->type = OP_OVERLAY_CONNECT; | ||
1465 | fopc->opc = | ||
1466 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
1467 | slave->controller, op_id, | ||
1468 | &msg->header, | ||
1469 | &GST_forwarded_operation_reply_relay, | ||
1470 | fopc); | ||
1471 | fopc->timeout_task = | ||
1472 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
1473 | &GST_forwarded_operation_timeout, | ||
1474 | fopc); | ||
1475 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, | ||
1476 | fopcq_tail, | ||
1477 | fopc); | ||
1478 | } | ||
1479 | |||
1480 | |||
1481 | /** | ||
1482 | * Callback called when a connection to the controller of peer2 has been | ||
1483 | * established | ||
1484 | * | ||
1485 | * @param cls the overlay connect contexts | ||
1486 | * @param c handle to the controller connection | ||
1487 | */ | ||
1488 | static void | ||
1489 | p2_controller_connect_cb (void *cls, | ||
1490 | struct GNUNET_TESTBED_Controller *c) | ||
1491 | { | ||
1492 | struct OverlayConnectContext *occ = cls; | ||
1493 | struct RemotePeer2Context *rp2c; | ||
1494 | struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg; | ||
1495 | |||
1496 | GNUNET_assert (OCC_TYPE_LOCAL != occ->type); | ||
1497 | rp2c = &occ->p2ctx.remote; | ||
1498 | rp2c->ncn = NULL; | ||
1499 | rp2c->p2c = c; | ||
1500 | cmsg.header.size = | ||
1501 | htons (sizeof(struct GNUNET_TESTBED_PeerGetConfigurationMessage)); | ||
1502 | cmsg.header.type = | ||
1503 | htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION); | ||
1504 | cmsg.peer_id = htonl (occ->other_peer_id); | ||
1505 | cmsg.operation_id = GNUNET_htonll (occ->op_id); | ||
1506 | rp2c->opc = | ||
1507 | GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c, | ||
1508 | occ->op_id, | ||
1509 | &cmsg.header, | ||
1510 | &overlay_connect_get_config, | ||
1511 | occ); | ||
1512 | GNUNET_free (occ->emsg); | ||
1513 | GNUNET_asprintf (&occ->emsg, | ||
1514 | "0x%llx: Timeout while getting peer identity of peer " | ||
1515 | "with id: %u", | ||
1516 | (unsigned long long) occ->op_id, | ||
1517 | occ->other_peer_id); | ||
1518 | } | ||
1519 | |||
1520 | |||
1521 | /** | ||
1522 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages | ||
1523 | * | ||
1524 | * @param cls identification of the client | ||
1525 | * @param msg the actual message | ||
1526 | */ | ||
1527 | void | ||
1528 | handle_overlay_connect (void *cls, | ||
1529 | const struct GNUNET_TESTBED_OverlayConnectMessage *msg) | ||
1530 | { | ||
1531 | struct GNUNET_SERVICE_Client *client = cls; | ||
1532 | struct Peer *peer; | ||
1533 | struct Peer *peer2; | ||
1534 | struct OverlayConnectContext *occ; | ||
1535 | struct Neighbour *p2n; | ||
1536 | uint64_t operation_id; | ||
1537 | uint32_t p1; | ||
1538 | uint32_t p2; | ||
1539 | uint32_t peer2_host_id; | ||
1540 | |||
1541 | p1 = ntohl (msg->peer1); | ||
1542 | p2 = ntohl (msg->peer2); | ||
1543 | if (! VALID_PEER_ID (p1)) | ||
1544 | { | ||
1545 | GNUNET_break (0); | ||
1546 | GNUNET_SERVICE_client_drop (client); | ||
1547 | return; | ||
1548 | } | ||
1549 | peer = GST_peer_list[p1]; | ||
1550 | operation_id = GNUNET_ntohll (msg->operation_id); | ||
1551 | LOG_DEBUG | ||
1552 | ("Received overlay connect for peers %u and %u with op id: 0x%llx\n", | ||
1553 | p1, | ||
1554 | p2, | ||
1555 | (unsigned long long) operation_id); | ||
1556 | peer2_host_id = ntohl (msg->peer2_host_id); | ||
1557 | if (GNUNET_YES == peer->is_remote) | ||
1558 | { | ||
1559 | if (! VALID_HOST_ID (peer2_host_id)) | ||
1560 | { | ||
1561 | GNUNET_break (0); | ||
1562 | GNUNET_SERVICE_client_drop (client); | ||
1563 | return; | ||
1564 | } | ||
1565 | forward_overlay_connect (msg, client); | ||
1566 | GNUNET_SERVICE_client_continue (client); | ||
1567 | return; | ||
1568 | } | ||
1569 | p2n = NULL; | ||
1570 | occ = GNUNET_new (struct OverlayConnectContext); | ||
1571 | occ->type = OCC_TYPE_LOCAL; | ||
1572 | if (! VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */ | ||
1573 | { | ||
1574 | if (NULL == (p2n = GST_get_neighbour (peer2_host_id))) | ||
1575 | { | ||
1576 | if (! VALID_HOST_ID (peer2_host_id)) | ||
1577 | { | ||
1578 | GNUNET_break (0); | ||
1579 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1580 | "0x%llx: Peer %u's host not in our neighbours list\n", | ||
1581 | (unsigned long long) operation_id, p2); | ||
1582 | GNUNET_SERVICE_client_drop (client); | ||
1583 | GNUNET_free (occ); | ||
1584 | return; | ||
1585 | } | ||
1586 | p2n = GST_create_neighbour (GST_host_list[peer2_host_id]); | ||
1587 | } | ||
1588 | occ->type = OCC_TYPE_REMOTE_LATERAL; | ||
1589 | occ->p2ctx.remote.p2n = p2n; | ||
1590 | } | ||
1591 | else if (GNUNET_YES == GST_peer_list[p2]->is_remote) | ||
1592 | { | ||
1593 | occ->type = OCC_TYPE_REMOTE_SLAVE; | ||
1594 | occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller; | ||
1595 | } | ||
1596 | GNUNET_CONTAINER_DLL_insert_tail (occq_head, | ||
1597 | occq_tail, | ||
1598 | occ); | ||
1599 | occ->client = client; | ||
1600 | occ->other_peer_id = p2; | ||
1601 | GST_peer_list[p1]->reference_cnt++; | ||
1602 | occ->peer = GST_peer_list[p1]; | ||
1603 | occ->op_id = operation_id; | ||
1604 | GNUNET_assert (NULL == occ->timeout_task); | ||
1605 | occ->timeout_task = | ||
1606 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
1607 | &timeout_overlay_connect, | ||
1608 | occ); | ||
1609 | switch (occ->type) | ||
1610 | { | ||
1611 | case OCC_TYPE_REMOTE_LATERAL: | ||
1612 | GNUNET_asprintf (&occ->emsg, | ||
1613 | "0x%llx: Timeout while acquiring connection to peer %u's " | ||
1614 | "host: %u\n", | ||
1615 | (unsigned long long) occ->op_id, | ||
1616 | occ->other_peer_id, | ||
1617 | peer2_host_id); | ||
1618 | occ->p2ctx.remote.ncn | ||
1619 | = GST_neighbour_get_connection (p2n, | ||
1620 | &p2_controller_connect_cb, | ||
1621 | occ); | ||
1622 | break; | ||
1623 | |||
1624 | case OCC_TYPE_REMOTE_SLAVE: | ||
1625 | p2_controller_connect_cb (occ, | ||
1626 | occ->p2ctx.remote.p2c); | ||
1627 | break; | ||
1628 | |||
1629 | case OCC_TYPE_LOCAL: | ||
1630 | peer2 = GST_peer_list[occ->other_peer_id]; | ||
1631 | peer2->reference_cnt++; | ||
1632 | GNUNET_TESTING_peer_get_identity (peer2->details.local.peer, | ||
1633 | &occ->other_peer_identity); | ||
1634 | GNUNET_asprintf (&occ->emsg, | ||
1635 | "0x%llx: Timeout while connecting to CORE of peer with " | ||
1636 | "id: %u", | ||
1637 | (unsigned long long) occ->op_id, | ||
1638 | occ->peer->id); | ||
1639 | occ->cgh_ch = | ||
1640 | GST_connection_pool_get_handle (occ->peer->id, | ||
1641 | occ->peer->details.local.cfg, | ||
1642 | GST_CONNECTIONPOOL_SERVICE_CORE, | ||
1643 | occ_cache_get_handle_core_cb, occ, | ||
1644 | &occ->other_peer_identity, | ||
1645 | &overlay_connect_notify, occ); | ||
1646 | break; | ||
1647 | } | ||
1648 | GNUNET_SERVICE_client_continue (client); | ||
1649 | } | ||
1650 | |||
1651 | |||
1652 | /** | ||
1653 | * Function to cleanup RemoteOverlayConnectCtx and any associated tasks | ||
1654 | * with it | ||
1655 | * | ||
1656 | * @param rocc the RemoteOverlayConnectCtx | ||
1657 | */ | ||
1658 | static void | ||
1659 | cleanup_rocc (struct RemoteOverlayConnectCtx *rocc) | ||
1660 | { | ||
1661 | LOG_DEBUG ("0x%llx: Cleaning up rocc\n", | ||
1662 | (unsigned long long) rocc->op_id); | ||
1663 | if (NULL != rocc->attempt_connect_task_id) | ||
1664 | GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id); | ||
1665 | if (NULL != rocc->timeout_rocc_task_id) | ||
1666 | GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id); | ||
1667 | if (NULL != rocc->ohh) | ||
1668 | GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh); | ||
1669 | if (NULL != rocc->tcc.csh) | ||
1670 | GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh); | ||
1671 | GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th); | ||
1672 | GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats); | ||
1673 | GNUNET_assert (rocc->peer->reference_cnt > 0); | ||
1674 | rocc->peer->reference_cnt--; | ||
1675 | if ((GNUNET_YES == rocc->peer->destroy_flag) && | ||
1676 | (0 == rocc->peer->reference_cnt)) | ||
1677 | GST_destroy_peer (rocc->peer); | ||
1678 | GNUNET_free (rocc->hello); | ||
1679 | GNUNET_CONTAINER_DLL_remove (roccq_head, | ||
1680 | roccq_tail, | ||
1681 | rocc); | ||
1682 | GNUNET_free (rocc); | ||
1683 | } | ||
1684 | |||
1685 | |||
1686 | /** | ||
1687 | * Task to timeout rocc and cleanit up | ||
1688 | * | ||
1689 | * @param cls the RemoteOverlayConnectCtx | ||
1690 | */ | ||
1691 | static void | ||
1692 | timeout_rocc_task (void *cls) | ||
1693 | { | ||
1694 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1695 | |||
1696 | GNUNET_assert (rocc->timeout_rocc_task_id != NULL); | ||
1697 | rocc->timeout_rocc_task_id = NULL; | ||
1698 | LOG_DEBUG ("0x%llx: rocc timed out\n", | ||
1699 | (unsigned long long) rocc->op_id); | ||
1700 | cleanup_rocc (rocc); | ||
1701 | } | ||
1702 | |||
1703 | |||
1704 | /** | ||
1705 | * Function called to notify transport users that another | ||
1706 | * peer connected to us. | ||
1707 | * | ||
1708 | * @param cls the RemoteOverlayConnectContext | ||
1709 | * @param new_peer the peer that connected | ||
1710 | */ | ||
1711 | static void | ||
1712 | cache_transport_peer_connect_notify (void *cls, | ||
1713 | const struct GNUNET_PeerIdentity *new_peer) | ||
1714 | { | ||
1715 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1716 | |||
1717 | LOG_DEBUG ("0x%llx: Request Overlay connect notify\n", | ||
1718 | (unsigned long long) rocc->op_id); | ||
1719 | GNUNET_assert (0 == | ||
1720 | memcmp (new_peer, &rocc->a_id, | ||
1721 | sizeof(struct GNUNET_PeerIdentity))); | ||
1722 | LOG_DEBUG ("0x%llx: Peer %s connected\n", | ||
1723 | (unsigned long long) rocc->op_id, | ||
1724 | GNUNET_i2s (&rocc->a_id)); | ||
1725 | cleanup_rocc (rocc); | ||
1726 | } | ||
1727 | |||
1728 | |||
1729 | /** | ||
1730 | * Task to offer the HELLO message to the peer and ask it to connect to the peer | ||
1731 | * whose identity is in RemoteOverlayConnectCtx | ||
1732 | * | ||
1733 | * @param cls the RemoteOverlayConnectCtx | ||
1734 | */ | ||
1735 | static void | ||
1736 | attempt_connect_task (void *cls); | ||
1737 | |||
1738 | |||
1739 | /** | ||
1740 | * Task that is run when hello has been sent If tc->reason = | ||
1741 | * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if | ||
1742 | * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded | ||
1743 | * | ||
1744 | * @param cls the overlay connect context | ||
1745 | */ | ||
1746 | static void | ||
1747 | rocc_hello_sent_cb (void *cls) | ||
1748 | { | ||
1749 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1750 | |||
1751 | rocc->ohh = NULL; | ||
1752 | GNUNET_assert (NULL == rocc->attempt_connect_task_id); | ||
1753 | LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n", | ||
1754 | (unsigned long long) rocc->op_id, | ||
1755 | GNUNET_i2s (&rocc->a_id), | ||
1756 | rocc->peer->id); | ||
1757 | rocc->tcc.cgh_p2_ats = | ||
1758 | GST_connection_pool_get_handle (rocc->peer->id, | ||
1759 | rocc->peer->details.local.cfg, | ||
1760 | GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY, | ||
1761 | &occ_cache_get_handle_ats_rocc_cb, | ||
1762 | rocc, NULL, NULL, NULL); | ||
1763 | } | ||
1764 | |||
1765 | |||
1766 | /** | ||
1767 | * Task to offer the HELLO message to the peer and ask it to connect to the peer | ||
1768 | * whose identity is in RemoteOverlayConnectCtx | ||
1769 | * | ||
1770 | * @param cls the RemoteOverlayConnectCtx | ||
1771 | */ | ||
1772 | static void | ||
1773 | attempt_connect_task (void *cls) | ||
1774 | { | ||
1775 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1776 | |||
1777 | GNUNET_assert (NULL != rocc->attempt_connect_task_id); | ||
1778 | rocc->attempt_connect_task_id = NULL; | ||
1779 | LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n", | ||
1780 | (unsigned long long) rocc->op_id, | ||
1781 | GNUNET_i2s (&rocc->a_id), | ||
1782 | rocc->peer->id); | ||
1783 | rocc->ohh = | ||
1784 | GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg, | ||
1785 | rocc->hello, | ||
1786 | &rocc_hello_sent_cb, | ||
1787 | rocc); | ||
1788 | if (NULL == rocc->ohh) | ||
1789 | rocc->attempt_connect_task_id = | ||
1790 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
1791 | (GNUNET_TIME_UNIT_MILLISECONDS, | ||
1792 | 100 | ||
1793 | + GNUNET_CRYPTO_random_u32 | ||
1794 | (GNUNET_CRYPTO_QUALITY_WEAK, 500)), | ||
1795 | &attempt_connect_task, rocc); | ||
1796 | } | ||
1797 | |||
1798 | |||
1799 | /** | ||
1800 | * Callback from cache with needed handles set | ||
1801 | * | ||
1802 | * @param cls the closure passed to GST_cache_get_handle_transport() | ||
1803 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
1804 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
1805 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
1806 | * @param ignore_ peer identity which is ignored in this callback | ||
1807 | */ | ||
1808 | static void | ||
1809 | rocc_cache_get_handle_transport_cb (void *cls, | ||
1810 | struct GNUNET_CORE_Handle *ch, | ||
1811 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
1812 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
1813 | const struct GNUNET_PeerIdentity *ignore_, | ||
1814 | const struct | ||
1815 | GNUNET_CONFIGURATION_Handle *cfg) | ||
1816 | { | ||
1817 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1818 | |||
1819 | if (NULL == th) | ||
1820 | { | ||
1821 | rocc->timeout_rocc_task_id = | ||
1822 | GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc); | ||
1823 | return; | ||
1824 | } | ||
1825 | rocc->tcc.th_ = th; | ||
1826 | rocc->tcc.cfg = cfg; | ||
1827 | if (NULL != | ||
1828 | GNUNET_TRANSPORT_core_get_mq (rocc->tcc.th_, | ||
1829 | &rocc->a_id)) | ||
1830 | { | ||
1831 | LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n", | ||
1832 | (unsigned long long) rocc->op_id, | ||
1833 | GNUNET_i2s (&rocc->a_id), | ||
1834 | rocc->peer->id); | ||
1835 | cleanup_rocc (rocc); | ||
1836 | return; | ||
1837 | } | ||
1838 | rocc->attempt_connect_task_id = | ||
1839 | GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc); | ||
1840 | } | ||
1841 | |||
1842 | |||
1843 | /** | ||
1844 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages | ||
1845 | * | ||
1846 | * @param cls identification of the client | ||
1847 | * @param msg the actual message | ||
1848 | * @return #GNUNET_OK if @a msg is well-formed | ||
1849 | */ | ||
1850 | int | ||
1851 | check_remote_overlay_connect (void *cls, | ||
1852 | const struct | ||
1853 | GNUNET_TESTBED_RemoteOverlayConnectMessage *msg) | ||
1854 | { | ||
1855 | uint32_t peer_id; | ||
1856 | uint16_t msize; | ||
1857 | uint16_t hsize; | ||
1858 | |||
1859 | msize = ntohs (msg->header.size); | ||
1860 | if (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type)) | ||
1861 | { | ||
1862 | GNUNET_break (0); | ||
1863 | return GNUNET_SYSERR; | ||
1864 | } | ||
1865 | hsize = ntohs (msg->hello->size); | ||
1866 | if ((sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) != | ||
1867 | msize) | ||
1868 | { | ||
1869 | GNUNET_break (0); | ||
1870 | return GNUNET_SYSERR; | ||
1871 | } | ||
1872 | peer_id = ntohl (msg->peer); | ||
1873 | if ((peer_id >= GST_peer_list_size) || | ||
1874 | (NULL == GST_peer_list[peer_id])) | ||
1875 | { | ||
1876 | GNUNET_break_op (0); | ||
1877 | return GNUNET_SYSERR; | ||
1878 | } | ||
1879 | return GNUNET_OK; | ||
1880 | } | ||
1881 | |||
1882 | |||
1883 | /** | ||
1884 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages | ||
1885 | * | ||
1886 | * @param cls identification of the client | ||
1887 | * @param msg the actual message | ||
1888 | */ | ||
1889 | void | ||
1890 | handle_remote_overlay_connect (void *cls, | ||
1891 | const struct | ||
1892 | GNUNET_TESTBED_RemoteOverlayConnectMessage *msg) | ||
1893 | { | ||
1894 | struct GNUNET_SERVICE_Client *client = cls; | ||
1895 | struct RemoteOverlayConnectCtx *rocc; | ||
1896 | struct Peer *peer; | ||
1897 | struct GNUNET_PeerIdentity pid; | ||
1898 | static char pid_str[16]; | ||
1899 | uint32_t peer_id; | ||
1900 | uint16_t hsize; | ||
1901 | |||
1902 | hsize = ntohs (msg->hello->size); | ||
1903 | peer_id = ntohl (msg->peer); | ||
1904 | peer = GST_peer_list[peer_id]; | ||
1905 | if (GNUNET_YES == peer->is_remote) | ||
1906 | { | ||
1907 | struct GNUNET_MessageHeader *msg2; | ||
1908 | |||
1909 | msg2 = GNUNET_copy_message (&msg->header); | ||
1910 | GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller, | ||
1911 | msg2); | ||
1912 | GNUNET_SERVICE_client_continue (client); | ||
1913 | return; | ||
1914 | } | ||
1915 | rocc = GNUNET_new (struct RemoteOverlayConnectCtx); | ||
1916 | rocc->op_id = GNUNET_ntohll (msg->operation_id); | ||
1917 | GNUNET_CONTAINER_DLL_insert_tail (roccq_head, | ||
1918 | roccq_tail, | ||
1919 | rocc); | ||
1920 | rocc->a_id = msg->peer_identity; | ||
1921 | GNUNET_TESTING_peer_get_identity (peer->details.local.peer, | ||
1922 | &pid); | ||
1923 | (void) GNUNET_strlcpy (pid_str, | ||
1924 | GNUNET_i2s (&pid), | ||
1925 | sizeof(pid_str)); | ||
1926 | LOG_DEBUG ( | ||
1927 | "0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n", | ||
1928 | (unsigned long long) rocc->op_id, | ||
1929 | pid_str, | ||
1930 | GNUNET_i2s (&rocc->a_id), | ||
1931 | hsize); | ||
1932 | rocc->peer = peer; | ||
1933 | rocc->peer->reference_cnt++; | ||
1934 | rocc->hello = GNUNET_malloc (hsize); | ||
1935 | GNUNET_memcpy (rocc->hello, | ||
1936 | msg->hello, | ||
1937 | hsize); | ||
1938 | rocc->tcc.cgh_p2_th = | ||
1939 | GST_connection_pool_get_handle (peer_id, | ||
1940 | rocc->peer->details.local.cfg, | ||
1941 | GST_CONNECTIONPOOL_SERVICE_TRANSPORT, | ||
1942 | &rocc_cache_get_handle_transport_cb, | ||
1943 | rocc, | ||
1944 | &rocc->a_id, | ||
1945 | &cache_transport_peer_connect_notify, | ||
1946 | rocc); | ||
1947 | rocc->timeout_rocc_task_id = | ||
1948 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
1949 | &timeout_rocc_task, | ||
1950 | rocc); | ||
1951 | GNUNET_SERVICE_client_continue (client); | ||
1952 | } | ||
1953 | |||
1954 | |||
1955 | /** | ||
1956 | * Clears all pending overlay connect contexts in queue | ||
1957 | */ | ||
1958 | void | ||
1959 | GST_free_occq () | ||
1960 | { | ||
1961 | struct OverlayConnectContext *occ; | ||
1962 | |||
1963 | while (NULL != (occ = occq_head)) | ||
1964 | cleanup_occ (occ); | ||
1965 | } | ||
1966 | |||
1967 | |||
1968 | /** | ||
1969 | * Clears all pending remote overlay connect contexts in queue | ||
1970 | */ | ||
1971 | void | ||
1972 | GST_free_roccq () | ||
1973 | { | ||
1974 | struct RemoteOverlayConnectCtx *rocc; | ||
1975 | |||
1976 | while (NULL != (rocc = roccq_head)) | ||
1977 | cleanup_rocc (rocc); | ||
1978 | } | ||
diff --git a/src/testbed/gnunet-service-testbed_peers.c b/src/testbed/gnunet-service-testbed_peers.c deleted file mode 100644 index 0bfeb4583..000000000 --- a/src/testbed/gnunet-service-testbed_peers.c +++ /dev/null | |||
@@ -1,1569 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2013, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | |||
22 | /** | ||
23 | * @file testbed/gnunet-service-testbed_peers.c | ||
24 | * @brief implementation of TESTBED service that deals with peer management | ||
25 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
26 | */ | ||
27 | |||
28 | #include "gnunet-service-testbed.h" | ||
29 | #include "gnunet_arm_service.h" | ||
30 | #include <zlib.h> | ||
31 | |||
32 | |||
33 | /** | ||
34 | * A list of peers we know about | ||
35 | */ | ||
36 | struct Peer **GST_peer_list; | ||
37 | |||
38 | /** | ||
39 | * The current number of peers running locally under this controller | ||
40 | */ | ||
41 | unsigned int GST_num_local_peers; | ||
42 | |||
43 | |||
44 | /** | ||
45 | * Context information to manage peers' services | ||
46 | */ | ||
47 | struct ManageServiceContext | ||
48 | { | ||
49 | /** | ||
50 | * DLL next ptr | ||
51 | */ | ||
52 | struct ManageServiceContext *next; | ||
53 | |||
54 | /** | ||
55 | * DLL prev ptr | ||
56 | */ | ||
57 | struct ManageServiceContext *prev; | ||
58 | |||
59 | /** | ||
60 | * The ARM handle of the peer | ||
61 | */ | ||
62 | struct GNUNET_ARM_Handle *ah; | ||
63 | |||
64 | /** | ||
65 | * peer whose service has to be managed | ||
66 | */ | ||
67 | struct Peer *peer; | ||
68 | |||
69 | /** | ||
70 | * The client which requested to manage the peer's service | ||
71 | */ | ||
72 | struct GNUNET_SERVICE_Client *client; | ||
73 | |||
74 | /** | ||
75 | * Name of the service. | ||
76 | */ | ||
77 | char *service; | ||
78 | |||
79 | /** | ||
80 | * The operation id of the associated request | ||
81 | */ | ||
82 | uint64_t op_id; | ||
83 | |||
84 | /** | ||
85 | * 1 if the service at the peer has to be started; 0 if it has to be stopped | ||
86 | */ | ||
87 | uint8_t start; | ||
88 | |||
89 | /** | ||
90 | * Is this context expired? Do not work on this context if it is set to | ||
91 | * GNUNET_YES | ||
92 | */ | ||
93 | uint8_t expired; | ||
94 | }; | ||
95 | |||
96 | |||
97 | /** | ||
98 | * Context information for peer re-configure operations | ||
99 | */ | ||
100 | struct PeerReconfigureContext | ||
101 | { | ||
102 | /** | ||
103 | * DLL next for inclusoin in peer reconfigure operations list | ||
104 | */ | ||
105 | struct PeerReconfigureContext *next; | ||
106 | |||
107 | /** | ||
108 | * DLL prev | ||
109 | */ | ||
110 | struct PeerReconfigureContext *prev; | ||
111 | |||
112 | /** | ||
113 | * The client which gave this operation to us | ||
114 | */ | ||
115 | struct GNUNET_SERVICE_Client *client; | ||
116 | |||
117 | /** | ||
118 | * The configuration handle to use as the new template | ||
119 | */ | ||
120 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
121 | |||
122 | /** | ||
123 | * The id of the operation | ||
124 | */ | ||
125 | uint64_t op_id; | ||
126 | |||
127 | /** | ||
128 | * The id of the peer which has to be reconfigured | ||
129 | */ | ||
130 | uint32_t peer_id; | ||
131 | |||
132 | /** | ||
133 | * The the peer stopped? Used while cleaning up this context to decide | ||
134 | * whether the asynchronous stop request through Testing/ARM API has to be | ||
135 | * cancelled | ||
136 | */ | ||
137 | uint8_t stopped; | ||
138 | }; | ||
139 | |||
140 | /** | ||
141 | * The DLL head for the peer reconfigure list | ||
142 | */ | ||
143 | static struct PeerReconfigureContext *prc_head; | ||
144 | |||
145 | /** | ||
146 | * The DLL tail for the peer reconfigure list | ||
147 | */ | ||
148 | static struct PeerReconfigureContext *prc_tail; | ||
149 | |||
150 | |||
151 | /** | ||
152 | * DLL head for queue of manage service requests | ||
153 | */ | ||
154 | static struct ManageServiceContext *mctx_head; | ||
155 | |||
156 | /** | ||
157 | * DLL tail for queue of manage service requests | ||
158 | */ | ||
159 | static struct ManageServiceContext *mctx_tail; | ||
160 | |||
161 | |||
162 | /** | ||
163 | * Adds a peer to the peer array | ||
164 | * | ||
165 | * @param peer the peer to add | ||
166 | */ | ||
167 | static void | ||
168 | peer_list_add (struct Peer *peer) | ||
169 | { | ||
170 | if (peer->id >= GST_peer_list_size) | ||
171 | GST_array_grow_large_enough (GST_peer_list, GST_peer_list_size, peer->id); | ||
172 | GNUNET_assert (NULL == GST_peer_list[peer->id]); | ||
173 | GST_peer_list[peer->id] = peer; | ||
174 | if (GNUNET_NO == peer->is_remote) | ||
175 | GST_num_local_peers++; | ||
176 | } | ||
177 | |||
178 | |||
179 | /** | ||
180 | * Removes a the give peer from the peer array | ||
181 | * | ||
182 | * @param peer the peer to be removed | ||
183 | */ | ||
184 | static void | ||
185 | peer_list_remove (struct Peer *peer) | ||
186 | { | ||
187 | unsigned int orig_size; | ||
188 | uint32_t id; | ||
189 | |||
190 | if (GNUNET_NO == peer->is_remote) | ||
191 | GST_num_local_peers--; | ||
192 | GST_peer_list[peer->id] = NULL; | ||
193 | orig_size = GST_peer_list_size; | ||
194 | while (GST_peer_list_size >= LIST_GROW_STEP) | ||
195 | { | ||
196 | for (id = GST_peer_list_size - 1; | ||
197 | (id >= GST_peer_list_size - LIST_GROW_STEP) && (id != UINT32_MAX); | ||
198 | id--) | ||
199 | if (NULL != GST_peer_list[id]) | ||
200 | break; | ||
201 | if (id != ((GST_peer_list_size - LIST_GROW_STEP) - 1)) | ||
202 | break; | ||
203 | GST_peer_list_size -= LIST_GROW_STEP; | ||
204 | } | ||
205 | if (orig_size == GST_peer_list_size) | ||
206 | return; | ||
207 | GST_peer_list = | ||
208 | GNUNET_realloc (GST_peer_list, | ||
209 | sizeof(struct Peer *) * GST_peer_list_size); | ||
210 | } | ||
211 | |||
212 | |||
213 | /** | ||
214 | * The task to be executed if the forwarded peer create operation has been | ||
215 | * timed out | ||
216 | * | ||
217 | * @param cls the FowardedOperationContext | ||
218 | */ | ||
219 | static void | ||
220 | peer_create_forward_timeout (void *cls) | ||
221 | { | ||
222 | struct ForwardedOperationContext *fopc = cls; | ||
223 | |||
224 | GNUNET_free (fopc->cls); | ||
225 | GST_forwarded_operation_timeout (fopc); | ||
226 | } | ||
227 | |||
228 | |||
229 | /** | ||
230 | * Callback to be called when forwarded peer create operation is successful. We | ||
231 | * have to relay the reply msg back to the client | ||
232 | * | ||
233 | * @param cls ForwardedOperationContext | ||
234 | * @param msg the peer create success message | ||
235 | */ | ||
236 | static void | ||
237 | peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) | ||
238 | { | ||
239 | struct ForwardedOperationContext *fopc = cls; | ||
240 | struct Peer *remote_peer; | ||
241 | |||
242 | if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS) | ||
243 | { | ||
244 | GNUNET_assert (NULL != fopc->cls); | ||
245 | remote_peer = fopc->cls; | ||
246 | peer_list_add (remote_peer); | ||
247 | } | ||
248 | GST_forwarded_operation_reply_relay (fopc, | ||
249 | msg); | ||
250 | } | ||
251 | |||
252 | |||
253 | /** | ||
254 | * Function to destroy a peer | ||
255 | * | ||
256 | * @param peer the peer structure to destroy | ||
257 | */ | ||
258 | void | ||
259 | GST_destroy_peer (struct Peer *peer) | ||
260 | { | ||
261 | GNUNET_break (0 == peer->reference_cnt); | ||
262 | if (GNUNET_YES == peer->is_remote) | ||
263 | { | ||
264 | peer_list_remove (peer); | ||
265 | GNUNET_free (peer); | ||
266 | return; | ||
267 | } | ||
268 | if (GNUNET_YES == peer->details.local.is_running) | ||
269 | { | ||
270 | GNUNET_TESTING_peer_stop (peer->details.local.peer); | ||
271 | peer->details.local.is_running = GNUNET_NO; | ||
272 | } | ||
273 | GNUNET_TESTING_peer_destroy (peer->details.local.peer); | ||
274 | GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); | ||
275 | peer_list_remove (peer); | ||
276 | GNUNET_free (peer); | ||
277 | } | ||
278 | |||
279 | |||
280 | /** | ||
281 | * Cleanup the context information created for managing a peer's service | ||
282 | * | ||
283 | * @param mctx the ManageServiceContext | ||
284 | */ | ||
285 | static void | ||
286 | cleanup_mctx (struct ManageServiceContext *mctx) | ||
287 | { | ||
288 | mctx->expired = GNUNET_YES; | ||
289 | GNUNET_CONTAINER_DLL_remove (mctx_head, | ||
290 | mctx_tail, | ||
291 | mctx); | ||
292 | GNUNET_ARM_disconnect (mctx->ah); | ||
293 | GNUNET_assert (0 < mctx->peer->reference_cnt); | ||
294 | mctx->peer->reference_cnt--; | ||
295 | if ((GNUNET_YES == mctx->peer->destroy_flag) && | ||
296 | (0 == mctx->peer->reference_cnt)) | ||
297 | GST_destroy_peer (mctx->peer); | ||
298 | GNUNET_free (mctx->service); | ||
299 | GNUNET_free (mctx); | ||
300 | } | ||
301 | |||
302 | |||
303 | /** | ||
304 | * Stops a peer | ||
305 | * | ||
306 | * @param peer the peer to stop | ||
307 | * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure | ||
308 | */ | ||
309 | static int | ||
310 | stop_peer (struct Peer *peer) | ||
311 | { | ||
312 | GNUNET_assert (GNUNET_NO == peer->is_remote); | ||
313 | if (GNUNET_OK != GNUNET_TESTING_peer_kill (peer->details.local.peer)) | ||
314 | return GNUNET_SYSERR; | ||
315 | peer->details.local.is_running = GNUNET_NO; | ||
316 | return GNUNET_OK; | ||
317 | } | ||
318 | |||
319 | |||
320 | /** | ||
321 | * Cleans up the given PeerReconfigureContext | ||
322 | * | ||
323 | * @param prc the PeerReconfigureContext | ||
324 | */ | ||
325 | static void | ||
326 | cleanup_prc (struct PeerReconfigureContext *prc) | ||
327 | { | ||
328 | struct Peer *peer; | ||
329 | |||
330 | if (VALID_PEER_ID (prc->peer_id)) | ||
331 | { | ||
332 | peer = GST_peer_list [prc->peer_id]; | ||
333 | if (1 != prc->stopped) | ||
334 | { | ||
335 | GNUNET_TESTING_peer_stop_async_cancel (peer->details.local.peer); | ||
336 | stop_peer (peer); /* Stop the peer synchronously */ | ||
337 | } | ||
338 | } | ||
339 | if (NULL != prc->cfg) | ||
340 | GNUNET_CONFIGURATION_destroy (prc->cfg); | ||
341 | GNUNET_CONTAINER_DLL_remove (prc_head, | ||
342 | prc_tail, | ||
343 | prc); | ||
344 | GNUNET_free (prc); | ||
345 | } | ||
346 | |||
347 | |||
348 | /** | ||
349 | * Notify peers subsystem that @a client disconnected. | ||
350 | * | ||
351 | * @param client the client that disconnected | ||
352 | */ | ||
353 | void | ||
354 | GST_notify_client_disconnect_peers (struct GNUNET_SERVICE_Client *client) | ||
355 | { | ||
356 | struct ForwardedOperationContext *fopc; | ||
357 | struct ForwardedOperationContext *fopcn; | ||
358 | struct ManageServiceContext *mctx; | ||
359 | struct ManageServiceContext *mctxn; | ||
360 | struct PeerReconfigureContext *prc; | ||
361 | struct PeerReconfigureContext *prcn; | ||
362 | |||
363 | for (fopc = fopcq_head; NULL != fopc; fopc = fopcn) | ||
364 | { | ||
365 | fopcn = fopc->next; | ||
366 | if (client == fopc->client) | ||
367 | { | ||
368 | if (OP_PEER_CREATE == fopc->type) | ||
369 | GNUNET_free (fopc->cls); | ||
370 | GNUNET_SCHEDULER_cancel (fopc->timeout_task); | ||
371 | GST_forwarded_operation_timeout (fopc); | ||
372 | } | ||
373 | } | ||
374 | for (mctx = mctx_head; NULL != mctx; mctx = mctxn) | ||
375 | { | ||
376 | mctxn = mctx->next; | ||
377 | if (client == mctx->client) | ||
378 | cleanup_mctx (mctx); | ||
379 | } | ||
380 | for (prc = prc_head; NULL != prc; prc = prcn) | ||
381 | { | ||
382 | prcn = prc->next; | ||
383 | if (client == prc->client) | ||
384 | cleanup_prc (prc); | ||
385 | } | ||
386 | } | ||
387 | |||
388 | |||
389 | /** | ||
390 | * Callback to be called when forwarded peer destroy operation is successful. We | ||
391 | * have to relay the reply msg back to the client | ||
392 | * | ||
393 | * @param cls ForwardedOperationContext | ||
394 | * @param msg the peer create success message | ||
395 | */ | ||
396 | static void | ||
397 | peer_destroy_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) | ||
398 | { | ||
399 | struct ForwardedOperationContext *fopc = cls; | ||
400 | struct Peer *remote_peer; | ||
401 | |||
402 | if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS == | ||
403 | ntohs (msg->type)) | ||
404 | { | ||
405 | remote_peer = fopc->cls; | ||
406 | GNUNET_assert (NULL != remote_peer); | ||
407 | remote_peer->destroy_flag = GNUNET_YES; | ||
408 | if (0 == remote_peer->reference_cnt) | ||
409 | GST_destroy_peer (remote_peer); | ||
410 | } | ||
411 | GST_forwarded_operation_reply_relay (fopc, | ||
412 | msg); | ||
413 | } | ||
414 | |||
415 | |||
416 | /** | ||
417 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages | ||
418 | * | ||
419 | * @param cls identification of the client | ||
420 | * @param msg the actual message | ||
421 | * @return #GNUNET_OK if @a msg is well-formed | ||
422 | */ | ||
423 | int | ||
424 | check_peer_create (void *cls, | ||
425 | const struct GNUNET_TESTBED_PeerCreateMessage *msg) | ||
426 | { | ||
427 | return GNUNET_OK; /* checked later */ | ||
428 | } | ||
429 | |||
430 | |||
431 | /** | ||
432 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages | ||
433 | * | ||
434 | * @param cls identification of the client | ||
435 | * @param msg the actual message | ||
436 | */ | ||
437 | void | ||
438 | handle_peer_create (void *cls, | ||
439 | const struct GNUNET_TESTBED_PeerCreateMessage *msg) | ||
440 | { | ||
441 | struct GNUNET_SERVICE_Client *client = cls; | ||
442 | struct GNUNET_MQ_Envelope *env; | ||
443 | struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply; | ||
444 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
445 | struct ForwardedOperationContext *fo_ctxt; | ||
446 | struct Route *route; | ||
447 | struct Peer *peer; | ||
448 | char *emsg; | ||
449 | uint32_t host_id; | ||
450 | uint32_t peer_id; | ||
451 | |||
452 | host_id = ntohl (msg->host_id); | ||
453 | peer_id = ntohl (msg->peer_id); | ||
454 | if (VALID_PEER_ID (peer_id)) | ||
455 | { | ||
456 | (void) GNUNET_asprintf (&emsg, | ||
457 | "Peer with ID %u already exists", | ||
458 | peer_id); | ||
459 | GST_send_operation_fail_msg (client, | ||
460 | GNUNET_ntohll (msg->operation_id), | ||
461 | emsg); | ||
462 | GNUNET_free (emsg); | ||
463 | GNUNET_SERVICE_client_continue (client); | ||
464 | return; | ||
465 | } | ||
466 | if (UINT32_MAX == peer_id) | ||
467 | { | ||
468 | GST_send_operation_fail_msg (client, | ||
469 | GNUNET_ntohll (msg->operation_id), | ||
470 | "Cannot create peer with given ID"); | ||
471 | GNUNET_SERVICE_client_continue (client); | ||
472 | return; | ||
473 | } | ||
474 | if (host_id == GST_context->host_id) | ||
475 | { | ||
476 | /* We are responsible for this peer */ | ||
477 | cfg = GNUNET_TESTBED_extract_config_ (&msg->header); | ||
478 | if (NULL == cfg) | ||
479 | { | ||
480 | GNUNET_break (0); | ||
481 | GNUNET_SERVICE_client_drop (client); | ||
482 | return; | ||
483 | } | ||
484 | GNUNET_CONFIGURATION_set_value_number (cfg, | ||
485 | "TESTBED", | ||
486 | "PEERID", | ||
487 | (unsigned long long) peer_id); | ||
488 | |||
489 | GNUNET_CONFIGURATION_set_value_number (cfg, | ||
490 | "PATHS", | ||
491 | "PEERID", | ||
492 | (unsigned long long) peer_id); | ||
493 | peer = GNUNET_new (struct Peer); | ||
494 | peer->is_remote = GNUNET_NO; | ||
495 | peer->details.local.cfg = cfg; | ||
496 | peer->id = peer_id; | ||
497 | LOG_DEBUG ("Creating peer with id: %u\n", | ||
498 | (unsigned int) peer->id); | ||
499 | peer->details.local.peer = | ||
500 | GNUNET_TESTING_peer_configure (GST_context->system, | ||
501 | peer->details.local.cfg, peer->id, | ||
502 | NULL /* Peer id */, | ||
503 | &emsg); | ||
504 | if (NULL == peer->details.local.peer) | ||
505 | { | ||
506 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
507 | "Configuring peer failed: %s\n", | ||
508 | emsg); | ||
509 | GNUNET_free (emsg); | ||
510 | GNUNET_free (peer); | ||
511 | GNUNET_break (0); | ||
512 | GNUNET_SERVICE_client_drop (client); | ||
513 | return; | ||
514 | } | ||
515 | peer->details.local.is_running = GNUNET_NO; | ||
516 | peer_list_add (peer); | ||
517 | env = GNUNET_MQ_msg (reply, | ||
518 | GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS); | ||
519 | reply->peer_id = msg->peer_id; | ||
520 | reply->operation_id = msg->operation_id; | ||
521 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
522 | env); | ||
523 | GNUNET_SERVICE_client_continue (client); | ||
524 | return; | ||
525 | } | ||
526 | |||
527 | /* Forward peer create request */ | ||
528 | route = GST_find_dest_route (host_id); | ||
529 | if (NULL == route) | ||
530 | { | ||
531 | GNUNET_break (0); | ||
532 | GNUNET_SERVICE_client_continue (client); // ? | ||
533 | return; | ||
534 | } | ||
535 | peer = GNUNET_new (struct Peer); | ||
536 | peer->is_remote = GNUNET_YES; | ||
537 | peer->id = peer_id; | ||
538 | peer->details.remote.slave = GST_slave_list[route->dest]; | ||
539 | peer->details.remote.remote_host_id = host_id; | ||
540 | fo_ctxt = GNUNET_new (struct ForwardedOperationContext); | ||
541 | fo_ctxt->client = client; | ||
542 | fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id); | ||
543 | fo_ctxt->cls = peer; | ||
544 | fo_ctxt->type = OP_PEER_CREATE; | ||
545 | fo_ctxt->opc = | ||
546 | GNUNET_TESTBED_forward_operation_msg_ (GST_slave_list | ||
547 | [route->dest]->controller, | ||
548 | fo_ctxt->operation_id, | ||
549 | &msg->header, | ||
550 | &peer_create_success_cb, | ||
551 | fo_ctxt); | ||
552 | fo_ctxt->timeout_task = | ||
553 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
554 | &peer_create_forward_timeout, | ||
555 | fo_ctxt); | ||
556 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, | ||
557 | fopcq_tail, | ||
558 | fo_ctxt); | ||
559 | GNUNET_SERVICE_client_continue (client); | ||
560 | } | ||
561 | |||
562 | |||
563 | /** | ||
564 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages | ||
565 | * | ||
566 | * @param cls identification of the client | ||
567 | * @param msg the actual message | ||
568 | */ | ||
569 | void | ||
570 | handle_peer_destroy (void *cls, | ||
571 | const struct GNUNET_TESTBED_PeerDestroyMessage *msg) | ||
572 | { | ||
573 | struct GNUNET_SERVICE_Client *client = cls; | ||
574 | struct ForwardedOperationContext *fopc; | ||
575 | struct Peer *peer; | ||
576 | uint32_t peer_id; | ||
577 | |||
578 | peer_id = ntohl (msg->peer_id); | ||
579 | LOG_DEBUG ("Received peer destroy on peer: %u and operation id: %llu\n", | ||
580 | (unsigned int) peer_id, | ||
581 | (unsigned long long) GNUNET_ntohll (msg->operation_id)); | ||
582 | if (! VALID_PEER_ID (peer_id)) | ||
583 | { | ||
584 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
585 | "Asked to destroy a non existent peer with id: %u\n", peer_id); | ||
586 | GST_send_operation_fail_msg (client, | ||
587 | GNUNET_ntohll (msg->operation_id), | ||
588 | "Peer doesn't exist"); | ||
589 | GNUNET_SERVICE_client_continue (client); | ||
590 | return; | ||
591 | } | ||
592 | peer = GST_peer_list[peer_id]; | ||
593 | if (GNUNET_YES == peer->is_remote) | ||
594 | { | ||
595 | /* Forward the destroy message to sub controller */ | ||
596 | fopc = GNUNET_new (struct ForwardedOperationContext); | ||
597 | fopc->client = client; | ||
598 | fopc->cls = peer; | ||
599 | fopc->type = OP_PEER_DESTROY; | ||
600 | fopc->operation_id = GNUNET_ntohll (msg->operation_id); | ||
601 | fopc->opc = | ||
602 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
603 | slave->controller, | ||
604 | fopc->operation_id, | ||
605 | &msg->header, | ||
606 | &peer_destroy_success_cb, | ||
607 | fopc); | ||
608 | fopc->timeout_task = | ||
609 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
610 | &GST_forwarded_operation_timeout, | ||
611 | fopc); | ||
612 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, | ||
613 | fopcq_tail, | ||
614 | fopc); | ||
615 | GNUNET_SERVICE_client_continue (client); | ||
616 | return; | ||
617 | } | ||
618 | peer->destroy_flag = GNUNET_YES; | ||
619 | if (0 == peer->reference_cnt) | ||
620 | GST_destroy_peer (peer); | ||
621 | else | ||
622 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
623 | "Delaying peer destroy as peer is currently in use\n"); | ||
624 | GST_send_operation_success_msg (client, | ||
625 | GNUNET_ntohll (msg->operation_id)); | ||
626 | GNUNET_SERVICE_client_continue (client); | ||
627 | } | ||
628 | |||
629 | |||
630 | /** | ||
631 | * Stats a peer | ||
632 | * | ||
633 | * @param peer the peer to start | ||
634 | * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure | ||
635 | */ | ||
636 | static int | ||
637 | start_peer (struct Peer *peer) | ||
638 | { | ||
639 | GNUNET_assert (GNUNET_NO == peer->is_remote); | ||
640 | if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer)) | ||
641 | return GNUNET_SYSERR; | ||
642 | peer->details.local.is_running = GNUNET_YES; | ||
643 | return GNUNET_OK; | ||
644 | } | ||
645 | |||
646 | |||
647 | /** | ||
648 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_START_PEER messages | ||
649 | * | ||
650 | * @param cls identification of the client | ||
651 | * @param msg the actual message | ||
652 | */ | ||
653 | void | ||
654 | handle_peer_start (void *cls, | ||
655 | const struct GNUNET_TESTBED_PeerStartMessage *msg) | ||
656 | { | ||
657 | struct GNUNET_SERVICE_Client *client = cls; | ||
658 | struct GNUNET_MQ_Envelope *env; | ||
659 | struct GNUNET_TESTBED_PeerEventMessage *reply; | ||
660 | struct ForwardedOperationContext *fopc; | ||
661 | struct Peer *peer; | ||
662 | uint32_t peer_id; | ||
663 | |||
664 | peer_id = ntohl (msg->peer_id); | ||
665 | if (! VALID_PEER_ID (peer_id)) | ||
666 | { | ||
667 | GNUNET_break (0); | ||
668 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
669 | "Asked to start a non existent peer with id: %u\n", | ||
670 | peer_id); | ||
671 | GNUNET_SERVICE_client_continue (client); | ||
672 | return; | ||
673 | } | ||
674 | peer = GST_peer_list[peer_id]; | ||
675 | if (GNUNET_YES == peer->is_remote) | ||
676 | { | ||
677 | fopc = GNUNET_new (struct ForwardedOperationContext); | ||
678 | fopc->client = client; | ||
679 | fopc->operation_id = GNUNET_ntohll (msg->operation_id); | ||
680 | fopc->type = OP_PEER_START; | ||
681 | fopc->opc = | ||
682 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
683 | slave->controller, | ||
684 | fopc->operation_id, &msg->header, | ||
685 | & | ||
686 | GST_forwarded_operation_reply_relay, | ||
687 | fopc); | ||
688 | fopc->timeout_task = | ||
689 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
690 | &GST_forwarded_operation_timeout, | ||
691 | fopc); | ||
692 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, | ||
693 | fopcq_tail, | ||
694 | fopc); | ||
695 | GNUNET_SERVICE_client_continue (client); | ||
696 | return; | ||
697 | } | ||
698 | if (GNUNET_OK != start_peer (peer)) | ||
699 | { | ||
700 | GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), | ||
701 | "Failed to start"); | ||
702 | GNUNET_SERVICE_client_continue (client); | ||
703 | return; | ||
704 | } | ||
705 | env = GNUNET_MQ_msg (reply, | ||
706 | GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); | ||
707 | reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START); | ||
708 | reply->host_id = htonl (GST_context->host_id); | ||
709 | reply->peer_id = msg->peer_id; | ||
710 | reply->operation_id = msg->operation_id; | ||
711 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
712 | env); | ||
713 | GNUNET_SERVICE_client_continue (client); | ||
714 | } | ||
715 | |||
716 | |||
717 | /** | ||
718 | * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER messages | ||
719 | * | ||
720 | * @param cls identification of the client | ||
721 | * @param msg the actual message | ||
722 | */ | ||
723 | void | ||
724 | handle_peer_stop (void *cls, | ||
725 | const struct GNUNET_TESTBED_PeerStopMessage *msg) | ||
726 | { | ||
727 | struct GNUNET_SERVICE_Client *client = cls; | ||
728 | struct GNUNET_MQ_Envelope *env; | ||
729 | struct GNUNET_TESTBED_PeerEventMessage *reply; | ||
730 | struct ForwardedOperationContext *fopc; | ||
731 | struct Peer *peer; | ||
732 | uint32_t peer_id; | ||
733 | |||
734 | peer_id = ntohl (msg->peer_id); | ||
735 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
736 | "Received PEER_STOP for peer %u\n", | ||
737 | (unsigned int) peer_id); | ||
738 | if (! VALID_PEER_ID (peer_id)) | ||
739 | { | ||
740 | GST_send_operation_fail_msg (client, | ||
741 | GNUNET_ntohll (msg->operation_id), | ||
742 | "Peer not found"); | ||
743 | GNUNET_SERVICE_client_continue (client); | ||
744 | return; | ||
745 | } | ||
746 | peer = GST_peer_list[peer_id]; | ||
747 | if (GNUNET_YES == peer->is_remote) | ||
748 | { | ||
749 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
750 | "Forwarding PEER_STOP for peer %u\n", | ||
751 | (unsigned int) peer_id); | ||
752 | fopc = GNUNET_new (struct ForwardedOperationContext); | ||
753 | fopc->client = client; | ||
754 | fopc->operation_id = GNUNET_ntohll (msg->operation_id); | ||
755 | fopc->type = OP_PEER_STOP; | ||
756 | fopc->opc = | ||
757 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
758 | slave->controller, | ||
759 | fopc->operation_id, | ||
760 | &msg->header, | ||
761 | & | ||
762 | GST_forwarded_operation_reply_relay, | ||
763 | fopc); | ||
764 | fopc->timeout_task = | ||
765 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
766 | &GST_forwarded_operation_timeout, | ||
767 | fopc); | ||
768 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, | ||
769 | fopcq_tail, | ||
770 | fopc); | ||
771 | GNUNET_SERVICE_client_continue (client); | ||
772 | return; | ||
773 | } | ||
774 | if (GNUNET_OK != stop_peer (peer)) | ||
775 | { | ||
776 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
777 | "Stopping peer %u failed\n", | ||
778 | (unsigned int) peer_id); | ||
779 | GST_send_operation_fail_msg (client, | ||
780 | GNUNET_ntohll (msg->operation_id), | ||
781 | "Peer not running"); | ||
782 | GNUNET_SERVICE_client_continue (client); | ||
783 | return; | ||
784 | } | ||
785 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
786 | "Peer %u successfully stopped\n", | ||
787 | (unsigned int) peer_id); | ||
788 | env = GNUNET_MQ_msg (reply, | ||
789 | GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); | ||
790 | reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP); | ||
791 | reply->host_id = htonl (GST_context->host_id); | ||
792 | reply->peer_id = msg->peer_id; | ||
793 | reply->operation_id = msg->operation_id; | ||
794 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
795 | env); | ||
796 | GNUNET_SERVICE_client_continue (client); | ||
797 | GNUNET_TESTING_peer_wait (peer->details.local.peer); | ||
798 | } | ||
799 | |||
800 | |||
801 | /** | ||
802 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION messages | ||
803 | * | ||
804 | * @param cls identification of the client | ||
805 | * @param msg the actual message | ||
806 | */ | ||
807 | void | ||
808 | handle_peer_get_config (void *cls, | ||
809 | const struct | ||
810 | GNUNET_TESTBED_PeerGetConfigurationMessage *msg) | ||
811 | { | ||
812 | struct GNUNET_SERVICE_Client *client = cls; | ||
813 | struct GNUNET_MQ_Envelope *env; | ||
814 | struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply; | ||
815 | struct ForwardedOperationContext *fopc; | ||
816 | struct Peer *peer; | ||
817 | char *config; | ||
818 | char *xconfig; | ||
819 | size_t c_size; | ||
820 | size_t xc_size; | ||
821 | uint32_t peer_id; | ||
822 | |||
823 | peer_id = ntohl (msg->peer_id); | ||
824 | LOG_DEBUG ("Received GET_CONFIG for peer %u\n", | ||
825 | (unsigned int) peer_id); | ||
826 | if (! VALID_PEER_ID (peer_id)) | ||
827 | { | ||
828 | GST_send_operation_fail_msg (client, | ||
829 | GNUNET_ntohll (msg->operation_id), | ||
830 | "Peer not found"); | ||
831 | GNUNET_SERVICE_client_continue (client); | ||
832 | return; | ||
833 | } | ||
834 | peer = GST_peer_list[peer_id]; | ||
835 | if (GNUNET_YES == peer->is_remote) | ||
836 | { | ||
837 | LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n", | ||
838 | (unsigned int) peer_id); | ||
839 | fopc = GNUNET_new (struct ForwardedOperationContext); | ||
840 | fopc->client = client; | ||
841 | fopc->operation_id = GNUNET_ntohll (msg->operation_id); | ||
842 | fopc->type = OP_PEER_INFO; | ||
843 | fopc->opc = | ||
844 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
845 | slave->controller, | ||
846 | fopc->operation_id, | ||
847 | &msg->header, | ||
848 | & | ||
849 | GST_forwarded_operation_reply_relay, | ||
850 | fopc); | ||
851 | fopc->timeout_task = | ||
852 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
853 | &GST_forwarded_operation_timeout, | ||
854 | fopc); | ||
855 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, | ||
856 | fopcq_tail, | ||
857 | fopc); | ||
858 | GNUNET_SERVICE_client_continue (client); | ||
859 | return; | ||
860 | } | ||
861 | LOG_DEBUG ("Received PEER_GET_CONFIG for peer: %u\n", | ||
862 | peer_id); | ||
863 | config = | ||
864 | GNUNET_CONFIGURATION_serialize (GST_peer_list[peer_id]->details.local.cfg, | ||
865 | &c_size); | ||
866 | xc_size = GNUNET_TESTBED_compress_config_ (config, | ||
867 | c_size, | ||
868 | &xconfig); | ||
869 | GNUNET_free (config); | ||
870 | env = GNUNET_MQ_msg_extra (reply, | ||
871 | xc_size, | ||
872 | GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION); | ||
873 | reply->peer_id = msg->peer_id; | ||
874 | reply->operation_id = msg->operation_id; | ||
875 | GNUNET_TESTING_peer_get_identity (GST_peer_list[peer_id]->details.local.peer, | ||
876 | &reply->peer_identity); | ||
877 | reply->config_size = htons ((uint16_t) c_size); | ||
878 | GNUNET_memcpy (&reply[1], | ||
879 | xconfig, | ||
880 | xc_size); | ||
881 | GNUNET_free (xconfig); | ||
882 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
883 | env); | ||
884 | GNUNET_SERVICE_client_continue (client); | ||
885 | } | ||
886 | |||
887 | |||
888 | /** | ||
889 | * Cleans up the Peer reconfigure context list | ||
890 | */ | ||
891 | void | ||
892 | GST_free_prcq () | ||
893 | { | ||
894 | while (NULL != prc_head) | ||
895 | cleanup_prc (prc_head); | ||
896 | } | ||
897 | |||
898 | |||
899 | /** | ||
900 | * Update peer configuration | ||
901 | * | ||
902 | * @param peer the peer to update | ||
903 | * @param cfg the new configuration | ||
904 | * @return error message (freshly allocated); NULL upon success | ||
905 | */ | ||
906 | static char * | ||
907 | update_peer_config (struct Peer *peer, | ||
908 | struct GNUNET_CONFIGURATION_Handle *cfg) | ||
909 | { | ||
910 | char *emsg; | ||
911 | |||
912 | GNUNET_TESTING_peer_destroy (peer->details.local.peer); | ||
913 | GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); | ||
914 | peer->details.local.cfg = cfg; | ||
915 | emsg = NULL; | ||
916 | peer->details.local.peer | ||
917 | = GNUNET_TESTING_peer_configure (GST_context->system, | ||
918 | peer->details.local.cfg, | ||
919 | peer->id, | ||
920 | NULL /* Peer id */, | ||
921 | &emsg); | ||
922 | return emsg; | ||
923 | } | ||
924 | |||
925 | |||
926 | /** | ||
927 | * Callback to inform whether the peer is running or stopped. | ||
928 | * | ||
929 | * @param cls the closure given to GNUNET_TESTING_peer_stop_async() | ||
930 | * @param p the respective peer whose status is being reported | ||
931 | * @param success #GNUNET_YES if the peer is stopped; #GNUNET_SYSERR upon any | ||
932 | * error | ||
933 | */ | ||
934 | static void | ||
935 | prc_stop_cb (void *cls, | ||
936 | struct GNUNET_TESTING_Peer *p, | ||
937 | int success) | ||
938 | { | ||
939 | struct PeerReconfigureContext *prc = cls; | ||
940 | struct Peer *peer; | ||
941 | char *emsg; | ||
942 | |||
943 | GNUNET_assert (VALID_PEER_ID (prc->peer_id)); | ||
944 | peer = GST_peer_list [prc->peer_id]; | ||
945 | GNUNET_assert (GNUNET_NO == peer->is_remote); | ||
946 | emsg = update_peer_config (peer, prc->cfg); | ||
947 | prc->cfg = NULL; | ||
948 | prc->stopped = 1; | ||
949 | if (NULL != emsg) | ||
950 | { | ||
951 | GST_send_operation_fail_msg (prc->client, | ||
952 | prc->op_id, | ||
953 | emsg); | ||
954 | goto cleanup; | ||
955 | } | ||
956 | if (GNUNET_OK != start_peer (peer)) | ||
957 | { | ||
958 | GST_send_operation_fail_msg (prc->client, | ||
959 | prc->op_id, | ||
960 | "Failed to start reconfigured peer"); | ||
961 | goto cleanup; | ||
962 | } | ||
963 | GST_send_operation_success_msg (prc->client, | ||
964 | prc->op_id); | ||
965 | |||
966 | cleanup: | ||
967 | cleanup_prc (prc); | ||
968 | return; | ||
969 | } | ||
970 | |||
971 | |||
972 | /** | ||
973 | * Check #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. | ||
974 | * | ||
975 | * @param cls identification of the client | ||
976 | * @param msg the actual message | ||
977 | * @return #GNUNET_OK if @a msg is well-formed | ||
978 | */ | ||
979 | int | ||
980 | check_peer_reconfigure (void *cls, | ||
981 | const struct GNUNET_TESTBED_PeerReconfigureMessage *msg) | ||
982 | { | ||
983 | return GNUNET_OK; /* checked later */ | ||
984 | } | ||
985 | |||
986 | |||
987 | /** | ||
988 | * Handler for #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. | ||
989 | * Should stop the peer asynchronously, destroy it and create it again with the | ||
990 | * new configuration. | ||
991 | * | ||
992 | * @param cls identification of the client | ||
993 | * @param msg the actual message | ||
994 | */ | ||
995 | void | ||
996 | handle_peer_reconfigure (void *cls, | ||
997 | const struct | ||
998 | GNUNET_TESTBED_PeerReconfigureMessage *msg) | ||
999 | { | ||
1000 | struct GNUNET_SERVICE_Client *client = cls; | ||
1001 | struct Peer *peer; | ||
1002 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
1003 | struct ForwardedOperationContext *fopc; | ||
1004 | struct PeerReconfigureContext *prc; | ||
1005 | char *emsg; | ||
1006 | uint64_t op_id; | ||
1007 | uint32_t peer_id; | ||
1008 | |||
1009 | peer_id = ntohl (msg->peer_id); | ||
1010 | op_id = GNUNET_ntohll (msg->operation_id); | ||
1011 | if (! VALID_PEER_ID (peer_id)) | ||
1012 | { | ||
1013 | GNUNET_break (0); | ||
1014 | GST_send_operation_fail_msg (client, | ||
1015 | op_id, | ||
1016 | "Peer not found"); | ||
1017 | GNUNET_SERVICE_client_continue (client); | ||
1018 | return; | ||
1019 | } | ||
1020 | peer = GST_peer_list[peer_id]; | ||
1021 | if (GNUNET_YES == peer->is_remote) | ||
1022 | { | ||
1023 | LOG_DEBUG ("Forwarding PEER_RECONFIGURE for peer: %u\n", peer_id); | ||
1024 | fopc = GNUNET_new (struct ForwardedOperationContext); | ||
1025 | fopc->client = client; | ||
1026 | fopc->operation_id = op_id; | ||
1027 | fopc->type = OP_PEER_RECONFIGURE; | ||
1028 | fopc->opc = | ||
1029 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
1030 | slave->controller, | ||
1031 | fopc->operation_id, | ||
1032 | &msg->header, | ||
1033 | & | ||
1034 | GST_forwarded_operation_reply_relay, | ||
1035 | fopc); | ||
1036 | fopc->timeout_task = | ||
1037 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
1038 | &GST_forwarded_operation_timeout, | ||
1039 | fopc); | ||
1040 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, | ||
1041 | fopcq_tail, | ||
1042 | fopc); | ||
1043 | GNUNET_SERVICE_client_continue (client); | ||
1044 | return; | ||
1045 | } | ||
1046 | LOG_DEBUG ("Received PEER_RECONFIGURE for peer %u\n", | ||
1047 | (unsigned int) peer_id); | ||
1048 | if (0 < peer->reference_cnt) | ||
1049 | { | ||
1050 | GNUNET_break (0); | ||
1051 | GST_send_operation_fail_msg (client, | ||
1052 | op_id, | ||
1053 | "Peer in use"); | ||
1054 | GNUNET_SERVICE_client_continue (client); | ||
1055 | return; | ||
1056 | } | ||
1057 | if (GNUNET_YES == peer->destroy_flag) | ||
1058 | { | ||
1059 | GNUNET_break (0); | ||
1060 | GST_send_operation_fail_msg (client, | ||
1061 | op_id, | ||
1062 | "Peer is being destroyed"); | ||
1063 | GNUNET_SERVICE_client_continue (client); | ||
1064 | return; | ||
1065 | } | ||
1066 | cfg = GNUNET_TESTBED_extract_config_ (&msg->header); | ||
1067 | if (NULL == cfg) | ||
1068 | { | ||
1069 | GNUNET_break (0); | ||
1070 | GST_send_operation_fail_msg (client, | ||
1071 | op_id, | ||
1072 | "Compression error"); | ||
1073 | GNUNET_SERVICE_client_continue (client); | ||
1074 | return; | ||
1075 | } | ||
1076 | if (GNUNET_NO == peer->details.local.is_running) | ||
1077 | { | ||
1078 | emsg = update_peer_config (peer, | ||
1079 | cfg); | ||
1080 | if (NULL != emsg) | ||
1081 | GST_send_operation_fail_msg (client, | ||
1082 | op_id, | ||
1083 | emsg); | ||
1084 | GST_send_operation_success_msg (client, | ||
1085 | op_id); | ||
1086 | GNUNET_SERVICE_client_continue (client); | ||
1087 | GNUNET_free (emsg); | ||
1088 | return; | ||
1089 | } | ||
1090 | prc = GNUNET_new (struct PeerReconfigureContext); | ||
1091 | if (GNUNET_OK != | ||
1092 | GNUNET_TESTING_peer_stop_async (peer->details.local.peer, | ||
1093 | &prc_stop_cb, | ||
1094 | prc)) | ||
1095 | { | ||
1096 | GNUNET_assert (0 < GNUNET_asprintf (&emsg, | ||
1097 | "Error trying to stop peer %u asynchronously\n", | ||
1098 | peer_id)); | ||
1099 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1100 | "%s\n", | ||
1101 | emsg); | ||
1102 | GST_send_operation_fail_msg (client, | ||
1103 | op_id, | ||
1104 | emsg); | ||
1105 | GNUNET_SERVICE_client_continue (client); | ||
1106 | GNUNET_free (prc); | ||
1107 | GNUNET_free (emsg); | ||
1108 | return; | ||
1109 | } | ||
1110 | prc->cfg = cfg; | ||
1111 | prc->peer_id = peer_id; | ||
1112 | prc->op_id = op_id; | ||
1113 | prc->client = client; | ||
1114 | GNUNET_CONTAINER_DLL_insert_tail (prc_head, | ||
1115 | prc_tail, | ||
1116 | prc); | ||
1117 | GNUNET_SERVICE_client_continue (client); | ||
1118 | } | ||
1119 | |||
1120 | |||
1121 | /** | ||
1122 | * Frees the ManageServiceContext queue | ||
1123 | */ | ||
1124 | void | ||
1125 | GST_free_mctxq () | ||
1126 | { | ||
1127 | while (NULL != mctx_head) | ||
1128 | cleanup_mctx (mctx_head); | ||
1129 | } | ||
1130 | |||
1131 | |||
1132 | /** | ||
1133 | * Returns a string interpretation of @a rs. | ||
1134 | * | ||
1135 | * @param rs the request status from ARM | ||
1136 | * @return a string interpretation of the request status | ||
1137 | */ | ||
1138 | static const char * | ||
1139 | arm_req_string (enum GNUNET_ARM_RequestStatus rs) | ||
1140 | { | ||
1141 | switch (rs) | ||
1142 | { | ||
1143 | case GNUNET_ARM_REQUEST_SENT_OK: | ||
1144 | return _ ("Message was sent successfully"); | ||
1145 | |||
1146 | case GNUNET_ARM_REQUEST_DISCONNECTED: | ||
1147 | return _ ("We disconnected from ARM before we could send a request"); | ||
1148 | } | ||
1149 | return _ ("Unknown request status"); | ||
1150 | } | ||
1151 | |||
1152 | |||
1153 | /** | ||
1154 | * Returns a string interpretation of the @a result. | ||
1155 | * | ||
1156 | * @param result the arm result | ||
1157 | * @return a string interpretation | ||
1158 | */ | ||
1159 | static const char * | ||
1160 | arm_ret_string (enum GNUNET_ARM_Result result) | ||
1161 | { | ||
1162 | switch (result) | ||
1163 | { | ||
1164 | case GNUNET_ARM_RESULT_STOPPED: | ||
1165 | return _ ("%s is stopped"); | ||
1166 | |||
1167 | case GNUNET_ARM_RESULT_STARTING: | ||
1168 | return _ ("%s is starting"); | ||
1169 | |||
1170 | case GNUNET_ARM_RESULT_STOPPING: | ||
1171 | return _ ("%s is stopping"); | ||
1172 | |||
1173 | case GNUNET_ARM_RESULT_IS_STARTING_ALREADY: | ||
1174 | return _ ("%s is starting already"); | ||
1175 | |||
1176 | case GNUNET_ARM_RESULT_IS_STOPPING_ALREADY: | ||
1177 | return _ ("%s is stopping already"); | ||
1178 | |||
1179 | case GNUNET_ARM_RESULT_IS_STARTED_ALREADY: | ||
1180 | return _ ("%s is started already"); | ||
1181 | |||
1182 | case GNUNET_ARM_RESULT_IS_STOPPED_ALREADY: | ||
1183 | return _ ("%s is stopped already"); | ||
1184 | |||
1185 | case GNUNET_ARM_RESULT_IS_NOT_KNOWN: | ||
1186 | return _ ("%s service is not known to ARM"); | ||
1187 | |||
1188 | case GNUNET_ARM_RESULT_START_FAILED: | ||
1189 | return _ ("%s service failed to start"); | ||
1190 | |||
1191 | case GNUNET_ARM_RESULT_IN_SHUTDOWN: | ||
1192 | return _ ("%s service can't be started because ARM is shutting down"); | ||
1193 | } | ||
1194 | return _ ("%.s Unknown result code."); | ||
1195 | } | ||
1196 | |||
1197 | |||
1198 | /** | ||
1199 | * Function called in response to a start/stop request. | ||
1200 | * Will be called when request was not sent successfully, | ||
1201 | * or when a reply comes. If the request was not sent successfully, | ||
1202 | * @a rs will indicate that, and @a result will be undefined. | ||
1203 | * | ||
1204 | * @param cls ManageServiceContext | ||
1205 | * @param rs status of the request | ||
1206 | * @param result result of the operation | ||
1207 | */ | ||
1208 | static void | ||
1209 | service_manage_result_cb (void *cls, | ||
1210 | enum GNUNET_ARM_RequestStatus rs, | ||
1211 | enum GNUNET_ARM_Result result) | ||
1212 | { | ||
1213 | struct ManageServiceContext *mctx = cls; | ||
1214 | char *emsg; | ||
1215 | |||
1216 | emsg = NULL; | ||
1217 | if (GNUNET_YES == mctx->expired) | ||
1218 | return; | ||
1219 | if (GNUNET_ARM_REQUEST_SENT_OK != rs) | ||
1220 | { | ||
1221 | GNUNET_asprintf (&emsg, | ||
1222 | "Error communicating with Peer %u's ARM: %s", | ||
1223 | mctx->peer->id, | ||
1224 | arm_req_string (rs)); | ||
1225 | goto ret; | ||
1226 | } | ||
1227 | if (1 == mctx->start) | ||
1228 | goto service_start_check; | ||
1229 | if (! ((GNUNET_ARM_RESULT_STOPPED == result) | ||
1230 | || (GNUNET_ARM_RESULT_STOPPING == result) | ||
1231 | || (GNUNET_ARM_RESULT_IS_STOPPING_ALREADY == result) | ||
1232 | || (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY == result))) | ||
1233 | { | ||
1234 | /* stopping a service failed */ | ||
1235 | GNUNET_asprintf (&emsg, | ||
1236 | arm_ret_string (result), | ||
1237 | mctx->service); | ||
1238 | goto ret; | ||
1239 | } | ||
1240 | /* service stopped successfully */ | ||
1241 | goto ret; | ||
1242 | |||
1243 | service_start_check: | ||
1244 | if (! ((GNUNET_ARM_RESULT_STARTING == result) | ||
1245 | || (GNUNET_ARM_RESULT_IS_STARTING_ALREADY == result) | ||
1246 | || (GNUNET_ARM_RESULT_IS_STARTED_ALREADY == result))) | ||
1247 | { | ||
1248 | /* starting a service failed */ | ||
1249 | GNUNET_asprintf (&emsg, | ||
1250 | arm_ret_string (result), | ||
1251 | mctx->service); | ||
1252 | goto ret; | ||
1253 | } | ||
1254 | /* service started successfully */ | ||
1255 | |||
1256 | ret: | ||
1257 | if (NULL != emsg) | ||
1258 | { | ||
1259 | LOG_DEBUG ("%s\n", emsg); | ||
1260 | GST_send_operation_fail_msg (mctx->client, | ||
1261 | mctx->op_id, | ||
1262 | emsg); | ||
1263 | } | ||
1264 | else | ||
1265 | GST_send_operation_success_msg (mctx->client, | ||
1266 | mctx->op_id); | ||
1267 | GNUNET_free (emsg); | ||
1268 | cleanup_mctx (mctx); | ||
1269 | } | ||
1270 | |||
1271 | |||
1272 | /** | ||
1273 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE message | ||
1274 | * | ||
1275 | * @param cls identification of client | ||
1276 | * @param msg the actual message | ||
1277 | * @return #GNUNET_OK if @a msg is well-formed | ||
1278 | */ | ||
1279 | int | ||
1280 | check_manage_peer_service (void *cls, | ||
1281 | const struct | ||
1282 | GNUNET_TESTBED_ManagePeerServiceMessage *msg) | ||
1283 | { | ||
1284 | uint16_t msize; | ||
1285 | const char*service; | ||
1286 | |||
1287 | msize = ntohs (msg->header.size); | ||
1288 | service = (const char *) &msg[1]; | ||
1289 | if ('\0' != service[msize - sizeof | ||
1290 | (struct GNUNET_TESTBED_ManagePeerServiceMessage) - 1]) | ||
1291 | { | ||
1292 | GNUNET_break_op (0); | ||
1293 | return GNUNET_SYSERR; | ||
1294 | } | ||
1295 | if (1 < msg->start) | ||
1296 | { | ||
1297 | GNUNET_break_op (0); | ||
1298 | return GNUNET_SYSERR; | ||
1299 | } | ||
1300 | return GNUNET_OK; | ||
1301 | } | ||
1302 | |||
1303 | |||
1304 | /** | ||
1305 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE messages | ||
1306 | * | ||
1307 | * @param cls identification of client | ||
1308 | * @param msg the actual message | ||
1309 | */ | ||
1310 | void | ||
1311 | handle_manage_peer_service (void *cls, | ||
1312 | const struct | ||
1313 | GNUNET_TESTBED_ManagePeerServiceMessage *msg) | ||
1314 | { | ||
1315 | struct GNUNET_SERVICE_Client *client = cls; | ||
1316 | const char*service; | ||
1317 | struct Peer *peer; | ||
1318 | char *emsg; | ||
1319 | struct GNUNET_ARM_Handle *ah; | ||
1320 | struct ManageServiceContext *mctx; | ||
1321 | struct ForwardedOperationContext *fopc; | ||
1322 | uint64_t op_id; | ||
1323 | uint32_t peer_id; | ||
1324 | |||
1325 | service = (const char *) &msg[1]; | ||
1326 | peer_id = ntohl (msg->peer_id); | ||
1327 | op_id = GNUNET_ntohll (msg->operation_id); | ||
1328 | LOG_DEBUG ("Received request to manage service %s on peer %u\n", | ||
1329 | service, (unsigned int) peer_id); | ||
1330 | if ((GST_peer_list_size <= peer_id) | ||
1331 | || (NULL == (peer = GST_peer_list[peer_id]))) | ||
1332 | { | ||
1333 | GNUNET_asprintf (&emsg, "Asked to manage service of a non existent peer " | ||
1334 | "with id: %u", peer_id); | ||
1335 | goto err_ret; | ||
1336 | } | ||
1337 | if (0 == strcasecmp ("arm", service)) | ||
1338 | { | ||
1339 | emsg = GNUNET_strdup ("Cannot start/stop peer's ARM service. " | ||
1340 | "Use peer start/stop for that"); | ||
1341 | goto err_ret; | ||
1342 | } | ||
1343 | if (GNUNET_YES == peer->is_remote) | ||
1344 | { | ||
1345 | /* Forward the destroy message to sub controller */ | ||
1346 | fopc = GNUNET_new (struct ForwardedOperationContext); | ||
1347 | fopc->client = client; | ||
1348 | fopc->cls = peer; | ||
1349 | fopc->type = OP_MANAGE_SERVICE; | ||
1350 | fopc->operation_id = op_id; | ||
1351 | fopc->opc = | ||
1352 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
1353 | slave->controller, | ||
1354 | fopc->operation_id, | ||
1355 | &msg->header, | ||
1356 | & | ||
1357 | GST_forwarded_operation_reply_relay, | ||
1358 | fopc); | ||
1359 | fopc->timeout_task = | ||
1360 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
1361 | &GST_forwarded_operation_timeout, | ||
1362 | fopc); | ||
1363 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, | ||
1364 | fopcq_tail, | ||
1365 | fopc); | ||
1366 | GNUNET_SERVICE_client_continue (client); | ||
1367 | return; | ||
1368 | } | ||
1369 | if (GNUNET_NO == peer->details.local.is_running) | ||
1370 | { | ||
1371 | emsg = GNUNET_strdup ("Peer not running\n"); | ||
1372 | goto err_ret; | ||
1373 | } | ||
1374 | if ((0 != peer->reference_cnt) | ||
1375 | && ((0 == strcasecmp ("core", service)) | ||
1376 | || (0 == strcasecmp ("transport", service)))) | ||
1377 | { | ||
1378 | GNUNET_asprintf (&emsg, "Cannot stop %s service of peer with id: %u " | ||
1379 | "since it is required by existing operations", | ||
1380 | service, peer_id); | ||
1381 | goto err_ret; | ||
1382 | } | ||
1383 | ah = GNUNET_ARM_connect (peer->details.local.cfg, NULL, NULL); | ||
1384 | if (NULL == ah) | ||
1385 | { | ||
1386 | GNUNET_asprintf (&emsg, | ||
1387 | "Cannot connect to ARM service of peer with id: %u", | ||
1388 | peer_id); | ||
1389 | goto err_ret; | ||
1390 | } | ||
1391 | mctx = GNUNET_new (struct ManageServiceContext); | ||
1392 | mctx->peer = peer; | ||
1393 | peer->reference_cnt++; | ||
1394 | mctx->op_id = op_id; | ||
1395 | mctx->ah = ah; | ||
1396 | mctx->client = client; | ||
1397 | mctx->start = msg->start; | ||
1398 | mctx->service = GNUNET_strdup (service); | ||
1399 | GNUNET_CONTAINER_DLL_insert_tail (mctx_head, | ||
1400 | mctx_tail, | ||
1401 | mctx); | ||
1402 | if (1 == mctx->start) | ||
1403 | GNUNET_ARM_request_service_start (mctx->ah, | ||
1404 | service, | ||
1405 | GNUNET_OS_INHERIT_STD_ERR, | ||
1406 | &service_manage_result_cb, | ||
1407 | mctx); | ||
1408 | else | ||
1409 | GNUNET_ARM_request_service_stop (mctx->ah, service, | ||
1410 | &service_manage_result_cb, | ||
1411 | mctx); | ||
1412 | GNUNET_SERVICE_client_continue (client); | ||
1413 | return; | ||
1414 | |||
1415 | err_ret: | ||
1416 | LOG (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg); | ||
1417 | GST_send_operation_fail_msg (client, op_id, emsg); | ||
1418 | GNUNET_free (emsg); | ||
1419 | GNUNET_SERVICE_client_continue (client); | ||
1420 | } | ||
1421 | |||
1422 | |||
1423 | /** | ||
1424 | * Stops and destroys all peers | ||
1425 | */ | ||
1426 | void | ||
1427 | GST_destroy_peers () | ||
1428 | { | ||
1429 | struct Peer *peer; | ||
1430 | unsigned int id; | ||
1431 | |||
1432 | if (NULL == GST_peer_list) | ||
1433 | return; | ||
1434 | for (id = 0; id < GST_peer_list_size; id++) | ||
1435 | { | ||
1436 | peer = GST_peer_list[id]; | ||
1437 | if (NULL == peer) | ||
1438 | continue; | ||
1439 | /* If destroy flag is set it means that this peer should have been | ||
1440 | * destroyed by a context which we destroy before */ | ||
1441 | GNUNET_break (GNUNET_NO == peer->destroy_flag); | ||
1442 | /* counter should be zero as we free all contexts before */ | ||
1443 | GNUNET_break (0 == peer->reference_cnt); | ||
1444 | if ((GNUNET_NO == peer->is_remote) && | ||
1445 | (GNUNET_YES == peer->details.local.is_running)) | ||
1446 | GNUNET_TESTING_peer_kill (peer->details.local.peer); | ||
1447 | } | ||
1448 | for (id = 0; id < GST_peer_list_size; id++) | ||
1449 | { | ||
1450 | peer = GST_peer_list[id]; | ||
1451 | if (NULL == peer) | ||
1452 | continue; | ||
1453 | if (GNUNET_NO == peer->is_remote) | ||
1454 | { | ||
1455 | if (GNUNET_YES == peer->details.local.is_running) | ||
1456 | GNUNET_TESTING_peer_wait (peer->details.local.peer); | ||
1457 | GNUNET_TESTING_peer_destroy (peer->details.local.peer); | ||
1458 | GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); | ||
1459 | } | ||
1460 | GNUNET_free (peer); | ||
1461 | } | ||
1462 | GNUNET_free (GST_peer_list); | ||
1463 | GST_peer_list = NULL; | ||
1464 | GST_peer_list_size = 0; | ||
1465 | } | ||
1466 | |||
1467 | |||
1468 | /** | ||
1469 | * The reply msg handler forwarded SHUTDOWN_PEERS operation. Checks if a | ||
1470 | * success reply is received from all clients and then sends the success message | ||
1471 | * to the client | ||
1472 | * | ||
1473 | * @param cls ForwardedOperationContext | ||
1474 | * @param msg the message to relay | ||
1475 | */ | ||
1476 | static void | ||
1477 | shutdown_peers_reply_cb (void *cls, | ||
1478 | const struct GNUNET_MessageHeader *msg) | ||
1479 | { | ||
1480 | struct ForwardedOperationContext *fo_ctxt = cls; | ||
1481 | struct HandlerContext_ShutdownPeers *hc; | ||
1482 | |||
1483 | hc = fo_ctxt->cls; | ||
1484 | GNUNET_assert (0 < hc->nslaves); | ||
1485 | hc->nslaves--; | ||
1486 | if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS != | ||
1487 | ntohs (msg->type)) | ||
1488 | hc->timeout = GNUNET_YES; | ||
1489 | if (0 == hc->nslaves) | ||
1490 | { | ||
1491 | if (GNUNET_YES == hc->timeout) | ||
1492 | GST_send_operation_fail_msg (fo_ctxt->client, | ||
1493 | fo_ctxt->operation_id, | ||
1494 | "Timeout at a slave controller"); | ||
1495 | else | ||
1496 | GST_send_operation_success_msg (fo_ctxt->client, | ||
1497 | fo_ctxt->operation_id); | ||
1498 | GNUNET_free (hc); | ||
1499 | hc = NULL; | ||
1500 | } | ||
1501 | GNUNET_CONTAINER_DLL_remove (fopcq_head, | ||
1502 | fopcq_tail, | ||
1503 | fo_ctxt); | ||
1504 | GNUNET_free (fo_ctxt); | ||
1505 | } | ||
1506 | |||
1507 | |||
1508 | /** | ||
1509 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages | ||
1510 | * | ||
1511 | * @param cls identification of the client | ||
1512 | * @param msg the actual message | ||
1513 | */ | ||
1514 | void | ||
1515 | handle_shutdown_peers (void *cls, | ||
1516 | const struct GNUNET_TESTBED_ShutdownPeersMessage *msg) | ||
1517 | { | ||
1518 | struct GNUNET_SERVICE_Client *client = cls; | ||
1519 | struct HandlerContext_ShutdownPeers *hc; | ||
1520 | struct Slave *slave; | ||
1521 | struct ForwardedOperationContext *fo_ctxt; | ||
1522 | uint64_t op_id; | ||
1523 | unsigned int cnt; | ||
1524 | |||
1525 | LOG_DEBUG ("Received SHUTDOWN_PEERS\n"); | ||
1526 | /* Stop and destroy all peers */ | ||
1527 | GST_free_mctxq (); | ||
1528 | GST_free_occq (); | ||
1529 | GST_free_roccq (); | ||
1530 | GST_clear_fopcq (); | ||
1531 | /* Forward to all slaves which we have started */ | ||
1532 | op_id = GNUNET_ntohll (msg->operation_id); | ||
1533 | hc = GNUNET_new (struct HandlerContext_ShutdownPeers); | ||
1534 | /* FIXME: have a better implementation where we track which slaves are | ||
1535 | started by this controller */ | ||
1536 | for (cnt = 0; cnt < GST_slave_list_size; cnt++) | ||
1537 | { | ||
1538 | slave = GST_slave_list[cnt]; | ||
1539 | if (NULL == slave) | ||
1540 | continue; | ||
1541 | if (NULL == slave->controller_proc) /* We didn't start the slave */ | ||
1542 | continue; | ||
1543 | LOG_DEBUG ("Forwarding SHUTDOWN_PEERS\n"); | ||
1544 | hc->nslaves++; | ||
1545 | fo_ctxt = GNUNET_new (struct ForwardedOperationContext); | ||
1546 | fo_ctxt->client = client; | ||
1547 | fo_ctxt->operation_id = op_id; | ||
1548 | fo_ctxt->cls = hc; | ||
1549 | fo_ctxt->type = OP_SHUTDOWN_PEERS; | ||
1550 | fo_ctxt->opc = | ||
1551 | GNUNET_TESTBED_forward_operation_msg_ (slave->controller, | ||
1552 | fo_ctxt->operation_id, | ||
1553 | &msg->header, | ||
1554 | shutdown_peers_reply_cb, | ||
1555 | fo_ctxt); | ||
1556 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, | ||
1557 | fopcq_tail, | ||
1558 | fo_ctxt); | ||
1559 | } | ||
1560 | LOG_DEBUG ("Shutting down peers\n"); | ||
1561 | GST_destroy_peers (); | ||
1562 | if (0 == hc->nslaves) | ||
1563 | { | ||
1564 | GST_send_operation_success_msg (client, | ||
1565 | op_id); | ||
1566 | GNUNET_free (hc); | ||
1567 | } | ||
1568 | GNUNET_SERVICE_client_continue (client); | ||
1569 | } | ||
diff --git a/src/testbed/gnunet-testbed-profiler.c b/src/testbed/gnunet-testbed-profiler.c deleted file mode 100644 index 49d975119..000000000 --- a/src/testbed/gnunet-testbed-profiler.c +++ /dev/null | |||
@@ -1,323 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-testbed-profiler.c | ||
23 | * @brief Profiling driver for the testbed. | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | #include "testbed_api_hosts.h" | ||
31 | |||
32 | /** | ||
33 | * Generic loggins shorthand | ||
34 | */ | ||
35 | #define LOG(kind, ...) \ | ||
36 | GNUNET_log (kind, __VA_ARGS__) | ||
37 | |||
38 | |||
39 | /** | ||
40 | * Handle to global configuration | ||
41 | */ | ||
42 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
43 | |||
44 | /** | ||
45 | * Peer linking - topology operation | ||
46 | */ | ||
47 | struct GNUNET_TESTBED_Operation *topology_op; | ||
48 | |||
49 | /** | ||
50 | * Name of the file with the hosts to run the test over (configuration option). | ||
51 | * It will be NULL if ENABLE_LL is set | ||
52 | */ | ||
53 | static char *hosts_file; | ||
54 | |||
55 | /** | ||
56 | * Abort task identifier | ||
57 | */ | ||
58 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
59 | |||
60 | /** | ||
61 | * Global event mask for all testbed events | ||
62 | */ | ||
63 | uint64_t event_mask; | ||
64 | |||
65 | /** | ||
66 | * Number of peers to be started by the profiler | ||
67 | */ | ||
68 | static unsigned int num_peers; | ||
69 | |||
70 | /** | ||
71 | * Number of timeout failures to tolerate | ||
72 | */ | ||
73 | static unsigned int num_cont_fails; | ||
74 | |||
75 | /** | ||
76 | * Continuous failures during overlay connect operations | ||
77 | */ | ||
78 | static unsigned int cont_fails; | ||
79 | |||
80 | /** | ||
81 | * Links which are successfully established | ||
82 | */ | ||
83 | static unsigned int established_links; | ||
84 | |||
85 | /** | ||
86 | * Links which are not successfully established | ||
87 | */ | ||
88 | static unsigned int failed_links; | ||
89 | |||
90 | /** | ||
91 | * Global testing status | ||
92 | */ | ||
93 | static int result; | ||
94 | |||
95 | /** | ||
96 | * Are we running non interactively | ||
97 | */ | ||
98 | static int noninteractive; | ||
99 | |||
100 | |||
101 | /** | ||
102 | * Shutdown nicely | ||
103 | * | ||
104 | * @param cls NULL | ||
105 | */ | ||
106 | static void | ||
107 | do_shutdown (void *cls) | ||
108 | { | ||
109 | if (NULL != abort_task) | ||
110 | { | ||
111 | GNUNET_SCHEDULER_cancel (abort_task); | ||
112 | abort_task = NULL; | ||
113 | } | ||
114 | if (NULL != cfg) | ||
115 | { | ||
116 | GNUNET_CONFIGURATION_destroy (cfg); | ||
117 | cfg = NULL; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | |||
122 | /** | ||
123 | * abort task to run on test timed out | ||
124 | * | ||
125 | * @param cls NULL | ||
126 | */ | ||
127 | static void | ||
128 | do_abort (void *cls) | ||
129 | { | ||
130 | abort_task = NULL; | ||
131 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
132 | "Aborting\n"); | ||
133 | result = GNUNET_SYSERR; | ||
134 | GNUNET_SCHEDULER_shutdown (); | ||
135 | } | ||
136 | |||
137 | |||
138 | /** | ||
139 | * Function to print summary about how many overlay links we have made and how | ||
140 | * many failed | ||
141 | */ | ||
142 | static void | ||
143 | print_overlay_links_summary () | ||
144 | { | ||
145 | static int printed_already; | ||
146 | |||
147 | if (GNUNET_YES == printed_already) | ||
148 | return; | ||
149 | printed_already = GNUNET_YES; | ||
150 | printf ("%u links succeeded\n", established_links); | ||
151 | printf ("%u links failed due to timeouts\n", failed_links); | ||
152 | } | ||
153 | |||
154 | |||
155 | /** | ||
156 | * Controller event callback | ||
157 | * | ||
158 | * @param cls NULL | ||
159 | * @param event the controller event | ||
160 | */ | ||
161 | static void | ||
162 | controller_event_cb (void *cls, | ||
163 | const struct GNUNET_TESTBED_EventInformation *event) | ||
164 | { | ||
165 | switch (event->type) | ||
166 | { | ||
167 | case GNUNET_TESTBED_ET_OPERATION_FINISHED: | ||
168 | /* Control reaches here when a peer linking operation fails */ | ||
169 | if (NULL != event->details.operation_finished.emsg) | ||
170 | { | ||
171 | printf ("F"); | ||
172 | fflush (stdout); | ||
173 | failed_links++; | ||
174 | if (++cont_fails > num_cont_fails) | ||
175 | { | ||
176 | printf ("\nAborting due to very high failure rate\n"); | ||
177 | print_overlay_links_summary (); | ||
178 | GNUNET_SCHEDULER_shutdown (); | ||
179 | return; | ||
180 | } | ||
181 | } | ||
182 | break; | ||
183 | |||
184 | case GNUNET_TESTBED_ET_CONNECT: | ||
185 | { | ||
186 | if (0 != cont_fails) | ||
187 | cont_fails--; | ||
188 | if (0 == established_links) | ||
189 | printf ("Establishing links. Please wait\n"); | ||
190 | printf ("."); | ||
191 | fflush (stdout); | ||
192 | established_links++; | ||
193 | } | ||
194 | break; | ||
195 | |||
196 | default: | ||
197 | GNUNET_break (0); | ||
198 | } | ||
199 | } | ||
200 | |||
201 | |||
202 | /** | ||
203 | * Signature of a main function for a testcase. | ||
204 | * | ||
205 | * @param cls closure | ||
206 | * @param h the run handle | ||
207 | * @param num_peers number of peers in 'peers' | ||
208 | * @param peers handle to peers run in the testbed | ||
209 | * @param links_succeeded the number of overlay link connection attempts that | ||
210 | * succeeded | ||
211 | * @param links_failed the number of overlay link | ||
212 | */ | ||
213 | static void | ||
214 | test_run (void *cls, | ||
215 | struct GNUNET_TESTBED_RunHandle *h, | ||
216 | unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, | ||
217 | unsigned int links_succeeded, | ||
218 | unsigned int links_failed) | ||
219 | { | ||
220 | result = GNUNET_OK; | ||
221 | fprintf (stdout, "\n"); | ||
222 | print_overlay_links_summary (); | ||
223 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
224 | if (noninteractive) | ||
225 | { | ||
226 | GNUNET_SCHEDULER_cancel (abort_task); | ||
227 | abort_task = NULL; | ||
228 | return; | ||
229 | } | ||
230 | fprintf (stdout, "Testbed running, waiting for keystroke to shut down\n"); | ||
231 | fflush (stdout); | ||
232 | (void) getc (stdin); | ||
233 | fprintf (stdout, "Shutting down. Please wait\n"); | ||
234 | fflush (stdout); | ||
235 | GNUNET_SCHEDULER_shutdown (); | ||
236 | } | ||
237 | |||
238 | |||
239 | /** | ||
240 | * Main function that will be run by the scheduler. | ||
241 | * | ||
242 | * @param cls closure | ||
243 | * @param args remaining command-line arguments | ||
244 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
245 | * @param config configuration | ||
246 | */ | ||
247 | static void | ||
248 | run (void *cls, char *const *args, const char *cfgfile, | ||
249 | const struct GNUNET_CONFIGURATION_Handle *config) | ||
250 | { | ||
251 | if (0 == num_peers) | ||
252 | { | ||
253 | LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Exiting as the number of peers is %u\n"), | ||
254 | num_peers); | ||
255 | return; | ||
256 | } | ||
257 | cfg = GNUNET_CONFIGURATION_dup (config); | ||
258 | event_mask = 0; | ||
259 | event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); | ||
260 | event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
261 | GNUNET_TESTBED_run (hosts_file, cfg, num_peers, event_mask, | ||
262 | &controller_event_cb, NULL, | ||
263 | &test_run, NULL); | ||
264 | abort_task = | ||
265 | GNUNET_SCHEDULER_add_shutdown (&do_abort, | ||
266 | NULL); | ||
267 | } | ||
268 | |||
269 | |||
270 | /** | ||
271 | * Main function. | ||
272 | * | ||
273 | * @return 0 on success | ||
274 | */ | ||
275 | int | ||
276 | main (int argc, char *const *argv) | ||
277 | { | ||
278 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
279 | GNUNET_GETOPT_option_uint ('p', | ||
280 | "num-peers", | ||
281 | "COUNT", | ||
282 | gettext_noop ("create COUNT number of peers"), | ||
283 | &num_peers), | ||
284 | GNUNET_GETOPT_option_uint ('e', | ||
285 | "num-errors", | ||
286 | "COUNT", | ||
287 | gettext_noop ( | ||
288 | "tolerate COUNT number of continuous timeout failures"), | ||
289 | &num_cont_fails), | ||
290 | GNUNET_GETOPT_option_flag ('n', | ||
291 | "non-interactive", | ||
292 | gettext_noop ( | ||
293 | "run profiler in non-interactive mode where upon " | ||
294 | "testbed setup the profiler does not wait for a " | ||
295 | "keystroke but continues to run until a termination " | ||
296 | "signal is received"), | ||
297 | &noninteractive), | ||
298 | GNUNET_GETOPT_option_string ('H', | ||
299 | "hosts", | ||
300 | "FILENAME", | ||
301 | gettext_noop ( | ||
302 | "name of the file with the login information for the testbed"), | ||
303 | &hosts_file), | ||
304 | GNUNET_GETOPT_OPTION_END | ||
305 | }; | ||
306 | const char *binaryHelp = "gnunet-testbed-profiler [OPTIONS]"; | ||
307 | int ret; | ||
308 | |||
309 | unsetenv ("XDG_DATA_HOME"); | ||
310 | unsetenv ("XDG_CONFIG_HOME"); | ||
311 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
312 | return 2; | ||
313 | result = GNUNET_SYSERR; | ||
314 | ret = | ||
315 | GNUNET_PROGRAM_run (argc, argv, "gnunet-testbed-profiler", binaryHelp, | ||
316 | options, &run, NULL); | ||
317 | GNUNET_free_nz ((void *) argv); | ||
318 | if (GNUNET_OK != ret) | ||
319 | return ret; | ||
320 | if (GNUNET_OK != result) | ||
321 | return 1; | ||
322 | return 0; | ||
323 | } | ||
diff --git a/src/testbed/gnunet_mpi_test.c b/src/testbed/gnunet_mpi_test.c deleted file mode 100644 index 2ee707fe6..000000000 --- a/src/testbed/gnunet_mpi_test.c +++ /dev/null | |||
@@ -1,108 +0,0 @@ | |||
1 | #include "platform.h" | ||
2 | #include "gnunet_util_lib.h" | ||
3 | #include <mpi.h> | ||
4 | |||
5 | /** | ||
6 | * Generic logging shorthand | ||
7 | */ | ||
8 | #define LOG(kind, ...) \ | ||
9 | GNUNET_log_from (kind, "gnunet-mpi-test", __VA_ARGS__) | ||
10 | |||
11 | int | ||
12 | main (int argc, char *argv[]) | ||
13 | { | ||
14 | char *msg; | ||
15 | char *filename; | ||
16 | char **argv2; | ||
17 | struct GNUNET_OS_Process *proc; | ||
18 | unsigned long code; | ||
19 | pid_t pid; | ||
20 | enum GNUNET_OS_ProcessStatusType proc_status; | ||
21 | int ntasks; | ||
22 | int rank; | ||
23 | int msg_size; | ||
24 | int ret; | ||
25 | unsigned int cnt; | ||
26 | |||
27 | ret = GNUNET_SYSERR; | ||
28 | if (argc < 2) | ||
29 | { | ||
30 | printf ("Need arguments: gnunet-mpi-test <cmd> <cmd_args>"); | ||
31 | return 1; | ||
32 | } | ||
33 | if (MPI_SUCCESS != MPI_Init (&argc, &argv)) | ||
34 | { | ||
35 | GNUNET_break (0); | ||
36 | return 1; | ||
37 | } | ||
38 | if (MPI_SUCCESS != MPI_Comm_size (MPI_COMM_WORLD, &ntasks)) | ||
39 | { | ||
40 | GNUNET_break (0); | ||
41 | goto finalize; | ||
42 | } | ||
43 | if (MPI_SUCCESS != MPI_Comm_rank (MPI_COMM_WORLD, &rank)) | ||
44 | { | ||
45 | GNUNET_break (0); | ||
46 | goto finalize; | ||
47 | } | ||
48 | pid = getpid (); | ||
49 | (void) GNUNET_asprintf (&filename, "%d-%d.mpiout", (int) pid, rank); | ||
50 | msg_size = GNUNET_asprintf (&msg, "My rank is: %d\n", rank); | ||
51 | printf ("%s", msg); | ||
52 | (void) GNUNET_DISK_directory_remove (filename); | ||
53 | if (GNUNET_OK == | ||
54 | GNUNET_DISK_fn_write (filename, msg, msg_size, | ||
55 | GNUNET_DISK_PERM_USER_READ | ||
56 | | GNUNET_DISK_PERM_GROUP_READ | ||
57 | | GNUNET_DISK_PERM_USER_WRITE | ||
58 | | GNUNET_DISK_PERM_GROUP_WRITE)) | ||
59 | ret = GNUNET_OK; | ||
60 | GNUNET_free (filename); | ||
61 | GNUNET_free (msg); | ||
62 | if (GNUNET_OK != ret) | ||
63 | { | ||
64 | GNUNET_break (0); | ||
65 | goto finalize; | ||
66 | } | ||
67 | |||
68 | ret = GNUNET_SYSERR; | ||
69 | argv2 = GNUNET_malloc (sizeof(char *) * (argc)); | ||
70 | for (cnt = 1; cnt < argc; cnt++) | ||
71 | argv2[cnt - 1] = argv[cnt]; | ||
72 | proc = | ||
73 | GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL, | ||
74 | NULL, NULL, argv2[0], argv2); | ||
75 | if (NULL == proc) | ||
76 | { | ||
77 | printf ("Cannot exec\n"); | ||
78 | GNUNET_free (argv2); | ||
79 | goto finalize; | ||
80 | } | ||
81 | do | ||
82 | { | ||
83 | (void) sleep (1); | ||
84 | ret = GNUNET_OS_process_status (proc, &proc_status, &code); | ||
85 | } | ||
86 | while (GNUNET_NO == ret); | ||
87 | GNUNET_free (argv2); | ||
88 | GNUNET_assert (GNUNET_NO != ret); | ||
89 | if (GNUNET_OK == ret) | ||
90 | { | ||
91 | if (0 != code) | ||
92 | { | ||
93 | LOG (GNUNET_ERROR_TYPE_WARNING, "Child terminated abnormally\n"); | ||
94 | ret = GNUNET_SYSERR; | ||
95 | GNUNET_break (0); | ||
96 | goto finalize; | ||
97 | } | ||
98 | } | ||
99 | else | ||
100 | GNUNET_break (0); | ||
101 | |||
102 | finalize: | ||
103 | (void) MPI_Finalize (); | ||
104 | if (GNUNET_OK == ret) | ||
105 | return 0; | ||
106 | printf ("Something went wrong\n"); | ||
107 | return 1; | ||
108 | } | ||
diff --git a/src/testbed/misc.supp b/src/testbed/misc.supp deleted file mode 100644 index 4e4424b6c..000000000 --- a/src/testbed/misc.supp +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | { | ||
2 | <get_log_call_status> | ||
3 | Memcheck:Leak | ||
4 | fun:malloc | ||
5 | ... | ||
6 | fun:re_acquire_state_context | ||
7 | fun:build_trtable | ||
8 | fun:re_search_internal | ||
9 | fun:regexec@@GLIBC_2.3.4 | ||
10 | fun:GNUNET_get_log_call_status | ||
11 | ... | ||
12 | } | ||
13 | { | ||
14 | <log_setup> | ||
15 | Memcheck:Leak | ||
16 | ... | ||
17 | fun:GNUNET_log_setup | ||
18 | ... | ||
19 | } | ||
20 | { | ||
21 | <get_log_status> | ||
22 | Memcheck:Leak | ||
23 | ... | ||
24 | fun:GNUNET_get_log_call_status | ||
25 | ... | ||
26 | } | ||
27 | { | ||
28 | <linux-loader> | ||
29 | Memcheck:Leak | ||
30 | fun:malloc | ||
31 | obj:/lib/i386-linux-gnu/libgcrypt.so.11.7.0 | ||
32 | ... | ||
33 | obj:/lib/i386-linux-gnu/ld-2.15.so | ||
34 | } | ||
35 | { | ||
36 | <glibc-networking> | ||
37 | Memcheck:Leak | ||
38 | fun:malloc | ||
39 | fun:make_request | ||
40 | fun:__check_pf | ||
41 | } | ||
42 | { | ||
43 | <crypto-reachable> | ||
44 | Memcheck:Leak | ||
45 | ... | ||
46 | fun:GNUNET_CRYPTO_random_init | ||
47 | fun:call_init | ||
48 | ... | ||
49 | } | ||
diff --git a/src/testbed/overlay_topology.txt b/src/testbed/overlay_topology.txt deleted file mode 100644 index 420dbb6a6..000000000 --- a/src/testbed/overlay_topology.txt +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | |||
2 | 1:2|3 | ||
3 | 3:4| 0| 1 | ||
4 | 2: 3|1|0 | ||
5 | 0: 2 | ||
diff --git a/src/testbed/profile-testbed.patch b/src/testbed/profile-testbed.patch deleted file mode 100644 index 50a8d5fed..000000000 --- a/src/testbed/profile-testbed.patch +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | Index: Makefile.am | ||
2 | =================================================================== | ||
3 | --- Makefile.am (revision 29343) | ||
4 | +++ Makefile.am (working copy) | ||
5 | @@ -59,7 +59,7 @@ | ||
6 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
7 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
8 | $(top_builddir)/src/arm/libgnunetarm.la \ | ||
9 | - $(LTLIBINTL) $(Z_LIBS) | ||
10 | + $(LTLIBINTL) $(Z_LIBS) -lprofiler | ||
11 | gnunet_service_testbed_DEPENDENCIES = \ | ||
12 | libgnunettestbed.la | ||
13 | |||
14 | Index: gnunet-service-testbed.c | ||
15 | =================================================================== | ||
16 | --- gnunet-service-testbed.c (revision 29341) | ||
17 | +++ gnunet-service-testbed.c (working copy) | ||
18 | @@ -26,6 +26,7 @@ | ||
19 | |||
20 | #include "gnunet-service-testbed.h" | ||
21 | #include "gnunet-service-testbed_barriers.h" | ||
22 | +#include <gperftools/profiler.h> | ||
23 | |||
24 | /***********/ | ||
25 | /* Globals */ | ||
26 | @@ -956,9 +957,14 @@ | ||
27 | main (int argc, char *const *argv) | ||
28 | { | ||
29 | //sleep (15); /* Debugging */ | ||
30 | - return (GNUNET_OK == | ||
31 | - GNUNET_SERVICE_run (argc, argv, "testbed", GNUNET_SERVICE_OPTION_NONE, | ||
32 | - &testbed_run, NULL)) ? 0 : 1; | ||
33 | + int ret; | ||
34 | + | ||
35 | + ProfilerStart (NULL); | ||
36 | + ret = GNUNET_SERVICE_run (argc, argv, "testbed", GNUNET_SERVICE_OPTION_NONE, | ||
37 | + &testbed_run, NULL); | ||
38 | + ProfilerStop (); | ||
39 | + return (GNUNET_OK == ret) ? 0 : 1; | ||
40 | + | ||
41 | } | ||
42 | |||
43 | /* end of gnunet-service-testbed.c */ | ||
diff --git a/src/testbed/sample.job b/src/testbed/sample.job deleted file mode 100755 index da3ee47f4..000000000 --- a/src/testbed/sample.job +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | # This job command file is called job.cmd | ||
3 | #@ job_type = parallel | ||
4 | #@ class = general | ||
5 | #@ node = 1 | ||
6 | #@ output = job$(jobid).out | ||
7 | #@ error = job$(jobid).err | ||
8 | #@ total_tasks=16 | ||
9 | #@ wall_clock_limit = 0:0:1 | ||
10 | #@ network.MPI = sn_all,not_shared,us | ||
11 | ##@ ... other LoadLeveler keywords (see below) | ||
12 | #@ notification = always | ||
13 | #@ notify_user = totakura@in.tum.de | ||
14 | #@ queue | ||
15 | |||
16 | #@ executable = /bin/bash | ||
diff --git a/src/testbed/sample_hosts.txt b/src/testbed/sample_hosts.txt deleted file mode 100644 index 32b87e87e..000000000 --- a/src/testbed/sample_hosts.txt +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | totakura@192.168.0.1:22 | ||
2 | totakura@192.168.0.2:22 | ||
3 | totakura@opt01:22 | ||
4 | totakura@i19-n015:2022 | ||
5 | totakura@asgard.realm | ||
6 | rivendal | ||
7 | rohan:561 | ||
diff --git a/src/testbed/test-underlay.sqlite b/src/testbed/test-underlay.sqlite deleted file mode 100644 index 46f48d9db..000000000 --- a/src/testbed/test-underlay.sqlite +++ /dev/null | |||
Binary files differ | |||
diff --git a/src/testbed/test_gnunet_helper_testbed.c b/src/testbed/test_gnunet_helper_testbed.c deleted file mode 100644 index ea303a86c..000000000 --- a/src/testbed/test_gnunet_helper_testbed.c +++ /dev/null | |||
@@ -1,255 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/test_gnunet_helper_testbed.c | ||
23 | * @brief Testcase for testing gnunet-helper-testbed.c | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | #include <zlib.h> | ||
31 | |||
32 | #include "testbed_api.h" | ||
33 | #include "testbed_helper.h" | ||
34 | #include "testbed_api_hosts.h" | ||
35 | |||
36 | /** | ||
37 | * Generic logging shortcut | ||
38 | */ | ||
39 | #define LOG(kind, ...) \ | ||
40 | GNUNET_log (kind, __VA_ARGS__) | ||
41 | |||
42 | |||
43 | /** | ||
44 | * Handle to the helper process | ||
45 | */ | ||
46 | static struct GNUNET_HELPER_Handle *helper; | ||
47 | |||
48 | /** | ||
49 | * Message to helper | ||
50 | */ | ||
51 | static struct GNUNET_TESTBED_HelperInit *msg; | ||
52 | |||
53 | /** | ||
54 | * Message send handle | ||
55 | */ | ||
56 | static struct GNUNET_HELPER_SendHandle *shandle; | ||
57 | |||
58 | /** | ||
59 | * Abort task identifier | ||
60 | */ | ||
61 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
62 | |||
63 | /** | ||
64 | * Shutdown task identifier | ||
65 | */ | ||
66 | static struct GNUNET_SCHEDULER_Task *shutdown_task; | ||
67 | |||
68 | /** | ||
69 | * Configuration handle. | ||
70 | */ | ||
71 | static struct GNUNET_CONFIGURATION_Handle *cfg; | ||
72 | |||
73 | /** | ||
74 | * Global testing status | ||
75 | */ | ||
76 | static int result; | ||
77 | |||
78 | |||
79 | /** | ||
80 | * Shutdown nicely | ||
81 | * | ||
82 | * @param cls NULL | ||
83 | */ | ||
84 | static void | ||
85 | do_shutdown (void *cls) | ||
86 | { | ||
87 | if (NULL != abort_task) | ||
88 | GNUNET_SCHEDULER_cancel (abort_task); | ||
89 | if (NULL != helper) | ||
90 | GNUNET_HELPER_stop (helper, GNUNET_NO); | ||
91 | GNUNET_free (msg); | ||
92 | if (NULL != cfg) | ||
93 | GNUNET_CONFIGURATION_destroy (cfg); | ||
94 | } | ||
95 | |||
96 | |||
97 | /** | ||
98 | * abort task to run on test timed out | ||
99 | * | ||
100 | * @param cls NULL | ||
101 | */ | ||
102 | static void | ||
103 | do_abort (void *cls) | ||
104 | { | ||
105 | abort_task = NULL; | ||
106 | LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); | ||
107 | result = GNUNET_SYSERR; | ||
108 | if (NULL != shandle) | ||
109 | GNUNET_HELPER_send_cancel (shandle); | ||
110 | if (NULL == shutdown_task) | ||
111 | shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
112 | } | ||
113 | |||
114 | |||
115 | /** | ||
116 | * Continuation function. | ||
117 | * | ||
118 | * @param cls closure | ||
119 | * @param result #GNUNET_OK on success, | ||
120 | * #GNUNET_NO if helper process died | ||
121 | * #GNUNET_SYSERR during GNUNET_HELPER_stop() | ||
122 | */ | ||
123 | static void | ||
124 | cont_cb (void *cls, | ||
125 | int result) | ||
126 | { | ||
127 | shandle = NULL; | ||
128 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
129 | "Message sent\n"); | ||
130 | GNUNET_assert (GNUNET_OK == result); | ||
131 | } | ||
132 | |||
133 | |||
134 | /** | ||
135 | * Functions with this signature are called whenever a | ||
136 | * complete message is received by the tokenizer. | ||
137 | * | ||
138 | * Do not call GNUNET_SERVER_mst_destroy in callback | ||
139 | * | ||
140 | * @param cls closure | ||
141 | * @param client identification of the client | ||
142 | * @param message the actual message | ||
143 | * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing | ||
144 | */ | ||
145 | static int | ||
146 | mst_cb (void *cls, | ||
147 | const struct GNUNET_MessageHeader *message) | ||
148 | { | ||
149 | const struct GNUNET_TESTBED_HelperReply *msg; | ||
150 | char *config; | ||
151 | uLongf config_size; | ||
152 | uLongf xconfig_size; | ||
153 | |||
154 | msg = (const struct GNUNET_TESTBED_HelperReply *) message; | ||
155 | config_size = 0; | ||
156 | xconfig_size = 0; | ||
157 | GNUNET_assert (sizeof(struct GNUNET_TESTBED_HelperReply) < | ||
158 | ntohs (msg->header.size)); | ||
159 | GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY == | ||
160 | ntohs (msg->header.type)); | ||
161 | config_size = (uLongf) ntohs (msg->config_size); | ||
162 | xconfig_size = | ||
163 | (uLongf) (ntohs (msg->header.size) | ||
164 | - sizeof(struct GNUNET_TESTBED_HelperReply)); | ||
165 | config = GNUNET_malloc (config_size); | ||
166 | GNUNET_assert (Z_OK == | ||
167 | uncompress ((Bytef *) config, &config_size, | ||
168 | (const Bytef *) &msg[1], xconfig_size)); | ||
169 | GNUNET_free (config); | ||
170 | if (NULL == shutdown_task) | ||
171 | shutdown_task = | ||
172 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
173 | (GNUNET_TIME_UNIT_SECONDS, 1), | ||
174 | &do_shutdown, NULL); | ||
175 | return GNUNET_OK; | ||
176 | } | ||
177 | |||
178 | |||
179 | /** | ||
180 | * Callback that will be called when the helper process dies. This is not called | ||
181 | * when the helper process is stopped using GNUNET_HELPER_stop() | ||
182 | * | ||
183 | * @param cls the closure from GNUNET_HELPER_start() | ||
184 | */ | ||
185 | static void | ||
186 | exp_cb (void *cls) | ||
187 | { | ||
188 | helper = NULL; | ||
189 | result = GNUNET_SYSERR; | ||
190 | } | ||
191 | |||
192 | |||
193 | /** | ||
194 | * Main function that will be run. | ||
195 | * | ||
196 | * @param cls closure | ||
197 | * @param args remaining command-line arguments | ||
198 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
199 | * @param cfg configuration | ||
200 | */ | ||
201 | static void | ||
202 | run (void *cls, char *const *args, const char *cfgfile, | ||
203 | const struct GNUNET_CONFIGURATION_Handle *cfg2) | ||
204 | { | ||
205 | static char *const binary_argv[] = { | ||
206 | "gnunet-helper-testbed", | ||
207 | NULL | ||
208 | }; | ||
209 | const char *trusted_ip = "127.0.0.1"; | ||
210 | |||
211 | helper = | ||
212 | GNUNET_HELPER_start (GNUNET_YES, | ||
213 | "gnunet-helper-testbed", | ||
214 | binary_argv, | ||
215 | &mst_cb, | ||
216 | &exp_cb, | ||
217 | NULL); | ||
218 | GNUNET_assert (NULL != helper); | ||
219 | cfg = GNUNET_CONFIGURATION_dup (cfg2); | ||
220 | msg = GNUNET_TESTBED_create_helper_init_msg_ (trusted_ip, NULL, cfg); | ||
221 | shandle = | ||
222 | GNUNET_HELPER_send (helper, &msg->header, GNUNET_NO, &cont_cb, NULL); | ||
223 | GNUNET_assert (NULL != shandle); | ||
224 | abort_task = | ||
225 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
226 | (GNUNET_TIME_UNIT_MINUTES, 1), &do_abort, | ||
227 | NULL); | ||
228 | } | ||
229 | |||
230 | |||
231 | /** | ||
232 | * Main function | ||
233 | * | ||
234 | * @param argc the number of command line arguments | ||
235 | * @param argv command line arg array | ||
236 | * @return return code | ||
237 | */ | ||
238 | int | ||
239 | main (int argc, char **argv) | ||
240 | { | ||
241 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
242 | GNUNET_GETOPT_OPTION_END | ||
243 | }; | ||
244 | |||
245 | result = GNUNET_OK; | ||
246 | if (GNUNET_OK != | ||
247 | GNUNET_PROGRAM_run (argc, argv, "test_gnunet_helper_testbed", | ||
248 | "Testcase for testing gnunet-helper-testbed.c", | ||
249 | options, &run, NULL)) | ||
250 | return 1; | ||
251 | return (GNUNET_OK == result) ? 0 : 1; | ||
252 | } | ||
253 | |||
254 | |||
255 | /* end of test_gnunet_helper_testbed.c */ | ||
diff --git a/src/testbed/test_testbed_api.c b/src/testbed/test_testbed_api.c deleted file mode 100644 index a46a7596a..000000000 --- a/src/testbed/test_testbed_api.c +++ /dev/null | |||
@@ -1,515 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/test_testbed_api.c | ||
23 | * @brief testcases for the testbed api | ||
24 | * @author Sree Harsha Totakura | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_arm_service.h" | ||
30 | #include "gnunet_testing_lib.h" | ||
31 | #include "gnunet_testbed_service.h" | ||
32 | |||
33 | /** | ||
34 | * Generic logging shortcut | ||
35 | */ | ||
36 | #define LOG(kind, ...) \ | ||
37 | GNUNET_log (kind, __VA_ARGS__) | ||
38 | |||
39 | /** | ||
40 | * Relative time seconds shorthand | ||
41 | */ | ||
42 | #define TIME_REL_SECS(sec) \ | ||
43 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) | ||
44 | |||
45 | /** | ||
46 | * Our localhost | ||
47 | */ | ||
48 | static struct GNUNET_TESTBED_Host *host; | ||
49 | |||
50 | /** | ||
51 | * The controller process | ||
52 | */ | ||
53 | static struct GNUNET_TESTBED_ControllerProc *cp; | ||
54 | |||
55 | /** | ||
56 | * The controller handle | ||
57 | */ | ||
58 | static struct GNUNET_TESTBED_Controller *controller; | ||
59 | |||
60 | /** | ||
61 | * A neighbouring host | ||
62 | */ | ||
63 | static struct GNUNET_TESTBED_Host *neighbour; | ||
64 | |||
65 | /** | ||
66 | * Handle for neighbour registration | ||
67 | */ | ||
68 | static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle; | ||
69 | |||
70 | /** | ||
71 | * Handle for a peer | ||
72 | */ | ||
73 | static struct GNUNET_TESTBED_Peer *peer; | ||
74 | |||
75 | /** | ||
76 | * Handle to configuration | ||
77 | */ | ||
78 | static struct GNUNET_CONFIGURATION_Handle *cfg; | ||
79 | |||
80 | /** | ||
81 | * Handle to operation | ||
82 | */ | ||
83 | static struct GNUNET_TESTBED_Operation *operation; | ||
84 | |||
85 | /** | ||
86 | * Handle to peer's ARM service | ||
87 | */ | ||
88 | static struct GNUNET_ARM_Handle *arm_handle; | ||
89 | |||
90 | /** | ||
91 | * Abort task identifier | ||
92 | */ | ||
93 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
94 | |||
95 | /** | ||
96 | * The testing result | ||
97 | */ | ||
98 | static int result; | ||
99 | |||
100 | |||
101 | /** | ||
102 | * Enumeration of sub testcases | ||
103 | */ | ||
104 | enum Test | ||
105 | { | ||
106 | /** | ||
107 | * Test cases which are not covered by the below ones | ||
108 | */ | ||
109 | OTHER, | ||
110 | |||
111 | /** | ||
112 | * Test where we get a peer config from controller | ||
113 | */ | ||
114 | PEER_GETCONFIG, | ||
115 | |||
116 | /** | ||
117 | * Test where we connect to a service running on the peer | ||
118 | */ | ||
119 | PEER_SERVICE_CONNECT, | ||
120 | |||
121 | /** | ||
122 | * Test where we get a peer's identity from controller | ||
123 | */ | ||
124 | PEER_DESTROY | ||
125 | }; | ||
126 | |||
127 | /** | ||
128 | * Testing status | ||
129 | */ | ||
130 | static enum Test sub_test; | ||
131 | |||
132 | /** | ||
133 | * Shutdown nicely | ||
134 | * | ||
135 | * @param cls NULL | ||
136 | * @param tc the task context | ||
137 | */ | ||
138 | static void | ||
139 | do_shutdown (void *cls) | ||
140 | { | ||
141 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down...\n"); | ||
142 | if (NULL != abort_task) | ||
143 | GNUNET_SCHEDULER_cancel (abort_task); | ||
144 | if (NULL != reg_handle) | ||
145 | GNUNET_TESTBED_cancel_registration (reg_handle); | ||
146 | if (NULL != controller) | ||
147 | GNUNET_TESTBED_controller_disconnect (controller); | ||
148 | if (NULL != cfg) | ||
149 | GNUNET_CONFIGURATION_destroy (cfg); | ||
150 | if (NULL != cp) | ||
151 | GNUNET_TESTBED_controller_stop (cp); | ||
152 | if (NULL != neighbour) | ||
153 | GNUNET_TESTBED_host_destroy (neighbour); | ||
154 | if (NULL != host) | ||
155 | GNUNET_TESTBED_host_destroy (host); | ||
156 | } | ||
157 | |||
158 | |||
159 | /** | ||
160 | * shortcut to exit during failure | ||
161 | */ | ||
162 | #define FAIL_TEST(cond, ret) do { \ | ||
163 | if (! (cond)) { \ | ||
164 | GNUNET_break (0); \ | ||
165 | if (NULL != abort_task) \ | ||
166 | GNUNET_SCHEDULER_cancel (abort_task); \ | ||
167 | abort_task = NULL; \ | ||
168 | GNUNET_SCHEDULER_add_now (do_shutdown, NULL); \ | ||
169 | ret; \ | ||
170 | } \ | ||
171 | } while (0) | ||
172 | |||
173 | |||
174 | /** | ||
175 | * abort task to run on test timed out | ||
176 | * | ||
177 | * @param cls NULL | ||
178 | * @param tc the task context | ||
179 | */ | ||
180 | static void | ||
181 | do_abort (void *cls) | ||
182 | { | ||
183 | LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); | ||
184 | abort_task = NULL; | ||
185 | do_shutdown (cls); | ||
186 | } | ||
187 | |||
188 | |||
189 | /** | ||
190 | * Adapter function called to establish a connection to | ||
191 | * a service. | ||
192 | * | ||
193 | * @param cls closure | ||
194 | * @param cfg configuration of the peer to connect to; will be available until | ||
195 | * GNUNET_TESTBED_operation_done() is called on the operation returned | ||
196 | * from GNUNET_TESTBED_service_connect() | ||
197 | * @return service handle to return in 'op_result', NULL on error | ||
198 | */ | ||
199 | static void * | ||
200 | arm_connect_adapter (void *cls, | ||
201 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
202 | { | ||
203 | FAIL_TEST (NULL == cls, return NULL); | ||
204 | FAIL_TEST (OTHER == sub_test, return NULL); | ||
205 | sub_test = PEER_SERVICE_CONNECT; | ||
206 | arm_handle = GNUNET_ARM_connect (cfg, NULL, NULL); | ||
207 | return arm_handle; | ||
208 | } | ||
209 | |||
210 | |||
211 | /** | ||
212 | * Adapter function called to destroy a connection to | ||
213 | * a service. | ||
214 | * | ||
215 | * @param cls closure | ||
216 | * @param op_result service handle returned from the connect adapter | ||
217 | */ | ||
218 | static void | ||
219 | arm_disconnect_adapter (void *cls, | ||
220 | void *op_result) | ||
221 | { | ||
222 | FAIL_TEST (NULL != op_result, return ); | ||
223 | FAIL_TEST (op_result == arm_handle, return ); | ||
224 | GNUNET_ARM_disconnect (arm_handle); | ||
225 | arm_handle = NULL; | ||
226 | FAIL_TEST (PEER_SERVICE_CONNECT == sub_test, return ); | ||
227 | FAIL_TEST (NULL != operation, return ); | ||
228 | operation = GNUNET_TESTBED_peer_stop (NULL, peer, NULL, NULL); | ||
229 | FAIL_TEST (NULL != operation, return ); | ||
230 | } | ||
231 | |||
232 | |||
233 | /** | ||
234 | * Callback to be called when a service connect operation is completed | ||
235 | * | ||
236 | * @param cls the callback closure from functions generating an operation | ||
237 | * @param op the operation that has been finished | ||
238 | * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() | ||
239 | * @param emsg error message in case the operation has failed; will be NULL if | ||
240 | * operation has executed successfully. | ||
241 | */ | ||
242 | static void | ||
243 | service_connect_comp_cb (void *cls, | ||
244 | struct GNUNET_TESTBED_Operation *op, | ||
245 | void *ca_result, | ||
246 | const char *emsg) | ||
247 | { | ||
248 | switch (sub_test) | ||
249 | { | ||
250 | case PEER_SERVICE_CONNECT: | ||
251 | FAIL_TEST (operation == op, return ); | ||
252 | FAIL_TEST (NULL == emsg, return ); | ||
253 | FAIL_TEST (NULL == cls, return ); | ||
254 | FAIL_TEST (ca_result == arm_handle, return ); | ||
255 | GNUNET_TESTBED_operation_done (operation); /* This results in call to | ||
256 | * disconnect adapter */ | ||
257 | break; | ||
258 | |||
259 | default: | ||
260 | FAIL_TEST (0, return ); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | |||
265 | /** | ||
266 | * Callback to be called when the requested peer information is available | ||
267 | * | ||
268 | * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information() | ||
269 | * @param op the operation this callback corresponds to | ||
270 | * @param pinfo the result; will be NULL if the operation has failed | ||
271 | * @param emsg error message if the operation has failed; will be NULL if the | ||
272 | * operation is successful | ||
273 | */ | ||
274 | static void | ||
275 | peerinfo_cb (void *cb_cls, | ||
276 | struct GNUNET_TESTBED_Operation *op, | ||
277 | const struct GNUNET_TESTBED_PeerInformation *pinfo, | ||
278 | const char *emsg) | ||
279 | { | ||
280 | switch (sub_test) | ||
281 | { | ||
282 | case PEER_GETCONFIG: | ||
283 | FAIL_TEST (NULL != pinfo, return ); | ||
284 | FAIL_TEST (NULL == emsg, return ); | ||
285 | FAIL_TEST (NULL == cb_cls, return ); | ||
286 | FAIL_TEST (operation == op, return ); | ||
287 | FAIL_TEST (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit, return ); | ||
288 | FAIL_TEST (NULL != pinfo->result.cfg, return ); | ||
289 | sub_test = PEER_DESTROY; | ||
290 | GNUNET_TESTBED_operation_done (operation); | ||
291 | operation = GNUNET_TESTBED_peer_destroy (peer); | ||
292 | break; | ||
293 | |||
294 | default: | ||
295 | FAIL_TEST (0, return ); | ||
296 | } | ||
297 | } | ||
298 | |||
299 | |||
300 | /** | ||
301 | * Signature of the event handler function called by the | ||
302 | * respective event controller. | ||
303 | * | ||
304 | * @param cls closure | ||
305 | * @param event information about the event | ||
306 | */ | ||
307 | static void | ||
308 | controller_cb (void *cls, | ||
309 | const struct GNUNET_TESTBED_EventInformation *event) | ||
310 | { | ||
311 | switch (event->type) | ||
312 | { | ||
313 | case GNUNET_TESTBED_ET_OPERATION_FINISHED: | ||
314 | switch (sub_test) | ||
315 | { | ||
316 | case PEER_DESTROY: | ||
317 | FAIL_TEST (event->op == operation, return ); | ||
318 | FAIL_TEST (NULL == event->op_cls, return ); | ||
319 | FAIL_TEST (NULL == event->details.operation_finished.emsg, return ); | ||
320 | FAIL_TEST (NULL == event->details.operation_finished.generic, return ); | ||
321 | GNUNET_TESTBED_operation_done (operation); | ||
322 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
323 | break; | ||
324 | |||
325 | case PEER_SERVICE_CONNECT: | ||
326 | FAIL_TEST (event->op == operation, return ); | ||
327 | FAIL_TEST (NULL == event->op_cls, return ); | ||
328 | FAIL_TEST (NULL == event->details.operation_finished.emsg, return ); | ||
329 | FAIL_TEST (NULL != arm_handle, return ); | ||
330 | FAIL_TEST (event->details.operation_finished.generic == arm_handle, | ||
331 | return ); | ||
332 | break; | ||
333 | |||
334 | default: | ||
335 | FAIL_TEST (0, return ); | ||
336 | break; | ||
337 | } | ||
338 | break; | ||
339 | |||
340 | case GNUNET_TESTBED_ET_PEER_START: | ||
341 | FAIL_TEST (event->details.peer_start.host == host, return ); | ||
342 | FAIL_TEST (event->details.peer_start.peer == peer, return ); | ||
343 | FAIL_TEST (OTHER == sub_test, return ); | ||
344 | GNUNET_TESTBED_operation_done (operation); | ||
345 | operation = | ||
346 | GNUNET_TESTBED_service_connect (NULL, peer, "dht", | ||
347 | &service_connect_comp_cb, NULL, | ||
348 | &arm_connect_adapter, | ||
349 | &arm_disconnect_adapter, NULL); | ||
350 | FAIL_TEST (NULL != operation, return ); | ||
351 | break; | ||
352 | |||
353 | case GNUNET_TESTBED_ET_PEER_STOP: | ||
354 | FAIL_TEST (event->details.peer_stop.peer == peer, return ); | ||
355 | FAIL_TEST (PEER_SERVICE_CONNECT == sub_test, return ); | ||
356 | result = GNUNET_YES; | ||
357 | sub_test = PEER_GETCONFIG; | ||
358 | GNUNET_TESTBED_operation_done (operation); | ||
359 | operation = | ||
360 | GNUNET_TESTBED_peer_get_information (peer, | ||
361 | GNUNET_TESTBED_PIT_CONFIGURATION, | ||
362 | &peerinfo_cb, NULL); | ||
363 | break; | ||
364 | |||
365 | default: | ||
366 | FAIL_TEST (0, return ); /* We should never reach this state */ | ||
367 | } | ||
368 | } | ||
369 | |||
370 | |||
371 | /** | ||
372 | * Functions of this signature are called when a peer has been successfully | ||
373 | * created | ||
374 | * | ||
375 | * @param cls the closure from GNUNET_TESTBED_peer_create() | ||
376 | * @param peer the handle for the created peer; NULL on any error during | ||
377 | * creation | ||
378 | * @param emsg NULL if peer is not NULL; else MAY contain the error description | ||
379 | */ | ||
380 | static void | ||
381 | peer_create_cb (void *cls, | ||
382 | struct GNUNET_TESTBED_Peer *peer, | ||
383 | const char *emsg) | ||
384 | { | ||
385 | struct GNUNET_TESTBED_Peer **peer_ptr; | ||
386 | |||
387 | peer_ptr = cls; | ||
388 | FAIL_TEST (NULL != peer, return ); | ||
389 | FAIL_TEST (NULL != peer_ptr, return ); | ||
390 | *peer_ptr = peer; | ||
391 | GNUNET_TESTBED_operation_done (operation); | ||
392 | operation = GNUNET_TESTBED_peer_start (NULL, | ||
393 | peer, | ||
394 | NULL, | ||
395 | NULL); | ||
396 | FAIL_TEST (NULL != operation, return ); | ||
397 | } | ||
398 | |||
399 | |||
400 | /** | ||
401 | * Callback which will be called to after a host registration succeeded or failed | ||
402 | * | ||
403 | * @param cls the host which has been registered | ||
404 | * @param emsg the error message; NULL if host registration is successful | ||
405 | */ | ||
406 | static void | ||
407 | registration_comp (void *cls, | ||
408 | const char *emsg) | ||
409 | { | ||
410 | FAIL_TEST (cls == neighbour, return ); | ||
411 | reg_handle = NULL; | ||
412 | operation = | ||
413 | GNUNET_TESTBED_peer_create (controller, | ||
414 | host, | ||
415 | cfg, | ||
416 | &peer_create_cb, | ||
417 | &peer); | ||
418 | FAIL_TEST (NULL != operation, return ); | ||
419 | } | ||
420 | |||
421 | |||
422 | /** | ||
423 | * Callback to signal successful startup of the controller process | ||
424 | * | ||
425 | * @param cls the closure from GNUNET_TESTBED_controller_start() | ||
426 | * @param cfg the configuration with which the controller has been started; | ||
427 | * NULL if status is not #GNUNET_OK | ||
428 | * @param status #GNUNET_OK if the startup is successful; #GNUNET_SYSERR if not, | ||
429 | * GNUNET_TESTBED_controller_stop() shouldn't be called in this case | ||
430 | */ | ||
431 | static void | ||
432 | status_cb (void *cls, | ||
433 | const struct GNUNET_CONFIGURATION_Handle *cfg_, | ||
434 | int status) | ||
435 | { | ||
436 | uint64_t event_mask; | ||
437 | |||
438 | if (GNUNET_OK != status) | ||
439 | { | ||
440 | cp = NULL; | ||
441 | FAIL_TEST (0, return ); | ||
442 | return; | ||
443 | } | ||
444 | event_mask = 0; | ||
445 | event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START); | ||
446 | event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP); | ||
447 | event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); | ||
448 | event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
449 | controller = | ||
450 | GNUNET_TESTBED_controller_connect (host, event_mask, &controller_cb, | ||
451 | NULL); | ||
452 | FAIL_TEST (NULL != controller, return ); | ||
453 | neighbour = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0); | ||
454 | FAIL_TEST (NULL != neighbour, return ); | ||
455 | reg_handle = | ||
456 | GNUNET_TESTBED_register_host (controller, neighbour, ®istration_comp, | ||
457 | neighbour); | ||
458 | FAIL_TEST (NULL != reg_handle, return ); | ||
459 | } | ||
460 | |||
461 | |||
462 | /** | ||
463 | * Main run function. | ||
464 | * | ||
465 | * @param cls NULL | ||
466 | * @param args arguments passed to #GNUNET_PROGRAM_run() | ||
467 | * @param cfgfile the path to configuration file | ||
468 | * @param cfg the configuration file handle | ||
469 | */ | ||
470 | static void | ||
471 | run (void *cls, | ||
472 | char *const *args, | ||
473 | const char *cfgfile, | ||
474 | const struct GNUNET_CONFIGURATION_Handle *config) | ||
475 | { | ||
476 | cfg = GNUNET_CONFIGURATION_dup (config); | ||
477 | host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); | ||
478 | FAIL_TEST (NULL != host, return ); | ||
479 | cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, | ||
480 | &status_cb, | ||
481 | NULL); | ||
482 | abort_task = | ||
483 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
484 | (GNUNET_TIME_UNIT_MINUTES, 5), | ||
485 | &do_abort, | ||
486 | NULL); | ||
487 | } | ||
488 | |||
489 | |||
490 | /** | ||
491 | * Main function | ||
492 | */ | ||
493 | int | ||
494 | main (int argc, char **argv) | ||
495 | { | ||
496 | int ret; | ||
497 | |||
498 | char *const argv2[] = { "test_testbed_api", | ||
499 | "-c", "test_testbed_api.conf", | ||
500 | NULL }; | ||
501 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
502 | GNUNET_GETOPT_OPTION_END | ||
503 | }; | ||
504 | |||
505 | result = GNUNET_SYSERR; | ||
506 | ret = | ||
507 | GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, | ||
508 | "test_testbed_api", "nohelp", options, &run, NULL); | ||
509 | if ((GNUNET_OK != ret) || (GNUNET_OK != result)) | ||
510 | return 1; | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | |||
515 | /* end of test_testbed_api.c */ | ||
diff --git a/src/testbed/test_testbed_api.conf b/src/testbed/test_testbed_api.conf deleted file mode 100644 index e5f286d5b..000000000 --- a/src/testbed/test_testbed_api.conf +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
diff --git a/src/testbed/test_testbed_api_2peers_1controller.c b/src/testbed/test_testbed_api_2peers_1controller.c deleted file mode 100644 index 1ca1d1b2e..000000000 --- a/src/testbed/test_testbed_api_2peers_1controller.c +++ /dev/null | |||
@@ -1,540 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/test_testbed_api_2peers_1controller.c | ||
23 | * @brief testcases for the testbed api: 2 peers are configured, started and | ||
24 | * connected together. The 2 peer reside on a single controller. | ||
25 | * @author Sree Harsha Totakura | ||
26 | */ | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_testing_lib.h" | ||
31 | #include "gnunet_testbed_service.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Generic logging shortcut | ||
36 | */ | ||
37 | #define LOG(kind, ...) \ | ||
38 | GNUNET_log (kind, __VA_ARGS__) | ||
39 | |||
40 | /** | ||
41 | * Relative time seconds shorthand | ||
42 | */ | ||
43 | #define TIME_REL_SECS(sec) \ | ||
44 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) | ||
45 | |||
46 | /** | ||
47 | * Peer context | ||
48 | */ | ||
49 | struct PeerContext | ||
50 | { | ||
51 | /** | ||
52 | * The peer handle | ||
53 | */ | ||
54 | struct GNUNET_TESTBED_Peer *peer; | ||
55 | |||
56 | /** | ||
57 | * Operations involving this peer | ||
58 | */ | ||
59 | struct GNUNET_TESTBED_Operation *operation; | ||
60 | |||
61 | /** | ||
62 | * set to GNUNET_YES when peer is started | ||
63 | */ | ||
64 | int is_running; | ||
65 | }; | ||
66 | |||
67 | /** | ||
68 | * Our localhost | ||
69 | */ | ||
70 | static struct GNUNET_TESTBED_Host *host; | ||
71 | |||
72 | /** | ||
73 | * The controller process | ||
74 | */ | ||
75 | static struct GNUNET_TESTBED_ControllerProc *cp; | ||
76 | |||
77 | /** | ||
78 | * The controller handle | ||
79 | */ | ||
80 | static struct GNUNET_TESTBED_Controller *controller; | ||
81 | |||
82 | /** | ||
83 | * A neighbouring host | ||
84 | */ | ||
85 | static struct GNUNET_TESTBED_Host *neighbour; | ||
86 | |||
87 | /** | ||
88 | * Handle for neighbour registration | ||
89 | */ | ||
90 | static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle; | ||
91 | |||
92 | /** | ||
93 | * peer 1 | ||
94 | */ | ||
95 | static struct PeerContext peer1; | ||
96 | |||
97 | /** | ||
98 | * peer2 | ||
99 | */ | ||
100 | static struct PeerContext peer2; | ||
101 | |||
102 | /** | ||
103 | * Handle to configuration | ||
104 | */ | ||
105 | static struct GNUNET_CONFIGURATION_Handle *cfg; | ||
106 | |||
107 | /** | ||
108 | * Handle to operations involving both peers | ||
109 | */ | ||
110 | static struct GNUNET_TESTBED_Operation *common_operation; | ||
111 | |||
112 | /** | ||
113 | * Abort task identifier | ||
114 | */ | ||
115 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
116 | |||
117 | /** | ||
118 | * Delayed connect job identifier | ||
119 | */ | ||
120 | static struct GNUNET_SCHEDULER_Task *delayed_connect_task; | ||
121 | |||
122 | /** | ||
123 | * Different stages in testing | ||
124 | */ | ||
125 | enum Stage | ||
126 | { | ||
127 | /** | ||
128 | * Initial stage | ||
129 | */ | ||
130 | INIT, | ||
131 | |||
132 | /** | ||
133 | * peers are created | ||
134 | */ | ||
135 | PEERS_CREATED, | ||
136 | |||
137 | /** | ||
138 | * peers are started | ||
139 | */ | ||
140 | PEERS_STARTED, | ||
141 | |||
142 | /** | ||
143 | * peers are connected | ||
144 | */ | ||
145 | PEERS_CONNECTED, | ||
146 | |||
147 | /** | ||
148 | * Peers are connected once again (this should not fail as they are already connected) | ||
149 | */ | ||
150 | PEERS_CONNECTED_2, | ||
151 | |||
152 | /** | ||
153 | * peers are stopped | ||
154 | */ | ||
155 | PEERS_STOPPED, | ||
156 | |||
157 | /** | ||
158 | * Final success stage | ||
159 | */ | ||
160 | SUCCESS | ||
161 | }; | ||
162 | |||
163 | /** | ||
164 | * The testing result | ||
165 | */ | ||
166 | static enum Stage result; | ||
167 | |||
168 | |||
169 | /** | ||
170 | * shortcut to exit during failure | ||
171 | */ | ||
172 | #define FAIL_TEST(cond) do { \ | ||
173 | if (! (cond)) { \ | ||
174 | GNUNET_break (0); \ | ||
175 | if (NULL != abort_task) \ | ||
176 | GNUNET_SCHEDULER_cancel (abort_task); \ | ||
177 | abort_task = NULL; \ | ||
178 | GNUNET_SCHEDULER_add_now (do_shutdown, NULL); \ | ||
179 | return; \ | ||
180 | } \ | ||
181 | } while (0) | ||
182 | |||
183 | |||
184 | /** | ||
185 | * Shutdown nicely | ||
186 | * | ||
187 | * @param cls NULL | ||
188 | */ | ||
189 | static void | ||
190 | do_shutdown (void *cls) | ||
191 | { | ||
192 | if (NULL != abort_task) | ||
193 | GNUNET_SCHEDULER_cancel (abort_task); | ||
194 | if (NULL != delayed_connect_task) | ||
195 | GNUNET_SCHEDULER_cancel (delayed_connect_task); | ||
196 | if (NULL != reg_handle) | ||
197 | GNUNET_TESTBED_cancel_registration (reg_handle); | ||
198 | GNUNET_TESTBED_controller_disconnect (controller); | ||
199 | GNUNET_CONFIGURATION_destroy (cfg); | ||
200 | if (NULL != cp) | ||
201 | GNUNET_TESTBED_controller_stop (cp); | ||
202 | GNUNET_TESTBED_host_destroy (neighbour); | ||
203 | GNUNET_TESTBED_host_destroy (host); | ||
204 | } | ||
205 | |||
206 | |||
207 | /** | ||
208 | * abort task to run on test timed out | ||
209 | * | ||
210 | * @param cls NULL | ||
211 | */ | ||
212 | static void | ||
213 | do_abort (void *cls) | ||
214 | { | ||
215 | LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); | ||
216 | abort_task = NULL; | ||
217 | do_shutdown (cls); | ||
218 | } | ||
219 | |||
220 | |||
221 | /** | ||
222 | * Callback to be called when an operation is completed | ||
223 | * | ||
224 | * @param cls the callback closure from functions generating an operation | ||
225 | * @param op the operation that has been finished | ||
226 | * @param emsg error message in case the operation has failed; will be NULL if | ||
227 | * operation has executed successfully. | ||
228 | */ | ||
229 | static void | ||
230 | op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg); | ||
231 | |||
232 | |||
233 | /** | ||
234 | * task for delaying a connect | ||
235 | * | ||
236 | * @param cls NULL | ||
237 | */ | ||
238 | static void | ||
239 | do_delayed_connect (void *cls) | ||
240 | { | ||
241 | delayed_connect_task = NULL; | ||
242 | FAIL_TEST (NULL == common_operation); | ||
243 | common_operation = | ||
244 | GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer1.peer, | ||
245 | peer2.peer); | ||
246 | } | ||
247 | |||
248 | |||
249 | /** | ||
250 | * Callback to be called when an operation is completed | ||
251 | * | ||
252 | * @param cls the callback closure from functions generating an operation | ||
253 | * @param op the operation that has been finished | ||
254 | * @param emsg error message in case the operation has failed; will be NULL if | ||
255 | * operation has executed successfully. | ||
256 | */ | ||
257 | static void | ||
258 | op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) | ||
259 | { | ||
260 | FAIL_TEST (common_operation == op); | ||
261 | switch (result) | ||
262 | { | ||
263 | case PEERS_STARTED: | ||
264 | FAIL_TEST (NULL == peer1.operation); | ||
265 | FAIL_TEST (NULL == peer2.operation); | ||
266 | FAIL_TEST (NULL != common_operation); | ||
267 | break; | ||
268 | |||
269 | case PEERS_CONNECTED: | ||
270 | FAIL_TEST (NULL == peer1.operation); | ||
271 | FAIL_TEST (NULL == peer2.operation); | ||
272 | FAIL_TEST (NULL != common_operation); | ||
273 | break; | ||
274 | |||
275 | default: | ||
276 | FAIL_TEST (0); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | |||
281 | /** | ||
282 | * Signature of the event handler function called by the | ||
283 | * respective event controller. | ||
284 | * | ||
285 | * @param cls closure | ||
286 | * @param event information about the event | ||
287 | */ | ||
288 | static void | ||
289 | controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) | ||
290 | { | ||
291 | switch (event->type) | ||
292 | { | ||
293 | case GNUNET_TESTBED_ET_OPERATION_FINISHED: /* Will be reached when we destroy peers */ | ||
294 | FAIL_TEST (PEERS_STOPPED == result); | ||
295 | FAIL_TEST (NULL == event->op_cls); | ||
296 | FAIL_TEST (NULL == event->details.operation_finished.emsg); | ||
297 | FAIL_TEST (NULL == event->details.operation_finished.generic); | ||
298 | if (event->op == peer1.operation) | ||
299 | { | ||
300 | GNUNET_TESTBED_operation_done (peer1.operation); | ||
301 | peer1.operation = NULL; | ||
302 | peer1.peer = NULL; | ||
303 | } | ||
304 | else if (event->op == peer2.operation) | ||
305 | { | ||
306 | GNUNET_TESTBED_operation_done (peer2.operation); | ||
307 | peer2.operation = NULL; | ||
308 | peer2.peer = NULL; | ||
309 | } | ||
310 | else | ||
311 | FAIL_TEST (0); | ||
312 | if ((NULL == peer1.peer) && (NULL == peer2.peer)) | ||
313 | { | ||
314 | result = SUCCESS; | ||
315 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
316 | } | ||
317 | break; | ||
318 | |||
319 | case GNUNET_TESTBED_ET_PEER_START: | ||
320 | FAIL_TEST (INIT == result); | ||
321 | FAIL_TEST (event->details.peer_start.host == host); | ||
322 | if (event->details.peer_start.peer == peer1.peer) | ||
323 | { | ||
324 | peer1.is_running = GNUNET_YES; | ||
325 | GNUNET_TESTBED_operation_done (peer1.operation); | ||
326 | peer1.operation = NULL; | ||
327 | } | ||
328 | else if (event->details.peer_start.peer == peer2.peer) | ||
329 | { | ||
330 | peer2.is_running = GNUNET_YES; | ||
331 | GNUNET_TESTBED_operation_done (peer2.operation); | ||
332 | peer2.operation = NULL; | ||
333 | } | ||
334 | else | ||
335 | FAIL_TEST (0); | ||
336 | if ((GNUNET_YES == peer1.is_running) && (GNUNET_YES == peer2.is_running)) | ||
337 | { | ||
338 | result = PEERS_STARTED; | ||
339 | common_operation = | ||
340 | GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer1.peer, | ||
341 | peer2.peer); | ||
342 | } | ||
343 | break; | ||
344 | |||
345 | case GNUNET_TESTBED_ET_PEER_STOP: | ||
346 | FAIL_TEST (PEERS_CONNECTED_2 == result); | ||
347 | if (event->details.peer_stop.peer == peer1.peer) | ||
348 | { | ||
349 | peer1.is_running = GNUNET_NO; | ||
350 | GNUNET_TESTBED_operation_done (peer1.operation); | ||
351 | peer1.operation = GNUNET_TESTBED_peer_destroy (peer1.peer); | ||
352 | } | ||
353 | else if (event->details.peer_stop.peer == peer2.peer) | ||
354 | { | ||
355 | peer2.is_running = GNUNET_NO; | ||
356 | GNUNET_TESTBED_operation_done (peer2.operation); | ||
357 | peer2.operation = GNUNET_TESTBED_peer_destroy (peer2.peer); | ||
358 | } | ||
359 | else | ||
360 | FAIL_TEST (0); | ||
361 | if ((GNUNET_NO == peer1.is_running) && (GNUNET_NO == peer2.is_running)) | ||
362 | result = PEERS_STOPPED; | ||
363 | break; | ||
364 | |||
365 | case GNUNET_TESTBED_ET_CONNECT: | ||
366 | switch (result) | ||
367 | { | ||
368 | case PEERS_STARTED: | ||
369 | FAIL_TEST (NULL == peer1.operation); | ||
370 | FAIL_TEST (NULL == peer2.operation); | ||
371 | FAIL_TEST (NULL != common_operation); | ||
372 | FAIL_TEST ((event->details.peer_connect.peer1 == peer1.peer) && | ||
373 | (event->details.peer_connect.peer2 == peer2.peer)); | ||
374 | GNUNET_TESTBED_operation_done (common_operation); | ||
375 | common_operation = NULL; | ||
376 | result = PEERS_CONNECTED; | ||
377 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected\n"); | ||
378 | delayed_connect_task = | ||
379 | GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (3), &do_delayed_connect, | ||
380 | NULL); | ||
381 | break; | ||
382 | |||
383 | case PEERS_CONNECTED: | ||
384 | FAIL_TEST (NULL == peer1.operation); | ||
385 | FAIL_TEST (NULL == peer2.operation); | ||
386 | FAIL_TEST (NULL != common_operation); | ||
387 | GNUNET_TESTBED_operation_done (common_operation); | ||
388 | common_operation = NULL; | ||
389 | result = PEERS_CONNECTED_2; | ||
390 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected again\n"); | ||
391 | peer1.operation = GNUNET_TESTBED_peer_stop (NULL, peer1.peer, NULL, NULL); | ||
392 | peer2.operation = GNUNET_TESTBED_peer_stop (NULL, peer2.peer, NULL, NULL); | ||
393 | break; | ||
394 | |||
395 | default: | ||
396 | FAIL_TEST (0); | ||
397 | } | ||
398 | break; | ||
399 | |||
400 | default: | ||
401 | FAIL_TEST (0); | ||
402 | } | ||
403 | ; | ||
404 | } | ||
405 | |||
406 | |||
407 | /** | ||
408 | * Functions of this signature are called when a peer has been successfully | ||
409 | * created | ||
410 | * | ||
411 | * @param cls the closure from GNUNET_TESTBED_peer_create() | ||
412 | * @param peer the handle for the created peer; NULL on any error during | ||
413 | * creation | ||
414 | * @param emsg NULL if peer is not NULL; else MAY contain the error description | ||
415 | */ | ||
416 | static void | ||
417 | peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) | ||
418 | { | ||
419 | struct PeerContext *pc = cls; | ||
420 | |||
421 | FAIL_TEST (NULL != pc->operation); | ||
422 | FAIL_TEST (NULL != peer); | ||
423 | FAIL_TEST (NULL == pc->peer); | ||
424 | pc->peer = peer; | ||
425 | GNUNET_TESTBED_operation_done (pc->operation); | ||
426 | pc->operation = GNUNET_TESTBED_peer_start (NULL, pc->peer, NULL, NULL); | ||
427 | } | ||
428 | |||
429 | |||
430 | /** | ||
431 | * Callback which will be called to after a host registration succeeded or failed | ||
432 | * | ||
433 | * @param cls the host which has been registered | ||
434 | * @param emsg the error message; NULL if host registration is successful | ||
435 | */ | ||
436 | static void | ||
437 | registration_comp (void *cls, const char *emsg) | ||
438 | { | ||
439 | FAIL_TEST (cls == neighbour); | ||
440 | reg_handle = NULL; | ||
441 | peer1.operation = | ||
442 | GNUNET_TESTBED_peer_create (controller, host, cfg, &peer_create_cb, | ||
443 | &peer1); | ||
444 | peer2.operation = | ||
445 | GNUNET_TESTBED_peer_create (controller, host, cfg, &peer_create_cb, | ||
446 | &peer2); | ||
447 | FAIL_TEST (NULL != peer1.operation); | ||
448 | FAIL_TEST (NULL != peer2.operation); | ||
449 | } | ||
450 | |||
451 | |||
452 | /** | ||
453 | * Callback to signal successful startup of the controller process | ||
454 | * | ||
455 | * @param cls the closure from GNUNET_TESTBED_controller_start() | ||
456 | * @param cfg the configuration with which the controller has been started; | ||
457 | * NULL if status is not GNUNET_OK | ||
458 | * @param status GNUNET_OK if the startup is successful; GNUNET_SYSERR if not, | ||
459 | * GNUNET_TESTBED_controller_stop() shouldn't be called in this case | ||
460 | */ | ||
461 | static void | ||
462 | status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg_, int | ||
463 | status) | ||
464 | { | ||
465 | uint64_t event_mask; | ||
466 | |||
467 | if (GNUNET_OK != status) | ||
468 | { | ||
469 | cp = NULL; | ||
470 | FAIL_TEST (0); | ||
471 | } | ||
472 | event_mask = 0; | ||
473 | event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START); | ||
474 | event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP); | ||
475 | event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); | ||
476 | event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
477 | controller = | ||
478 | GNUNET_TESTBED_controller_connect (host, event_mask, &controller_cb, | ||
479 | NULL); | ||
480 | FAIL_TEST (NULL != controller); | ||
481 | neighbour = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0); | ||
482 | FAIL_TEST (NULL != neighbour); | ||
483 | reg_handle = | ||
484 | GNUNET_TESTBED_register_host (controller, neighbour, ®istration_comp, | ||
485 | neighbour); | ||
486 | FAIL_TEST (NULL != reg_handle); | ||
487 | } | ||
488 | |||
489 | |||
490 | /** | ||
491 | * Main run function. | ||
492 | * | ||
493 | * @param cls NULL | ||
494 | * @param args arguments passed to GNUNET_PROGRAM_run | ||
495 | * @param cfgfile the path to configuration file | ||
496 | * @param cfg the configuration file handle | ||
497 | */ | ||
498 | static void | ||
499 | run (void *cls, char *const *args, const char *cfgfile, | ||
500 | const struct GNUNET_CONFIGURATION_Handle *config) | ||
501 | { | ||
502 | cfg = GNUNET_CONFIGURATION_dup (config); | ||
503 | host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); | ||
504 | FAIL_TEST (NULL != host); | ||
505 | cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb, | ||
506 | NULL); | ||
507 | abort_task = | ||
508 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
509 | (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort, | ||
510 | NULL); | ||
511 | } | ||
512 | |||
513 | |||
514 | /** | ||
515 | * Main function | ||
516 | */ | ||
517 | int | ||
518 | main (int argc, char **argv) | ||
519 | { | ||
520 | int ret; | ||
521 | |||
522 | char *const argv2[] = { "test_testbed_api_2peers_1controller", | ||
523 | "-c", "test_testbed_api.conf", | ||
524 | NULL }; | ||
525 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
526 | GNUNET_GETOPT_OPTION_END | ||
527 | }; | ||
528 | |||
529 | result = INIT; | ||
530 | ret = | ||
531 | GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, | ||
532 | "test_testbed_api_2peers_1controller", "nohelp", | ||
533 | options, &run, NULL); | ||
534 | if ((GNUNET_OK != ret) || (SUCCESS != result)) | ||
535 | return 1; | ||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | |||
540 | /* end of test_testbed_api_2peers_1controller.c */ | ||
diff --git a/src/testbed/test_testbed_api_3peers_3controllers.c b/src/testbed/test_testbed_api_3peers_3controllers.c deleted file mode 100644 index 17072ffa8..000000000 --- a/src/testbed/test_testbed_api_3peers_3controllers.c +++ /dev/null | |||
@@ -1,964 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/test_testbed_api_3peers_3controllers.c | ||
23 | * @brief testcases for the testbed api: 3 peers are configured, started and | ||
24 | * connected together. Each peer resides on its own controller. | ||
25 | * @author Sree Harsha Totakura | ||
26 | */ | ||
27 | |||
28 | |||
29 | /** | ||
30 | * The testing architecture is: | ||
31 | * A | ||
32 | * / \ | ||
33 | * / \ | ||
34 | * B === C | ||
35 | * A is the master controller and B, C are slave controllers. B links to C | ||
36 | * laterally. | ||
37 | * Peers are mapped to controllers in the following relations: | ||
38 | * Peer Controller | ||
39 | * 1 A | ||
40 | * 2 B | ||
41 | * 3 C | ||
42 | * | ||
43 | */ | ||
44 | |||
45 | #include "platform.h" | ||
46 | #include "gnunet_util_lib.h" | ||
47 | #include "gnunet_testing_lib.h" | ||
48 | #include "gnunet_testbed_service.h" | ||
49 | |||
50 | |||
51 | /** | ||
52 | * Generic logging shortcut | ||
53 | */ | ||
54 | #define LOG(kind, ...) \ | ||
55 | GNUNET_log (kind, __VA_ARGS__) | ||
56 | |||
57 | /** | ||
58 | * Relative time seconds shorthand | ||
59 | */ | ||
60 | #define TIME_REL_SECS(sec) \ | ||
61 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Peer context | ||
66 | */ | ||
67 | struct PeerContext | ||
68 | { | ||
69 | /** | ||
70 | * The peer handle | ||
71 | */ | ||
72 | struct GNUNET_TESTBED_Peer *peer; | ||
73 | |||
74 | /** | ||
75 | * Operations involving this peer | ||
76 | */ | ||
77 | struct GNUNET_TESTBED_Operation *operation; | ||
78 | |||
79 | /** | ||
80 | * set to GNUNET_YES when peer is started | ||
81 | */ | ||
82 | int is_running; | ||
83 | }; | ||
84 | |||
85 | /** | ||
86 | * Our localhost | ||
87 | */ | ||
88 | static struct GNUNET_TESTBED_Host *host; | ||
89 | |||
90 | /** | ||
91 | * The controller process of one controller | ||
92 | */ | ||
93 | static struct GNUNET_TESTBED_ControllerProc *cp1; | ||
94 | |||
95 | /** | ||
96 | * A neighbouring host | ||
97 | */ | ||
98 | static struct GNUNET_TESTBED_Host *neighbour1; | ||
99 | |||
100 | /** | ||
101 | * Another neighbouring host | ||
102 | */ | ||
103 | static struct GNUNET_TESTBED_Host *neighbour2; | ||
104 | |||
105 | /** | ||
106 | * Handle for neighbour registration | ||
107 | */ | ||
108 | static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle; | ||
109 | |||
110 | /** | ||
111 | * The controller handle of one controller | ||
112 | */ | ||
113 | static struct GNUNET_TESTBED_Controller *controller1; | ||
114 | |||
115 | /** | ||
116 | * peer 1 | ||
117 | */ | ||
118 | static struct PeerContext peer1; | ||
119 | |||
120 | /** | ||
121 | * peer2 | ||
122 | */ | ||
123 | static struct PeerContext peer2; | ||
124 | |||
125 | /** | ||
126 | * peer3 | ||
127 | */ | ||
128 | static struct PeerContext peer3; | ||
129 | |||
130 | /** | ||
131 | * Handle to starting configuration | ||
132 | */ | ||
133 | static struct GNUNET_CONFIGURATION_Handle *cfg; | ||
134 | |||
135 | /** | ||
136 | * Handle to slave controller C's configuration, used to establish lateral link from | ||
137 | * master controller | ||
138 | */ | ||
139 | static struct GNUNET_CONFIGURATION_Handle *cfg2; | ||
140 | |||
141 | /** | ||
142 | * Handle to operations involving both peers | ||
143 | */ | ||
144 | static struct GNUNET_TESTBED_Operation *common_operation; | ||
145 | |||
146 | /** | ||
147 | * The handle for whether a host is habitable or not | ||
148 | */ | ||
149 | struct GNUNET_TESTBED_HostHabitableCheckHandle *hc_handle; | ||
150 | |||
151 | /** | ||
152 | * Abort task identifier | ||
153 | */ | ||
154 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
155 | |||
156 | /** | ||
157 | * Delayed connect job identifier | ||
158 | */ | ||
159 | static struct GNUNET_SCHEDULER_Task *delayed_connect_task; | ||
160 | |||
161 | /** | ||
162 | * Different stages in testing | ||
163 | */ | ||
164 | enum Stage | ||
165 | { | ||
166 | /** | ||
167 | * Initial stage | ||
168 | */ | ||
169 | INIT, | ||
170 | |||
171 | /** | ||
172 | * Controller 1 has started | ||
173 | */ | ||
174 | CONTROLLER1_UP, | ||
175 | |||
176 | /** | ||
177 | * peer1 is created | ||
178 | */ | ||
179 | PEER1_CREATED, | ||
180 | |||
181 | /** | ||
182 | * peer1 is started | ||
183 | */ | ||
184 | PEER1_STARTED, | ||
185 | |||
186 | /** | ||
187 | * Controller 2 has started | ||
188 | */ | ||
189 | CONTROLLER2_UP, | ||
190 | |||
191 | /** | ||
192 | * peer2 is created | ||
193 | */ | ||
194 | PEER2_CREATED, | ||
195 | |||
196 | /** | ||
197 | * peer2 is started | ||
198 | */ | ||
199 | PEER2_STARTED, | ||
200 | |||
201 | /** | ||
202 | * Controller 3 has started | ||
203 | */ | ||
204 | CONTROLLER3_UP, | ||
205 | |||
206 | /** | ||
207 | * Peer3 is created | ||
208 | */ | ||
209 | PEER3_CREATED, | ||
210 | |||
211 | /** | ||
212 | * Peer3 started | ||
213 | */ | ||
214 | PEER3_STARTED, | ||
215 | |||
216 | /** | ||
217 | * peer1 and peer2 are connected | ||
218 | */ | ||
219 | PEERS_1_2_CONNECTED, | ||
220 | |||
221 | /** | ||
222 | * peer2 and peer3 are connected | ||
223 | */ | ||
224 | PEERS_2_3_CONNECTED, | ||
225 | |||
226 | /** | ||
227 | * Peers are connected once again (this should not fail as they are already connected) | ||
228 | */ | ||
229 | PEERS_CONNECTED_2, | ||
230 | |||
231 | /** | ||
232 | * peers are stopped | ||
233 | */ | ||
234 | PEERS_STOPPED, | ||
235 | |||
236 | /** | ||
237 | * Final success stage | ||
238 | */ | ||
239 | SUCCESS, | ||
240 | |||
241 | /** | ||
242 | * Optional stage for marking test to be skipped | ||
243 | */ | ||
244 | SKIP | ||
245 | }; | ||
246 | |||
247 | /** | ||
248 | * The testing result | ||
249 | */ | ||
250 | static enum Stage result; | ||
251 | |||
252 | /** | ||
253 | * Shutdown nicely | ||
254 | * | ||
255 | * @param cls NULL | ||
256 | */ | ||
257 | static void | ||
258 | do_shutdown (void *cls) | ||
259 | { | ||
260 | if (NULL != abort_task) | ||
261 | GNUNET_SCHEDULER_cancel (abort_task); | ||
262 | if (NULL != hc_handle) | ||
263 | GNUNET_TESTBED_is_host_habitable_cancel (hc_handle); | ||
264 | GNUNET_assert (NULL == delayed_connect_task); | ||
265 | if (NULL != common_operation) | ||
266 | GNUNET_TESTBED_operation_done (common_operation); | ||
267 | if (NULL != reg_handle) | ||
268 | GNUNET_TESTBED_cancel_registration (reg_handle); | ||
269 | if (NULL != controller1) | ||
270 | GNUNET_TESTBED_controller_disconnect (controller1); | ||
271 | GNUNET_CONFIGURATION_destroy (cfg); | ||
272 | if (NULL != cfg2) | ||
273 | GNUNET_CONFIGURATION_destroy (cfg2); | ||
274 | if (NULL != cp1) | ||
275 | GNUNET_TESTBED_controller_stop (cp1); | ||
276 | if (NULL != host) | ||
277 | GNUNET_TESTBED_host_destroy (host); | ||
278 | if (NULL != neighbour1) | ||
279 | GNUNET_TESTBED_host_destroy (neighbour1); | ||
280 | if (NULL != neighbour2) | ||
281 | GNUNET_TESTBED_host_destroy (neighbour2); | ||
282 | } | ||
283 | |||
284 | |||
285 | /** | ||
286 | * abort task to run on test timed out | ||
287 | * | ||
288 | * @param cls NULL | ||
289 | */ | ||
290 | static void | ||
291 | do_abort (void *cls) | ||
292 | { | ||
293 | LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); | ||
294 | abort_task = NULL; | ||
295 | if (NULL != delayed_connect_task) | ||
296 | { | ||
297 | GNUNET_SCHEDULER_cancel (delayed_connect_task); | ||
298 | delayed_connect_task = NULL; | ||
299 | } | ||
300 | do_shutdown (cls); | ||
301 | } | ||
302 | |||
303 | |||
304 | static void | ||
305 | abort_test () | ||
306 | { | ||
307 | if (NULL != abort_task) | ||
308 | GNUNET_SCHEDULER_cancel (abort_task); | ||
309 | abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); | ||
310 | } | ||
311 | |||
312 | |||
313 | /** | ||
314 | * Callback to be called when an operation is completed | ||
315 | * | ||
316 | * @param cls the callback closure from functions generating an operation | ||
317 | * @param op the operation that has been finished | ||
318 | * @param emsg error message in case the operation has failed; will be NULL if | ||
319 | * operation has executed successfully. | ||
320 | */ | ||
321 | static void | ||
322 | op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg); | ||
323 | |||
324 | |||
325 | /** | ||
326 | * task for delaying a connect | ||
327 | * | ||
328 | * @param cls NULL | ||
329 | */ | ||
330 | static void | ||
331 | do_delayed_connect (void *cls) | ||
332 | { | ||
333 | delayed_connect_task = NULL; | ||
334 | if (NULL != common_operation) | ||
335 | { | ||
336 | GNUNET_break (0); | ||
337 | abort_test (); | ||
338 | return; | ||
339 | } | ||
340 | common_operation = | ||
341 | GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer1.peer, | ||
342 | peer2.peer); | ||
343 | } | ||
344 | |||
345 | |||
346 | /** | ||
347 | * Callback to be called when an operation is completed | ||
348 | * | ||
349 | * @param cls the callback closure from functions generating an operation | ||
350 | * @param op the operation that has been finished | ||
351 | * @param emsg error message in case the operation has failed; will be NULL if | ||
352 | * operation has executed successfully. | ||
353 | */ | ||
354 | static void | ||
355 | op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) | ||
356 | { | ||
357 | if (common_operation != op) | ||
358 | { | ||
359 | GNUNET_break (0); | ||
360 | abort_test (); | ||
361 | return; | ||
362 | } | ||
363 | |||
364 | switch (result) | ||
365 | { | ||
366 | case PEER3_STARTED: | ||
367 | case PEERS_2_3_CONNECTED: | ||
368 | case PEERS_1_2_CONNECTED: | ||
369 | break; | ||
370 | |||
371 | default: | ||
372 | GNUNET_break (0); | ||
373 | abort_test (); | ||
374 | return; | ||
375 | } | ||
376 | if ((NULL != peer1.operation) || (NULL != peer2.operation) || | ||
377 | (NULL != peer3.operation)) | ||
378 | { | ||
379 | GNUNET_break (0); | ||
380 | abort_test (); | ||
381 | return; | ||
382 | } | ||
383 | } | ||
384 | |||
385 | |||
386 | /** | ||
387 | * Functions of this signature are called when a peer has been successfully | ||
388 | * created | ||
389 | * | ||
390 | * @param cls NULL | ||
391 | * @param peer the handle for the created peer; NULL on any error during | ||
392 | * creation | ||
393 | * @param emsg NULL if peer is not NULL; else MAY contain the error description | ||
394 | */ | ||
395 | static void | ||
396 | peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) | ||
397 | { | ||
398 | switch (result) | ||
399 | { | ||
400 | case CONTROLLER1_UP: | ||
401 | if ((NULL == peer1.operation) || (NULL == peer) || (NULL != peer1.peer)) | ||
402 | { | ||
403 | GNUNET_break (0); | ||
404 | abort_test (); | ||
405 | return; | ||
406 | } | ||
407 | peer1.peer = peer; | ||
408 | GNUNET_TESTBED_operation_done (peer1.operation); | ||
409 | result = PEER1_CREATED; | ||
410 | peer1.operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL); | ||
411 | break; | ||
412 | |||
413 | case CONTROLLER2_UP: | ||
414 | if ((NULL == peer2.operation) || (NULL == peer) || (NULL != peer2.peer)) | ||
415 | { | ||
416 | GNUNET_break (0); | ||
417 | abort_test (); | ||
418 | return; | ||
419 | } | ||
420 | peer2.peer = peer; | ||
421 | GNUNET_TESTBED_operation_done (peer2.operation); | ||
422 | result = PEER2_CREATED; | ||
423 | peer2.operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL); | ||
424 | break; | ||
425 | |||
426 | case CONTROLLER3_UP: | ||
427 | if ((NULL == peer3.operation) || (NULL == peer) || (NULL != peer3.peer)) | ||
428 | { | ||
429 | GNUNET_break (0); | ||
430 | abort_test (); | ||
431 | return; | ||
432 | } | ||
433 | peer3.peer = peer; | ||
434 | GNUNET_TESTBED_operation_done (peer3.operation); | ||
435 | result = PEER3_CREATED; | ||
436 | peer3.operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL); | ||
437 | break; | ||
438 | |||
439 | default: | ||
440 | GNUNET_break (0); | ||
441 | abort_test (); | ||
442 | return; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | |||
447 | /** | ||
448 | * Signature of the event handler function called by the | ||
449 | * respective event controller. | ||
450 | * | ||
451 | * @param cls closure | ||
452 | * @param event information about the event | ||
453 | */ | ||
454 | static void | ||
455 | controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) | ||
456 | { | ||
457 | switch (event->type) | ||
458 | { | ||
459 | case GNUNET_TESTBED_ET_OPERATION_FINISHED: | ||
460 | if ((NULL != event->op_cls) || | ||
461 | (NULL != event->details.operation_finished.emsg)) | ||
462 | { | ||
463 | GNUNET_break (0); | ||
464 | abort_test (); | ||
465 | return; | ||
466 | } | ||
467 | switch (result) | ||
468 | { | ||
469 | case PEERS_STOPPED: | ||
470 | if (NULL != event->details.operation_finished.generic) | ||
471 | { | ||
472 | GNUNET_break (0); | ||
473 | abort_test (); | ||
474 | return; | ||
475 | } | ||
476 | if (event->op == peer1.operation) | ||
477 | { | ||
478 | GNUNET_TESTBED_operation_done (peer1.operation); | ||
479 | peer1.operation = NULL; | ||
480 | peer1.peer = NULL; | ||
481 | } | ||
482 | else if (event->op == peer2.operation) | ||
483 | { | ||
484 | GNUNET_TESTBED_operation_done (peer2.operation); | ||
485 | peer2.operation = NULL; | ||
486 | peer2.peer = NULL; | ||
487 | } | ||
488 | else if (event->op == peer3.operation) | ||
489 | { | ||
490 | GNUNET_TESTBED_operation_done (peer3.operation); | ||
491 | peer3.operation = NULL; | ||
492 | peer3.peer = NULL; | ||
493 | } | ||
494 | else | ||
495 | { | ||
496 | GNUNET_break (0); | ||
497 | abort_test (); | ||
498 | return; | ||
499 | } | ||
500 | if ((NULL == peer1.peer) && (NULL == peer2.peer) && (NULL == peer3.peer)) | ||
501 | { | ||
502 | result = SUCCESS; | ||
503 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
504 | } | ||
505 | break; | ||
506 | |||
507 | case PEER1_STARTED: | ||
508 | if ((NULL != event->details.operation_finished.generic) || | ||
509 | (NULL == common_operation)) | ||
510 | { | ||
511 | GNUNET_break (0); | ||
512 | abort_test (); | ||
513 | return; | ||
514 | } | ||
515 | GNUNET_TESTBED_operation_done (common_operation); | ||
516 | common_operation = NULL; | ||
517 | result = CONTROLLER2_UP; | ||
518 | peer2.operation = | ||
519 | GNUNET_TESTBED_peer_create (controller1, neighbour1, cfg, | ||
520 | &peer_create_cb, NULL); | ||
521 | if (NULL == peer2.operation) | ||
522 | { | ||
523 | GNUNET_break (0); | ||
524 | abort_test (); | ||
525 | return; | ||
526 | } | ||
527 | break; | ||
528 | |||
529 | case PEER2_STARTED: | ||
530 | if ((NULL != event->details.operation_finished.generic) || | ||
531 | (NULL == common_operation)) | ||
532 | { | ||
533 | GNUNET_break (0); | ||
534 | abort_test (); | ||
535 | return; | ||
536 | } | ||
537 | GNUNET_TESTBED_operation_done (common_operation); | ||
538 | common_operation = NULL; | ||
539 | result = CONTROLLER3_UP; | ||
540 | peer3.operation = | ||
541 | GNUNET_TESTBED_peer_create (controller1, neighbour2, cfg, | ||
542 | &peer_create_cb, NULL); | ||
543 | if (NULL == peer3.operation) | ||
544 | { | ||
545 | GNUNET_break (0); | ||
546 | abort_test (); | ||
547 | return; | ||
548 | } | ||
549 | break; | ||
550 | |||
551 | default: | ||
552 | GNUNET_break (0); | ||
553 | abort_test (); | ||
554 | return; | ||
555 | } | ||
556 | break; | ||
557 | |||
558 | case GNUNET_TESTBED_ET_PEER_START: | ||
559 | switch (result) | ||
560 | { | ||
561 | case PEER1_CREATED: | ||
562 | if (event->details.peer_start.host != host) | ||
563 | { | ||
564 | GNUNET_break (0); | ||
565 | abort_test (); | ||
566 | return; | ||
567 | } | ||
568 | peer1.is_running = GNUNET_YES; | ||
569 | GNUNET_TESTBED_operation_done (peer1.operation); | ||
570 | peer1.operation = NULL; | ||
571 | result = PEER1_STARTED; | ||
572 | common_operation = | ||
573 | GNUNET_TESTBED_controller_link (NULL, controller1, neighbour1, NULL, | ||
574 | GNUNET_YES); | ||
575 | break; | ||
576 | |||
577 | case PEER2_CREATED: | ||
578 | if (event->details.peer_start.host != neighbour1) | ||
579 | { | ||
580 | GNUNET_break (0); | ||
581 | abort_test (); | ||
582 | return; | ||
583 | } | ||
584 | peer2.is_running = GNUNET_YES; | ||
585 | GNUNET_TESTBED_operation_done (peer2.operation); | ||
586 | peer2.operation = NULL; | ||
587 | result = PEER2_STARTED; | ||
588 | if (NULL != common_operation) | ||
589 | { | ||
590 | GNUNET_break (0); | ||
591 | abort_test (); | ||
592 | return; | ||
593 | } | ||
594 | common_operation = | ||
595 | GNUNET_TESTBED_controller_link (NULL, controller1, neighbour2, NULL, | ||
596 | GNUNET_YES); | ||
597 | if (NULL == common_operation) | ||
598 | { | ||
599 | GNUNET_break (0); | ||
600 | abort_test (); | ||
601 | return; | ||
602 | } | ||
603 | break; | ||
604 | |||
605 | case PEER3_CREATED: | ||
606 | if (event->details.peer_start.host != neighbour2) | ||
607 | { | ||
608 | GNUNET_break (0); | ||
609 | abort_test (); | ||
610 | return; | ||
611 | } | ||
612 | peer3.is_running = GNUNET_YES; | ||
613 | GNUNET_TESTBED_operation_done (peer3.operation); | ||
614 | peer3.operation = NULL; | ||
615 | result = PEER3_STARTED; | ||
616 | common_operation = | ||
617 | GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer2.peer, | ||
618 | peer1.peer); | ||
619 | break; | ||
620 | |||
621 | default: | ||
622 | GNUNET_break (0); | ||
623 | abort_test (); | ||
624 | return; | ||
625 | } | ||
626 | break; | ||
627 | |||
628 | case GNUNET_TESTBED_ET_PEER_STOP: | ||
629 | if (PEERS_CONNECTED_2 != result) | ||
630 | { | ||
631 | GNUNET_break (0); | ||
632 | abort_test (); | ||
633 | return; | ||
634 | } | ||
635 | if (event->details.peer_stop.peer == peer1.peer) | ||
636 | { | ||
637 | peer1.is_running = GNUNET_NO; | ||
638 | GNUNET_TESTBED_operation_done (peer1.operation); | ||
639 | } | ||
640 | else if (event->details.peer_stop.peer == peer2.peer) | ||
641 | { | ||
642 | peer2.is_running = GNUNET_NO; | ||
643 | GNUNET_TESTBED_operation_done (peer2.operation); | ||
644 | } | ||
645 | else if (event->details.peer_stop.peer == peer3.peer) | ||
646 | { | ||
647 | peer3.is_running = GNUNET_NO; | ||
648 | GNUNET_TESTBED_operation_done (peer3.operation); | ||
649 | } | ||
650 | else | ||
651 | { | ||
652 | GNUNET_break (0); | ||
653 | abort_test (); | ||
654 | return; | ||
655 | } | ||
656 | if ((GNUNET_NO == peer1.is_running) && (GNUNET_NO == peer2.is_running) && | ||
657 | (GNUNET_NO == peer3.is_running)) | ||
658 | { | ||
659 | result = PEERS_STOPPED; | ||
660 | peer1.operation = GNUNET_TESTBED_peer_destroy (peer1.peer); | ||
661 | peer2.operation = GNUNET_TESTBED_peer_destroy (peer2.peer); | ||
662 | peer3.operation = GNUNET_TESTBED_peer_destroy (peer3.peer); | ||
663 | } | ||
664 | break; | ||
665 | |||
666 | case GNUNET_TESTBED_ET_CONNECT: | ||
667 | if ((NULL != peer1.operation) || (NULL != peer2.operation) || | ||
668 | (NULL != peer3.operation) || (NULL == common_operation)) | ||
669 | { | ||
670 | GNUNET_break (0); | ||
671 | abort_test (); | ||
672 | return; | ||
673 | } | ||
674 | switch (result) | ||
675 | { | ||
676 | case PEER3_STARTED: | ||
677 | if ((event->details.peer_connect.peer1 != peer2.peer) || | ||
678 | (event->details.peer_connect.peer2 != peer1.peer)) | ||
679 | { | ||
680 | GNUNET_break (0); | ||
681 | abort_test (); | ||
682 | return; | ||
683 | } | ||
684 | GNUNET_TESTBED_operation_done (common_operation); | ||
685 | common_operation = NULL; | ||
686 | result = PEERS_1_2_CONNECTED; | ||
687 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected\n"); | ||
688 | common_operation = | ||
689 | GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer2.peer, | ||
690 | peer3.peer); | ||
691 | break; | ||
692 | |||
693 | case PEERS_1_2_CONNECTED: | ||
694 | if ((event->details.peer_connect.peer1 != peer2.peer) || | ||
695 | (event->details.peer_connect.peer2 != peer3.peer)) | ||
696 | { | ||
697 | GNUNET_break (0); | ||
698 | abort_test (); | ||
699 | return; | ||
700 | } | ||
701 | GNUNET_TESTBED_operation_done (common_operation); | ||
702 | common_operation = NULL; | ||
703 | result = PEERS_2_3_CONNECTED; | ||
704 | delayed_connect_task = | ||
705 | GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (3), &do_delayed_connect, | ||
706 | NULL); | ||
707 | break; | ||
708 | |||
709 | case PEERS_2_3_CONNECTED: | ||
710 | if ((event->details.peer_connect.peer1 != peer1.peer) || | ||
711 | (event->details.peer_connect.peer2 != peer2.peer)) | ||
712 | { | ||
713 | GNUNET_break (0); | ||
714 | abort_test (); | ||
715 | return; | ||
716 | } | ||
717 | GNUNET_TESTBED_operation_done (common_operation); | ||
718 | common_operation = NULL; | ||
719 | result = PEERS_CONNECTED_2; | ||
720 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected again\n"); | ||
721 | peer1.operation = GNUNET_TESTBED_peer_stop (NULL, peer1.peer, NULL, NULL); | ||
722 | peer2.operation = GNUNET_TESTBED_peer_stop (NULL, peer2.peer, NULL, NULL); | ||
723 | peer3.operation = GNUNET_TESTBED_peer_stop (NULL, peer3.peer, NULL, NULL); | ||
724 | break; | ||
725 | |||
726 | default: | ||
727 | GNUNET_break (0); | ||
728 | abort_test (); | ||
729 | return; | ||
730 | } | ||
731 | break; | ||
732 | |||
733 | default: | ||
734 | GNUNET_break (0); | ||
735 | abort_test (); | ||
736 | return; | ||
737 | } | ||
738 | } | ||
739 | |||
740 | |||
741 | /** | ||
742 | * Callback which will be called to after a host registration succeeded or failed | ||
743 | * | ||
744 | * @param cls the host which has been registered | ||
745 | * @param emsg the error message; NULL if host registration is successful | ||
746 | */ | ||
747 | static void | ||
748 | registration_comp (void *cls, const char *emsg) | ||
749 | { | ||
750 | reg_handle = NULL; | ||
751 | if (cls == neighbour1) | ||
752 | { | ||
753 | neighbour2 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, cfg, 0); | ||
754 | if (NULL == neighbour2) | ||
755 | { | ||
756 | GNUNET_break (0); | ||
757 | abort_test (); | ||
758 | return; | ||
759 | } | ||
760 | reg_handle = | ||
761 | GNUNET_TESTBED_register_host (controller1, neighbour2, | ||
762 | ®istration_comp, neighbour2); | ||
763 | if (NULL == reg_handle) | ||
764 | { | ||
765 | GNUNET_break (0); | ||
766 | abort_test (); | ||
767 | return; | ||
768 | } | ||
769 | return; | ||
770 | } | ||
771 | if (cls != neighbour2) | ||
772 | { | ||
773 | GNUNET_break (0); | ||
774 | abort_test (); | ||
775 | return; | ||
776 | } | ||
777 | peer1.operation = | ||
778 | GNUNET_TESTBED_peer_create (controller1, host, cfg, &peer_create_cb, | ||
779 | &peer1); | ||
780 | if (NULL == peer1.operation) | ||
781 | { | ||
782 | GNUNET_break (0); | ||
783 | abort_test (); | ||
784 | return; | ||
785 | } | ||
786 | } | ||
787 | |||
788 | |||
789 | /** | ||
790 | * Callback to signal successful startup of the controller process | ||
791 | * | ||
792 | * @param cls the closure from GNUNET_TESTBED_controller_start() | ||
793 | * @param cfg the configuration with which the controller has been started; | ||
794 | * NULL if status is not GNUNET_OK | ||
795 | * @param status GNUNET_OK if the startup is successful; GNUNET_SYSERR if not, | ||
796 | * GNUNET_TESTBED_controller_stop() shouldn't be called in this case | ||
797 | */ | ||
798 | static void | ||
799 | status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, | ||
800 | int status) | ||
801 | { | ||
802 | uint64_t event_mask; | ||
803 | |||
804 | if (GNUNET_OK != status) | ||
805 | { | ||
806 | GNUNET_break (0); | ||
807 | cp1 = NULL; | ||
808 | abort_test (); | ||
809 | return; | ||
810 | } | ||
811 | event_mask = 0; | ||
812 | event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START); | ||
813 | event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP); | ||
814 | event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); | ||
815 | event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
816 | switch (result) | ||
817 | { | ||
818 | case INIT: | ||
819 | controller1 = | ||
820 | GNUNET_TESTBED_controller_connect (host, event_mask, | ||
821 | &controller_cb, NULL); | ||
822 | if (NULL == controller1) | ||
823 | { | ||
824 | GNUNET_break (0); | ||
825 | abort_test (); | ||
826 | return; | ||
827 | } | ||
828 | result = CONTROLLER1_UP; | ||
829 | neighbour1 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, cfg, 0); | ||
830 | if (NULL == neighbour1) | ||
831 | { | ||
832 | GNUNET_break (0); | ||
833 | abort_test (); | ||
834 | return; | ||
835 | } | ||
836 | reg_handle = | ||
837 | GNUNET_TESTBED_register_host (controller1, neighbour1, | ||
838 | ®istration_comp, neighbour1); | ||
839 | if (NULL == reg_handle) | ||
840 | { | ||
841 | GNUNET_break (0); | ||
842 | abort_test (); | ||
843 | return; | ||
844 | } | ||
845 | break; | ||
846 | |||
847 | default: | ||
848 | GNUNET_break (0); | ||
849 | abort_test (); | ||
850 | return; | ||
851 | } | ||
852 | } | ||
853 | |||
854 | |||
855 | /** | ||
856 | * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to | ||
857 | * inform whether the given host is habitable or not. The Handle returned by | ||
858 | * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called | ||
859 | * | ||
860 | * @param cls NULL | ||
861 | * @param host the host whose status is being reported; will be NULL if the host | ||
862 | * given to GNUNET_TESTBED_is_host_habitable() is NULL | ||
863 | * @param status #GNUNET_YES if it is habitable; #GNUNET_NO if not | ||
864 | */ | ||
865 | static void | ||
866 | host_habitable_cb (void *cls, | ||
867 | const struct GNUNET_TESTBED_Host *_host, | ||
868 | int status) | ||
869 | { | ||
870 | hc_handle = NULL; | ||
871 | if (GNUNET_NO == status) | ||
872 | { | ||
873 | (void) printf ("%s", | ||
874 | "Unable to run the test as this system is not configured " | ||
875 | "to use password less SSH logins to localhost.\n" | ||
876 | "Skipping test\n"); | ||
877 | GNUNET_SCHEDULER_cancel (abort_task); | ||
878 | abort_task = NULL; | ||
879 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
880 | result = SKIP; | ||
881 | return; | ||
882 | } | ||
883 | cp1 = | ||
884 | GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb, NULL); | ||
885 | } | ||
886 | |||
887 | |||
888 | /** | ||
889 | * Main run function. | ||
890 | * | ||
891 | * @param cls NULL | ||
892 | * @param args arguments passed to GNUNET_PROGRAM_run | ||
893 | * @param cfgfile the path to configuration file | ||
894 | * @param cfg the configuration file handle | ||
895 | */ | ||
896 | static void | ||
897 | run (void *cls, char *const *args, const char *cfgfile, | ||
898 | const struct GNUNET_CONFIGURATION_Handle *config) | ||
899 | { | ||
900 | cfg = GNUNET_CONFIGURATION_dup (config); | ||
901 | host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); | ||
902 | if (NULL == host) | ||
903 | { | ||
904 | GNUNET_break (0); | ||
905 | abort_test (); | ||
906 | return; | ||
907 | } | ||
908 | if (NULL == | ||
909 | (hc_handle = | ||
910 | GNUNET_TESTBED_is_host_habitable (host, config, &host_habitable_cb, | ||
911 | NULL))) | ||
912 | { | ||
913 | GNUNET_TESTBED_host_destroy (host); | ||
914 | host = NULL; | ||
915 | (void) printf ("%s", | ||
916 | "Unable to run the test as this system is not configured " | ||
917 | "to use password less SSH logins to localhost.\n" | ||
918 | "Skipping test\n"); | ||
919 | result = SKIP; | ||
920 | return; | ||
921 | } | ||
922 | abort_task = | ||
923 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
924 | (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort, | ||
925 | NULL); | ||
926 | } | ||
927 | |||
928 | |||
929 | /** | ||
930 | * Main function | ||
931 | */ | ||
932 | int | ||
933 | main (int argc, char **argv) | ||
934 | { | ||
935 | char *const argv2[] = { "test_testbed_api_3peers_3controllers", | ||
936 | "-c", "test_testbed_api.conf", | ||
937 | NULL }; | ||
938 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
939 | GNUNET_GETOPT_OPTION_END | ||
940 | }; | ||
941 | int ret; | ||
942 | |||
943 | result = INIT; | ||
944 | ret = | ||
945 | GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, | ||
946 | "test_testbed_api_3peers_3controllers", "nohelp", | ||
947 | options, &run, NULL); | ||
948 | if (GNUNET_OK != ret) | ||
949 | return 1; | ||
950 | switch (result) | ||
951 | { | ||
952 | case SUCCESS: | ||
953 | return 0; | ||
954 | |||
955 | case SKIP: | ||
956 | return 77; /* Mark test as skipped */ | ||
957 | |||
958 | default: | ||
959 | return 1; | ||
960 | } | ||
961 | } | ||
962 | |||
963 | |||
964 | /* end of test_testbed_api_3peers_3controllers.c */ | ||
diff --git a/src/testbed/test_testbed_api_barriers.c b/src/testbed/test_testbed_api_barriers.c deleted file mode 100644 index 74dd89126..000000000 --- a/src/testbed/test_testbed_api_barriers.c +++ /dev/null | |||
@@ -1,234 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/test_testbed_api_barriers.c | ||
23 | * @brief testcase binary for testing testbed barriers API | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | #include "test_testbed_api_barriers.h" | ||
31 | |||
32 | |||
33 | /** | ||
34 | * logging short hand | ||
35 | */ | ||
36 | #define LOG(type, ...) \ | ||
37 | GNUNET_log (type, __VA_ARGS__); | ||
38 | |||
39 | /** | ||
40 | * Number of peers we start in this test case | ||
41 | */ | ||
42 | #define NUM_PEERS 3 | ||
43 | |||
44 | |||
45 | /** | ||
46 | * Our barrier | ||
47 | */ | ||
48 | struct GNUNET_TESTBED_Barrier *barrier; | ||
49 | |||
50 | /** | ||
51 | * Identifier for the shutdown task | ||
52 | */ | ||
53 | static struct GNUNET_SCHEDULER_Task *timeout_task; | ||
54 | |||
55 | /** | ||
56 | * Result of this test case | ||
57 | */ | ||
58 | static int result; | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Handle SIGINT and SIGTERM | ||
63 | */ | ||
64 | static void | ||
65 | shutdown_handler (void *cls) | ||
66 | { | ||
67 | if (NULL != timeout_task) | ||
68 | { | ||
69 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
70 | timeout_task = NULL; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | |||
75 | /** | ||
76 | * Shutdown this test case when it takes too long | ||
77 | * | ||
78 | * @param cls NULL | ||
79 | */ | ||
80 | static void | ||
81 | do_timeout (void *cls) | ||
82 | { | ||
83 | timeout_task = NULL; | ||
84 | if (barrier != NULL) | ||
85 | GNUNET_TESTBED_barrier_cancel (barrier); | ||
86 | GNUNET_SCHEDULER_shutdown (); | ||
87 | } | ||
88 | |||
89 | |||
90 | /** | ||
91 | * Functions of this type are to be given as callback argument to | ||
92 | * GNUNET_TESTBED_barrier_init(). The callback will be called when status | ||
93 | * information is available for the barrier. | ||
94 | * | ||
95 | * @param cls the closure given to GNUNET_TESTBED_barrier_init() | ||
96 | * @param name the name of the barrier | ||
97 | * @param barrier the barrier handle | ||
98 | * @param status status of the barrier; #GNUNET_OK if the barrier is crossed; | ||
99 | * #GNUNET_SYSERR upon error | ||
100 | * @param emsg if the status were to be #GNUNET_SYSERR, this parameter has the | ||
101 | * error message | ||
102 | */ | ||
103 | static void | ||
104 | barrier_cb (void *cls, | ||
105 | const char *name, | ||
106 | struct GNUNET_TESTBED_Barrier *_barrier, | ||
107 | enum GNUNET_TESTBED_BarrierStatus status, | ||
108 | const char *emsg) | ||
109 | { | ||
110 | static enum GNUNET_TESTBED_BarrierStatus old_status; | ||
111 | |||
112 | GNUNET_assert (NULL == cls); | ||
113 | GNUNET_assert (_barrier == barrier); | ||
114 | switch (status) | ||
115 | { | ||
116 | case GNUNET_TESTBED_BARRIERSTATUS_INITIALISED: | ||
117 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
118 | "Barrier initialised\n"); | ||
119 | old_status = status; | ||
120 | return; | ||
121 | |||
122 | case GNUNET_TESTBED_BARRIERSTATUS_ERROR: | ||
123 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
124 | "Barrier initialisation failed: %s", | ||
125 | (NULL == emsg) ? "unknown reason" : emsg); | ||
126 | break; | ||
127 | |||
128 | case GNUNET_TESTBED_BARRIERSTATUS_CROSSED: | ||
129 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
130 | "Barrier crossed\n"); | ||
131 | if (old_status == GNUNET_TESTBED_BARRIERSTATUS_INITIALISED) | ||
132 | result = GNUNET_OK; | ||
133 | break; | ||
134 | |||
135 | default: | ||
136 | GNUNET_assert (0); | ||
137 | return; | ||
138 | } | ||
139 | barrier = NULL; | ||
140 | GNUNET_SCHEDULER_shutdown (); | ||
141 | } | ||
142 | |||
143 | |||
144 | /** | ||
145 | * Signature of a main function for a testcase. | ||
146 | * | ||
147 | * @param cls closure | ||
148 | * @param h the run handle | ||
149 | * @param num_peers number of peers in 'peers' | ||
150 | * @param peers_ handle to peers run in the testbed | ||
151 | * @param links_succeeded the number of overlay link connection attempts that | ||
152 | * succeeded | ||
153 | * @param links_failed the number of overlay link connection attempts that | ||
154 | * failed | ||
155 | */ | ||
156 | static void | ||
157 | test_master (void *cls, | ||
158 | struct GNUNET_TESTBED_RunHandle *h, | ||
159 | unsigned int num_peers, | ||
160 | struct GNUNET_TESTBED_Peer **peers_, | ||
161 | unsigned int links_succeeded, | ||
162 | unsigned int links_failed) | ||
163 | { | ||
164 | struct GNUNET_TESTBED_Controller *c; | ||
165 | |||
166 | GNUNET_assert (NULL == cls); | ||
167 | if (NULL == peers_) | ||
168 | { | ||
169 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
170 | "Failing test due to timeout\n"); | ||
171 | return; | ||
172 | } | ||
173 | GNUNET_assert (NUM_PEERS == num_peers); | ||
174 | c = GNUNET_TESTBED_run_get_controller_handle (h); | ||
175 | barrier = GNUNET_TESTBED_barrier_init (c, | ||
176 | TEST_BARRIER_NAME, | ||
177 | 100, | ||
178 | &barrier_cb, | ||
179 | NULL); | ||
180 | timeout_task = | ||
181 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
182 | (GNUNET_TIME_UNIT_SECONDS, | ||
183 | 10 * (NUM_PEERS + 1)), | ||
184 | &do_timeout, NULL); | ||
185 | GNUNET_SCHEDULER_add_shutdown (&shutdown_handler, NULL); | ||
186 | } | ||
187 | |||
188 | |||
189 | #ifndef PATH_MAX | ||
190 | /** | ||
191 | * Assumed maximum path length (for the log file name). | ||
192 | */ | ||
193 | #define PATH_MAX 4096 | ||
194 | #endif | ||
195 | |||
196 | |||
197 | /** | ||
198 | * Main function | ||
199 | */ | ||
200 | int | ||
201 | main (int argc, char **argv) | ||
202 | { | ||
203 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
204 | char pwd[PATH_MAX]; | ||
205 | char *binary; | ||
206 | uint64_t event_mask; | ||
207 | |||
208 | result = GNUNET_SYSERR; | ||
209 | event_mask = 0; | ||
210 | cfg = GNUNET_CONFIGURATION_create (); | ||
211 | GNUNET_assert (GNUNET_YES == | ||
212 | GNUNET_CONFIGURATION_parse (cfg, | ||
213 | "test_testbed_api_barriers.conf.in")); | ||
214 | if (NULL == getcwd (pwd, PATH_MAX)) | ||
215 | return 1; | ||
216 | GNUNET_assert (0 < GNUNET_asprintf (&binary, "%s/%s", pwd, | ||
217 | "gnunet-service-test-barriers")); | ||
218 | GNUNET_CONFIGURATION_set_value_string (cfg, "test-barriers", "BINARY", | ||
219 | binary); | ||
220 | GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_write | ||
221 | (cfg, "test_testbed_api_barriers.conf")); | ||
222 | GNUNET_CONFIGURATION_destroy (cfg); | ||
223 | cfg = NULL; | ||
224 | GNUNET_free (binary); | ||
225 | binary = NULL; | ||
226 | (void) GNUNET_TESTBED_test_run ("test_testbed_api_barriers", | ||
227 | "test_testbed_api_barriers.conf", NUM_PEERS, | ||
228 | event_mask, NULL, NULL, | ||
229 | &test_master, NULL); | ||
230 | (void) unlink ("test_testbed_api_barriers.conf"); | ||
231 | if (GNUNET_OK != result) | ||
232 | return 1; | ||
233 | return 0; | ||
234 | } | ||
diff --git a/src/testbed/test_testbed_api_barriers.conf.in b/src/testbed/test_testbed_api_barriers.conf.in deleted file mode 100644 index 2e9c0038d..000000000 --- a/src/testbed/test_testbed_api_barriers.conf.in +++ /dev/null | |||
@@ -1,103 +0,0 @@ | |||
1 | [testbed] | ||
2 | START_ON_DEMAND = NO | ||
3 | PORT = 12113 | ||
4 | ACCEPT_FROM = 127.0.0.1; | ||
5 | HOSTNAME = localhost | ||
6 | TOPOLOGY = RANDOM | ||
7 | #PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args | ||
8 | |||
9 | [arm] | ||
10 | PORT = 12366 | ||
11 | |||
12 | [test-barriers] | ||
13 | START_ON_DEMAND = NO | ||
14 | PORT = 12114 | ||
15 | BINARY = /will/be/overwritten/in/test_testbed_api_barriers/ | ||
16 | IMMEDIATE_START = YES | ||
17 | |||
18 | [fs] | ||
19 | START_ON_DEMAND = NO | ||
20 | IMMEDIATE_START = NO | ||
21 | |||
22 | [resolver] | ||
23 | HOSTNAME = localhost | ||
24 | START_ON_DEMAND = NO | ||
25 | |||
26 | [cadet] | ||
27 | START_ON_DEMAND = NO | ||
28 | IMMEDIATE_START = NO | ||
29 | |||
30 | [dht] | ||
31 | START_ON_DEMAND = NO | ||
32 | IMMEDIATE_START = NO | ||
33 | |||
34 | [dhtcache] | ||
35 | QUOTA = 1 MB | ||
36 | DATABASE = heap | ||
37 | |||
38 | [transport] | ||
39 | PLUGINS = udp | ||
40 | ACCEPT_FROM6 = ::1; | ||
41 | ACCEPT_FROM = 127.0.0.1; | ||
42 | NEIGHBOUR_LIMIT = 50 | ||
43 | PORT = 12365 | ||
44 | IMMEDIATE_START = YES | ||
45 | |||
46 | [ats] | ||
47 | WAN_QUOTA_OUT = 3932160 | ||
48 | WAN_QUOTA_IN = 3932160 | ||
49 | |||
50 | [core] | ||
51 | PORT = 12092 | ||
52 | START_ON_DEMAND = YES | ||
53 | IMMEDIATE_START = YES | ||
54 | USE_EPHEMERAL_KEYS = NO | ||
55 | |||
56 | [transport-udp] | ||
57 | TIMEOUT = 300 s | ||
58 | PORT = 12368 | ||
59 | |||
60 | [PATHS] | ||
61 | GNUNET_TEST_HOME = $GNUNET_TMP/test-testbed/ | ||
62 | |||
63 | [dns] | ||
64 | START_ON_DEMAND = NO | ||
65 | IMMEDIATE_START = NO | ||
66 | |||
67 | [nse] | ||
68 | START_ON_DEMAND = NO | ||
69 | IMMEDIATE_START = NO | ||
70 | |||
71 | [vpn] | ||
72 | START_ON_DEMAND = NO | ||
73 | IMMEDIATE_START = NO | ||
74 | |||
75 | [nat] | ||
76 | RETURN_LOCAL_ADDRESSES = YES | ||
77 | IMMEDIATE_START = NO | ||
78 | |||
79 | [gns-helper-service-w32] | ||
80 | START_ON_DEMAND = NO | ||
81 | |||
82 | [consensus] | ||
83 | START_ON_DEMAND = NO | ||
84 | IMMEDIATE_START = NO | ||
85 | |||
86 | [gns] | ||
87 | START_ON_DEMAND = NO | ||
88 | IMMEDIATE_START = NO | ||
89 | |||
90 | [statistics] | ||
91 | START_ON_DEMAND = NO | ||
92 | IMMEDIATE_START = NO | ||
93 | |||
94 | [peerinfo] | ||
95 | NO_IO = YES | ||
96 | |||
97 | [set] | ||
98 | START_ON_DEMAND = NO | ||
99 | IMMEDIATE_START = NO | ||
100 | |||
101 | [revocation] | ||
102 | START_ON_DEMAND = NO | ||
103 | IMMEDIATE_START = NO | ||
diff --git a/src/testbed/test_testbed_api_barriers.h b/src/testbed/test_testbed_api_barriers.h deleted file mode 100644 index c0a34472d..000000000 --- a/src/testbed/test_testbed_api_barriers.h +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | /** | ||
2 | * The name to use for the barrier in the test cases | ||
3 | */ | ||
4 | #define TEST_BARRIER_NAME "test_barrier" | ||
diff --git a/src/testbed/test_testbed_api_controllerlink.c b/src/testbed/test_testbed_api_controllerlink.c deleted file mode 100644 index 0ec9d63e1..000000000 --- a/src/testbed/test_testbed_api_controllerlink.c +++ /dev/null | |||
@@ -1,881 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/test_testbed_api_controllerlink.c | ||
23 | * @brief testcase for testing controller to subcontroller linking | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | |||
28 | /** | ||
29 | * The controller architecture we try to achieve in this test case: | ||
30 | * | ||
31 | * Master Controller | ||
32 | * // \\ | ||
33 | * // \\ | ||
34 | * Slave Controller 1---------Slave Controller 3 | ||
35 | * || | ||
36 | * || | ||
37 | * Slave Controller 2 | ||
38 | */ | ||
39 | |||
40 | #include "platform.h" | ||
41 | #include "gnunet_util_lib.h" | ||
42 | #include "gnunet_testing_lib.h" | ||
43 | #include "gnunet_testbed_service.h" | ||
44 | |||
45 | /** | ||
46 | * Generic logging shortcut | ||
47 | */ | ||
48 | #define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__) | ||
49 | |||
50 | /** | ||
51 | * Debug logging shorthand | ||
52 | */ | ||
53 | #define LOG_DEBUG(...) LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) | ||
54 | |||
55 | /** | ||
56 | * Different stages in testing | ||
57 | */ | ||
58 | enum Stage | ||
59 | { | ||
60 | /** | ||
61 | * Initial stage | ||
62 | */ | ||
63 | INIT, | ||
64 | |||
65 | /** | ||
66 | * Master controller has started | ||
67 | */ | ||
68 | MASTER_STARTED, | ||
69 | |||
70 | /** | ||
71 | * A peer has been created on master | ||
72 | */ | ||
73 | MASTER_PEER_CREATE_SUCCESS, | ||
74 | |||
75 | /** | ||
76 | * Peer on master controller has been started successfully. | ||
77 | */ | ||
78 | MASTER_PEER_START_SUCCESS, | ||
79 | |||
80 | /** | ||
81 | * The first slave has been registered at master controller | ||
82 | */ | ||
83 | SLAVE1_REGISTERED, | ||
84 | |||
85 | /** | ||
86 | * The second slave has been registered at the master controller | ||
87 | */ | ||
88 | SLAVE2_REGISTERED, | ||
89 | |||
90 | /** | ||
91 | * Link from master to slave 1 has been successfully created | ||
92 | */ | ||
93 | SLAVE1_LINK_SUCCESS, | ||
94 | |||
95 | /** | ||
96 | * Peer create on slave 1 successful | ||
97 | */ | ||
98 | SLAVE1_PEER_CREATE_SUCCESS, | ||
99 | |||
100 | /** | ||
101 | * Peer startup on slave 1 successful | ||
102 | */ | ||
103 | SLAVE1_PEER_START_SUCCESS, | ||
104 | |||
105 | /** | ||
106 | * Link from slave 1 to slave 2 has been successfully created. | ||
107 | */ | ||
108 | SLAVE2_LINK_SUCCESS, | ||
109 | |||
110 | /** | ||
111 | * Peer create on slave 2 successful | ||
112 | */ | ||
113 | SLAVE2_PEER_CREATE_SUCCESS, | ||
114 | |||
115 | /** | ||
116 | * Peer on slave 1 successfully stopped | ||
117 | */ | ||
118 | SLAVE1_PEER_STOP_SUCCESS, | ||
119 | |||
120 | /** | ||
121 | * Peer startup on slave 2 successful | ||
122 | */ | ||
123 | SLAVE2_PEER_START_SUCCESS, | ||
124 | |||
125 | /** | ||
126 | * Try to connect peers on master and slave 2. | ||
127 | */ | ||
128 | MASTER_SLAVE2_PEERS_CONNECTED, | ||
129 | |||
130 | /** | ||
131 | * Slave 3 has successfully registered | ||
132 | */ | ||
133 | SLAVE3_REGISTERED, | ||
134 | |||
135 | /** | ||
136 | * Slave 3 has successfully started | ||
137 | */ | ||
138 | SLAVE3_STARTED, | ||
139 | |||
140 | /** | ||
141 | * Peer created on slave 3 | ||
142 | */ | ||
143 | SLAVE3_PEER_CREATE_SUCCESS, | ||
144 | |||
145 | /** | ||
146 | * Peer started at slave 3 | ||
147 | */ | ||
148 | SLAVE3_PEER_START_SUCCESS, | ||
149 | |||
150 | /** | ||
151 | * Try to connect peers on slave2 and slave3 | ||
152 | */ | ||
153 | SLAVE2_SLAVE3_PEERS_CONNECTED, | ||
154 | |||
155 | /** | ||
156 | * Peer on slave 2 successfully stopped | ||
157 | */ | ||
158 | SLAVE2_PEER_STOP_SUCCESS, | ||
159 | |||
160 | /** | ||
161 | * Peer destroy on slave 1 successful | ||
162 | */ | ||
163 | SLAVE1_PEER_DESTROY_SUCCESS, | ||
164 | |||
165 | /** | ||
166 | * Peer destroy on slave 2 successful | ||
167 | */ | ||
168 | SLAVE2_PEER_DESTROY_SUCCESS, | ||
169 | |||
170 | /** | ||
171 | * The configuration of slave 3 is acquired | ||
172 | */ | ||
173 | SLAVE3_GET_CONFIG_SUCCESS, | ||
174 | |||
175 | /** | ||
176 | * Slave 1 has linked to slave 3; | ||
177 | */ | ||
178 | SLAVE3_LINK_SUCCESS, | ||
179 | |||
180 | /** | ||
181 | * Master peer destroyed. Destroy slave 3 peer | ||
182 | */ | ||
183 | MASTER_PEER_DESTROY_SUCCESS, | ||
184 | |||
185 | /** | ||
186 | * Slave 3 peer destroyed. Mark test as success | ||
187 | */ | ||
188 | SUCCESS, | ||
189 | |||
190 | /** | ||
191 | * Marks test as skipped | ||
192 | */ | ||
193 | SKIP | ||
194 | }; | ||
195 | |||
196 | /** | ||
197 | * Host for running master controller | ||
198 | */ | ||
199 | static struct GNUNET_TESTBED_Host *host; | ||
200 | |||
201 | /** | ||
202 | * The master controller process | ||
203 | */ | ||
204 | static struct GNUNET_TESTBED_ControllerProc *cp; | ||
205 | |||
206 | /** | ||
207 | * Handle to master controller | ||
208 | */ | ||
209 | static struct GNUNET_TESTBED_Controller *mc; | ||
210 | |||
211 | /** | ||
212 | * Slave host for running slave controller | ||
213 | */ | ||
214 | static struct GNUNET_TESTBED_Host *slave; | ||
215 | |||
216 | /** | ||
217 | * Another slave host for running another slave controller | ||
218 | */ | ||
219 | static struct GNUNET_TESTBED_Host *slave2; | ||
220 | |||
221 | /** | ||
222 | * Host for slave 3 | ||
223 | */ | ||
224 | static struct GNUNET_TESTBED_Host *slave3; | ||
225 | |||
226 | /** | ||
227 | * Slave host registration handle | ||
228 | */ | ||
229 | static struct GNUNET_TESTBED_HostRegistrationHandle *rh; | ||
230 | |||
231 | /** | ||
232 | * Handle to global configuration | ||
233 | */ | ||
234 | static struct GNUNET_CONFIGURATION_Handle *cfg; | ||
235 | |||
236 | /** | ||
237 | * Configuration of slave 3 controller | ||
238 | */ | ||
239 | static struct GNUNET_CONFIGURATION_Handle *cfg3; | ||
240 | |||
241 | /** | ||
242 | * Abort task | ||
243 | */ | ||
244 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
245 | |||
246 | /** | ||
247 | * Operation handle for linking controllers | ||
248 | */ | ||
249 | static struct GNUNET_TESTBED_Operation *op; | ||
250 | |||
251 | /** | ||
252 | * Handle to peer started at slave 1 | ||
253 | */ | ||
254 | static struct GNUNET_TESTBED_Peer *slave1_peer; | ||
255 | |||
256 | /** | ||
257 | * Handle to peer started at slave 2 | ||
258 | */ | ||
259 | static struct GNUNET_TESTBED_Peer *slave2_peer; | ||
260 | |||
261 | /** | ||
262 | * Handle to peer started at slave 2 | ||
263 | */ | ||
264 | static struct GNUNET_TESTBED_Peer *slave3_peer; | ||
265 | |||
266 | /** | ||
267 | * Handle to a peer started at master controller | ||
268 | */ | ||
269 | static struct GNUNET_TESTBED_Peer *master_peer; | ||
270 | |||
271 | /** | ||
272 | * The handle for whether a host is habitable or not | ||
273 | */ | ||
274 | static struct GNUNET_TESTBED_HostHabitableCheckHandle *hc_handle; | ||
275 | |||
276 | /** | ||
277 | * The task handle for the delay task | ||
278 | */ | ||
279 | static struct GNUNET_SCHEDULER_Task *delay_task_id; | ||
280 | |||
281 | /** | ||
282 | * Event mask | ||
283 | */ | ||
284 | static uint64_t event_mask; | ||
285 | |||
286 | /** | ||
287 | * Global testing status | ||
288 | */ | ||
289 | static enum Stage result; | ||
290 | |||
291 | /** | ||
292 | * shortcut to exit during failure | ||
293 | */ | ||
294 | #define FAIL_TEST(cond) \ | ||
295 | do \ | ||
296 | { \ | ||
297 | if (! (cond)) \ | ||
298 | { \ | ||
299 | GNUNET_break (0); \ | ||
300 | if (NULL != abort_task) \ | ||
301 | GNUNET_SCHEDULER_cancel (abort_task); \ | ||
302 | abort_task = NULL; \ | ||
303 | GNUNET_SCHEDULER_shutdown (); \ | ||
304 | return; \ | ||
305 | } \ | ||
306 | } while (0) | ||
307 | |||
308 | |||
309 | /** | ||
310 | * Shutdown nicely | ||
311 | * | ||
312 | * @param cls NULL | ||
313 | */ | ||
314 | static void | ||
315 | do_shutdown (void *cls) | ||
316 | { | ||
317 | if (NULL != abort_task) | ||
318 | GNUNET_SCHEDULER_cancel (abort_task); | ||
319 | if (NULL != delay_task_id) | ||
320 | { | ||
321 | GNUNET_SCHEDULER_cancel (delay_task_id); | ||
322 | delay_task_id = NULL; | ||
323 | } | ||
324 | if (NULL != hc_handle) | ||
325 | GNUNET_TESTBED_is_host_habitable_cancel (hc_handle); | ||
326 | if (NULL != op) | ||
327 | { | ||
328 | GNUNET_TESTBED_operation_done (op); | ||
329 | op = NULL; | ||
330 | } | ||
331 | if (NULL != mc) | ||
332 | GNUNET_TESTBED_controller_disconnect (mc); | ||
333 | if (NULL != cp) | ||
334 | GNUNET_TESTBED_controller_stop (cp); | ||
335 | if (NULL != slave3) | ||
336 | GNUNET_TESTBED_host_destroy (slave3); | ||
337 | if (NULL != slave2) | ||
338 | GNUNET_TESTBED_host_destroy (slave2); | ||
339 | if (NULL != slave) | ||
340 | GNUNET_TESTBED_host_destroy (slave); | ||
341 | if (NULL != host) | ||
342 | GNUNET_TESTBED_host_destroy (host); | ||
343 | if (NULL != cfg) | ||
344 | GNUNET_CONFIGURATION_destroy (cfg); | ||
345 | if (NULL != cfg3) | ||
346 | GNUNET_CONFIGURATION_destroy (cfg3); | ||
347 | if (NULL != rh) | ||
348 | GNUNET_TESTBED_cancel_registration (rh); | ||
349 | } | ||
350 | |||
351 | |||
352 | /** | ||
353 | * abort task to run on test timed out | ||
354 | * | ||
355 | * @param cls NULL | ||
356 | */ | ||
357 | static void | ||
358 | do_abort (void *cls) | ||
359 | { | ||
360 | LOG (GNUNET_ERROR_TYPE_WARNING, "Aborting in stage %d\n", result); | ||
361 | abort_task = NULL; | ||
362 | GNUNET_SCHEDULER_shutdown (); | ||
363 | } | ||
364 | |||
365 | |||
366 | /** | ||
367 | * Calls abort now | ||
368 | * | ||
369 | * @param | ||
370 | * @return | ||
371 | */ | ||
372 | static void | ||
373 | do_abort_now (void *cls) | ||
374 | { | ||
375 | if (NULL != abort_task) | ||
376 | GNUNET_SCHEDULER_cancel (abort_task); | ||
377 | abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); | ||
378 | } | ||
379 | |||
380 | |||
381 | /** | ||
382 | * Callback which will be called to after a host registration succeeded or failed | ||
383 | * | ||
384 | * @param cls the host which has been registered | ||
385 | * @param emsg the error message; NULL if host registration is successful | ||
386 | */ | ||
387 | static void | ||
388 | registration_cont (void *cls, const char *emsg); | ||
389 | |||
390 | |||
391 | /** | ||
392 | * Task for inserting delay between tests | ||
393 | * | ||
394 | * @param | ||
395 | * @return | ||
396 | */ | ||
397 | static void | ||
398 | delay_task (void *cls) | ||
399 | { | ||
400 | delay_task_id = NULL; | ||
401 | switch (result) | ||
402 | { | ||
403 | case SLAVE2_PEER_CREATE_SUCCESS: | ||
404 | op = GNUNET_TESTBED_peer_stop (NULL, slave1_peer, NULL, NULL); | ||
405 | FAIL_TEST (NULL != op); | ||
406 | break; | ||
407 | |||
408 | case MASTER_SLAVE2_PEERS_CONNECTED: | ||
409 | slave3 = GNUNET_TESTBED_host_create_with_id (3, "127.0.0.1", NULL, cfg, 0); | ||
410 | rh = GNUNET_TESTBED_register_host (mc, slave3, ®istration_cont, NULL); | ||
411 | break; | ||
412 | |||
413 | case SLAVE2_SLAVE3_PEERS_CONNECTED: | ||
414 | op = GNUNET_TESTBED_peer_stop (NULL, slave2_peer, NULL, NULL); | ||
415 | FAIL_TEST (NULL != op); | ||
416 | break; | ||
417 | |||
418 | default: | ||
419 | FAIL_TEST (0); | ||
420 | } | ||
421 | } | ||
422 | |||
423 | |||
424 | /** | ||
425 | * Functions of this signature are called when a peer has been successfully | ||
426 | * created | ||
427 | * | ||
428 | * @param cls the closure from GNUNET_TESTBED_peer_create() | ||
429 | * @param peer the handle for the created peer; NULL on any error during | ||
430 | * creation | ||
431 | * @param emsg NULL if peer is not NULL; else MAY contain the error description | ||
432 | */ | ||
433 | static void | ||
434 | peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) | ||
435 | { | ||
436 | FAIL_TEST (NULL != peer); | ||
437 | FAIL_TEST (NULL == emsg); | ||
438 | switch (result) | ||
439 | { | ||
440 | case MASTER_STARTED: | ||
441 | result = MASTER_PEER_CREATE_SUCCESS; | ||
442 | master_peer = peer; | ||
443 | GNUNET_TESTBED_operation_done (op); | ||
444 | op = GNUNET_TESTBED_peer_start (NULL, master_peer, NULL, NULL); | ||
445 | break; | ||
446 | |||
447 | case SLAVE1_LINK_SUCCESS: | ||
448 | result = SLAVE1_PEER_CREATE_SUCCESS; | ||
449 | slave1_peer = peer; | ||
450 | GNUNET_TESTBED_operation_done (op); | ||
451 | op = GNUNET_TESTBED_peer_start (NULL, slave1_peer, NULL, NULL); | ||
452 | break; | ||
453 | |||
454 | case SLAVE2_LINK_SUCCESS: | ||
455 | result = SLAVE2_PEER_CREATE_SUCCESS; | ||
456 | slave2_peer = peer; | ||
457 | GNUNET_TESTBED_operation_done (op); | ||
458 | op = NULL; | ||
459 | delay_task_id = GNUNET_SCHEDULER_add_delayed ( | ||
460 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), | ||
461 | &delay_task, | ||
462 | NULL); | ||
463 | return; | ||
464 | |||
465 | case SLAVE3_STARTED: | ||
466 | result = SLAVE3_PEER_CREATE_SUCCESS; | ||
467 | slave3_peer = peer; | ||
468 | GNUNET_TESTBED_operation_done (op); | ||
469 | op = GNUNET_TESTBED_peer_start (NULL, slave3_peer, NULL, NULL); | ||
470 | break; | ||
471 | |||
472 | default: | ||
473 | FAIL_TEST (0); | ||
474 | } | ||
475 | FAIL_TEST (NULL != op); | ||
476 | } | ||
477 | |||
478 | |||
479 | /** | ||
480 | * Checks the event if it is an operation finished event and if indicates a | ||
481 | * successful completion of operation | ||
482 | * | ||
483 | * @param event the event information to check | ||
484 | */ | ||
485 | static void | ||
486 | check_operation_success (const struct GNUNET_TESTBED_EventInformation *event) | ||
487 | { | ||
488 | FAIL_TEST (NULL != event); | ||
489 | FAIL_TEST (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type); | ||
490 | FAIL_TEST (event->op == op); | ||
491 | FAIL_TEST (NULL == event->op_cls); | ||
492 | FAIL_TEST (NULL == event->details.operation_finished.emsg); | ||
493 | FAIL_TEST (NULL == event->details.operation_finished.generic); | ||
494 | } | ||
495 | |||
496 | |||
497 | /** | ||
498 | * Signature of the event handler function called by the | ||
499 | * respective event controller. | ||
500 | * | ||
501 | * @param cls closure | ||
502 | * @param event information about the event | ||
503 | */ | ||
504 | static void | ||
505 | controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) | ||
506 | { | ||
507 | switch (result) | ||
508 | { | ||
509 | case SLAVE2_REGISTERED: | ||
510 | check_operation_success (event); | ||
511 | GNUNET_TESTBED_operation_done (op); | ||
512 | op = NULL; | ||
513 | result = SLAVE1_LINK_SUCCESS; | ||
514 | FAIL_TEST (NULL != slave2); | ||
515 | FAIL_TEST (NULL != slave); | ||
516 | op = GNUNET_TESTBED_peer_create (mc, slave, cfg, peer_create_cb, NULL); | ||
517 | FAIL_TEST (NULL != op); | ||
518 | break; | ||
519 | |||
520 | case SLAVE1_PEER_START_SUCCESS: | ||
521 | check_operation_success (event); | ||
522 | GNUNET_TESTBED_operation_done (op); | ||
523 | result = SLAVE2_LINK_SUCCESS; | ||
524 | op = GNUNET_TESTBED_peer_create (mc, slave2, cfg, peer_create_cb, NULL); | ||
525 | FAIL_TEST (NULL != op); | ||
526 | break; | ||
527 | |||
528 | case MASTER_PEER_CREATE_SUCCESS: | ||
529 | FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type); | ||
530 | FAIL_TEST (event->details.peer_start.host == host); | ||
531 | FAIL_TEST (event->details.peer_start.peer == master_peer); | ||
532 | GNUNET_TESTBED_operation_done (op); | ||
533 | op = NULL; | ||
534 | result = MASTER_PEER_START_SUCCESS; | ||
535 | slave = GNUNET_TESTBED_host_create_with_id (1, "127.0.0.1", NULL, cfg, 0); | ||
536 | FAIL_TEST (NULL != slave); | ||
537 | rh = GNUNET_TESTBED_register_host (mc, slave, ®istration_cont, NULL); | ||
538 | FAIL_TEST (NULL != rh); | ||
539 | break; | ||
540 | |||
541 | case SLAVE1_PEER_CREATE_SUCCESS: | ||
542 | FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type); | ||
543 | FAIL_TEST (event->details.peer_start.host == slave); | ||
544 | FAIL_TEST (event->details.peer_start.peer == slave1_peer); | ||
545 | GNUNET_TESTBED_operation_done (op); | ||
546 | result = SLAVE1_PEER_START_SUCCESS; | ||
547 | op = GNUNET_TESTBED_controller_link (NULL, mc, slave2, slave, GNUNET_YES); | ||
548 | break; | ||
549 | |||
550 | case SLAVE2_PEER_CREATE_SUCCESS: | ||
551 | FAIL_TEST (GNUNET_TESTBED_ET_PEER_STOP == event->type); | ||
552 | FAIL_TEST (event->details.peer_stop.peer == slave1_peer); | ||
553 | GNUNET_TESTBED_operation_done (op); | ||
554 | result = SLAVE1_PEER_STOP_SUCCESS; | ||
555 | op = GNUNET_TESTBED_peer_start (NULL, slave2_peer, NULL, NULL); | ||
556 | FAIL_TEST (NULL != op); | ||
557 | break; | ||
558 | |||
559 | case SLAVE3_PEER_CREATE_SUCCESS: | ||
560 | FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type); | ||
561 | FAIL_TEST (event->details.peer_start.host == slave3); | ||
562 | FAIL_TEST (event->details.peer_start.peer == slave3_peer); | ||
563 | GNUNET_TESTBED_operation_done (op); | ||
564 | result = SLAVE3_PEER_START_SUCCESS; | ||
565 | sleep (1); | ||
566 | LOG_DEBUG ("**************************************\n"); | ||
567 | op = | ||
568 | GNUNET_TESTBED_overlay_connect (mc, NULL, NULL, slave2_peer, slave3_peer); | ||
569 | FAIL_TEST (NULL != op); | ||
570 | break; | ||
571 | |||
572 | case SLAVE3_PEER_START_SUCCESS: | ||
573 | FAIL_TEST (NULL != event); | ||
574 | FAIL_TEST (GNUNET_TESTBED_ET_CONNECT == event->type); | ||
575 | FAIL_TEST (event->details.peer_connect.peer1 == slave2_peer); | ||
576 | FAIL_TEST (event->details.peer_connect.peer2 == slave3_peer); | ||
577 | result = SLAVE2_SLAVE3_PEERS_CONNECTED; | ||
578 | GNUNET_TESTBED_operation_done (op); | ||
579 | op = NULL; | ||
580 | delay_task_id = GNUNET_SCHEDULER_add_delayed ( | ||
581 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), | ||
582 | &delay_task, | ||
583 | NULL); | ||
584 | break; | ||
585 | |||
586 | case SLAVE1_PEER_STOP_SUCCESS: | ||
587 | FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type); | ||
588 | FAIL_TEST (event->details.peer_start.host == slave2); | ||
589 | FAIL_TEST (event->details.peer_start.peer == slave2_peer); | ||
590 | GNUNET_TESTBED_operation_done (op); | ||
591 | result = SLAVE2_PEER_START_SUCCESS; | ||
592 | op = | ||
593 | GNUNET_TESTBED_overlay_connect (mc, NULL, NULL, master_peer, slave2_peer); | ||
594 | break; | ||
595 | |||
596 | case SLAVE2_PEER_START_SUCCESS: | ||
597 | FAIL_TEST (NULL != event); | ||
598 | FAIL_TEST (GNUNET_TESTBED_ET_CONNECT == event->type); | ||
599 | FAIL_TEST (event->details.peer_connect.peer1 == master_peer); | ||
600 | FAIL_TEST (event->details.peer_connect.peer2 == slave2_peer); | ||
601 | result = MASTER_SLAVE2_PEERS_CONNECTED; | ||
602 | GNUNET_TESTBED_operation_done (op); | ||
603 | op = NULL; | ||
604 | delay_task_id = GNUNET_SCHEDULER_add_delayed ( | ||
605 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), | ||
606 | &delay_task, | ||
607 | NULL); | ||
608 | break; | ||
609 | |||
610 | case SLAVE2_SLAVE3_PEERS_CONNECTED: | ||
611 | FAIL_TEST (GNUNET_TESTBED_ET_PEER_STOP == event->type); | ||
612 | FAIL_TEST (event->details.peer_stop.peer == slave2_peer); | ||
613 | GNUNET_TESTBED_operation_done (op); | ||
614 | result = SLAVE2_PEER_STOP_SUCCESS; | ||
615 | op = GNUNET_TESTBED_peer_destroy (slave1_peer); | ||
616 | FAIL_TEST (NULL != op); | ||
617 | break; | ||
618 | |||
619 | case SLAVE2_PEER_STOP_SUCCESS: | ||
620 | check_operation_success (event); | ||
621 | GNUNET_TESTBED_operation_done (op); | ||
622 | result = SLAVE1_PEER_DESTROY_SUCCESS; | ||
623 | op = GNUNET_TESTBED_peer_destroy (slave2_peer); | ||
624 | FAIL_TEST (NULL != op); | ||
625 | break; | ||
626 | |||
627 | case SLAVE1_PEER_DESTROY_SUCCESS: | ||
628 | check_operation_success (event); | ||
629 | GNUNET_TESTBED_operation_done (op); | ||
630 | op = NULL; | ||
631 | result = SLAVE2_PEER_DESTROY_SUCCESS; | ||
632 | op = GNUNET_TESTBED_get_slave_config (NULL, mc, slave3); | ||
633 | FAIL_TEST (NULL != op); | ||
634 | break; | ||
635 | |||
636 | case SLAVE2_PEER_DESTROY_SUCCESS: | ||
637 | FAIL_TEST (NULL != event); | ||
638 | FAIL_TEST (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type); | ||
639 | FAIL_TEST (event->op == op); | ||
640 | FAIL_TEST (NULL == event->op_cls); | ||
641 | FAIL_TEST (NULL == event->details.operation_finished.emsg); | ||
642 | cfg3 = GNUNET_CONFIGURATION_dup (event->details.operation_finished.generic); | ||
643 | GNUNET_TESTBED_operation_done (op); | ||
644 | result = SLAVE3_GET_CONFIG_SUCCESS; | ||
645 | op = GNUNET_TESTBED_controller_link (NULL, mc, slave3, slave, GNUNET_NO); | ||
646 | break; | ||
647 | |||
648 | case SLAVE3_REGISTERED: | ||
649 | check_operation_success (event); | ||
650 | GNUNET_TESTBED_operation_done (op); | ||
651 | result = SLAVE3_STARTED; | ||
652 | op = GNUNET_TESTBED_peer_create (mc, slave3, cfg, peer_create_cb, NULL); | ||
653 | FAIL_TEST (NULL != op); | ||
654 | break; | ||
655 | |||
656 | case SLAVE3_GET_CONFIG_SUCCESS: | ||
657 | result = SLAVE3_LINK_SUCCESS; | ||
658 | GNUNET_TESTBED_operation_done (op); | ||
659 | op = GNUNET_TESTBED_peer_destroy (master_peer); | ||
660 | break; | ||
661 | |||
662 | case SLAVE3_LINK_SUCCESS: | ||
663 | check_operation_success (event); | ||
664 | result = MASTER_PEER_DESTROY_SUCCESS; | ||
665 | GNUNET_TESTBED_operation_done (op); | ||
666 | op = GNUNET_TESTBED_peer_destroy (slave3_peer); | ||
667 | break; | ||
668 | |||
669 | case MASTER_PEER_DESTROY_SUCCESS: | ||
670 | result = SUCCESS; | ||
671 | GNUNET_TESTBED_operation_done (op); | ||
672 | op = NULL; | ||
673 | GNUNET_SCHEDULER_shutdown (); | ||
674 | break; | ||
675 | |||
676 | default: | ||
677 | FAIL_TEST (0); | ||
678 | } | ||
679 | } | ||
680 | |||
681 | |||
682 | /** | ||
683 | * Callback which will be called to after a host registration succeeded or failed | ||
684 | * | ||
685 | * @param cls the host which has been registered | ||
686 | * @param emsg the error message; NULL if host registration is successful | ||
687 | */ | ||
688 | static void | ||
689 | registration_cont (void *cls, const char *emsg) | ||
690 | { | ||
691 | rh = NULL; | ||
692 | switch (result) | ||
693 | { | ||
694 | case MASTER_PEER_START_SUCCESS: | ||
695 | FAIL_TEST (NULL == emsg); | ||
696 | FAIL_TEST (NULL != mc); | ||
697 | result = SLAVE1_REGISTERED; | ||
698 | slave2 = GNUNET_TESTBED_host_create_with_id (2, "127.0.0.1", NULL, cfg, 0); | ||
699 | FAIL_TEST (NULL != slave2); | ||
700 | rh = GNUNET_TESTBED_register_host (mc, slave2, ®istration_cont, NULL); | ||
701 | FAIL_TEST (NULL != rh); | ||
702 | break; | ||
703 | |||
704 | case SLAVE1_REGISTERED: | ||
705 | FAIL_TEST (NULL == emsg); | ||
706 | FAIL_TEST (NULL != mc); | ||
707 | result = SLAVE2_REGISTERED; | ||
708 | FAIL_TEST (NULL != cfg); | ||
709 | op = GNUNET_TESTBED_controller_link (NULL, mc, slave, NULL, GNUNET_YES); | ||
710 | FAIL_TEST (NULL != op); | ||
711 | break; | ||
712 | |||
713 | case MASTER_SLAVE2_PEERS_CONNECTED: | ||
714 | FAIL_TEST (NULL == emsg); | ||
715 | FAIL_TEST (NULL != mc); | ||
716 | FAIL_TEST (NULL == op); | ||
717 | result = SLAVE3_REGISTERED; | ||
718 | op = GNUNET_TESTBED_controller_link (NULL, mc, slave3, NULL, GNUNET_YES); | ||
719 | FAIL_TEST (NULL != op); | ||
720 | break; | ||
721 | |||
722 | default: | ||
723 | GNUNET_break (0); | ||
724 | do_abort_now (NULL); | ||
725 | } | ||
726 | } | ||
727 | |||
728 | |||
729 | /** | ||
730 | * Callback to signal successful startup of the controller process | ||
731 | * | ||
732 | * @param cls the closure from GNUNET_TESTBED_controller_start() | ||
733 | * @param cfg the configuration with which the controller has been started; | ||
734 | * NULL if status is not GNUNET_OK | ||
735 | * @param status GNUNET_OK if the startup is successful; GNUNET_SYSERR if not, | ||
736 | * GNUNET_TESTBED_controller_stop() shouldn't be called in this case | ||
737 | */ | ||
738 | static void | ||
739 | status_cb (void *cls, | ||
740 | const struct GNUNET_CONFIGURATION_Handle *config, | ||
741 | int status) | ||
742 | { | ||
743 | switch (result) | ||
744 | { | ||
745 | case INIT: | ||
746 | FAIL_TEST (GNUNET_OK == status); | ||
747 | event_mask = 0; | ||
748 | event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START); | ||
749 | event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP); | ||
750 | event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); | ||
751 | event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
752 | mc = GNUNET_TESTBED_controller_connect (host, | ||
753 | event_mask, | ||
754 | &controller_cb, | ||
755 | NULL); | ||
756 | FAIL_TEST (NULL != mc); | ||
757 | result = MASTER_STARTED; | ||
758 | op = GNUNET_TESTBED_peer_create (mc, host, cfg, peer_create_cb, NULL); | ||
759 | FAIL_TEST (NULL != op); | ||
760 | break; | ||
761 | |||
762 | default: | ||
763 | GNUNET_break (0); | ||
764 | cp = NULL; | ||
765 | do_abort_now (NULL); | ||
766 | } | ||
767 | } | ||
768 | |||
769 | |||
770 | /** | ||
771 | * Callbacks of this type are called by #GNUNET_TESTBED_is_host_habitable to | ||
772 | * inform whether the given host is habitable or not. The Handle returned by | ||
773 | * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called | ||
774 | * | ||
775 | * @param cls NULL | ||
776 | * @param host the host whose status is being reported; will be NULL if the host | ||
777 | * given to GNUNET_TESTBED_is_host_habitable() is NULL | ||
778 | * @param status #GNUNET_YES if it is habitable; #GNUNET_NO if not | ||
779 | */ | ||
780 | static void | ||
781 | host_habitable_cb (void *cls, | ||
782 | const struct GNUNET_TESTBED_Host *_host, | ||
783 | int status) | ||
784 | { | ||
785 | hc_handle = NULL; | ||
786 | if (GNUNET_NO == status) | ||
787 | { | ||
788 | (void) printf ("%s", | ||
789 | "Unable to run the test as this system is not configured " | ||
790 | "to use password less SSH logins to localhost.\n" | ||
791 | "Skipping test\n"); | ||
792 | GNUNET_SCHEDULER_cancel (abort_task); | ||
793 | abort_task = NULL; | ||
794 | GNUNET_SCHEDULER_shutdown (); | ||
795 | result = SKIP; | ||
796 | return; | ||
797 | } | ||
798 | cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb, NULL); | ||
799 | } | ||
800 | |||
801 | |||
802 | /** | ||
803 | * Main run function. | ||
804 | * | ||
805 | * @param cls NULL | ||
806 | * @param args arguments passed to #GNUNET_PROGRAM_run() | ||
807 | * @param cfgfile the path to configuration file | ||
808 | * @param cfg the configuration file handle | ||
809 | */ | ||
810 | static void | ||
811 | run (void *cls, | ||
812 | char *const *args, | ||
813 | const char *cfgfile, | ||
814 | const struct GNUNET_CONFIGURATION_Handle *config) | ||
815 | { | ||
816 | cfg = GNUNET_CONFIGURATION_dup (config); | ||
817 | host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); | ||
818 | FAIL_TEST (NULL != host); | ||
819 | if (NULL == (hc_handle = GNUNET_TESTBED_is_host_habitable (host, | ||
820 | config, | ||
821 | &host_habitable_cb, | ||
822 | NULL))) | ||
823 | { | ||
824 | GNUNET_TESTBED_host_destroy (host); | ||
825 | GNUNET_CONFIGURATION_destroy (cfg); | ||
826 | cfg = NULL; | ||
827 | host = NULL; | ||
828 | (void) printf ("%s", | ||
829 | "Unable to run the test as this system is not configured " | ||
830 | "to use password less SSH logins to localhost.\n" | ||
831 | "Marking test as successful\n"); | ||
832 | result = SKIP; | ||
833 | return; | ||
834 | } | ||
835 | abort_task = GNUNET_SCHEDULER_add_delayed ( | ||
836 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5), | ||
837 | &do_abort, | ||
838 | NULL); | ||
839 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
840 | } | ||
841 | |||
842 | |||
843 | /** | ||
844 | * Main function | ||
845 | */ | ||
846 | int | ||
847 | main (int argc, char **argv) | ||
848 | { | ||
849 | char *const argv2[] = { "test_testbed_api_controllerlink", | ||
850 | "-c", | ||
851 | "test_testbed_api.conf", | ||
852 | NULL }; | ||
853 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
854 | { GNUNET_GETOPT_OPTION_END }; | ||
855 | int ret; | ||
856 | |||
857 | result = INIT; | ||
858 | ret = GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, | ||
859 | argv2, | ||
860 | "test_testbed_api_controllerlink", | ||
861 | "nohelp", | ||
862 | options, | ||
863 | &run, | ||
864 | NULL); | ||
865 | if (GNUNET_OK != ret) | ||
866 | return 1; | ||
867 | switch (result) | ||
868 | { | ||
869 | case SUCCESS: | ||
870 | return 0; | ||
871 | |||
872 | case SKIP: | ||
873 | return 77; /* Mark test as skipped */ | ||
874 | |||
875 | default: | ||
876 | return 1; | ||
877 | } | ||
878 | } | ||
879 | |||
880 | |||
881 | /* end of test_testbed_api_controllerlink.c */ | ||
diff --git a/src/testbed/test_testbed_api_hosts.c b/src/testbed/test_testbed_api_hosts.c deleted file mode 100644 index 9e49debf7..000000000 --- a/src/testbed/test_testbed_api_hosts.c +++ /dev/null | |||
@@ -1,183 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/test_testbed_api_hosts.c | ||
23 | * @brief tests cases for testbed_api_hosts.c | ||
24 | * @author Sree Harsha Totakura | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | #include "testbed_api_hosts.h" | ||
31 | |||
32 | |||
33 | #define TIME_REL_SECS(sec) \ | ||
34 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) | ||
35 | |||
36 | /** | ||
37 | * configuration handle to use as template configuration while creating hosts | ||
38 | */ | ||
39 | static struct GNUNET_CONFIGURATION_Handle *cfg; | ||
40 | |||
41 | /** | ||
42 | * Host we are creating and using | ||
43 | */ | ||
44 | static struct GNUNET_TESTBED_Host *host; | ||
45 | |||
46 | /** | ||
47 | * An array of hosts which are loaded from a file | ||
48 | */ | ||
49 | static struct GNUNET_TESTBED_Host **hosts; | ||
50 | |||
51 | /** | ||
52 | * Number of hosts in the above list | ||
53 | */ | ||
54 | static unsigned int num_hosts; | ||
55 | |||
56 | /** | ||
57 | * Global test status | ||
58 | */ | ||
59 | static int status; | ||
60 | |||
61 | |||
62 | /** | ||
63 | * The shutdown task | ||
64 | * | ||
65 | * @param cls NULL | ||
66 | */ | ||
67 | static void | ||
68 | do_shutdown (void *cls) | ||
69 | { | ||
70 | GNUNET_TESTBED_host_destroy (host); | ||
71 | while (0 != num_hosts) | ||
72 | { | ||
73 | GNUNET_TESTBED_host_destroy (hosts[num_hosts - 1]); | ||
74 | num_hosts--; | ||
75 | } | ||
76 | GNUNET_free (hosts); | ||
77 | if (NULL != cfg) | ||
78 | { | ||
79 | GNUNET_CONFIGURATION_destroy (cfg); | ||
80 | cfg = NULL; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | |||
85 | /** | ||
86 | * Main run function. | ||
87 | * | ||
88 | * @param cls NULL | ||
89 | * @param args arguments passed to GNUNET_PROGRAM_run | ||
90 | * @param cfgfile the path to configuration file | ||
91 | * @param cfg the configuration file handle | ||
92 | */ | ||
93 | static void | ||
94 | run (void *cls, char *const *args, const char *cfgfile, | ||
95 | const struct GNUNET_CONFIGURATION_Handle *config) | ||
96 | { | ||
97 | unsigned int cnt; | ||
98 | |||
99 | cfg = GNUNET_CONFIGURATION_dup (config); | ||
100 | host = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0); | ||
101 | GNUNET_assert (NULL != host); | ||
102 | GNUNET_assert (0 != GNUNET_TESTBED_host_get_id_ (host)); | ||
103 | GNUNET_TESTBED_host_destroy (host); | ||
104 | host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); | ||
105 | GNUNET_assert (NULL != host); | ||
106 | GNUNET_assert (0 == GNUNET_TESTBED_host_get_id_ (host)); | ||
107 | GNUNET_assert (host == GNUNET_TESTBED_host_lookup_by_id_ (0)); | ||
108 | hosts = NULL; | ||
109 | num_hosts = GNUNET_TESTBED_hosts_load_from_file ("sample_hosts.txt", cfg, | ||
110 | &hosts); | ||
111 | GNUNET_assert (7 == num_hosts); | ||
112 | GNUNET_assert (NULL != hosts); | ||
113 | for (cnt = 0; cnt < num_hosts; cnt++) | ||
114 | { | ||
115 | if (cnt < 3) | ||
116 | { | ||
117 | GNUNET_assert (0 == strcmp ("totakura", | ||
118 | GNUNET_TESTBED_host_get_username_ | ||
119 | (hosts[cnt]))); | ||
120 | GNUNET_assert (NULL != GNUNET_TESTBED_host_get_hostname (hosts[cnt])); | ||
121 | GNUNET_assert (22 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); | ||
122 | } | ||
123 | if (3 == cnt) | ||
124 | { | ||
125 | GNUNET_assert (0 == strcmp ("totakura", | ||
126 | GNUNET_TESTBED_host_get_username_ | ||
127 | (hosts[cnt]))); | ||
128 | GNUNET_assert (NULL != GNUNET_TESTBED_host_get_hostname (hosts[cnt])); | ||
129 | GNUNET_assert (2022 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); | ||
130 | } | ||
131 | if (4 == cnt) | ||
132 | { | ||
133 | GNUNET_assert (0 == strcmp ("totakura", | ||
134 | GNUNET_TESTBED_host_get_username_ | ||
135 | (hosts[cnt]))); | ||
136 | GNUNET_assert (0 == strcmp ("asgard.realm", | ||
137 | GNUNET_TESTBED_host_get_hostname | ||
138 | (hosts[cnt]))); | ||
139 | GNUNET_assert (22 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); | ||
140 | } | ||
141 | if (5 == cnt) | ||
142 | { | ||
143 | GNUNET_assert (NULL == GNUNET_TESTBED_host_get_username_ (hosts[cnt])); | ||
144 | GNUNET_assert (0 == strcmp ("rivendal", | ||
145 | GNUNET_TESTBED_host_get_hostname | ||
146 | (hosts[cnt]))); | ||
147 | GNUNET_assert (22 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); | ||
148 | } | ||
149 | if (6 == cnt) | ||
150 | { | ||
151 | GNUNET_assert (NULL == GNUNET_TESTBED_host_get_username_ (hosts[cnt])); | ||
152 | GNUNET_assert (0 == strcmp ("rohan", | ||
153 | GNUNET_TESTBED_host_get_hostname | ||
154 | (hosts[cnt]))); | ||
155 | GNUNET_assert (561 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); | ||
156 | } | ||
157 | } | ||
158 | status = GNUNET_YES; | ||
159 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
160 | } | ||
161 | |||
162 | |||
163 | int | ||
164 | main (int argc, char **argv) | ||
165 | { | ||
166 | char *const argv2[] = { "test_testbed_api_hosts", | ||
167 | "-c", "test_testbed_api.conf", | ||
168 | NULL }; | ||
169 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
170 | GNUNET_GETOPT_OPTION_END | ||
171 | }; | ||
172 | |||
173 | status = GNUNET_SYSERR; | ||
174 | if (GNUNET_OK != | ||
175 | GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, | ||
176 | "test_testbed_api_hosts", "nohelp", options, &run, | ||
177 | NULL)) | ||
178 | return 1; | ||
179 | return (GNUNET_OK == status) ? 0 : 1; | ||
180 | } | ||
181 | |||
182 | |||
183 | /* end of test_testbed_api_hosts.c */ | ||
diff --git a/src/testbed/test_testbed_api_operations.c b/src/testbed/test_testbed_api_operations.c deleted file mode 100644 index 133aadf21..000000000 --- a/src/testbed/test_testbed_api_operations.c +++ /dev/null | |||
@@ -1,568 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/test_testbed_api_operations.c | ||
23 | * @brief tests cases for testbed_api_operations.c | ||
24 | * @author Sree Harsha Totakura | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "testbed_api_operations.h" | ||
30 | |||
31 | /** | ||
32 | * Generic logging shortcut | ||
33 | */ | ||
34 | #define LOG(kind, ...) \ | ||
35 | GNUNET_log (kind, __VA_ARGS__) | ||
36 | |||
37 | /** | ||
38 | * Delay to start step task | ||
39 | */ | ||
40 | #define STEP_DELAY \ | ||
41 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500) | ||
42 | |||
43 | /** | ||
44 | * Queue A. Initially the max active is set to 2 and then reduced to 0 - this | ||
45 | * should block op2 even after op1 has finished. Later the max active is set to | ||
46 | * 2 and this should start op2 | ||
47 | */ | ||
48 | struct OperationQueue *q1; | ||
49 | |||
50 | /** | ||
51 | * Queue B. Max active set to 2 is not changed throughout the test | ||
52 | */ | ||
53 | struct OperationQueue *q2; | ||
54 | |||
55 | /** | ||
56 | * This operation should go into both queues and block op2 until it is done | ||
57 | */ | ||
58 | struct GNUNET_TESTBED_Operation *op1; | ||
59 | |||
60 | /** | ||
61 | * This operation should go into q1 and q2 | ||
62 | */ | ||
63 | struct GNUNET_TESTBED_Operation *op2; | ||
64 | |||
65 | /** | ||
66 | * This operation should go into both queues and should consume 2 units of | ||
67 | * resources on both queues. Since op2 needs a resource from both queues and is | ||
68 | * queues before this operation, it will be blocked until op2 is released even | ||
69 | * though q1 has enough free resources | ||
70 | */ | ||
71 | struct GNUNET_TESTBED_Operation *op3; | ||
72 | |||
73 | /** | ||
74 | * Just like op3, this operation also consumes 2 units of resources on both | ||
75 | * queues. Since this is queued after op3 and both queues are at max active | ||
76 | * 2. This will be blocked until op3 is done. | ||
77 | */ | ||
78 | struct GNUNET_TESTBED_Operation *op4; | ||
79 | |||
80 | /** | ||
81 | * This operation is started after op4 is released and should consume only 1 | ||
82 | * resource on queue q1. It should be started along with op6 and op7 | ||
83 | */ | ||
84 | struct GNUNET_TESTBED_Operation *op5; | ||
85 | |||
86 | /** | ||
87 | * This operation is started after op4 is released and should consume only 1 | ||
88 | * resource on q2. It should be started along with op5 and op7 | ||
89 | */ | ||
90 | struct GNUNET_TESTBED_Operation *op6; | ||
91 | |||
92 | /** | ||
93 | * This operation is started after op4 is released and should consume 1 resource | ||
94 | * on both queues q1 and q1. It should be started along with op5 and op6. It is | ||
95 | * then inactivated when op6 is released. op8's start should release this | ||
96 | * operation implicitly. | ||
97 | */ | ||
98 | struct GNUNET_TESTBED_Operation *op7; | ||
99 | |||
100 | /** | ||
101 | * This operation is started after op6 is finished in step task. It consumes 2 | ||
102 | * resources on both queues q1 and q2. This operation should evict op7. After | ||
103 | * starting, it should be made inactive, active and inactive again in the step task. | ||
104 | */ | ||
105 | struct GNUNET_TESTBED_Operation *op8; | ||
106 | |||
107 | /** | ||
108 | * This operation is started after activating op8. It should consume a resource | ||
109 | * on queues q1 and q2. It should not be started until op8 is again made | ||
110 | * inactive at which point it should be released. It can be released as soon as | ||
111 | * it begins. | ||
112 | */ | ||
113 | struct GNUNET_TESTBED_Operation *op9; | ||
114 | |||
115 | /** | ||
116 | * The delay task identifier | ||
117 | */ | ||
118 | struct GNUNET_SCHEDULER_Task *step_task; | ||
119 | |||
120 | |||
121 | /** | ||
122 | * Enumeration of test stages | ||
123 | */ | ||
124 | enum Test | ||
125 | { | ||
126 | /** | ||
127 | * Initial stage | ||
128 | */ | ||
129 | TEST_INIT, | ||
130 | |||
131 | /** | ||
132 | * op1 has been started | ||
133 | */ | ||
134 | TEST_OP1_STARTED, | ||
135 | |||
136 | /** | ||
137 | * op1 has been released | ||
138 | */ | ||
139 | TEST_OP1_RELEASED, | ||
140 | |||
141 | /** | ||
142 | * Temporary pause where no operations should start as we set max active in q1 | ||
143 | * to 0 in stage TEST_OP1_STARTED | ||
144 | */ | ||
145 | TEST_PAUSE, | ||
146 | |||
147 | /** | ||
148 | * op2 has started | ||
149 | */ | ||
150 | TEST_OP2_STARTED, | ||
151 | |||
152 | /** | ||
153 | * op2 released | ||
154 | */ | ||
155 | TEST_OP2_RELEASED, | ||
156 | |||
157 | /** | ||
158 | * op3 has started | ||
159 | */ | ||
160 | TEST_OP3_STARTED, | ||
161 | |||
162 | /** | ||
163 | * op3 has finished | ||
164 | */ | ||
165 | TEST_OP3_RELEASED, | ||
166 | |||
167 | /** | ||
168 | * op4 has started | ||
169 | */ | ||
170 | TEST_OP4_STARTED, | ||
171 | |||
172 | /** | ||
173 | * op4 has released | ||
174 | */ | ||
175 | TEST_OP4_RELEASED, | ||
176 | |||
177 | /** | ||
178 | * op5, op6, op7 started | ||
179 | */ | ||
180 | TEST_OP5_6_7_STARTED, | ||
181 | |||
182 | /** | ||
183 | * op5 has released | ||
184 | */ | ||
185 | TEST_OP5_RELEASED, | ||
186 | |||
187 | /** | ||
188 | * op6 has released | ||
189 | */ | ||
190 | TEST_OP6_RELEASED, | ||
191 | |||
192 | /** | ||
193 | * op8 has began waiting | ||
194 | */ | ||
195 | TEST_OP8_WAITING, | ||
196 | |||
197 | /** | ||
198 | * op7 has released | ||
199 | */ | ||
200 | TEST_OP7_RELEASED, | ||
201 | |||
202 | /** | ||
203 | * op8 has started | ||
204 | */ | ||
205 | TEST_OP8_STARTED, | ||
206 | |||
207 | /** | ||
208 | * op8 is inactive | ||
209 | */ | ||
210 | TEST_OP8_INACTIVE_1, | ||
211 | |||
212 | /** | ||
213 | * op8 is active | ||
214 | */ | ||
215 | TEST_OP8_ACTIVE, | ||
216 | |||
217 | /** | ||
218 | * op8 has been released | ||
219 | */ | ||
220 | TEST_OP8_RELEASED, | ||
221 | |||
222 | /** | ||
223 | * op9 has started | ||
224 | */ | ||
225 | TEST_OP9_STARTED, | ||
226 | |||
227 | /** | ||
228 | * op9 has been released | ||
229 | */ | ||
230 | TEST_OP9_RELEASED | ||
231 | }; | ||
232 | |||
233 | /** | ||
234 | * The test result | ||
235 | */ | ||
236 | enum Test result; | ||
237 | |||
238 | |||
239 | /** | ||
240 | * Function to call to start an operation once all | ||
241 | * queues the operation is part of declare that the | ||
242 | * operation can be activated. | ||
243 | */ | ||
244 | static void | ||
245 | start_cb (void *cls); | ||
246 | |||
247 | |||
248 | /** | ||
249 | * Function to cancel an operation (release all associated resources). This can | ||
250 | * be because of a call to "GNUNET_TESTBED_operation_cancel" (before the | ||
251 | * operation generated an event) or AFTER the operation generated an event due | ||
252 | * to a call to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that | ||
253 | * a callback to the 'OperationStart' precedes the call to 'OperationRelease'. | ||
254 | * Implementations of this function are expected to clean up whatever state is | ||
255 | * in 'cls' and release all resources associated with the operation. | ||
256 | */ | ||
257 | static void | ||
258 | release_cb (void *cls); | ||
259 | |||
260 | |||
261 | /** | ||
262 | * Task to simulate artificial delay and change the test stage | ||
263 | * | ||
264 | * @param cls NULL | ||
265 | */ | ||
266 | static void | ||
267 | step (void *cls) | ||
268 | { | ||
269 | GNUNET_assert (NULL != step_task); | ||
270 | step_task = NULL; | ||
271 | switch (result) | ||
272 | { | ||
273 | case TEST_OP1_STARTED: | ||
274 | GNUNET_TESTBED_operation_release_ (op1); | ||
275 | GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 0); | ||
276 | op3 = GNUNET_TESTBED_operation_create_ (&op3, &start_cb, &release_cb); | ||
277 | GNUNET_TESTBED_operation_queue_insert2_ (q1, op3, 2); | ||
278 | GNUNET_TESTBED_operation_queue_insert2_ (q2, op3, 2); | ||
279 | GNUNET_TESTBED_operation_begin_wait_ (op3); | ||
280 | op4 = GNUNET_TESTBED_operation_create_ (&op4, &start_cb, &release_cb); | ||
281 | GNUNET_TESTBED_operation_queue_insert2_ (q1, op4, 2); | ||
282 | GNUNET_TESTBED_operation_queue_insert2_ (q2, op4, 2); | ||
283 | GNUNET_TESTBED_operation_begin_wait_ (op4); | ||
284 | break; | ||
285 | |||
286 | case TEST_OP1_RELEASED: | ||
287 | result = TEST_PAUSE; | ||
288 | GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 2); | ||
289 | break; | ||
290 | |||
291 | case TEST_OP2_STARTED: | ||
292 | GNUNET_TESTBED_operation_release_ (op2); | ||
293 | break; | ||
294 | |||
295 | case TEST_OP3_STARTED: | ||
296 | GNUNET_TESTBED_operation_release_ (op3); | ||
297 | break; | ||
298 | |||
299 | case TEST_OP4_STARTED: | ||
300 | GNUNET_TESTBED_operation_release_ (op4); | ||
301 | break; | ||
302 | |||
303 | case TEST_OP6_RELEASED: | ||
304 | op8 = GNUNET_TESTBED_operation_create_ (&op8, &start_cb, &release_cb); | ||
305 | GNUNET_TESTBED_operation_queue_insert2_ (q1, op8, 2); | ||
306 | GNUNET_TESTBED_operation_queue_insert2_ (q2, op8, 2); | ||
307 | result = TEST_OP8_WAITING; | ||
308 | GNUNET_TESTBED_operation_begin_wait_ (op8); | ||
309 | break; | ||
310 | |||
311 | case TEST_OP8_STARTED: | ||
312 | GNUNET_TESTBED_operation_inactivate_ (op8); | ||
313 | result = TEST_OP8_INACTIVE_1; | ||
314 | step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
315 | break; | ||
316 | |||
317 | case TEST_OP8_INACTIVE_1: | ||
318 | GNUNET_TESTBED_operation_activate_ (op8); | ||
319 | result = TEST_OP8_ACTIVE; | ||
320 | op9 = GNUNET_TESTBED_operation_create_ (&op9, &start_cb, &release_cb); | ||
321 | GNUNET_TESTBED_operation_queue_insert2_ (q1, op9, 1); | ||
322 | GNUNET_TESTBED_operation_queue_insert2_ (q2, op9, 1); | ||
323 | GNUNET_TESTBED_operation_begin_wait_ (op9); | ||
324 | step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
325 | break; | ||
326 | |||
327 | case TEST_OP8_ACTIVE: | ||
328 | GNUNET_TESTBED_operation_inactivate_ (op8); | ||
329 | /* op8 should be released by now due to above call */ | ||
330 | GNUNET_assert (TEST_OP8_RELEASED == result); | ||
331 | break; | ||
332 | |||
333 | case TEST_OP9_STARTED: | ||
334 | GNUNET_TESTBED_operation_release_ (op9); | ||
335 | break; | ||
336 | |||
337 | default: | ||
338 | GNUNET_assert (0); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | |||
343 | /** | ||
344 | * Function to call to start an operation once all | ||
345 | * queues the operation is part of declare that the | ||
346 | * operation can be activated. | ||
347 | */ | ||
348 | static void | ||
349 | start_cb (void *cls) | ||
350 | { | ||
351 | switch (result) | ||
352 | { | ||
353 | case TEST_INIT: | ||
354 | GNUNET_assert (&op1 == cls); | ||
355 | result = TEST_OP1_STARTED; | ||
356 | GNUNET_assert (NULL == step_task); | ||
357 | step_task = | ||
358 | GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
359 | break; | ||
360 | |||
361 | case TEST_PAUSE: | ||
362 | GNUNET_assert (&op2 == cls); | ||
363 | result = TEST_OP2_STARTED; | ||
364 | GNUNET_assert (NULL == step_task); | ||
365 | step_task = | ||
366 | GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
367 | break; | ||
368 | |||
369 | case TEST_OP2_RELEASED: | ||
370 | GNUNET_assert (&op3 == cls); | ||
371 | result = TEST_OP3_STARTED; | ||
372 | GNUNET_assert (NULL == step_task); | ||
373 | step_task = | ||
374 | GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
375 | break; | ||
376 | |||
377 | case TEST_OP3_RELEASED: | ||
378 | GNUNET_assert (&op4 == cls); | ||
379 | result = TEST_OP4_STARTED; | ||
380 | GNUNET_assert (NULL == step_task); | ||
381 | step_task = | ||
382 | GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
383 | break; | ||
384 | |||
385 | case TEST_OP4_RELEASED: | ||
386 | { | ||
387 | static int nops; | ||
388 | |||
389 | nops++; | ||
390 | if (nops == 3) | ||
391 | { | ||
392 | result = TEST_OP5_6_7_STARTED; | ||
393 | GNUNET_TESTBED_operation_release_ (op5); | ||
394 | op5 = NULL; | ||
395 | } | ||
396 | } | ||
397 | break; | ||
398 | |||
399 | case TEST_OP7_RELEASED: | ||
400 | GNUNET_assert (&op8 == cls); | ||
401 | result = TEST_OP8_STARTED; | ||
402 | step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
403 | break; | ||
404 | |||
405 | case TEST_OP8_RELEASED: | ||
406 | GNUNET_assert (&op9 == cls); | ||
407 | result = TEST_OP9_STARTED; | ||
408 | step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
409 | break; | ||
410 | |||
411 | default: | ||
412 | GNUNET_assert (0); | ||
413 | } | ||
414 | } | ||
415 | |||
416 | |||
417 | /** | ||
418 | * Function to cancel an operation (release all associated resources). This can | ||
419 | * be because of a call to "GNUNET_TESTBED_operation_cancel" (before the | ||
420 | * operation generated an event) or AFTER the operation generated an event due | ||
421 | * to a call to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that | ||
422 | * a callback to the 'OperationStart' precedes the call to 'OperationRelease'. | ||
423 | * Implementations of this function are expected to clean up whatever state is | ||
424 | * in 'cls' and release all resources associated with the operation. | ||
425 | */ | ||
426 | static void | ||
427 | release_cb (void *cls) | ||
428 | { | ||
429 | switch (result) | ||
430 | { | ||
431 | case TEST_OP1_STARTED: | ||
432 | GNUNET_assert (&op1 == cls); | ||
433 | result = TEST_OP1_RELEASED; | ||
434 | op1 = NULL; | ||
435 | step_task = | ||
436 | GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
437 | break; | ||
438 | |||
439 | case TEST_OP2_STARTED: | ||
440 | GNUNET_assert (&op2 == cls); | ||
441 | result = TEST_OP2_RELEASED; | ||
442 | GNUNET_assert (NULL == step_task); | ||
443 | break; | ||
444 | |||
445 | case TEST_OP3_STARTED: | ||
446 | GNUNET_assert (&op3 == cls); | ||
447 | result = TEST_OP3_RELEASED; | ||
448 | GNUNET_assert (NULL == step_task); | ||
449 | break; | ||
450 | |||
451 | case TEST_OP4_STARTED: | ||
452 | GNUNET_assert (&op4 == cls); | ||
453 | result = TEST_OP4_RELEASED; | ||
454 | GNUNET_assert (NULL == step_task); | ||
455 | op5 = GNUNET_TESTBED_operation_create_ (&op5, &start_cb, &release_cb); | ||
456 | GNUNET_TESTBED_operation_queue_insert2_ (q1, op5, 1); | ||
457 | GNUNET_TESTBED_operation_begin_wait_ (op5); | ||
458 | op6 = GNUNET_TESTBED_operation_create_ (&op6, &start_cb, &release_cb); | ||
459 | GNUNET_TESTBED_operation_queue_insert2_ (q2, op6, 1); | ||
460 | GNUNET_TESTBED_operation_begin_wait_ (op6); | ||
461 | op7 = GNUNET_TESTBED_operation_create_ (&op7, &start_cb, &release_cb); | ||
462 | GNUNET_TESTBED_operation_queue_insert2_ (q1, op7, 1); | ||
463 | GNUNET_TESTBED_operation_queue_insert2_ (q2, op7, 1); | ||
464 | GNUNET_TESTBED_operation_begin_wait_ (op7); | ||
465 | break; | ||
466 | |||
467 | case TEST_OP5_6_7_STARTED: | ||
468 | result = TEST_OP5_RELEASED; | ||
469 | op5 = NULL; | ||
470 | GNUNET_TESTBED_operation_release_ (op6); | ||
471 | break; | ||
472 | |||
473 | case TEST_OP5_RELEASED: | ||
474 | op6 = NULL; | ||
475 | result = TEST_OP6_RELEASED; | ||
476 | GNUNET_TESTBED_operation_inactivate_ (op7); | ||
477 | step_task = GNUNET_SCHEDULER_add_now (&step, NULL); | ||
478 | break; | ||
479 | |||
480 | case TEST_OP8_WAITING: | ||
481 | GNUNET_assert (&op7 == cls); | ||
482 | op7 = NULL; | ||
483 | result = TEST_OP7_RELEASED; | ||
484 | break; | ||
485 | |||
486 | case TEST_OP8_ACTIVE: | ||
487 | result = TEST_OP8_RELEASED; | ||
488 | op8 = NULL; | ||
489 | break; | ||
490 | |||
491 | case TEST_OP9_STARTED: | ||
492 | GNUNET_assert (&op9 == cls); | ||
493 | result = TEST_OP9_RELEASED; | ||
494 | GNUNET_TESTBED_operation_queue_destroy_ (q1); | ||
495 | GNUNET_TESTBED_operation_queue_destroy_ (q2); | ||
496 | q1 = NULL; | ||
497 | q2 = NULL; | ||
498 | break; | ||
499 | |||
500 | default: | ||
501 | GNUNET_assert (0); | ||
502 | } | ||
503 | } | ||
504 | |||
505 | |||
506 | /** | ||
507 | * Main run function. | ||
508 | * | ||
509 | * @param cls NULL | ||
510 | * @param args arguments passed to GNUNET_PROGRAM_run | ||
511 | * @param cfgfile the path to configuration file | ||
512 | * @param cfg the configuration file handle | ||
513 | */ | ||
514 | static void | ||
515 | run (void *cls, char *const *args, const char *cfgfile, | ||
516 | const struct GNUNET_CONFIGURATION_Handle *config) | ||
517 | { | ||
518 | q1 = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, 1); | ||
519 | GNUNET_assert (NULL != q1); | ||
520 | q2 = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, 2); | ||
521 | GNUNET_assert (NULL != q2); | ||
522 | op1 = GNUNET_TESTBED_operation_create_ (&op1, start_cb, release_cb); | ||
523 | GNUNET_assert (NULL != op1); | ||
524 | op2 = GNUNET_TESTBED_operation_create_ (&op2, start_cb, release_cb); | ||
525 | GNUNET_TESTBED_operation_queue_insert_ (q1, op1); | ||
526 | GNUNET_TESTBED_operation_queue_insert_ (q2, op1); | ||
527 | GNUNET_TESTBED_operation_begin_wait_ (op1); | ||
528 | GNUNET_TESTBED_operation_queue_insert_ (q1, op2); | ||
529 | GNUNET_TESTBED_operation_queue_insert_ (q2, op2); | ||
530 | GNUNET_TESTBED_operation_begin_wait_ (op2); | ||
531 | result = TEST_INIT; | ||
532 | } | ||
533 | |||
534 | |||
535 | /** | ||
536 | * Main function | ||
537 | */ | ||
538 | int | ||
539 | main (int argc, char **argv) | ||
540 | { | ||
541 | int ret; | ||
542 | char *const argv2[] = | ||
543 | { "test_testbed_api_operations", "-c", "test_testbed_api.conf", NULL }; | ||
544 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
545 | { GNUNET_GETOPT_OPTION_END }; | ||
546 | |||
547 | ret = | ||
548 | GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, | ||
549 | "test_testbed_api_operations", "nohelp", options, | ||
550 | &run, NULL); | ||
551 | if ((GNUNET_OK != ret) || (TEST_OP9_RELEASED != result)) | ||
552 | return 1; | ||
553 | op1 = NULL; | ||
554 | op2 = NULL; | ||
555 | op3 = NULL; | ||
556 | op4 = NULL; | ||
557 | op5 = NULL; | ||
558 | op6 = NULL; | ||
559 | op7 = NULL; | ||
560 | op8 = NULL; | ||
561 | op9 = NULL; | ||
562 | q1 = NULL; | ||
563 | q2 = NULL; | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | |||
568 | /* end of test_testbed_api_operations.c */ | ||
diff --git a/src/testbed/test_testbed_api_peer_reconfiguration.c b/src/testbed/test_testbed_api_peer_reconfiguration.c deleted file mode 100644 index 22dd46b53..000000000 --- a/src/testbed/test_testbed_api_peer_reconfiguration.c +++ /dev/null | |||
@@ -1,194 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/test_testbed_api_peer_reconfiguration.c | ||
23 | * @brief testcase for testing GNUNET_TESTBED_peer_manage_service() | ||
24 | * implementation | ||
25 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
26 | */ | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_testbed_service.h" | ||
31 | |||
32 | /** | ||
33 | * Number of peers we want to start | ||
34 | */ | ||
35 | #define NUM_PEERS 1 | ||
36 | |||
37 | /** | ||
38 | * The array of peers; we get them from the testbed | ||
39 | */ | ||
40 | static struct GNUNET_TESTBED_Peer **peers; | ||
41 | |||
42 | /** | ||
43 | * Operation handle | ||
44 | */ | ||
45 | static struct GNUNET_TESTBED_Operation *op; | ||
46 | |||
47 | /** | ||
48 | * Abort task identifier | ||
49 | */ | ||
50 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
51 | |||
52 | /** | ||
53 | * States in this test | ||
54 | */ | ||
55 | enum | ||
56 | { | ||
57 | /** | ||
58 | * Test has just been initialized | ||
59 | */ | ||
60 | STATE_INIT, | ||
61 | |||
62 | /** | ||
63 | * Peers have been started | ||
64 | */ | ||
65 | STATE_PEER_STARTED, | ||
66 | |||
67 | /** | ||
68 | * Peer has been reconfigured. Test completed successfully | ||
69 | */ | ||
70 | STATE_PEER_RECONFIGURED | ||
71 | } state; | ||
72 | |||
73 | /** | ||
74 | * Fail testcase | ||
75 | */ | ||
76 | #define FAIL_TEST(cond, ret) do { \ | ||
77 | if (! (cond)) { \ | ||
78 | GNUNET_break (0); \ | ||
79 | if (NULL != abort_task) \ | ||
80 | GNUNET_SCHEDULER_cancel (abort_task); \ | ||
81 | abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); \ | ||
82 | ret; \ | ||
83 | } \ | ||
84 | } while (0) | ||
85 | |||
86 | |||
87 | /** | ||
88 | * Abort task | ||
89 | * | ||
90 | * @param cls NULL | ||
91 | */ | ||
92 | static void | ||
93 | do_abort (void *cls) | ||
94 | { | ||
95 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting\n"); | ||
96 | abort_task = NULL; | ||
97 | if (NULL != op) | ||
98 | { | ||
99 | GNUNET_TESTBED_operation_done (op); | ||
100 | op = NULL; | ||
101 | } | ||
102 | GNUNET_SCHEDULER_shutdown (); | ||
103 | } | ||
104 | |||
105 | |||
106 | /** | ||
107 | * Signature of the event handler function called by the | ||
108 | * respective event controller. | ||
109 | * | ||
110 | * @param cls closure | ||
111 | * @param event information about the event | ||
112 | */ | ||
113 | static void | ||
114 | controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) | ||
115 | { | ||
116 | if (STATE_PEER_STARTED != state) | ||
117 | return; | ||
118 | if (GNUNET_TESTBED_ET_OPERATION_FINISHED != event->type) | ||
119 | { | ||
120 | GNUNET_TESTBED_operation_done (op); | ||
121 | op = NULL; | ||
122 | FAIL_TEST (0, return ); | ||
123 | } | ||
124 | if (NULL != event->details.operation_finished.emsg) | ||
125 | { | ||
126 | fprintf (stderr, "Operation failed: %s\n", | ||
127 | event->details.operation_finished.emsg); | ||
128 | GNUNET_TESTBED_operation_done (op); | ||
129 | op = NULL; | ||
130 | FAIL_TEST (0, return ); | ||
131 | } | ||
132 | GNUNET_TESTBED_operation_done (op); | ||
133 | state = STATE_PEER_RECONFIGURED; | ||
134 | GNUNET_SCHEDULER_cancel (abort_task); | ||
135 | abort_task = NULL; | ||
136 | GNUNET_SCHEDULER_shutdown (); | ||
137 | } | ||
138 | |||
139 | |||
140 | /** | ||
141 | * Signature of a main function for a testcase. | ||
142 | * | ||
143 | * @param cls closure | ||
144 | * @param h the run handle | ||
145 | * @param num_peers number of peers in 'peers' | ||
146 | * @param peers_ handle to peers run in the testbed | ||
147 | * @param links_succeeded the number of overlay link connection attempts that | ||
148 | * succeeded | ||
149 | * @param links_failed the number of overlay link connection attempts that | ||
150 | * failed | ||
151 | */ | ||
152 | static void | ||
153 | test_master (void *cls, | ||
154 | struct GNUNET_TESTBED_RunHandle *h, | ||
155 | unsigned int num_peers, | ||
156 | struct GNUNET_TESTBED_Peer **peers_, | ||
157 | unsigned int links_succeeded, | ||
158 | unsigned int links_failed) | ||
159 | { | ||
160 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
161 | |||
162 | FAIL_TEST (NUM_PEERS == num_peers, return ); | ||
163 | state = STATE_PEER_STARTED; | ||
164 | peers = peers_; | ||
165 | cfg = GNUNET_CONFIGURATION_create (); | ||
166 | FAIL_TEST (GNUNET_OK == GNUNET_CONFIGURATION_load | ||
167 | (cfg, "test_testbed_api_testbed_run_topologyrandom.conf"), | ||
168 | return ); | ||
169 | op = GNUNET_TESTBED_peer_update_configuration (peers[0], cfg); | ||
170 | GNUNET_CONFIGURATION_destroy (cfg); | ||
171 | FAIL_TEST (NULL != op, return ); | ||
172 | abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
173 | (GNUNET_TIME_UNIT_SECONDS, 30), | ||
174 | &do_abort, NULL); | ||
175 | } | ||
176 | |||
177 | |||
178 | /** | ||
179 | * Main function | ||
180 | */ | ||
181 | int | ||
182 | main (int argc, char **argv) | ||
183 | { | ||
184 | state = STATE_INIT; | ||
185 | (void) GNUNET_TESTBED_test_run ("test_testbed_api_peer_reconfiguration", | ||
186 | "test_testbed_api.conf", | ||
187 | NUM_PEERS, | ||
188 | 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED, | ||
189 | &controller_cb, NULL, | ||
190 | &test_master, NULL); | ||
191 | if (STATE_PEER_RECONFIGURED != state) | ||
192 | return 1; | ||
193 | return 0; | ||
194 | } | ||
diff --git a/src/testbed/test_testbed_api_peers_manage_services.c b/src/testbed/test_testbed_api_peers_manage_services.c deleted file mode 100644 index 93b0da550..000000000 --- a/src/testbed/test_testbed_api_peers_manage_services.c +++ /dev/null | |||
@@ -1,216 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/test_testbed_api_peers_manage_services.c | ||
23 | * @brief testcase for testing GNUNET_TESTBED_peer_manage_service() | ||
24 | * implementation | ||
25 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
26 | */ | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_testbed_service.h" | ||
31 | |||
32 | /** | ||
33 | * Number of peers we want to start | ||
34 | */ | ||
35 | #define NUM_PEERS 2 | ||
36 | |||
37 | /** | ||
38 | * The array of peers; we get them from the testbed | ||
39 | */ | ||
40 | static struct GNUNET_TESTBED_Peer **peers; | ||
41 | |||
42 | /** | ||
43 | * Operation handle | ||
44 | */ | ||
45 | static struct GNUNET_TESTBED_Operation *op; | ||
46 | |||
47 | /** | ||
48 | * dummy pointer | ||
49 | */ | ||
50 | static void *dummy_cls = (void *) 0xDEAD0001; | ||
51 | |||
52 | /** | ||
53 | * Abort task identifier | ||
54 | */ | ||
55 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
56 | |||
57 | /** | ||
58 | * States in this test | ||
59 | */ | ||
60 | enum | ||
61 | { | ||
62 | /** | ||
63 | * Test has just been initialized | ||
64 | */ | ||
65 | STATE_INIT, | ||
66 | |||
67 | /** | ||
68 | * Peers have been started | ||
69 | */ | ||
70 | STATE_PEERS_STARTED, | ||
71 | |||
72 | /** | ||
73 | * statistics service went down | ||
74 | */ | ||
75 | STATE_SERVICE_DOWN, | ||
76 | |||
77 | /** | ||
78 | * statistics service went up | ||
79 | */ | ||
80 | STATE_SERVICE_UP, | ||
81 | |||
82 | /** | ||
83 | * Testing completed successfully | ||
84 | */ | ||
85 | STATE_OK | ||
86 | } state; | ||
87 | |||
88 | /** | ||
89 | * Fail testcase | ||
90 | */ | ||
91 | #define FAIL_TEST(cond, ret) do { \ | ||
92 | if (! (cond)) { \ | ||
93 | GNUNET_break (0); \ | ||
94 | if (NULL != abort_task) \ | ||
95 | GNUNET_SCHEDULER_cancel (abort_task); \ | ||
96 | abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); \ | ||
97 | ret; \ | ||
98 | } \ | ||
99 | } while (0) | ||
100 | |||
101 | |||
102 | /** | ||
103 | * Abort task | ||
104 | * | ||
105 | * @param cls NULL | ||
106 | */ | ||
107 | static void | ||
108 | do_abort (void *cls) | ||
109 | { | ||
110 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting\n"); | ||
111 | abort_task = NULL; | ||
112 | if (NULL != op) | ||
113 | { | ||
114 | GNUNET_TESTBED_operation_done (op); | ||
115 | op = NULL; | ||
116 | } | ||
117 | GNUNET_SCHEDULER_shutdown (); | ||
118 | } | ||
119 | |||
120 | |||
121 | /** | ||
122 | * Callback to be called when an operation is completed | ||
123 | * | ||
124 | * @param cls the callback closure from functions generating an operation | ||
125 | * @param op the operation that has been finished | ||
126 | * @param emsg error message in case the operation has failed; will be NULL if | ||
127 | * operation has executed successfully. | ||
128 | */ | ||
129 | static void | ||
130 | op_comp_cb (void *cls, | ||
131 | struct GNUNET_TESTBED_Operation *op, | ||
132 | const char *emsg) | ||
133 | { | ||
134 | FAIL_TEST (cls == dummy_cls, return ); | ||
135 | FAIL_TEST (NULL == emsg, return ); | ||
136 | GNUNET_TESTBED_operation_done (op); | ||
137 | op = NULL; | ||
138 | switch (state) | ||
139 | { | ||
140 | case STATE_PEERS_STARTED: | ||
141 | state = STATE_SERVICE_DOWN; | ||
142 | op = GNUNET_TESTBED_peer_manage_service (dummy_cls, | ||
143 | peers[1], | ||
144 | "topology", | ||
145 | op_comp_cb, | ||
146 | dummy_cls, | ||
147 | 0); | ||
148 | GNUNET_assert (NULL != op); | ||
149 | break; | ||
150 | |||
151 | case STATE_SERVICE_DOWN: | ||
152 | state = STATE_SERVICE_UP; | ||
153 | GNUNET_SCHEDULER_cancel (abort_task); | ||
154 | abort_task = NULL; | ||
155 | state = STATE_OK; | ||
156 | GNUNET_SCHEDULER_shutdown (); | ||
157 | break; | ||
158 | |||
159 | default: | ||
160 | FAIL_TEST (0, return ); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | |||
165 | /** | ||
166 | * Signature of a main function for a testcase. | ||
167 | * | ||
168 | * @param cls closure | ||
169 | * @param h the run handle | ||
170 | * @param num_peers number of peers in 'peers' | ||
171 | * @param peers_ handle to peers run in the testbed | ||
172 | * @param links_succeeded the number of overlay link connection attempts that | ||
173 | * succeeded | ||
174 | * @param links_failed the number of overlay link connection attempts that | ||
175 | * failed | ||
176 | */ | ||
177 | static void | ||
178 | test_master (void *cls, | ||
179 | struct GNUNET_TESTBED_RunHandle *h, | ||
180 | unsigned int num_peers, | ||
181 | struct GNUNET_TESTBED_Peer **peers_, | ||
182 | unsigned int links_succeeded, | ||
183 | unsigned int links_failed) | ||
184 | { | ||
185 | FAIL_TEST (NUM_PEERS == num_peers, return ); | ||
186 | state = STATE_PEERS_STARTED; | ||
187 | peers = peers_; | ||
188 | op = GNUNET_TESTBED_peer_manage_service (dummy_cls, | ||
189 | peers[1], | ||
190 | "topology", | ||
191 | op_comp_cb, | ||
192 | dummy_cls, | ||
193 | 1); | ||
194 | FAIL_TEST (NULL != op, return ); | ||
195 | abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
196 | (GNUNET_TIME_UNIT_MINUTES, 1), | ||
197 | &do_abort, NULL); | ||
198 | } | ||
199 | |||
200 | |||
201 | /** | ||
202 | * Main function | ||
203 | */ | ||
204 | int | ||
205 | main (int argc, char **argv) | ||
206 | { | ||
207 | state = STATE_INIT; | ||
208 | (void) GNUNET_TESTBED_test_run ("test_testbed_api_peers_manage_services", | ||
209 | "test_testbed_api.conf", | ||
210 | NUM_PEERS, | ||
211 | 1LL, NULL, NULL, | ||
212 | &test_master, NULL); | ||
213 | if (STATE_OK != state) | ||
214 | return 1; | ||
215 | return 0; | ||
216 | } | ||
diff --git a/src/testbed/test_testbed_api_sd.c b/src/testbed/test_testbed_api_sd.c deleted file mode 100644 index 816f8e9a6..000000000 --- a/src/testbed/test_testbed_api_sd.c +++ /dev/null | |||
@@ -1,111 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | |||
22 | /** | ||
23 | * @file testbed/testbed_api_sd.c | ||
24 | * @brief test cases for calculating standard deviation | ||
25 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
26 | */ | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "testbed_api_sd.h" | ||
31 | |||
32 | /** | ||
33 | * Global return value | ||
34 | */ | ||
35 | static int ret; | ||
36 | |||
37 | /** | ||
38 | * Main run function. | ||
39 | * | ||
40 | * @param cls NULL | ||
41 | * @param args arguments passed to GNUNET_PROGRAM_run | ||
42 | * @param cfgfile the path to configuration file | ||
43 | * @param cfg the configuration file handle | ||
44 | */ | ||
45 | static void | ||
46 | run (void *cls, char *const *args, const char *cfgfile, | ||
47 | const struct GNUNET_CONFIGURATION_Handle *config) | ||
48 | { | ||
49 | struct SDHandle *h = GNUNET_TESTBED_SD_init_ (20); | ||
50 | int sd; | ||
51 | |||
52 | ret = 0; | ||
53 | GNUNET_TESTBED_SD_add_data_ (h, 40); | ||
54 | if (GNUNET_SYSERR != GNUNET_TESTBED_SD_deviation_factor_ (h, 10, &sd)) | ||
55 | { | ||
56 | GNUNET_break (0); | ||
57 | ret = 1; | ||
58 | goto err; | ||
59 | } | ||
60 | GNUNET_TESTBED_SD_add_data_ (h, 30); | ||
61 | if (GNUNET_SYSERR == GNUNET_TESTBED_SD_deviation_factor_ (h, 80, &sd)) | ||
62 | { | ||
63 | GNUNET_break (0); | ||
64 | ret = 1; | ||
65 | goto err; | ||
66 | } | ||
67 | GNUNET_TESTBED_SD_add_data_ (h, 40); | ||
68 | if ((GNUNET_SYSERR == GNUNET_TESTBED_SD_deviation_factor_ (h, 30, &sd)) | ||
69 | || (-2 != sd)) | ||
70 | { | ||
71 | GNUNET_break (0); | ||
72 | ret = 1; | ||
73 | goto err; | ||
74 | } | ||
75 | GNUNET_TESTBED_SD_add_data_ (h, 10); | ||
76 | GNUNET_TESTBED_SD_add_data_ (h, 30); | ||
77 | if ((GNUNET_SYSERR == GNUNET_TESTBED_SD_deviation_factor_ (h, 60, &sd)) | ||
78 | || (3 != sd)) | ||
79 | { | ||
80 | GNUNET_break (0); | ||
81 | ret = 1; | ||
82 | goto err; | ||
83 | } | ||
84 | |||
85 | err: | ||
86 | GNUNET_TESTBED_SD_destroy_ (h); | ||
87 | } | ||
88 | |||
89 | |||
90 | /** | ||
91 | * Main function | ||
92 | */ | ||
93 | int | ||
94 | main (int argc, char **argv) | ||
95 | { | ||
96 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
97 | GNUNET_GETOPT_OPTION_END | ||
98 | }; | ||
99 | int result; | ||
100 | |||
101 | result = GNUNET_SYSERR; | ||
102 | result = | ||
103 | GNUNET_PROGRAM_run (argc, argv, | ||
104 | "test_testbed_api_sd", "nohelp", options, &run, NULL); | ||
105 | if ((GNUNET_OK != result)) | ||
106 | return 1; | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | |||
111 | /* end of test_testbed_api_sd.c */ | ||
diff --git a/src/testbed/test_testbed_api_statistics.c b/src/testbed/test_testbed_api_statistics.c deleted file mode 100644 index 4d42cda6a..000000000 --- a/src/testbed/test_testbed_api_statistics.c +++ /dev/null | |||
@@ -1,205 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/test_testbed_api_statistics.c | ||
23 | * @brief testcase for testing GNUNET_TESTBED_get_statistics() implementation | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | |||
31 | /** | ||
32 | * Number of peers we want to start | ||
33 | */ | ||
34 | #define NUM_PEERS 5 | ||
35 | |||
36 | /** | ||
37 | * The array of peers; we get them from the testbed | ||
38 | */ | ||
39 | static struct GNUNET_TESTBED_Peer **peers; | ||
40 | |||
41 | /** | ||
42 | * Operation handle | ||
43 | */ | ||
44 | static struct GNUNET_TESTBED_Operation *op; | ||
45 | |||
46 | /** | ||
47 | * dummy pointer | ||
48 | */ | ||
49 | static void *dummy_cls = (void *) 0xDEAD0001; | ||
50 | |||
51 | /** | ||
52 | * Abort task identifier | ||
53 | */ | ||
54 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
55 | |||
56 | /** | ||
57 | * Global testing result | ||
58 | */ | ||
59 | static int result; | ||
60 | |||
61 | /** | ||
62 | * The peers we have seen in the statistics iterator | ||
63 | */ | ||
64 | static struct GNUNET_TESTBED_Peer **seen_peers; | ||
65 | |||
66 | /** | ||
67 | * Number of peers in the above array | ||
68 | */ | ||
69 | static unsigned int num_seen_peers; | ||
70 | |||
71 | |||
72 | /** | ||
73 | * Fail testcase | ||
74 | */ | ||
75 | #define FAIL_TEST(cond, ret) do { \ | ||
76 | if (! (cond)) { \ | ||
77 | GNUNET_break (0); \ | ||
78 | if (NULL != abort_task) \ | ||
79 | GNUNET_SCHEDULER_cancel (abort_task); \ | ||
80 | abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); \ | ||
81 | ret; \ | ||
82 | } \ | ||
83 | } while (0) | ||
84 | |||
85 | |||
86 | /** | ||
87 | * Abort task | ||
88 | * | ||
89 | * @param cls NULL | ||
90 | */ | ||
91 | static void | ||
92 | do_abort (void *cls) | ||
93 | { | ||
94 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test timed out -- Aborting\n"); | ||
95 | abort_task = NULL; | ||
96 | if (NULL != op) | ||
97 | { | ||
98 | GNUNET_TESTBED_operation_done (op); | ||
99 | op = NULL; | ||
100 | } | ||
101 | result = GNUNET_SYSERR; | ||
102 | } | ||
103 | |||
104 | |||
105 | /** | ||
106 | * Callback function to process statistic values from all peers. | ||
107 | * | ||
108 | * @param cls closure | ||
109 | * @param peer the peer the statistic belong to | ||
110 | * @param subsystem name of subsystem that created the statistic | ||
111 | * @param name the name of the datum | ||
112 | * @param value the current value | ||
113 | * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not | ||
114 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | ||
115 | */ | ||
116 | static int | ||
117 | stats_iterator (void *cls, | ||
118 | const struct GNUNET_TESTBED_Peer *peer, | ||
119 | const char *subsystem, const char *name, uint64_t value, | ||
120 | int is_persistent) | ||
121 | { | ||
122 | unsigned int cnt; | ||
123 | |||
124 | FAIL_TEST (cls == dummy_cls, return GNUNET_SYSERR); | ||
125 | for (cnt = 0; cnt < num_seen_peers; cnt++) | ||
126 | FAIL_TEST (peer != seen_peers[cnt], return GNUNET_SYSERR); | ||
127 | FAIL_TEST (NULL != subsystem, return GNUNET_SYSERR); | ||
128 | FAIL_TEST (NULL != name, return GNUNET_SYSERR); | ||
129 | GNUNET_array_append (seen_peers, num_seen_peers, | ||
130 | (struct GNUNET_TESTBED_Peer *) peer); | ||
131 | return GNUNET_SYSERR; | ||
132 | } | ||
133 | |||
134 | |||
135 | /** | ||
136 | * Callback to be called when an operation is completed | ||
137 | * | ||
138 | * @param cls the callback closure from functions generating an operation | ||
139 | * @param op the operation that has been finished | ||
140 | * @param emsg error message in case the operation has failed; will be NULL if | ||
141 | * operation has executed successfully. | ||
142 | */ | ||
143 | static void | ||
144 | op_comp_cb (void *cls, | ||
145 | struct GNUNET_TESTBED_Operation *op, | ||
146 | const char *emsg) | ||
147 | { | ||
148 | FAIL_TEST (cls == dummy_cls, return ); | ||
149 | result = GNUNET_OK; | ||
150 | GNUNET_TESTBED_operation_done (op); | ||
151 | op = NULL; | ||
152 | GNUNET_SCHEDULER_cancel (abort_task); | ||
153 | GNUNET_SCHEDULER_shutdown (); | ||
154 | } | ||
155 | |||
156 | |||
157 | /** | ||
158 | * Signature of a main function for a testcase. | ||
159 | * | ||
160 | * @param cls closure | ||
161 | * @param h the run handle | ||
162 | * @param num_peers number of peers in 'peers' | ||
163 | * @param peers_ handle to peers run in the testbed | ||
164 | * @param links_succeeded the number of overlay link connection attempts that | ||
165 | * succeeded | ||
166 | * @param links_failed the number of overlay link connection attempts that | ||
167 | * failed | ||
168 | */ | ||
169 | static void | ||
170 | test_master (void *cls, | ||
171 | struct GNUNET_TESTBED_RunHandle *h, | ||
172 | unsigned int num_peers, | ||
173 | struct GNUNET_TESTBED_Peer **peers_, | ||
174 | unsigned int links_succeeded, | ||
175 | unsigned int links_failed) | ||
176 | { | ||
177 | FAIL_TEST (NUM_PEERS == num_peers, return ); | ||
178 | peers = peers_; | ||
179 | op = GNUNET_TESTBED_get_statistics (num_peers, peers, | ||
180 | NULL, NULL, | ||
181 | &stats_iterator, | ||
182 | &op_comp_cb, | ||
183 | dummy_cls); | ||
184 | abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
185 | (GNUNET_TIME_UNIT_MINUTES, 1), | ||
186 | &do_abort, NULL); | ||
187 | } | ||
188 | |||
189 | |||
190 | /** | ||
191 | * Main function | ||
192 | */ | ||
193 | int | ||
194 | main (int argc, char **argv) | ||
195 | { | ||
196 | (void) GNUNET_TESTBED_test_run ("test_testbed_api_statistics", | ||
197 | "test_testbed_api_statistics.conf", | ||
198 | NUM_PEERS, | ||
199 | 1LL, NULL, NULL, | ||
200 | &test_master, NULL); | ||
201 | GNUNET_free (seen_peers); | ||
202 | if (GNUNET_OK != result) | ||
203 | return 1; | ||
204 | return 0; | ||
205 | } | ||
diff --git a/src/testbed/test_testbed_api_statistics.conf b/src/testbed/test_testbed_api_statistics.conf deleted file mode 100644 index edb2e2057..000000000 --- a/src/testbed/test_testbed_api_statistics.conf +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = 2D_TORUS | ||
5 | MAX_PARALLEL_SERVICE_CONNECTIONS = 2 | ||
6 | |||
7 | [statistics] | ||
8 | START_ON_DEMAND = YES | ||
9 | PORT = 59530 | ||
diff --git a/src/testbed/test_testbed_api_template.conf b/src/testbed/test_testbed_api_template.conf deleted file mode 100644 index ae0368a8b..000000000 --- a/src/testbed/test_testbed_api_template.conf +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | @INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf | ||
2 | @INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf | ||
3 | |||
4 | [testbed] | ||
5 | START_ON_DEMAND = NO | ||
6 | PORT = 12113 | ||
7 | ACCEPT_FROM = 127.0.0.1; | ||
8 | HOSTNAME = localhost | ||
9 | OVERLAY_TOPOLOGY = NONE | ||
10 | #PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args | ||
11 | |||
12 | [dhtcache] | ||
13 | QUOTA = 1 MB | ||
14 | DATABASE = heap | ||
15 | |||
16 | [transport] | ||
17 | PLUGINS = tcp | ||
18 | ACCEPT_FROM6 = ::1; | ||
19 | ACCEPT_FROM = 127.0.0.1; | ||
20 | NEIGHBOUR_LIMIT = 50 | ||
21 | IMMEDIATE_START = YES | ||
22 | |||
23 | # Transport requires resolver when connecting to a peer, so enable it | ||
24 | [resolver] | ||
25 | START_ON_DEMAND = YES | ||
26 | |||
27 | [ats] | ||
28 | WAN_QUOTA_OUT = 3932160 | ||
29 | WAN_QUOTA_IN = 3932160 | ||
30 | |||
31 | [core] | ||
32 | USE_EPHEMERAL_KEYS = NO | ||
33 | IMMEDIATE_START = YES | ||
34 | |||
35 | [transport-tcp] | ||
36 | TIMEOUT = 300 s | ||
37 | |||
38 | [PATHS] | ||
39 | GNUNET_TEST_HOME = $GNUNET_TMP/test-testbed/ | ||
40 | |||
41 | [nat] | ||
42 | RETURN_LOCAL_ADDRESSES = YES | ||
43 | |||
44 | [peerinfo] | ||
45 | NO_IO = YES | ||
46 | |||
47 | [rps] | ||
48 | START_ON_DEMAND = NO | ||
49 | IMMEDIATE_START = NO | ||
diff --git a/src/testbed/test_testbed_api_test.c b/src/testbed/test_testbed_api_test.c deleted file mode 100644 index f451c6555..000000000 --- a/src/testbed/test_testbed_api_test.c +++ /dev/null | |||
@@ -1,251 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/testbed/test_testbed_api_test.c | ||
23 | * @brief testing cases for testing high level testbed api helper functions | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | |||
31 | |||
32 | /** | ||
33 | * Generic logging shortcut | ||
34 | */ | ||
35 | #define LOG(kind, ...) \ | ||
36 | GNUNET_log (kind, __VA_ARGS__) | ||
37 | |||
38 | /** | ||
39 | * Number of peers we want to start | ||
40 | */ | ||
41 | #define NUM_PEERS 2 | ||
42 | |||
43 | /** | ||
44 | * Array of peers | ||
45 | */ | ||
46 | static struct GNUNET_TESTBED_Peer **peers; | ||
47 | |||
48 | /** | ||
49 | * Operation handle | ||
50 | */ | ||
51 | static struct GNUNET_TESTBED_Operation *op; | ||
52 | |||
53 | /** | ||
54 | * Abort task identifier | ||
55 | */ | ||
56 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
57 | |||
58 | /** | ||
59 | * shutdown task identifier | ||
60 | */ | ||
61 | static struct GNUNET_SCHEDULER_Task *shutdown_task; | ||
62 | |||
63 | /** | ||
64 | * Testing result | ||
65 | */ | ||
66 | static int result; | ||
67 | |||
68 | |||
69 | /** | ||
70 | * Shutdown nicely | ||
71 | * | ||
72 | * @param cls NULL | ||
73 | */ | ||
74 | static void | ||
75 | do_shutdown (void *cls) | ||
76 | { | ||
77 | shutdown_task = NULL; | ||
78 | if (NULL != abort_task) | ||
79 | GNUNET_SCHEDULER_cancel (abort_task); | ||
80 | if (NULL != op) | ||
81 | GNUNET_TESTBED_operation_done (op); | ||
82 | GNUNET_SCHEDULER_shutdown (); | ||
83 | } | ||
84 | |||
85 | |||
86 | /** | ||
87 | * shortcut to exit during failure | ||
88 | */ | ||
89 | #define FAIL_TEST(cond) do { \ | ||
90 | if (! (cond)) { \ | ||
91 | GNUNET_break (0); \ | ||
92 | if (NULL != abort_task) \ | ||
93 | GNUNET_SCHEDULER_cancel (abort_task); \ | ||
94 | abort_task = NULL; \ | ||
95 | if (NULL == shutdown_task) \ | ||
96 | shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); \ | ||
97 | return; \ | ||
98 | } \ | ||
99 | } while (0) | ||
100 | |||
101 | |||
102 | /** | ||
103 | * abort task to run on test timed out | ||
104 | * | ||
105 | * @param cls NULL | ||
106 | */ | ||
107 | static void | ||
108 | do_abort (void *cls) | ||
109 | { | ||
110 | LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); | ||
111 | abort_task = NULL; | ||
112 | if (NULL != shutdown_task) | ||
113 | GNUNET_SCHEDULER_cancel (shutdown_task); | ||
114 | do_shutdown (cls); | ||
115 | } | ||
116 | |||
117 | |||
118 | /** | ||
119 | * Callback to be called when the requested peer information is available | ||
120 | * | ||
121 | * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information() | ||
122 | * @param op the operation this callback corresponds to | ||
123 | * @param pinfo the result; will be NULL if the operation has failed | ||
124 | * @param emsg error message if the operation has failed; will be NULL if the | ||
125 | * operation is successful | ||
126 | */ | ||
127 | static void | ||
128 | peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_, | ||
129 | const struct GNUNET_TESTBED_PeerInformation *pinfo, | ||
130 | const char *emsg) | ||
131 | { | ||
132 | FAIL_TEST (op == op_); | ||
133 | FAIL_TEST (NULL == cb_cls); | ||
134 | FAIL_TEST (NULL == emsg); | ||
135 | FAIL_TEST (GNUNET_TESTBED_PIT_IDENTITY == pinfo->pit); | ||
136 | FAIL_TEST (NULL != pinfo->result.id); | ||
137 | GNUNET_TESTBED_operation_done (op); | ||
138 | op = NULL; | ||
139 | result = GNUNET_OK; | ||
140 | shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
141 | } | ||
142 | |||
143 | |||
144 | /** | ||
145 | * Callback to be called when an operation is completed | ||
146 | * | ||
147 | * @param cls the callback closure from functions generating an operation | ||
148 | * @param op the operation that has been finished | ||
149 | * @param emsg error message in case the operation has failed; will be NULL if | ||
150 | * operation has executed successfully. | ||
151 | */ | ||
152 | static void | ||
153 | op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op_, const char *emsg) | ||
154 | { | ||
155 | FAIL_TEST (NULL == cls); | ||
156 | FAIL_TEST (op == op_); | ||
157 | if (NULL != emsg) | ||
158 | { | ||
159 | LOG (GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg); | ||
160 | FAIL_TEST (0); | ||
161 | } | ||
162 | GNUNET_TESTBED_operation_done (op); | ||
163 | op = GNUNET_TESTBED_peer_get_information (peers[0], | ||
164 | GNUNET_TESTBED_PIT_IDENTITY, | ||
165 | &peerinfo_cb, NULL); | ||
166 | } | ||
167 | |||
168 | |||
169 | /** | ||
170 | * Controller event callback | ||
171 | * | ||
172 | * @param cls NULL | ||
173 | * @param event the controller event | ||
174 | */ | ||
175 | static void | ||
176 | controller_event_cb (void *cls, | ||
177 | const struct GNUNET_TESTBED_EventInformation *event) | ||
178 | { | ||
179 | switch (event->type) | ||
180 | { | ||
181 | case GNUNET_TESTBED_ET_CONNECT: | ||
182 | FAIL_TEST (event->details.peer_connect.peer1 == peers[0]); | ||
183 | FAIL_TEST (event->details.peer_connect.peer2 == peers[1]); | ||
184 | break; | ||
185 | |||
186 | default: | ||
187 | FAIL_TEST (0); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | |||
192 | /** | ||
193 | * Signature of a main function for a testcase. | ||
194 | * | ||
195 | * @param cls closure | ||
196 | * @param h the run handle | ||
197 | * @param num_peers number of peers in 'peers' | ||
198 | * @param peers- handle to peers run in the testbed | ||
199 | * @param links_succeeded the number of overlay link connection attempts that | ||
200 | * succeeded | ||
201 | * @param links_failed the number of overlay link connection attempts that | ||
202 | * failed | ||
203 | */ | ||
204 | static void | ||
205 | test_master (void *cls, | ||
206 | struct GNUNET_TESTBED_RunHandle *h, | ||
207 | unsigned int num_peers, | ||
208 | struct GNUNET_TESTBED_Peer **peers_, | ||
209 | unsigned int links_succeeded, | ||
210 | unsigned int links_failed) | ||
211 | { | ||
212 | unsigned int peer; | ||
213 | |||
214 | FAIL_TEST (NULL == cls); | ||
215 | FAIL_TEST (NUM_PEERS == num_peers); | ||
216 | FAIL_TEST (NULL != peers_); | ||
217 | for (peer = 0; peer < num_peers; peer++) | ||
218 | FAIL_TEST (NULL != peers_[peer]); | ||
219 | peers = peers_; | ||
220 | op = GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peers[0], | ||
221 | peers[1]); | ||
222 | abort_task = | ||
223 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
224 | (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort, | ||
225 | NULL); | ||
226 | } | ||
227 | |||
228 | |||
229 | /** | ||
230 | * Main function | ||
231 | */ | ||
232 | int | ||
233 | main (int argc, char **argv) | ||
234 | { | ||
235 | uint64_t event_mask; | ||
236 | |||
237 | result = GNUNET_SYSERR; | ||
238 | event_mask = 0; | ||
239 | event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); | ||
240 | event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
241 | (void) GNUNET_TESTBED_test_run ("test_testbed_api_test", | ||
242 | "test_testbed_api.conf", NUM_PEERS, | ||
243 | event_mask, &controller_event_cb, NULL, | ||
244 | &test_master, NULL); | ||
245 | if (GNUNET_OK != result) | ||
246 | return 1; | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | |||
251 | /* end of test_testbed_api_test.c */ | ||
diff --git a/src/testbed/test_testbed_api_test_timeout.c b/src/testbed/test_testbed_api_test_timeout.c deleted file mode 100644 index fe76ad441..000000000 --- a/src/testbed/test_testbed_api_test_timeout.c +++ /dev/null | |||
@@ -1,126 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/testbed/test_testbed_api_test.c | ||
23 | * @brief testing cases for testing notifications via test master callback upon | ||
24 | * timeout while setting up testbed using functions | ||
25 | * GNUNET_TESTBED_test_run() | ||
26 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
27 | */ | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_util_lib.h" | ||
31 | #include "gnunet_testbed_service.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Generic logging shortcut | ||
36 | */ | ||
37 | #define LOG(kind, ...) \ | ||
38 | GNUNET_log (kind, __VA_ARGS__) | ||
39 | |||
40 | /** | ||
41 | * Number of peers we want to start | ||
42 | */ | ||
43 | #define NUM_PEERS 25 | ||
44 | |||
45 | /** | ||
46 | * Testing result | ||
47 | */ | ||
48 | static int result; | ||
49 | |||
50 | |||
51 | /** | ||
52 | * shortcut to exit during failure | ||
53 | */ | ||
54 | #define FAIL_TEST(cond) do { \ | ||
55 | if (! (cond)) { \ | ||
56 | GNUNET_break (0); \ | ||
57 | GNUNET_SCHEDULER_shutdown (); \ | ||
58 | return; \ | ||
59 | } \ | ||
60 | } while (0) | ||
61 | |||
62 | |||
63 | /** | ||
64 | * Controller event callback | ||
65 | * | ||
66 | * @param cls NULL | ||
67 | * @param event the controller event | ||
68 | */ | ||
69 | static void | ||
70 | controller_event_cb (void *cls, | ||
71 | const struct GNUNET_TESTBED_EventInformation *event) | ||
72 | { | ||
73 | FAIL_TEST (0); | ||
74 | } | ||
75 | |||
76 | |||
77 | /** | ||
78 | * Signature of a main function for a testcase. | ||
79 | * | ||
80 | * @param cls closure | ||
81 | * @param h the run handle | ||
82 | * @param num_peers number of peers in 'peers' | ||
83 | * @param peers- handle to peers run in the testbed | ||
84 | * @param links_succeeded the number of overlay link connection attempts that | ||
85 | * succeeded | ||
86 | * @param links_failed the number of overlay link connection attempts that | ||
87 | * failed | ||
88 | */ | ||
89 | static void | ||
90 | test_master (void *cls, | ||
91 | struct GNUNET_TESTBED_RunHandle *h, | ||
92 | unsigned int num_peers, | ||
93 | struct GNUNET_TESTBED_Peer **peers_, | ||
94 | unsigned int links_succeeded, | ||
95 | unsigned int links_failed) | ||
96 | { | ||
97 | FAIL_TEST (NULL == cls); | ||
98 | FAIL_TEST (0 == num_peers); | ||
99 | FAIL_TEST (NULL == peers_); | ||
100 | result = GNUNET_OK; | ||
101 | GNUNET_SCHEDULER_shutdown (); | ||
102 | } | ||
103 | |||
104 | |||
105 | /** | ||
106 | * Main function | ||
107 | */ | ||
108 | int | ||
109 | main (int argc, char **argv) | ||
110 | { | ||
111 | uint64_t event_mask; | ||
112 | |||
113 | result = GNUNET_SYSERR; | ||
114 | event_mask = 0; | ||
115 | (void) GNUNET_TESTBED_test_run ("test_testbed_api_test", | ||
116 | "test_testbed_api_test_timeout.conf", | ||
117 | NUM_PEERS, | ||
118 | event_mask, &controller_event_cb, NULL, | ||
119 | &test_master, NULL); | ||
120 | if (GNUNET_OK != result) | ||
121 | return 1; | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | |||
126 | /* end of test_testbed_api_test.c */ | ||
diff --git a/src/testbed/test_testbed_api_test_timeout.conf b/src/testbed/test_testbed_api_test_timeout.conf deleted file mode 100644 index 8e283664d..000000000 --- a/src/testbed/test_testbed_api_test_timeout.conf +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = CLIQUE | ||
5 | SETUP_TIMEOUT = 2 ms | ||
diff --git a/src/testbed/test_testbed_api_testbed_run.c b/src/testbed/test_testbed_api_testbed_run.c deleted file mode 100644 index fda5c3223..000000000 --- a/src/testbed/test_testbed_api_testbed_run.c +++ /dev/null | |||
@@ -1,242 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/test_testbed_api_testbed_run.c | ||
23 | * @brief Test cases for testing high-level testbed management | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | |||
31 | /** | ||
32 | * Number of peers we want to start | ||
33 | */ | ||
34 | #define NUM_PEERS 5 | ||
35 | |||
36 | /** | ||
37 | * The array of peers; we fill this as the peers are given to us by the testbed | ||
38 | */ | ||
39 | static struct GNUNET_TESTBED_Peer *peers[NUM_PEERS]; | ||
40 | |||
41 | /** | ||
42 | * Operation handle | ||
43 | */ | ||
44 | static struct GNUNET_TESTBED_Operation *op; | ||
45 | |||
46 | /** | ||
47 | * Abort task identifier | ||
48 | */ | ||
49 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
50 | |||
51 | /** | ||
52 | * Current peer id | ||
53 | */ | ||
54 | static unsigned int peer_id; | ||
55 | |||
56 | /** | ||
57 | * Testing result | ||
58 | */ | ||
59 | static int result; | ||
60 | |||
61 | /** | ||
62 | * Should we wait forever after testbed is initialized? | ||
63 | */ | ||
64 | static int wait_forever; | ||
65 | |||
66 | |||
67 | /** | ||
68 | * Shutdown nicely | ||
69 | * | ||
70 | * @param cls NULL | ||
71 | */ | ||
72 | static void | ||
73 | do_shutdown (void *cls) | ||
74 | { | ||
75 | if (NULL != abort_task) | ||
76 | GNUNET_SCHEDULER_cancel (abort_task); | ||
77 | GNUNET_SCHEDULER_shutdown (); /* Stop scheduler to shutdown testbed run */ | ||
78 | } | ||
79 | |||
80 | |||
81 | /** | ||
82 | * abort task to run on test timed out | ||
83 | * | ||
84 | * @param cls NULL | ||
85 | */ | ||
86 | static void | ||
87 | do_abort (void *cls) | ||
88 | { | ||
89 | abort_task = NULL; | ||
90 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
91 | "Test timed out -- Aborting\n"); | ||
92 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
93 | } | ||
94 | |||
95 | |||
96 | /** | ||
97 | * Signature of a main function for a testcase. | ||
98 | * | ||
99 | * @param cls closure | ||
100 | * @param h the run handle | ||
101 | * @param num_peers number of peers in 'peers' | ||
102 | * @param peers_ handle to peers run in the testbed | ||
103 | * @param links_succeeded the number of overlay link connection attempts that | ||
104 | * succeeded | ||
105 | * @param links_failed the number of overlay link connection attempts that | ||
106 | * failed | ||
107 | */ | ||
108 | static void | ||
109 | test_master (void *cls, | ||
110 | struct GNUNET_TESTBED_RunHandle *h, | ||
111 | unsigned int num_peers, | ||
112 | struct GNUNET_TESTBED_Peer **peers_, | ||
113 | unsigned int links_succeeded, | ||
114 | unsigned int links_failed) | ||
115 | { | ||
116 | result = GNUNET_OK; | ||
117 | if (GNUNET_YES == wait_forever) | ||
118 | { | ||
119 | if (NULL == abort_task) | ||
120 | return; /* abort already scheduled */ | ||
121 | GNUNET_SCHEDULER_cancel (abort_task); | ||
122 | abort_task = NULL; | ||
123 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
124 | return; | ||
125 | } | ||
126 | GNUNET_assert (NULL != peers[0]); | ||
127 | op = GNUNET_TESTBED_peer_stop (NULL, peers[0], NULL, NULL); | ||
128 | GNUNET_assert (NULL != op); | ||
129 | } | ||
130 | |||
131 | |||
132 | /** | ||
133 | * Controller event callback | ||
134 | * | ||
135 | * @param cls NULL | ||
136 | * @param event the controller event | ||
137 | */ | ||
138 | static void | ||
139 | controller_event_cb (void *cls, | ||
140 | const struct GNUNET_TESTBED_EventInformation *event) | ||
141 | { | ||
142 | switch (event->type) | ||
143 | { | ||
144 | case GNUNET_TESTBED_ET_PEER_START: | ||
145 | GNUNET_assert (NULL == peers[peer_id]); | ||
146 | GNUNET_assert (NULL != event->details.peer_start.peer); | ||
147 | peers[peer_id++] = event->details.peer_start.peer; | ||
148 | break; | ||
149 | |||
150 | case GNUNET_TESTBED_ET_PEER_STOP: | ||
151 | GNUNET_assert (NULL != op); | ||
152 | GNUNET_TESTBED_operation_done (op); | ||
153 | GNUNET_assert (peers[0] == event->details.peer_stop.peer); | ||
154 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
155 | break; | ||
156 | |||
157 | default: | ||
158 | GNUNET_assert (0); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | |||
163 | /** | ||
164 | * Main run function. | ||
165 | * | ||
166 | * @param cls NULL | ||
167 | * @param args arguments passed to GNUNET_PROGRAM_run | ||
168 | * @param cfgfile the path to configuration file | ||
169 | * @param cfg the configuration file handle | ||
170 | */ | ||
171 | static void | ||
172 | run (void *cls, | ||
173 | char *const *args, | ||
174 | const char *cfgfile, | ||
175 | const struct GNUNET_CONFIGURATION_Handle *config) | ||
176 | { | ||
177 | uint64_t event_mask; | ||
178 | |||
179 | event_mask = 0; | ||
180 | event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START); | ||
181 | event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP); | ||
182 | GNUNET_TESTBED_run (NULL, config, NUM_PEERS, event_mask, | ||
183 | &controller_event_cb, NULL, | ||
184 | &test_master, NULL); | ||
185 | abort_task = | ||
186 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
187 | (GNUNET_TIME_UNIT_SECONDS, 300), | ||
188 | &do_abort, | ||
189 | NULL); | ||
190 | } | ||
191 | |||
192 | |||
193 | /** | ||
194 | * Main function | ||
195 | */ | ||
196 | int | ||
197 | main (int argc, char **argv) | ||
198 | { | ||
199 | char *argv2[] = { | ||
200 | "test_testbed_api_testbed_run", | ||
201 | "-c", NULL, | ||
202 | NULL | ||
203 | }; | ||
204 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
205 | GNUNET_GETOPT_OPTION_END | ||
206 | }; | ||
207 | char *testname; | ||
208 | char *config_filename; | ||
209 | int ret; | ||
210 | |||
211 | if (NULL == (testname = strrchr (argv[0], (int) '_'))) | ||
212 | { | ||
213 | GNUNET_break (0); | ||
214 | return 1; | ||
215 | } | ||
216 | testname++; | ||
217 | testname = GNUNET_strdup (testname); | ||
218 | |||
219 | if (0 == strcmp ("waitforever", testname)) | ||
220 | wait_forever = GNUNET_YES; | ||
221 | if ((GNUNET_YES != wait_forever) && (0 != strcmp ("run", testname))) | ||
222 | { | ||
223 | GNUNET_asprintf (&config_filename, "test_testbed_api_testbed_run_%s.conf", | ||
224 | testname); | ||
225 | } | ||
226 | else | ||
227 | config_filename = GNUNET_strdup ("test_testbed_api.conf"); | ||
228 | GNUNET_free (testname); | ||
229 | argv2[2] = config_filename; | ||
230 | result = GNUNET_SYSERR; | ||
231 | ret = | ||
232 | GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, | ||
233 | "test_testbed_api_testbed_run", "nohelp", options, | ||
234 | &run, NULL); | ||
235 | GNUNET_free (config_filename); | ||
236 | if ((GNUNET_OK != ret) || (GNUNET_OK != result)) | ||
237 | return 1; | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | |||
242 | /* end of test_testbed_api_testbed_run.c */ | ||
diff --git a/src/testbed/test_testbed_api_testbed_run_topology2dtorus.conf b/src/testbed/test_testbed_api_testbed_run_topology2dtorus.conf deleted file mode 100644 index 72704e80e..000000000 --- a/src/testbed/test_testbed_api_testbed_run_topology2dtorus.conf +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = 2D_TORUS | ||
5 | |||
diff --git a/src/testbed/test_testbed_api_testbed_run_topologyclique.conf b/src/testbed/test_testbed_api_testbed_run_topologyclique.conf deleted file mode 100644 index 9c5b8f439..000000000 --- a/src/testbed/test_testbed_api_testbed_run_topologyclique.conf +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = CLIQUE | ||
diff --git a/src/testbed/test_testbed_api_testbed_run_topologyfromfile.conf b/src/testbed/test_testbed_api_testbed_run_topologyfromfile.conf deleted file mode 100644 index b0e28227c..000000000 --- a/src/testbed/test_testbed_api_testbed_run_topologyfromfile.conf +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = FROM_FILE | ||
5 | OVERLAY_TOPOLOGY_FILE = overlay_topology.txt | ||
diff --git a/src/testbed/test_testbed_api_testbed_run_topologyline.conf b/src/testbed/test_testbed_api_testbed_run_topologyline.conf deleted file mode 100644 index f8e0343e0..000000000 --- a/src/testbed/test_testbed_api_testbed_run_topologyline.conf +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = LINE | ||
diff --git a/src/testbed/test_testbed_api_testbed_run_topologyrandom.conf b/src/testbed/test_testbed_api_testbed_run_topologyrandom.conf deleted file mode 100644 index c2bd85b01..000000000 --- a/src/testbed/test_testbed_api_testbed_run_topologyrandom.conf +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = RANDOM | ||
5 | OVERLAY_RANDOM_LINKS = 5 | ||
diff --git a/src/testbed/test_testbed_api_testbed_run_topologyring.conf b/src/testbed/test_testbed_api_testbed_run_topologyring.conf deleted file mode 100644 index 810edd91a..000000000 --- a/src/testbed/test_testbed_api_testbed_run_topologyring.conf +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = RING | ||
diff --git a/src/testbed/test_testbed_api_testbed_run_topologyscalefree.conf b/src/testbed/test_testbed_api_testbed_run_topologyscalefree.conf deleted file mode 100644 index 0f89ca83a..000000000 --- a/src/testbed/test_testbed_api_testbed_run_topologyscalefree.conf +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = SCALE_FREE | ||
5 | SCALE_FREE_TOPOLOGY_CAP = 70 | ||
6 | SCALE_FREE_TOPOLOGY_M = 5 | ||
diff --git a/src/testbed/test_testbed_api_testbed_run_topologysmallworld.conf b/src/testbed/test_testbed_api_testbed_run_topologysmallworld.conf deleted file mode 100644 index ba13a325c..000000000 --- a/src/testbed/test_testbed_api_testbed_run_topologysmallworld.conf +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = SMALL_WORLD | ||
5 | OVERLAY_RANDOM_LINKS = 3 | ||
diff --git a/src/testbed/test_testbed_api_testbed_run_topologysmallworldring.conf b/src/testbed/test_testbed_api_testbed_run_topologysmallworldring.conf deleted file mode 100644 index 0e1b32f13..000000000 --- a/src/testbed/test_testbed_api_testbed_run_topologysmallworldring.conf +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = SMALL_WORLD_RING | ||
5 | OVERLAY_RANDOM_LINKS = 3 | ||
diff --git a/src/testbed/test_testbed_api_testbed_run_topologystar.conf b/src/testbed/test_testbed_api_testbed_run_topologystar.conf deleted file mode 100644 index 13f8d1784..000000000 --- a/src/testbed/test_testbed_api_testbed_run_topologystar.conf +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = STAR | ||
diff --git a/src/testbed/test_testbed_api_topology.c b/src/testbed/test_testbed_api_topology.c deleted file mode 100644 index dada7286f..000000000 --- a/src/testbed/test_testbed_api_topology.c +++ /dev/null | |||
@@ -1,189 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/testbed/test_testbed_api_topology.c | ||
23 | * @brief testing cases for testing high level testbed api helper functions | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | |||
31 | /** | ||
32 | * Number of peers we want to start | ||
33 | */ | ||
34 | #define NUM_PEERS 10 | ||
35 | |||
36 | /** | ||
37 | * Array of peers | ||
38 | */ | ||
39 | static struct GNUNET_TESTBED_Peer **peers; | ||
40 | |||
41 | /** | ||
42 | * Operation handle | ||
43 | */ | ||
44 | static struct GNUNET_TESTBED_Operation *op; | ||
45 | |||
46 | /** | ||
47 | * Shutdown task | ||
48 | */ | ||
49 | static struct GNUNET_SCHEDULER_Task *shutdown_task; | ||
50 | |||
51 | /** | ||
52 | * Testing result | ||
53 | */ | ||
54 | static int result; | ||
55 | |||
56 | /** | ||
57 | * Counter for counting overlay connections | ||
58 | */ | ||
59 | static unsigned int overlay_connects; | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Shutdown nicely | ||
64 | * | ||
65 | * @param cls NULL | ||
66 | */ | ||
67 | static void | ||
68 | do_shutdown (void *cls) | ||
69 | { | ||
70 | shutdown_task = NULL; | ||
71 | if (NULL != op) | ||
72 | { | ||
73 | GNUNET_TESTBED_operation_done (op); | ||
74 | op = NULL; | ||
75 | } | ||
76 | GNUNET_SCHEDULER_shutdown (); | ||
77 | } | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Controller event callback | ||
82 | * | ||
83 | * @param cls NULL | ||
84 | * @param event the controller event | ||
85 | */ | ||
86 | static void | ||
87 | controller_event_cb (void *cls, | ||
88 | const struct GNUNET_TESTBED_EventInformation *event) | ||
89 | { | ||
90 | switch (event->type) | ||
91 | { | ||
92 | case GNUNET_TESTBED_ET_CONNECT: | ||
93 | overlay_connects++; | ||
94 | if ((NUM_PEERS) == overlay_connects) | ||
95 | { | ||
96 | result = GNUNET_OK; | ||
97 | GNUNET_SCHEDULER_cancel (shutdown_task); | ||
98 | shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
99 | } | ||
100 | break; | ||
101 | |||
102 | case GNUNET_TESTBED_ET_OPERATION_FINISHED: | ||
103 | GNUNET_assert (NULL != event->details.operation_finished.emsg); | ||
104 | break; | ||
105 | |||
106 | default: | ||
107 | GNUNET_break (0); | ||
108 | if ((GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type) && | ||
109 | (NULL != event->details.operation_finished.emsg)) | ||
110 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
111 | "An operation failed with error: %s\n", | ||
112 | event->details.operation_finished.emsg); | ||
113 | result = GNUNET_SYSERR; | ||
114 | GNUNET_SCHEDULER_cancel (shutdown_task); | ||
115 | shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | |||
120 | /** | ||
121 | * Signature of a main function for a testcase. | ||
122 | * | ||
123 | * @param cls closure | ||
124 | * @param h the run handle | ||
125 | * @param num_peers number of peers in 'peers' | ||
126 | * @param peers_ handle to peers run in the testbed | ||
127 | * @param links_succeeded the number of overlay link connection attempts that | ||
128 | * succeeded | ||
129 | * @param links_failed the number of overlay link connection attempts that | ||
130 | * failed | ||
131 | */ | ||
132 | static void | ||
133 | test_master (void *cls, | ||
134 | struct GNUNET_TESTBED_RunHandle *h, | ||
135 | unsigned int num_peers, | ||
136 | struct GNUNET_TESTBED_Peer **peers_, | ||
137 | unsigned int links_succeeded, | ||
138 | unsigned int links_failed) | ||
139 | { | ||
140 | unsigned int peer; | ||
141 | |||
142 | GNUNET_assert (NULL == cls); | ||
143 | if (NULL == peers_) | ||
144 | { | ||
145 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test due to timeout\n"); | ||
146 | return; | ||
147 | } | ||
148 | GNUNET_assert (NUM_PEERS == num_peers); | ||
149 | for (peer = 0; peer < num_peers; peer++) | ||
150 | GNUNET_assert (NULL != peers_[peer]); | ||
151 | peers = peers_; | ||
152 | overlay_connects = 0; | ||
153 | op = GNUNET_TESTBED_overlay_configure_topology (NULL, NUM_PEERS, peers, NULL, | ||
154 | NULL, | ||
155 | NULL, | ||
156 | GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, | ||
157 | NUM_PEERS, | ||
158 | GNUNET_TESTBED_TOPOLOGY_OPTION_END); | ||
159 | GNUNET_assert (NULL != op); | ||
160 | shutdown_task = | ||
161 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
162 | (GNUNET_TIME_UNIT_SECONDS, 300), | ||
163 | do_shutdown, NULL); | ||
164 | } | ||
165 | |||
166 | |||
167 | /** | ||
168 | * Main function | ||
169 | */ | ||
170 | int | ||
171 | main (int argc, char **argv) | ||
172 | { | ||
173 | uint64_t event_mask; | ||
174 | |||
175 | result = GNUNET_SYSERR; | ||
176 | event_mask = 0; | ||
177 | event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); | ||
178 | event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
179 | (void) GNUNET_TESTBED_test_run ("test_testbed_api_test", | ||
180 | "test_testbed_api.conf", NUM_PEERS, | ||
181 | event_mask, &controller_event_cb, NULL, | ||
182 | &test_master, NULL); | ||
183 | if (GNUNET_OK != result) | ||
184 | return 1; | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | |||
189 | /* end of test_testbed_api_topology.c */ | ||
diff --git a/src/testbed/test_testbed_api_topology_clique.c b/src/testbed/test_testbed_api_topology_clique.c deleted file mode 100644 index 33c21a69c..000000000 --- a/src/testbed/test_testbed_api_topology_clique.c +++ /dev/null | |||
@@ -1,185 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/testbed/test_testbed_api_topology.c | ||
23 | * @brief testing cases for testing high level testbed api helper functions | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | |||
31 | /** | ||
32 | * Number of peers we want to start | ||
33 | */ | ||
34 | #define NUM_PEERS 10 | ||
35 | |||
36 | /** | ||
37 | * Array of peers | ||
38 | */ | ||
39 | static struct GNUNET_TESTBED_Peer **peers; | ||
40 | |||
41 | /** | ||
42 | * Operation handle | ||
43 | */ | ||
44 | static struct GNUNET_TESTBED_Operation *op; | ||
45 | |||
46 | /** | ||
47 | * Shutdown task | ||
48 | */ | ||
49 | static struct GNUNET_SCHEDULER_Task *shutdown_task; | ||
50 | |||
51 | /** | ||
52 | * Testing result | ||
53 | */ | ||
54 | static int result; | ||
55 | |||
56 | /** | ||
57 | * Counter for counting overlay connections | ||
58 | */ | ||
59 | static unsigned int overlay_connects; | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Shutdown nicely | ||
64 | * | ||
65 | * @param cls NULL | ||
66 | */ | ||
67 | static void | ||
68 | do_shutdown (void *cls) | ||
69 | { | ||
70 | shutdown_task = NULL; | ||
71 | if (NULL != op) | ||
72 | { | ||
73 | GNUNET_TESTBED_operation_done (op); | ||
74 | op = NULL; | ||
75 | } | ||
76 | GNUNET_SCHEDULER_shutdown (); | ||
77 | } | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Controller event callback | ||
82 | * | ||
83 | * @param cls NULL | ||
84 | * @param event the controller event | ||
85 | */ | ||
86 | static void | ||
87 | controller_event_cb (void *cls, | ||
88 | const struct GNUNET_TESTBED_EventInformation *event) | ||
89 | { | ||
90 | switch (event->type) | ||
91 | { | ||
92 | case GNUNET_TESTBED_ET_CONNECT: | ||
93 | overlay_connects++; | ||
94 | if ((NUM_PEERS * (NUM_PEERS - 1)) == overlay_connects) | ||
95 | { | ||
96 | result = GNUNET_OK; | ||
97 | GNUNET_SCHEDULER_cancel (shutdown_task); | ||
98 | shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
99 | } | ||
100 | break; | ||
101 | |||
102 | case GNUNET_TESTBED_ET_OPERATION_FINISHED: | ||
103 | GNUNET_assert (NULL != event->details.operation_finished.emsg); | ||
104 | break; | ||
105 | |||
106 | default: | ||
107 | GNUNET_break (0); | ||
108 | result = GNUNET_SYSERR; | ||
109 | GNUNET_SCHEDULER_cancel (shutdown_task); | ||
110 | shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | |||
115 | /** | ||
116 | * Signature of a main function for a testcase. | ||
117 | * | ||
118 | * @param cls closure | ||
119 | * @param h the run handle | ||
120 | * @param num_peers number of peers in 'peers' | ||
121 | * @param peers_ handle to peers run in the testbed | ||
122 | * @param links_succeeded the number of overlay link connection attempts that | ||
123 | * succeeded | ||
124 | * @param links_failed the number of overlay link connection attempts that | ||
125 | * failed | ||
126 | */ | ||
127 | static void | ||
128 | test_master (void *cls, | ||
129 | struct GNUNET_TESTBED_RunHandle *h, | ||
130 | unsigned int num_peers, | ||
131 | struct GNUNET_TESTBED_Peer **peers_, | ||
132 | unsigned int links_succeeded, | ||
133 | unsigned int links_failed) | ||
134 | { | ||
135 | unsigned int peer; | ||
136 | |||
137 | GNUNET_assert (NULL == cls); | ||
138 | if (NULL == peers_) | ||
139 | { | ||
140 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test due to timeout\n"); | ||
141 | return; | ||
142 | } | ||
143 | GNUNET_assert (NUM_PEERS == num_peers); | ||
144 | for (peer = 0; peer < num_peers; peer++) | ||
145 | GNUNET_assert (NULL != peers_[peer]); | ||
146 | peers = peers_; | ||
147 | overlay_connects = 0; | ||
148 | op = GNUNET_TESTBED_overlay_configure_topology (NULL, NUM_PEERS, peers, NULL, | ||
149 | NULL, | ||
150 | NULL, | ||
151 | GNUNET_TESTBED_TOPOLOGY_CLIQUE, | ||
152 | /* GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, */ | ||
153 | /* NUM_PEERS, */ | ||
154 | GNUNET_TESTBED_TOPOLOGY_OPTION_END); | ||
155 | GNUNET_assert (NULL != op); | ||
156 | shutdown_task = | ||
157 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
158 | (GNUNET_TIME_UNIT_SECONDS, 300), | ||
159 | do_shutdown, NULL); | ||
160 | } | ||
161 | |||
162 | |||
163 | /** | ||
164 | * Main function | ||
165 | */ | ||
166 | int | ||
167 | main (int argc, char **argv) | ||
168 | { | ||
169 | uint64_t event_mask; | ||
170 | |||
171 | result = GNUNET_SYSERR; | ||
172 | event_mask = 0; | ||
173 | event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); | ||
174 | event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
175 | (void) GNUNET_TESTBED_test_run ("test_testbed_api_test", | ||
176 | "test_testbed_api.conf", NUM_PEERS, | ||
177 | event_mask, &controller_event_cb, NULL, | ||
178 | &test_master, NULL); | ||
179 | if (GNUNET_OK != result) | ||
180 | return 1; | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | |||
185 | /* end of test_testbed_api_topology.c */ | ||
diff --git a/src/testbed/test_testbed_underlay.c b/src/testbed/test_testbed_underlay.c deleted file mode 100644 index 8b706ff83..000000000 --- a/src/testbed/test_testbed_underlay.c +++ /dev/null | |||
@@ -1,174 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/test_testbed_underlay.c | ||
23 | * @brief testcase binary for testing testbed underlay restrictions | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | |||
31 | |||
32 | /** | ||
33 | * Number of peers we start in this test case | ||
34 | */ | ||
35 | #define NUM_PEERS 3 | ||
36 | |||
37 | /** | ||
38 | * Result of this test case | ||
39 | */ | ||
40 | static int result; | ||
41 | |||
42 | static struct GNUNET_TESTBED_Operation *op; | ||
43 | |||
44 | |||
45 | /** | ||
46 | * Shutdown testcase | ||
47 | * | ||
48 | * @param cls NULL | ||
49 | * @param tc scheduler task context | ||
50 | */ | ||
51 | static void | ||
52 | do_shutdown (void *cls) | ||
53 | { | ||
54 | if (NULL != op) | ||
55 | GNUNET_TESTBED_operation_done (op); | ||
56 | op = NULL; | ||
57 | } | ||
58 | |||
59 | |||
60 | /** | ||
61 | * Callback to be called when an operation is completed | ||
62 | * | ||
63 | * @param cls the callback closure from functions generating an operation | ||
64 | * @param op the operation that has been finished | ||
65 | * @param emsg error message in case the operation has failed; will be NULL if | ||
66 | * operation has executed successfully. | ||
67 | */ | ||
68 | static void | ||
69 | overlay_connect_status (void *cls, | ||
70 | struct GNUNET_TESTBED_Operation *op_, | ||
71 | const char *emsg) | ||
72 | { | ||
73 | GNUNET_assert (op_ == op); | ||
74 | GNUNET_TESTBED_operation_done (op); | ||
75 | op = NULL; | ||
76 | if (NULL == emsg) | ||
77 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
78 | "Peers 0 and 2 should not get connected\n"); | ||
79 | else | ||
80 | { | ||
81 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
82 | "Peers 0 and 2 not connected: %s. Success!\n", emsg); | ||
83 | result = GNUNET_OK; | ||
84 | } | ||
85 | GNUNET_SCHEDULER_shutdown (); | ||
86 | } | ||
87 | |||
88 | |||
89 | /** | ||
90 | * Signature of a main function for a testcase. | ||
91 | * | ||
92 | * @param cls closure | ||
93 | * @param h the run handle | ||
94 | * @param num_peers number of peers in 'peers' | ||
95 | * @param peers_ handle to peers run in the testbed | ||
96 | * @param links_succeeded the number of overlay link connection attempts that | ||
97 | * succeeded | ||
98 | * @param links_failed the number of overlay link connection attempts that | ||
99 | * failed | ||
100 | */ | ||
101 | static void | ||
102 | test_master (void *cls, | ||
103 | struct GNUNET_TESTBED_RunHandle *h, | ||
104 | unsigned int num_peers, | ||
105 | struct GNUNET_TESTBED_Peer **peers_, | ||
106 | unsigned int links_succeeded, | ||
107 | unsigned int links_failed) | ||
108 | { | ||
109 | GNUNET_assert (NULL == cls); | ||
110 | if (NULL == peers_) | ||
111 | { | ||
112 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test due to timeout\n"); | ||
113 | GNUNET_SCHEDULER_shutdown (); | ||
114 | return; | ||
115 | } | ||
116 | GNUNET_assert (NUM_PEERS == num_peers); | ||
117 | op = GNUNET_TESTBED_overlay_connect (NULL, | ||
118 | &overlay_connect_status, | ||
119 | NULL, | ||
120 | peers_[0], | ||
121 | peers_[2]); | ||
122 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply ( | ||
123 | GNUNET_TIME_UNIT_SECONDS, | ||
124 | 60), | ||
125 | &do_shutdown, NULL); | ||
126 | } | ||
127 | |||
128 | |||
129 | #ifndef PATH_MAX | ||
130 | /** | ||
131 | * Assumed maximum path length (for the log file name). | ||
132 | */ | ||
133 | #define PATH_MAX 4096 | ||
134 | #endif | ||
135 | |||
136 | |||
137 | /** | ||
138 | * Main function | ||
139 | */ | ||
140 | int | ||
141 | main (int argc, char **argv) | ||
142 | { | ||
143 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
144 | char pwd[PATH_MAX]; | ||
145 | char *dbfile; | ||
146 | uint64_t event_mask; | ||
147 | |||
148 | result = GNUNET_SYSERR; | ||
149 | event_mask = 0; | ||
150 | cfg = GNUNET_CONFIGURATION_create (); | ||
151 | GNUNET_assert (GNUNET_YES == | ||
152 | GNUNET_CONFIGURATION_parse (cfg, | ||
153 | "test_testbed_underlay.conf.in")); | ||
154 | if (NULL == getcwd (pwd, PATH_MAX)) | ||
155 | return 1; | ||
156 | GNUNET_assert (0 < GNUNET_asprintf (&dbfile, "%s/%s", pwd, | ||
157 | "test-underlay.sqlite")); | ||
158 | GNUNET_CONFIGURATION_set_value_string (cfg, "TESTBED-UNDERLAY", "DBFILE", | ||
159 | dbfile); | ||
160 | GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_write | ||
161 | (cfg, "test_testbed_underlay.conf")); | ||
162 | GNUNET_CONFIGURATION_destroy (cfg); | ||
163 | cfg = NULL; | ||
164 | GNUNET_free (dbfile); | ||
165 | dbfile = NULL; | ||
166 | (void) GNUNET_TESTBED_test_run ("test_testbed_underlay", | ||
167 | "test_testbed_underlay.conf", NUM_PEERS, | ||
168 | event_mask, NULL, NULL, | ||
169 | &test_master, NULL); | ||
170 | (void) unlink ("test_testbed_underlay.conf"); | ||
171 | if (GNUNET_OK != result) | ||
172 | return 1; | ||
173 | return 0; | ||
174 | } | ||
diff --git a/src/testbed/test_testbed_underlay.conf.in b/src/testbed/test_testbed_underlay.conf.in deleted file mode 100644 index 1916cc59d..000000000 --- a/src/testbed/test_testbed_underlay.conf.in +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | @INLINE@ test_testbed_api_template.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = LINE | ||
5 | OPERATION_TIMEOUT = 5 s | ||
6 | |||
7 | [testbed-underlay] | ||
8 | START_ON_DEMAND = NO | ||
9 | DBFILE = /will/be/overwritten/by/testcase | ||
10 | IMMEDIATE_START = YES | ||
11 | |||
12 | [dv] | ||
13 | START_ON_DEMAND = NO | ||
diff --git a/src/testbed/testbed.conf.in b/src/testbed/testbed.conf.in deleted file mode 100644 index c1d64b324..000000000 --- a/src/testbed/testbed.conf.in +++ /dev/null | |||
@@ -1,116 +0,0 @@ | |||
1 | [testbed] | ||
2 | START_ON_DEMAND = NO | ||
3 | @JAVAPORT@ PORT = 2101 | ||
4 | HOSTNAME = localhost | ||
5 | BINARY = gnunet-service-testbed | ||
6 | |||
7 | # How long should operations wait? | ||
8 | OPERATION_TIMEOUT = 30 s | ||
9 | |||
10 | # Set this to the path where the testbed helper is installed. By default the | ||
11 | # helper binary is searched in @prefix@/lib/gnunet/libexec/ | ||
12 | # HELPER_BINARY_PATH = @prefix@/lib/gnunet/libexec/gnunet-helper-testbed | ||
13 | |||
14 | # Add your local network address here. For example, if you want to run | ||
15 | # testbed on a group of hosts connected to network 192.168.1.0/24, then set | ||
16 | # ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24; | ||
17 | # Multiple network addresses can be given. They should be separated by `;' | ||
18 | ACCEPT_FROM = 127.0.0.1; | ||
19 | ACCEPT_FROM6 = ::1; | ||
20 | |||
21 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-testbed.sock | ||
22 | UNIX_MATCH_UID = YES | ||
23 | UNIX_MATCH_GID = YES | ||
24 | |||
25 | # How many maximum number of operations can be run in parallel. This number | ||
26 | # should be decreased if the system is getting overloaded and to reduce the load | ||
27 | # exerted by the emulation. | ||
28 | MAX_PARALLEL_OPERATIONS = 1000 | ||
29 | MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 1 | ||
30 | |||
31 | # What topology should be generated by the helper functions GNUNET_TESTBED_run() | ||
32 | # and GNUNET_TESTBED_test_run(). This option has no effect if testbed is | ||
33 | # initialized with other functions. Valid values can be found at: | ||
34 | # https://gnunet.org/supported-topologies | ||
35 | OVERLAY_TOPOLOGY = NONE | ||
36 | |||
37 | # Number of random links to be included to the generate the above topology. | ||
38 | # Note that not all topologies require this option and ignore it. Topologies | ||
39 | # requiring this option are RANDOM, SMALL_WORLD and SMALL_WORLD ring. | ||
40 | # OVERLAY_RANDOM_LINKS = | ||
41 | |||
42 | # This option is required if the OVERLAY_TOPOLOGY is set to FROM_FILE. It is | ||
43 | # ignored for all other topologies. This option should contain the path to | ||
44 | # the file containing the topology information. The format of the file is | ||
45 | # presented at: https://gnunet.org/topology-file-format | ||
46 | # OVERLAY_TOPOLOGY_FILE = /path/to/topology-file | ||
47 | |||
48 | # The following options are required if the OVERLAY_TOPOLOGY is set to | ||
49 | # SCALE_FREE. They are ignored in all other cases. | ||
50 | # The number of maximum peers which can connect to a peer | ||
51 | SCALE_FREE_TOPOLOGY_CAP = 70 | ||
52 | # The minimum number of peers which a peer has to connect | ||
53 | SCALE_FREE_TOPOLOGY_M = 5 | ||
54 | |||
55 | # How many maximum number of handles to peers' services should be kept open at | ||
56 | # any time. This number also keeps a check on the number of open descriptors as | ||
57 | # opening a service connection results in opening a file descriptor. | ||
58 | MAX_PARALLEL_SERVICE_CONNECTIONS = 256 | ||
59 | |||
60 | # Size of the internal testbed cache. It is used to cache handles to peers | ||
61 | # while trying to connect them. | ||
62 | CACHE_SIZE = 30 | ||
63 | |||
64 | # Maximum number of file descriptors a testbed controller is permitted to keep | ||
65 | # open. | ||
66 | MAX_OPEN_FDS = 512 | ||
67 | |||
68 | # How long should we wait for testbed to setup while using helper functions | ||
69 | # GNUNET_TESTBED_test_run() and GNUNET_TESTBED_run() | ||
70 | SETUP_TIMEOUT = 5 m | ||
71 | |||
72 | # Where should testbed write load statistics data | ||
73 | # STATS_DIR = /tmp/load | ||
74 | |||
75 | # What services should be shared among peers. | ||
76 | # Format is "[<service:share>] [<service:share>] ...". The shared services are | ||
77 | # started standalone without any other peer services or a hostkey. For this | ||
78 | # reason, only services which doesn't depend on other services can only be | ||
79 | # shared. Example: To share peerinfo among every 10 peers. The following spec | ||
80 | # will start 5 peerinfo services when 50 peers are started: | ||
81 | # | ||
82 | # SHARED_SERVICES = peerinfo:10 | ||
83 | # | ||
84 | # To share multiple services | ||
85 | # | ||
86 | # SHARED_SERVICES = service1:n_share1 service2:n_share2 ... | ||
87 | # | ||
88 | # Default is to share no services | ||
89 | SHARED_SERVICES = | ||
90 | |||
91 | |||
92 | [testbed-barrier] | ||
93 | START_ON_DEMAND = NO | ||
94 | @UNIXONLY@ PORT = 2103 | ||
95 | HOSTNAME = localhost | ||
96 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-testbed-barrier.sock | ||
97 | UNIX_MATCH_UID = YES | ||
98 | UNIX_MATCH_GID = YES | ||
99 | |||
100 | |||
101 | # This section is related to configuring underlay restrictions to simulate | ||
102 | # connectivity restrictions of NAT boxes | ||
103 | [testbed-underlay] | ||
104 | START_ON_DEMAND = NO | ||
105 | NOARMBIND = YES | ||
106 | BINARY = gnunet-daemon-testbed-underlay | ||
107 | # The sqlite3 database file containing information about what underlay | ||
108 | # restrictions to apply | ||
109 | # DBFILE = | ||
110 | |||
111 | [latency-logger] | ||
112 | START_ON_DEMAND = NO | ||
113 | NOARMBIND = YES | ||
114 | BINARY = gnunet-daemon-latency-logger | ||
115 | # The sqlite3 database file where the latency values are to be stored | ||
116 | # DBFILE = | ||
diff --git a/src/testbed/testbed.h b/src/testbed/testbed.h deleted file mode 100644 index 0f86c149b..000000000 --- a/src/testbed/testbed.h +++ /dev/null | |||
@@ -1,866 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed.h | ||
23 | * @brief IPC messages between testing API and service ("controller") | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | |||
27 | #ifndef TESTBED_H | ||
28 | #define TESTBED_H | ||
29 | |||
30 | #include "gnunet_util_lib.h" | ||
31 | |||
32 | GNUNET_NETWORK_STRUCT_BEGIN | ||
33 | /** | ||
34 | * Initial message from a client to a testing control service. | ||
35 | */ | ||
36 | struct GNUNET_TESTBED_InitMessage | ||
37 | { | ||
38 | /** | ||
39 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_INIT | ||
40 | */ | ||
41 | struct GNUNET_MessageHeader header; | ||
42 | |||
43 | /** | ||
44 | * Host ID that the controller is either given (if this is the | ||
45 | * dominating client) or assumed to have (for peer-connections | ||
46 | * between controllers). A controller must check that all | ||
47 | * connections make consistent claims... | ||
48 | */ | ||
49 | uint32_t host_id GNUNET_PACKED; | ||
50 | |||
51 | /** | ||
52 | * Event mask that specifies which events this client | ||
53 | * is interested in. In NBO. | ||
54 | */ | ||
55 | uint64_t event_mask GNUNET_PACKED; | ||
56 | |||
57 | /* Followed by 0-terminated hostname of the controller */ | ||
58 | }; | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Notify the service about a host that we intend to use. | ||
63 | */ | ||
64 | struct GNUNET_TESTBED_AddHostMessage | ||
65 | { | ||
66 | /** | ||
67 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST | ||
68 | */ | ||
69 | struct GNUNET_MessageHeader header; | ||
70 | |||
71 | /** | ||
72 | * Unique ID for the host (in NBO). | ||
73 | */ | ||
74 | uint32_t host_id GNUNET_PACKED; | ||
75 | |||
76 | /** | ||
77 | * SSH port to use, 0 for default (in NBO). | ||
78 | */ | ||
79 | uint16_t ssh_port GNUNET_PACKED; | ||
80 | |||
81 | /** | ||
82 | * Number of bytes in the user name that follows; | ||
83 | * 0 to use no user name; otherwise 'strlen (username)', | ||
84 | * excluding 0-termination! | ||
85 | */ | ||
86 | uint16_t username_length GNUNET_PACKED; | ||
87 | |||
88 | /** | ||
89 | * Number of bytes in the host name (excluding 0-termination) that follows the | ||
90 | * user name; cannot be 0 | ||
91 | */ | ||
92 | uint16_t hostname_length GNUNET_PACKED; | ||
93 | |||
94 | /** | ||
95 | * The length of the uncompressed configuration | ||
96 | */ | ||
97 | uint16_t config_size GNUNET_PACKED; | ||
98 | |||
99 | /* followed by non 0-terminated user name */ | ||
100 | |||
101 | /* followed by non 0-terminated host name */ | ||
102 | |||
103 | /* followed by gzip compressed configuration to start or connect to a | ||
104 | controller on this host. While starting the controller this configuration | ||
105 | is used as a template */ | ||
106 | }; | ||
107 | |||
108 | |||
109 | /** | ||
110 | * Confirmation from the service that adding a host | ||
111 | * worked (or failed). | ||
112 | * FIXME: Where is this required? | ||
113 | */ | ||
114 | struct GNUNET_TESTBED_HostConfirmedMessage | ||
115 | { | ||
116 | /** | ||
117 | * Type is GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS | ||
118 | */ | ||
119 | struct GNUNET_MessageHeader header; | ||
120 | |||
121 | /** | ||
122 | * Unique ID for the host (in NBO). | ||
123 | */ | ||
124 | uint32_t host_id GNUNET_PACKED; | ||
125 | |||
126 | /* followed by the 0-terminated error message (on failure) | ||
127 | * (typical errors include host-id already in use) */ | ||
128 | }; | ||
129 | |||
130 | |||
131 | /** | ||
132 | * Client notifies controller that it should delegate | ||
133 | * requests for a particular client to a particular | ||
134 | * sub-controller. | ||
135 | */ | ||
136 | struct GNUNET_TESTBED_ControllerLinkRequest | ||
137 | { | ||
138 | /** | ||
139 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS | ||
140 | */ | ||
141 | struct GNUNET_MessageHeader header; | ||
142 | |||
143 | /** | ||
144 | * For which host should requests be delegated? NBO. | ||
145 | */ | ||
146 | uint32_t delegated_host_id GNUNET_PACKED; | ||
147 | |||
148 | /** | ||
149 | * The id of the operation which created this message | ||
150 | */ | ||
151 | uint64_t operation_id GNUNET_PACKED; | ||
152 | |||
153 | /** | ||
154 | * Which host is responsible for managing the delegation? NBO | ||
155 | */ | ||
156 | uint32_t slave_host_id GNUNET_PACKED; | ||
157 | |||
158 | /** | ||
159 | * Set to 1 if the receiving controller is the master controller for | ||
160 | * the slave host (and thus responsible for starting it?). 0 if not | ||
161 | */ | ||
162 | uint8_t is_subordinate; | ||
163 | }; | ||
164 | |||
165 | |||
166 | /** | ||
167 | * Response message for ControllerLinkRequest message | ||
168 | */ | ||
169 | struct GNUNET_TESTBED_ControllerLinkResponse | ||
170 | { | ||
171 | /** | ||
172 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT | ||
173 | */ | ||
174 | struct GNUNET_MessageHeader header; | ||
175 | |||
176 | /** | ||
177 | * The size of the compressed configuration. Can be ZERO if the controller is | ||
178 | * not started (depends on the ControllerLinkRequest). NBO. | ||
179 | */ | ||
180 | uint16_t config_size GNUNET_PACKED; | ||
181 | |||
182 | /** | ||
183 | * Set to #GNUNET_YES to signify SUCCESS; #GNUNET_NO to signify failure | ||
184 | */ | ||
185 | uint16_t success GNUNET_PACKED; | ||
186 | |||
187 | /** | ||
188 | * The id of the operation which created this message. NBO | ||
189 | */ | ||
190 | uint64_t operation_id GNUNET_PACKED; | ||
191 | |||
192 | /* If controller linking is successful and configuration is present, then here | ||
193 | * comes the serialized gzip configuration with which the controller is | ||
194 | * running at the delegate host */ | ||
195 | |||
196 | /* In case of failure, here comes the error message (without \0 termination)*/ | ||
197 | }; | ||
198 | |||
199 | |||
200 | /** | ||
201 | * Message sent from client to testing service to | ||
202 | * create (configure, but not start) a peer. | ||
203 | */ | ||
204 | struct GNUNET_TESTBED_PeerCreateMessage | ||
205 | { | ||
206 | /** | ||
207 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER | ||
208 | */ | ||
209 | struct GNUNET_MessageHeader header; | ||
210 | |||
211 | /** | ||
212 | * On which host should the peer be started? | ||
213 | */ | ||
214 | uint32_t host_id GNUNET_PACKED; | ||
215 | |||
216 | /** | ||
217 | * Unique operation id | ||
218 | */ | ||
219 | uint64_t operation_id GNUNET_PACKED; | ||
220 | |||
221 | /** | ||
222 | * Unique ID for the peer. | ||
223 | */ | ||
224 | uint32_t peer_id GNUNET_PACKED; | ||
225 | |||
226 | /** | ||
227 | * Size of the uncompressed configuration | ||
228 | */ | ||
229 | uint16_t config_size GNUNET_PACKED; | ||
230 | |||
231 | /* followed by serialized peer configuration; | ||
232 | * gzip'ed configuration file in INI format */ | ||
233 | }; | ||
234 | |||
235 | |||
236 | /** | ||
237 | * Message sent from client to testing service to | ||
238 | * reconfigure a (stopped) a peer. | ||
239 | */ | ||
240 | struct GNUNET_TESTBED_PeerReconfigureMessage | ||
241 | { | ||
242 | /** | ||
243 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER | ||
244 | */ | ||
245 | struct GNUNET_MessageHeader header; | ||
246 | |||
247 | /** | ||
248 | * Unique ID for the peer. | ||
249 | */ | ||
250 | uint32_t peer_id GNUNET_PACKED; | ||
251 | |||
252 | /** | ||
253 | * Operation ID that is used to identify this operation. | ||
254 | */ | ||
255 | uint64_t operation_id GNUNET_PACKED; | ||
256 | |||
257 | /** | ||
258 | * The length of the serialized configuration when uncompressed | ||
259 | */ | ||
260 | uint16_t config_size GNUNET_PACKED; | ||
261 | |||
262 | /* followed by serialized peer configuration; | ||
263 | * gzip'ed configuration file in INI format */ | ||
264 | }; | ||
265 | |||
266 | |||
267 | /** | ||
268 | * Message sent from client to testing service to | ||
269 | * start a peer. | ||
270 | */ | ||
271 | struct GNUNET_TESTBED_PeerStartMessage | ||
272 | { | ||
273 | /** | ||
274 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_START_PEER | ||
275 | */ | ||
276 | struct GNUNET_MessageHeader header; | ||
277 | |||
278 | /** | ||
279 | * Unique ID for the peer. | ||
280 | */ | ||
281 | uint32_t peer_id GNUNET_PACKED; | ||
282 | |||
283 | /** | ||
284 | * Operation ID that is used to identify this operation. | ||
285 | */ | ||
286 | uint64_t operation_id GNUNET_PACKED; | ||
287 | }; | ||
288 | |||
289 | |||
290 | /** | ||
291 | * Message sent from client to testing service to | ||
292 | * stop a peer. | ||
293 | */ | ||
294 | struct GNUNET_TESTBED_PeerStopMessage | ||
295 | { | ||
296 | /** | ||
297 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER | ||
298 | */ | ||
299 | struct GNUNET_MessageHeader header; | ||
300 | |||
301 | /** | ||
302 | * Unique ID for the peer. | ||
303 | */ | ||
304 | uint32_t peer_id GNUNET_PACKED; | ||
305 | |||
306 | /** | ||
307 | * Operation ID that is used to identify this operation. | ||
308 | */ | ||
309 | uint64_t operation_id GNUNET_PACKED; | ||
310 | }; | ||
311 | |||
312 | |||
313 | /** | ||
314 | * Message sent from client to testing service to | ||
315 | * destroy a (stopped) peer. | ||
316 | */ | ||
317 | struct GNUNET_TESTBED_PeerDestroyMessage | ||
318 | { | ||
319 | /** | ||
320 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER | ||
321 | */ | ||
322 | struct GNUNET_MessageHeader header; | ||
323 | |||
324 | /** | ||
325 | * Unique ID for the peer. | ||
326 | */ | ||
327 | uint32_t peer_id GNUNET_PACKED; | ||
328 | |||
329 | /** | ||
330 | * Operation ID that is used to identify this operation. | ||
331 | */ | ||
332 | uint64_t operation_id GNUNET_PACKED; | ||
333 | }; | ||
334 | |||
335 | |||
336 | /** | ||
337 | * Message sent from client to testing service to | ||
338 | * (re)configure a "physical" link between two peers. | ||
339 | */ | ||
340 | struct GNUNET_TESTBED_ConfigureUnderlayLinkMessage | ||
341 | { | ||
342 | /** | ||
343 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_CONFIGURE_UNDERLAY_LINK | ||
344 | */ | ||
345 | struct GNUNET_MessageHeader header; | ||
346 | |||
347 | /** | ||
348 | * 'enum GNUNET_TESTBED_ConnectOption' of the option to change | ||
349 | */ | ||
350 | int32_t connect_option GNUNET_PACKED; | ||
351 | |||
352 | /** | ||
353 | * Unique ID for the first peer. | ||
354 | */ | ||
355 | uint32_t peer1 GNUNET_PACKED; | ||
356 | |||
357 | /** | ||
358 | * Unique ID for the second peer. | ||
359 | */ | ||
360 | uint32_t peer2 GNUNET_PACKED; | ||
361 | |||
362 | /** | ||
363 | * Operation ID that is used to identify this operation. | ||
364 | */ | ||
365 | uint64_t operation_id GNUNET_PACKED; | ||
366 | |||
367 | /* followed by option-dependent variable-size values */ | ||
368 | }; | ||
369 | |||
370 | |||
371 | /** | ||
372 | * Message sent from client to testing service to | ||
373 | * connect two peers. | ||
374 | */ | ||
375 | struct GNUNET_TESTBED_OverlayConnectMessage | ||
376 | { | ||
377 | /** | ||
378 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT | ||
379 | */ | ||
380 | struct GNUNET_MessageHeader header; | ||
381 | |||
382 | /** | ||
383 | * Unique ID for the first peer. | ||
384 | */ | ||
385 | uint32_t peer1 GNUNET_PACKED; | ||
386 | |||
387 | /** | ||
388 | * Operation ID that is used to identify this operation. | ||
389 | */ | ||
390 | uint64_t operation_id GNUNET_PACKED; | ||
391 | |||
392 | /** | ||
393 | * Unique ID for the second peer. | ||
394 | */ | ||
395 | uint32_t peer2 GNUNET_PACKED; | ||
396 | |||
397 | /** | ||
398 | * The ID of the host which runs peer2 | ||
399 | */ | ||
400 | uint32_t peer2_host_id GNUNET_PACKED; | ||
401 | }; | ||
402 | |||
403 | |||
404 | /** | ||
405 | * Message sent from host controller of a peer(A) to the host controller of | ||
406 | * another peer(B) to request B to connect to A | ||
407 | */ | ||
408 | struct GNUNET_TESTBED_RemoteOverlayConnectMessage | ||
409 | { | ||
410 | /** | ||
411 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT | ||
412 | */ | ||
413 | struct GNUNET_MessageHeader header; | ||
414 | |||
415 | /** | ||
416 | * The Unique ID of B | ||
417 | */ | ||
418 | uint32_t peer GNUNET_PACKED; | ||
419 | |||
420 | /** | ||
421 | * The Operation ID that is used to identify this operation | ||
422 | */ | ||
423 | uint64_t operation_id GNUNET_PACKED; | ||
424 | |||
425 | /** | ||
426 | * Identity of A | ||
427 | */ | ||
428 | struct GNUNET_PeerIdentity peer_identity; | ||
429 | |||
430 | /** | ||
431 | * To be followed by the HELLO message of A | ||
432 | */ | ||
433 | struct GNUNET_MessageHeader hello[0]; | ||
434 | // FIXME: we usually do not use this gcc-hack as some | ||
435 | // compilers / tools really get messed up by it... | ||
436 | }; | ||
437 | |||
438 | |||
439 | /** | ||
440 | * Event notification from a controller to a client. | ||
441 | */ | ||
442 | struct GNUNET_TESTBED_PeerEventMessage | ||
443 | { | ||
444 | /** | ||
445 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT | ||
446 | */ | ||
447 | struct GNUNET_MessageHeader header; | ||
448 | |||
449 | /** | ||
450 | * `enum GNUNET_TESTBED_EventType` (in NBO); | ||
451 | * either #GNUNET_TESTBED_ET_PEER_START or #GNUNET_TESTBED_ET_PEER_STOP. | ||
452 | */ | ||
453 | int32_t event_type GNUNET_PACKED; | ||
454 | |||
455 | /** | ||
456 | * Host where the peer is running. | ||
457 | */ | ||
458 | uint32_t host_id GNUNET_PACKED; | ||
459 | |||
460 | /** | ||
461 | * Peer that was started or stopped. | ||
462 | */ | ||
463 | uint32_t peer_id GNUNET_PACKED; | ||
464 | |||
465 | /** | ||
466 | * Operation ID that is used to identify this operation. | ||
467 | */ | ||
468 | uint64_t operation_id GNUNET_PACKED; | ||
469 | }; | ||
470 | |||
471 | |||
472 | /** | ||
473 | * Event notification from a controller to a client. | ||
474 | */ | ||
475 | struct GNUNET_TESTBED_ConnectionEventMessage | ||
476 | { | ||
477 | /** | ||
478 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT | ||
479 | */ | ||
480 | struct GNUNET_MessageHeader header; | ||
481 | |||
482 | /** | ||
483 | * 'enum GNUNET_TESTBED_EventType' (in NBO); | ||
484 | * either #GNUNET_TESTBED_ET_CONNECT or #GNUNET_TESTBED_ET_DISCONNECT. | ||
485 | */ | ||
486 | int32_t event_type GNUNET_PACKED; | ||
487 | |||
488 | /** | ||
489 | * First peer. | ||
490 | */ | ||
491 | uint32_t peer1 GNUNET_PACKED; | ||
492 | |||
493 | /** | ||
494 | * Second peer. | ||
495 | */ | ||
496 | uint32_t peer2 GNUNET_PACKED; | ||
497 | |||
498 | /** | ||
499 | * Operation ID that is used to identify this operation. | ||
500 | */ | ||
501 | uint64_t operation_id GNUNET_PACKED; | ||
502 | }; | ||
503 | |||
504 | |||
505 | /** | ||
506 | * Event notification from a controller to a client. | ||
507 | */ | ||
508 | struct GNUNET_TESTBED_OperationFailureEventMessage | ||
509 | { | ||
510 | /** | ||
511 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT | ||
512 | */ | ||
513 | struct GNUNET_MessageHeader header; | ||
514 | |||
515 | /** | ||
516 | * 'enum GNUNET_TESTBED_EventType' (in NBO); | ||
517 | * #GNUNET_TESTBED_ET_OPERATION_FINISHED. | ||
518 | */ | ||
519 | int32_t event_type GNUNET_PACKED; | ||
520 | |||
521 | /** | ||
522 | * Operation ID of the operation that created this event. | ||
523 | */ | ||
524 | uint64_t operation_id GNUNET_PACKED; | ||
525 | |||
526 | /* followed by 0-terminated error message */ | ||
527 | }; | ||
528 | |||
529 | |||
530 | /** | ||
531 | * Event notification from a controller to a client. | ||
532 | */ | ||
533 | struct GNUNET_TESTBED_PeerCreateSuccessEventMessage | ||
534 | { | ||
535 | /** | ||
536 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS | ||
537 | */ | ||
538 | struct GNUNET_MessageHeader header; | ||
539 | |||
540 | /** | ||
541 | * Peer identity of the peer that was created. | ||
542 | */ | ||
543 | uint32_t peer_id GNUNET_PACKED; | ||
544 | |||
545 | /** | ||
546 | * Operation ID of the operation that created this event. | ||
547 | */ | ||
548 | uint64_t operation_id GNUNET_PACKED; | ||
549 | }; | ||
550 | |||
551 | |||
552 | /** | ||
553 | * Event notification from a controller to a client for | ||
554 | * a generic operational success where the operation does | ||
555 | * not return any data. | ||
556 | */ | ||
557 | struct GNUNET_TESTBED_GenericOperationSuccessEventMessage | ||
558 | { | ||
559 | /** | ||
560 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS | ||
561 | */ | ||
562 | struct GNUNET_MessageHeader header; | ||
563 | |||
564 | /** | ||
565 | * 'enum GNUNET_TESTBED_EventType' (in NBO); | ||
566 | * #GNUNET_TESTBED_ET_OPERATION_FINISHED. | ||
567 | */ | ||
568 | int32_t event_type GNUNET_PACKED; | ||
569 | |||
570 | /** | ||
571 | * Operation ID of the operation that created this event. | ||
572 | */ | ||
573 | uint64_t operation_id GNUNET_PACKED; | ||
574 | }; | ||
575 | |||
576 | |||
577 | /** | ||
578 | * Message sent from client to testing service to | ||
579 | * obtain the configuration of a peer. | ||
580 | */ | ||
581 | struct GNUNET_TESTBED_PeerGetConfigurationMessage | ||
582 | { | ||
583 | /** | ||
584 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION | ||
585 | */ | ||
586 | struct GNUNET_MessageHeader header; | ||
587 | |||
588 | /** | ||
589 | * Unique ID for the peer. | ||
590 | */ | ||
591 | uint32_t peer_id GNUNET_PACKED; | ||
592 | |||
593 | /** | ||
594 | * Operation ID that is used to identify this operation. | ||
595 | */ | ||
596 | uint64_t operation_id GNUNET_PACKED; | ||
597 | }; | ||
598 | |||
599 | |||
600 | /** | ||
601 | * Peer configuration and identity reply from controller to a client. | ||
602 | */ | ||
603 | struct GNUNET_TESTBED_PeerConfigurationInformationMessage | ||
604 | { | ||
605 | /** | ||
606 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION | ||
607 | */ | ||
608 | struct GNUNET_MessageHeader header; | ||
609 | |||
610 | /** | ||
611 | * The id of the peer relevant to this information | ||
612 | */ | ||
613 | uint32_t peer_id GNUNET_PACKED; | ||
614 | |||
615 | /** | ||
616 | * Operation ID of the operation that created this event. | ||
617 | */ | ||
618 | uint64_t operation_id GNUNET_PACKED; | ||
619 | |||
620 | /** | ||
621 | * Identity of the peer. | ||
622 | */ | ||
623 | struct GNUNET_PeerIdentity peer_identity; | ||
624 | |||
625 | /** | ||
626 | * The size of configuration when uncompressed | ||
627 | */ | ||
628 | uint16_t config_size GNUNET_PACKED; | ||
629 | |||
630 | /* followed by gzip-compressed configuration of the peer */ | ||
631 | }; | ||
632 | |||
633 | |||
634 | /** | ||
635 | * Message to request configuration of a slave controller | ||
636 | */ | ||
637 | struct GNUNET_TESTBED_SlaveGetConfigurationMessage | ||
638 | { | ||
639 | /** | ||
640 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION | ||
641 | */ | ||
642 | struct GNUNET_MessageHeader header; | ||
643 | |||
644 | /** | ||
645 | * The id of the slave host | ||
646 | */ | ||
647 | uint32_t slave_id GNUNET_PACKED; | ||
648 | |||
649 | /** | ||
650 | * Operation ID | ||
651 | */ | ||
652 | uint64_t operation_id GNUNET_PACKED; | ||
653 | }; | ||
654 | |||
655 | |||
656 | /** | ||
657 | * Reply to #GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION message | ||
658 | */ | ||
659 | struct GNUNET_TESTBED_SlaveConfiguration | ||
660 | { | ||
661 | /** | ||
662 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION | ||
663 | */ | ||
664 | struct GNUNET_MessageHeader header; | ||
665 | |||
666 | /** | ||
667 | * The id of the host where the slave is running | ||
668 | */ | ||
669 | uint32_t slave_id GNUNET_PACKED; | ||
670 | |||
671 | /** | ||
672 | * Operation ID | ||
673 | */ | ||
674 | uint64_t operation_id GNUNET_PACKED; | ||
675 | |||
676 | /** | ||
677 | * The size of the configuration when uncompressed | ||
678 | */ | ||
679 | uint16_t config_size GNUNET_PACKED; | ||
680 | |||
681 | /* followed by gzip-compressed configuration of the peer */ | ||
682 | }; | ||
683 | |||
684 | |||
685 | /** | ||
686 | * Shutdown peers message | ||
687 | */ | ||
688 | struct GNUNET_TESTBED_ShutdownPeersMessage | ||
689 | { | ||
690 | /** | ||
691 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS | ||
692 | */ | ||
693 | struct GNUNET_MessageHeader header; | ||
694 | |||
695 | /** | ||
696 | * Operation ID | ||
697 | */ | ||
698 | uint64_t operation_id GNUNET_PACKED; | ||
699 | }; | ||
700 | |||
701 | |||
702 | /** | ||
703 | * Message to start/stop services of a peer | ||
704 | */ | ||
705 | struct GNUNET_TESTBED_ManagePeerServiceMessage | ||
706 | { | ||
707 | /** | ||
708 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS | ||
709 | */ | ||
710 | struct GNUNET_MessageHeader header; | ||
711 | |||
712 | /** | ||
713 | * Unique ID of the peer whose service has to be managed. | ||
714 | */ | ||
715 | uint32_t peer_id GNUNET_PACKED; | ||
716 | |||
717 | /** | ||
718 | * Operation ID | ||
719 | */ | ||
720 | uint64_t operation_id GNUNET_PACKED; | ||
721 | |||
722 | /** | ||
723 | * set this to 1 to start the service; 0 to stop the service | ||
724 | */ | ||
725 | uint8_t start; | ||
726 | |||
727 | /** | ||
728 | * The NULL-terminated name of the service to start/stop follows here | ||
729 | */ | ||
730 | }; | ||
731 | |||
732 | |||
733 | /** | ||
734 | * Message to send underlay link model of a peer. This message will be | ||
735 | * forwarded to the controller running the peer. | ||
736 | */ | ||
737 | struct GNUNET_TESTBED_UnderlayLinkModelMsg | ||
738 | { | ||
739 | /** | ||
740 | * Type is #GNUNET_MESSAGE_TYPE_UNDERLAYLINKMODELMSG | ||
741 | */ | ||
742 | struct GNUNET_MessageHeader header; | ||
743 | |||
744 | /** | ||
745 | * The number of peer entries contained in this message | ||
746 | */ | ||
747 | uint32_t nentries GNUNET_PACKED; | ||
748 | |||
749 | /** | ||
750 | * The number of link properties contained in this message | ||
751 | */ | ||
752 | uint32_t nprops GNUNET_PACKED; | ||
753 | |||
754 | /** | ||
755 | * Array of ids of peers to be in the blacklist/whitelist. Each id is of type | ||
756 | * uint32_t. Number of ids should be equal to nentries. | ||
757 | */ | ||
758 | |||
759 | /** | ||
760 | * Array of link properties. Each link property is to be arraged in a | ||
761 | * sequence of four integers of type uint32_t: peer_id, latency, loss and | ||
762 | * bandwidth. | ||
763 | */ | ||
764 | }; | ||
765 | |||
766 | |||
767 | /**************************************/ | ||
768 | /* Barriers IPC messages and protocol */ | ||
769 | /**************************************/ | ||
770 | |||
771 | |||
772 | /** | ||
773 | * The environmental variable which when available refers to the configuration | ||
774 | * file the local testbed controller is using | ||
775 | */ | ||
776 | #define ENV_TESTBED_CONFIG "GNUNET_TESTBED_CONTROLLER_CONFIG" | ||
777 | |||
778 | |||
779 | /** | ||
780 | * Message to initialise a barrier | ||
781 | */ | ||
782 | struct GNUNET_TESTBED_BarrierInit | ||
783 | { | ||
784 | /** | ||
785 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT | ||
786 | */ | ||
787 | struct GNUNET_MessageHeader header; | ||
788 | |||
789 | /** | ||
790 | * The quorum percentage needed for crossing the barrier | ||
791 | */ | ||
792 | uint8_t quorum; | ||
793 | |||
794 | /** | ||
795 | * name of the barrier. Non NULL-terminated. | ||
796 | */ | ||
797 | char name[0]; | ||
798 | }; | ||
799 | |||
800 | |||
801 | /** | ||
802 | * Message to cancel a barrier | ||
803 | */ | ||
804 | struct GNUNET_TESTBED_BarrierCancel | ||
805 | { | ||
806 | /** | ||
807 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL | ||
808 | */ | ||
809 | struct GNUNET_MessageHeader header; | ||
810 | |||
811 | /** | ||
812 | * The barrier name. Non NULL terminated | ||
813 | */ | ||
814 | char name[0]; | ||
815 | }; | ||
816 | |||
817 | |||
818 | /** | ||
819 | * Message for signalling status changes of a barrier | ||
820 | */ | ||
821 | struct GNUNET_TESTBED_BarrierStatusMsg | ||
822 | { | ||
823 | /** | ||
824 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS | ||
825 | */ | ||
826 | struct GNUNET_MessageHeader header; | ||
827 | |||
828 | /** | ||
829 | * status. Use enumerated values of enum BarrierStatus | ||
830 | */ | ||
831 | uint16_t status GNUNET_PACKED; | ||
832 | |||
833 | /** | ||
834 | * strlen of the barrier name | ||
835 | */ | ||
836 | uint16_t name_len GNUNET_PACKED; | ||
837 | |||
838 | /** | ||
839 | * the barrier name (0-terminated) concatenated with an error message | ||
840 | * (0-terminated) if the status were to indicate an error | ||
841 | */ | ||
842 | char data[0]; | ||
843 | }; | ||
844 | |||
845 | |||
846 | /** | ||
847 | * Message sent from peers to the testbed-barrier service to indicate that they | ||
848 | * have reached a barrier and are waiting for it to be crossed | ||
849 | */ | ||
850 | struct GNUNET_TESTBED_BarrierWait | ||
851 | { | ||
852 | /** | ||
853 | * Type is #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT | ||
854 | */ | ||
855 | struct GNUNET_MessageHeader header; | ||
856 | |||
857 | /** | ||
858 | * The name of the barrier they have reached. Non-NULL terminated. | ||
859 | */ | ||
860 | char name[0]; | ||
861 | }; | ||
862 | |||
863 | |||
864 | GNUNET_NETWORK_STRUCT_END | ||
865 | #endif | ||
866 | /* end of testbed.h */ | ||
diff --git a/src/testbed/testbed_api.c b/src/testbed/testbed_api.c deleted file mode 100644 index 18bb0c3f6..000000000 --- a/src/testbed/testbed_api.c +++ /dev/null | |||
@@ -1,2474 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api.c | ||
23 | * @brief API for accessing the GNUnet testing service. | ||
24 | * This library is supposed to make it easier to write | ||
25 | * testcases and script large-scale benchmarks. | ||
26 | * @author Christian Grothoff | ||
27 | * @author Sree Harsha Totakura | ||
28 | */ | ||
29 | #include "platform.h" | ||
30 | #include "gnunet_testbed_service.h" | ||
31 | #include "gnunet_core_service.h" | ||
32 | #include "gnunet_constants.h" | ||
33 | #include "gnunet_transport_service.h" | ||
34 | #include "gnunet_hello_lib.h" | ||
35 | #include <zlib.h> | ||
36 | |||
37 | #include "testbed.h" | ||
38 | #include "testbed_api.h" | ||
39 | #include "testbed_api_hosts.h" | ||
40 | #include "testbed_api_peers.h" | ||
41 | #include "testbed_api_operations.h" | ||
42 | #include "testbed_api_sd.h" | ||
43 | |||
44 | /** | ||
45 | * Generic logging shorthand | ||
46 | */ | ||
47 | #define LOG(kind, ...) GNUNET_log_from (kind, "testbed-api", __VA_ARGS__) | ||
48 | |||
49 | /** | ||
50 | * Debug logging | ||
51 | */ | ||
52 | #define LOG_DEBUG(...) LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) | ||
53 | |||
54 | /** | ||
55 | * Relative time seconds shorthand | ||
56 | */ | ||
57 | #define TIME_REL_SECS(sec) \ | ||
58 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Default server message sending retry timeout | ||
63 | */ | ||
64 | #define TIMEOUT_REL TIME_REL_SECS (1) | ||
65 | |||
66 | |||
67 | /** | ||
68 | * Context data for forwarded Operation | ||
69 | */ | ||
70 | struct ForwardedOperationData | ||
71 | { | ||
72 | /** | ||
73 | * The callback to call when reply is available | ||
74 | */ | ||
75 | GNUNET_MQ_MessageCallback cc; | ||
76 | |||
77 | /** | ||
78 | * The closure for the above callback | ||
79 | */ | ||
80 | void *cc_cls; | ||
81 | }; | ||
82 | |||
83 | |||
84 | /** | ||
85 | * Context data for get slave config operations | ||
86 | */ | ||
87 | struct GetSlaveConfigData | ||
88 | { | ||
89 | /** | ||
90 | * The id of the slave controller | ||
91 | */ | ||
92 | uint32_t slave_id; | ||
93 | }; | ||
94 | |||
95 | |||
96 | /** | ||
97 | * Context data for controller link operations | ||
98 | */ | ||
99 | struct ControllerLinkData | ||
100 | { | ||
101 | /** | ||
102 | * The controller link message | ||
103 | */ | ||
104 | struct GNUNET_TESTBED_ControllerLinkRequest *msg; | ||
105 | |||
106 | /** | ||
107 | * The id of the host which is hosting the controller to be linked | ||
108 | */ | ||
109 | uint32_t host_id; | ||
110 | }; | ||
111 | |||
112 | |||
113 | /** | ||
114 | * Date context for OP_SHUTDOWN_PEERS operations | ||
115 | */ | ||
116 | struct ShutdownPeersData | ||
117 | { | ||
118 | /** | ||
119 | * The operation completion callback to call | ||
120 | */ | ||
121 | GNUNET_TESTBED_OperationCompletionCallback cb; | ||
122 | |||
123 | /** | ||
124 | * The closure for the above callback | ||
125 | */ | ||
126 | void *cb_cls; | ||
127 | }; | ||
128 | |||
129 | |||
130 | /** | ||
131 | * An entry in the stack for keeping operations which are about to expire | ||
132 | */ | ||
133 | struct ExpireOperationEntry | ||
134 | { | ||
135 | /** | ||
136 | * DLL head; new entries are to be inserted here | ||
137 | */ | ||
138 | struct ExpireOperationEntry *next; | ||
139 | |||
140 | /** | ||
141 | * DLL tail; entries are deleted from here | ||
142 | */ | ||
143 | struct ExpireOperationEntry *prev; | ||
144 | |||
145 | /** | ||
146 | * The operation. This will be a dangling pointer when the operation is freed | ||
147 | */ | ||
148 | const struct GNUNET_TESTBED_Operation *op; | ||
149 | }; | ||
150 | |||
151 | |||
152 | /** | ||
153 | * DLL head for list of operations marked for expiry | ||
154 | */ | ||
155 | static struct ExpireOperationEntry *exop_head; | ||
156 | |||
157 | /** | ||
158 | * DLL tail for list of operation marked for expiry | ||
159 | */ | ||
160 | static struct ExpireOperationEntry *exop_tail; | ||
161 | |||
162 | |||
163 | /** | ||
164 | * Inserts an operation into the list of operations marked for expiry | ||
165 | * | ||
166 | * @param op the operation to insert | ||
167 | */ | ||
168 | static void | ||
169 | exop_insert (struct GNUNET_TESTBED_Operation *op) | ||
170 | { | ||
171 | struct ExpireOperationEntry *entry; | ||
172 | |||
173 | entry = GNUNET_new (struct ExpireOperationEntry); | ||
174 | entry->op = op; | ||
175 | GNUNET_CONTAINER_DLL_insert_tail (exop_head, exop_tail, entry); | ||
176 | } | ||
177 | |||
178 | |||
179 | /** | ||
180 | * Checks if an operation is present in the list of operations marked for | ||
181 | * expiry. If the operation is found, it and the tail of operations after it | ||
182 | * are removed from the list. | ||
183 | * | ||
184 | * @param op the operation to check | ||
185 | * @return GNUNET_NO if the operation is not present in the list; GNUNET_YES if | ||
186 | * the operation is found in the list (the operation is then removed | ||
187 | * from the list -- calling this function again with the same | ||
188 | * paramenter will return GNUNET_NO) | ||
189 | */ | ||
190 | static int | ||
191 | exop_check (const struct GNUNET_TESTBED_Operation *const op) | ||
192 | { | ||
193 | struct ExpireOperationEntry *entry; | ||
194 | struct ExpireOperationEntry *entry2; | ||
195 | int found; | ||
196 | |||
197 | found = GNUNET_NO; | ||
198 | entry = exop_head; | ||
199 | while (NULL != entry) | ||
200 | { | ||
201 | if (op == entry->op) | ||
202 | { | ||
203 | found = GNUNET_YES; | ||
204 | break; | ||
205 | } | ||
206 | entry = entry->next; | ||
207 | } | ||
208 | if (GNUNET_NO == found) | ||
209 | return GNUNET_NO; | ||
210 | /* Truncate the tail */ | ||
211 | while (NULL != entry) | ||
212 | { | ||
213 | entry2 = entry->next; | ||
214 | GNUNET_CONTAINER_DLL_remove (exop_head, exop_tail, entry); | ||
215 | GNUNET_free (entry); | ||
216 | entry = entry2; | ||
217 | } | ||
218 | return GNUNET_YES; | ||
219 | } | ||
220 | |||
221 | |||
222 | /** | ||
223 | * Context information to be used while searching for operation contexts | ||
224 | */ | ||
225 | struct SearchContext | ||
226 | { | ||
227 | /** | ||
228 | * The result of the search | ||
229 | */ | ||
230 | struct OperationContext *opc; | ||
231 | |||
232 | /** | ||
233 | * The id of the operation context we are searching for | ||
234 | */ | ||
235 | uint64_t id; | ||
236 | }; | ||
237 | |||
238 | |||
239 | /** | ||
240 | * Search iterator for searching an operation context | ||
241 | * | ||
242 | * @param cls the search context | ||
243 | * @param key current key code | ||
244 | * @param value value in the hash map | ||
245 | * @return #GNUNET_YES if we should continue to iterate, | ||
246 | * #GNUNET_NO if not. | ||
247 | */ | ||
248 | static int | ||
249 | opc_search_iterator (void *cls, uint32_t key, void *value) | ||
250 | { | ||
251 | struct SearchContext *sc = cls; | ||
252 | struct OperationContext *opc = value; | ||
253 | |||
254 | GNUNET_assert (NULL != opc); | ||
255 | GNUNET_assert (NULL == sc->opc); | ||
256 | if (opc->id != sc->id) | ||
257 | return GNUNET_YES; | ||
258 | sc->opc = opc; | ||
259 | return GNUNET_NO; | ||
260 | } | ||
261 | |||
262 | |||
263 | /** | ||
264 | * Returns the operation context with the given id if found in the Operation | ||
265 | * context queues of the controller | ||
266 | * | ||
267 | * @param c the controller whose operation context map is searched | ||
268 | * @param id the id which has to be checked | ||
269 | * @return the matching operation context; NULL if no match found | ||
270 | */ | ||
271 | static struct OperationContext * | ||
272 | find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id) | ||
273 | { | ||
274 | struct SearchContext sc; | ||
275 | |||
276 | sc.id = id; | ||
277 | sc.opc = NULL; | ||
278 | GNUNET_assert (NULL != c->opc_map); | ||
279 | if (GNUNET_SYSERR != | ||
280 | GNUNET_CONTAINER_multihashmap32_get_multiple (c->opc_map, | ||
281 | (uint32_t) id, | ||
282 | &opc_search_iterator, | ||
283 | &sc)) | ||
284 | return NULL; | ||
285 | return sc.opc; | ||
286 | } | ||
287 | |||
288 | |||
289 | /** | ||
290 | * Inserts the given operation context into the operation context map of the | ||
291 | * given controller. Creates the operation context map if one does not exist | ||
292 | * for the controller | ||
293 | * | ||
294 | * @param c the controller | ||
295 | * @param opc the operation context to be inserted | ||
296 | */ | ||
297 | void | ||
298 | GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c, | ||
299 | struct OperationContext *opc) | ||
300 | { | ||
301 | if (NULL == c->opc_map) | ||
302 | c->opc_map = GNUNET_CONTAINER_multihashmap32_create (256); | ||
303 | GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put ( | ||
304 | c->opc_map, | ||
305 | (uint32_t) opc->id, | ||
306 | opc, | ||
307 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); | ||
308 | } | ||
309 | |||
310 | |||
311 | /** | ||
312 | * Removes the given operation context from the operation context map of the | ||
313 | * given controller | ||
314 | * | ||
315 | * @param c the controller | ||
316 | * @param opc the operation context to remove | ||
317 | */ | ||
318 | void | ||
319 | GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c, | ||
320 | struct OperationContext *opc) | ||
321 | { | ||
322 | GNUNET_assert (NULL != c->opc_map); | ||
323 | GNUNET_assert (GNUNET_YES == | ||
324 | GNUNET_CONTAINER_multihashmap32_remove (c->opc_map, | ||
325 | (uint32_t) opc->id, | ||
326 | opc)); | ||
327 | if ((0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map)) && | ||
328 | (NULL != c->opcq_empty_cb)) | ||
329 | c->opcq_empty_cb (c->opcq_empty_cls); | ||
330 | } | ||
331 | |||
332 | |||
333 | /** | ||
334 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message is well-formed. | ||
335 | * | ||
336 | * @param cls the controller handler | ||
337 | * @param msg message received | ||
338 | * @return #GNUNET_OK if message is well-formed | ||
339 | */ | ||
340 | static int | ||
341 | check_add_host_confirm (void *cls, | ||
342 | const struct GNUNET_TESTBED_HostConfirmedMessage *msg) | ||
343 | { | ||
344 | const char *emsg; | ||
345 | uint16_t msg_size; | ||
346 | |||
347 | msg_size = ntohs (msg->header.size) - sizeof(*msg); | ||
348 | if (0 == msg_size) | ||
349 | return GNUNET_OK; | ||
350 | /* We have an error message */ | ||
351 | emsg = (const char *) &msg[1]; | ||
352 | if ('\0' != emsg[msg_size - 1]) | ||
353 | { | ||
354 | GNUNET_break (0); | ||
355 | return GNUNET_SYSERR; | ||
356 | } | ||
357 | return GNUNET_OK; | ||
358 | } | ||
359 | |||
360 | |||
361 | /** | ||
362 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from | ||
363 | * controller (testbed service) | ||
364 | * | ||
365 | * @param cls the controller handler | ||
366 | * @param msg message received | ||
367 | */ | ||
368 | static void | ||
369 | handle_add_host_confirm (void *cls, | ||
370 | const struct GNUNET_TESTBED_HostConfirmedMessage *msg) | ||
371 | { | ||
372 | struct GNUNET_TESTBED_Controller *c = cls; | ||
373 | struct GNUNET_TESTBED_HostRegistrationHandle *rh = c->rh; | ||
374 | const char *emsg; | ||
375 | uint16_t msg_size; | ||
376 | |||
377 | if (NULL == rh) | ||
378 | return; | ||
379 | if (GNUNET_TESTBED_host_get_id_ (rh->host) != ntohl (msg->host_id)) | ||
380 | { | ||
381 | LOG_DEBUG ("Mismatch in host id's %u, %u of host confirm msg\n", | ||
382 | GNUNET_TESTBED_host_get_id_ (rh->host), | ||
383 | ntohl (msg->host_id)); | ||
384 | return; | ||
385 | } | ||
386 | c->rh = NULL; | ||
387 | msg_size = ntohs (msg->header.size) - sizeof(*msg); | ||
388 | if (0 == msg_size) | ||
389 | { | ||
390 | LOG_DEBUG ("Host %u successfully registered\n", ntohl (msg->host_id)); | ||
391 | GNUNET_TESTBED_mark_host_registered_at_ (rh->host, c); | ||
392 | rh->cc (rh->cc_cls, NULL); | ||
393 | GNUNET_free (rh); | ||
394 | return; | ||
395 | } | ||
396 | /* We have an error message */ | ||
397 | emsg = (const char *) &msg[1]; | ||
398 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
399 | _ ("Adding host %u failed with error: %s\n"), | ||
400 | ntohl (msg->host_id), | ||
401 | emsg); | ||
402 | rh->cc (rh->cc_cls, emsg); | ||
403 | GNUNET_free (rh); | ||
404 | } | ||
405 | |||
406 | |||
407 | /** | ||
408 | * Handler for forwarded operations | ||
409 | * | ||
410 | * @param c the controller handle | ||
411 | * @param opc the operation context | ||
412 | * @param msg the message | ||
413 | */ | ||
414 | static void | ||
415 | handle_forwarded_operation_msg (void *cls, | ||
416 | struct OperationContext *opc, | ||
417 | const struct GNUNET_MessageHeader *msg) | ||
418 | { | ||
419 | struct GNUNET_TESTBED_Controller *c = cls; | ||
420 | struct ForwardedOperationData *fo_data; | ||
421 | |||
422 | fo_data = opc->data; | ||
423 | if (NULL != fo_data->cc) | ||
424 | fo_data->cc (fo_data->cc_cls, msg); | ||
425 | GNUNET_TESTBED_remove_opc_ (c, opc); | ||
426 | GNUNET_free (fo_data); | ||
427 | GNUNET_free (opc); | ||
428 | } | ||
429 | |||
430 | |||
431 | /** | ||
432 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS message from | ||
433 | * controller (testbed service) | ||
434 | * | ||
435 | * @param c the controller handler | ||
436 | * @param msg message received | ||
437 | */ | ||
438 | static void | ||
439 | handle_opsuccess ( | ||
440 | void *cls, | ||
441 | const struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg) | ||
442 | { | ||
443 | struct GNUNET_TESTBED_Controller *c = cls; | ||
444 | struct OperationContext *opc; | ||
445 | GNUNET_TESTBED_OperationCompletionCallback op_comp_cb; | ||
446 | void *op_comp_cb_cls; | ||
447 | struct GNUNET_TESTBED_EventInformation event; | ||
448 | uint64_t op_id; | ||
449 | |||
450 | op_id = GNUNET_ntohll (msg->operation_id); | ||
451 | LOG_DEBUG ("Operation %llu successful\n", | ||
452 | (unsigned long long) op_id); | ||
453 | if (NULL == (opc = find_opc (c, op_id))) | ||
454 | { | ||
455 | LOG_DEBUG ("Operation not found\n"); | ||
456 | return; | ||
457 | } | ||
458 | event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; | ||
459 | event.op = opc->op; | ||
460 | event.op_cls = opc->op_cls; | ||
461 | event.details.operation_finished.emsg = NULL; | ||
462 | event.details.operation_finished.generic = NULL; | ||
463 | op_comp_cb = NULL; | ||
464 | op_comp_cb_cls = NULL; | ||
465 | switch (opc->type) | ||
466 | { | ||
467 | case OP_FORWARDED: { | ||
468 | handle_forwarded_operation_msg (c, | ||
469 | opc, | ||
470 | (const struct | ||
471 | GNUNET_MessageHeader *) msg); | ||
472 | return; | ||
473 | } | ||
474 | break; | ||
475 | |||
476 | case OP_PEER_DESTROY: { | ||
477 | struct GNUNET_TESTBED_Peer *peer; | ||
478 | |||
479 | peer = opc->data; | ||
480 | GNUNET_TESTBED_peer_deregister_ (peer); | ||
481 | GNUNET_free (peer); | ||
482 | opc->data = NULL; | ||
483 | // PEERDESTROYDATA | ||
484 | } | ||
485 | break; | ||
486 | |||
487 | case OP_SHUTDOWN_PEERS: { | ||
488 | struct ShutdownPeersData *data; | ||
489 | |||
490 | data = opc->data; | ||
491 | op_comp_cb = data->cb; | ||
492 | op_comp_cb_cls = data->cb_cls; | ||
493 | GNUNET_free (data); | ||
494 | opc->data = NULL; | ||
495 | GNUNET_TESTBED_cleanup_peers_ (); | ||
496 | } | ||
497 | break; | ||
498 | |||
499 | case OP_MANAGE_SERVICE: { | ||
500 | struct ManageServiceData *data; | ||
501 | |||
502 | GNUNET_assert (NULL != (data = opc->data)); | ||
503 | op_comp_cb = data->cb; | ||
504 | op_comp_cb_cls = data->cb_cls; | ||
505 | GNUNET_free (data); | ||
506 | opc->data = NULL; | ||
507 | } | ||
508 | break; | ||
509 | |||
510 | case OP_PEER_RECONFIGURE: | ||
511 | break; | ||
512 | |||
513 | default: | ||
514 | GNUNET_assert (0); | ||
515 | } | ||
516 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
517 | opc->state = OPC_STATE_FINISHED; | ||
518 | exop_insert (event.op); | ||
519 | if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED))) | ||
520 | { | ||
521 | if (NULL != c->cc) | ||
522 | c->cc (c->cc_cls, &event); | ||
523 | if (GNUNET_NO == exop_check (event.op)) | ||
524 | return; | ||
525 | } | ||
526 | else | ||
527 | LOG_DEBUG ("Not calling callback\n"); | ||
528 | if (NULL != op_comp_cb) | ||
529 | op_comp_cb (op_comp_cb_cls, event.op, NULL); | ||
530 | /* You could have marked the operation as done by now */ | ||
531 | GNUNET_break (GNUNET_NO == exop_check (event.op)); | ||
532 | } | ||
533 | |||
534 | |||
535 | /** | ||
536 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS message from | ||
537 | * controller (testbed service) | ||
538 | * | ||
539 | * @param c the controller handle | ||
540 | * @param msg message received | ||
541 | */ | ||
542 | static void | ||
543 | handle_peer_create_success ( | ||
544 | void *cls, | ||
545 | const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg) | ||
546 | { | ||
547 | struct GNUNET_TESTBED_Controller *c = cls; | ||
548 | struct OperationContext *opc; | ||
549 | struct PeerCreateData *data; | ||
550 | struct GNUNET_TESTBED_Peer *peer; | ||
551 | struct GNUNET_TESTBED_Operation *op; | ||
552 | GNUNET_TESTBED_PeerCreateCallback cb; | ||
553 | void *cb_cls; | ||
554 | uint64_t op_id; | ||
555 | |||
556 | GNUNET_assert (sizeof(struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) == | ||
557 | ntohs (msg->header.size)); | ||
558 | op_id = GNUNET_ntohll (msg->operation_id); | ||
559 | if (NULL == (opc = find_opc (c, op_id))) | ||
560 | { | ||
561 | LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n"); | ||
562 | return; | ||
563 | } | ||
564 | if (OP_FORWARDED == opc->type) | ||
565 | { | ||
566 | handle_forwarded_operation_msg (c, | ||
567 | opc, | ||
568 | (const struct GNUNET_MessageHeader *) msg); | ||
569 | return; | ||
570 | } | ||
571 | GNUNET_assert (OP_PEER_CREATE == opc->type); | ||
572 | GNUNET_assert (NULL != opc->data); | ||
573 | data = opc->data; | ||
574 | GNUNET_assert (NULL != data->peer); | ||
575 | peer = data->peer; | ||
576 | GNUNET_assert (peer->unique_id == ntohl (msg->peer_id)); | ||
577 | peer->state = TESTBED_PS_CREATED; | ||
578 | GNUNET_TESTBED_peer_register_ (peer); | ||
579 | cb = data->cb; | ||
580 | cb_cls = data->cls; | ||
581 | op = opc->op; | ||
582 | GNUNET_free (opc->data); | ||
583 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
584 | opc->state = OPC_STATE_FINISHED; | ||
585 | exop_insert (op); | ||
586 | if (NULL != cb) | ||
587 | cb (cb_cls, peer, NULL); | ||
588 | /* You could have marked the operation as done by now */ | ||
589 | GNUNET_break (GNUNET_NO == exop_check (op)); | ||
590 | } | ||
591 | |||
592 | |||
593 | /** | ||
594 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT message from | ||
595 | * controller (testbed service) | ||
596 | * | ||
597 | * @param c the controller handler | ||
598 | * @param msg message received | ||
599 | */ | ||
600 | static void | ||
601 | handle_peer_event (void *cls, const struct GNUNET_TESTBED_PeerEventMessage *msg) | ||
602 | { | ||
603 | struct GNUNET_TESTBED_Controller *c = cls; | ||
604 | struct OperationContext *opc; | ||
605 | struct GNUNET_TESTBED_Peer *peer; | ||
606 | struct PeerEventData *data; | ||
607 | GNUNET_TESTBED_PeerChurnCallback pcc; | ||
608 | void *pcc_cls; | ||
609 | struct GNUNET_TESTBED_EventInformation event; | ||
610 | uint64_t op_id; | ||
611 | uint64_t mask; | ||
612 | |||
613 | GNUNET_assert (sizeof(struct GNUNET_TESTBED_PeerEventMessage) == | ||
614 | ntohs (msg->header.size)); | ||
615 | op_id = GNUNET_ntohll (msg->operation_id); | ||
616 | if (NULL == (opc = find_opc (c, op_id))) | ||
617 | { | ||
618 | LOG_DEBUG ("Operation not found\n"); | ||
619 | return; | ||
620 | } | ||
621 | if (OP_FORWARDED == opc->type) | ||
622 | { | ||
623 | handle_forwarded_operation_msg (c, | ||
624 | opc, | ||
625 | (const struct GNUNET_MessageHeader *) msg); | ||
626 | return; | ||
627 | } | ||
628 | GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type)); | ||
629 | data = opc->data; | ||
630 | GNUNET_assert (NULL != data); | ||
631 | peer = data->peer; | ||
632 | GNUNET_assert (NULL != peer); | ||
633 | event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type); | ||
634 | event.op = opc->op; | ||
635 | event.op_cls = opc->op_cls; | ||
636 | switch (event.type) | ||
637 | { | ||
638 | case GNUNET_TESTBED_ET_PEER_START: | ||
639 | peer->state = TESTBED_PS_STARTED; | ||
640 | event.details.peer_start.host = peer->host; | ||
641 | event.details.peer_start.peer = peer; | ||
642 | break; | ||
643 | |||
644 | case GNUNET_TESTBED_ET_PEER_STOP: | ||
645 | peer->state = TESTBED_PS_STOPPED; | ||
646 | event.details.peer_stop.peer = peer; | ||
647 | break; | ||
648 | |||
649 | default: | ||
650 | GNUNET_assert (0); /* We should never reach this state */ | ||
651 | } | ||
652 | pcc = data->pcc; | ||
653 | pcc_cls = data->pcc_cls; | ||
654 | GNUNET_free (data); | ||
655 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
656 | opc->state = OPC_STATE_FINISHED; | ||
657 | exop_insert (event.op); | ||
658 | mask = 1LL << GNUNET_TESTBED_ET_PEER_START; | ||
659 | mask |= 1LL << GNUNET_TESTBED_ET_PEER_STOP; | ||
660 | if (0 != (mask & c->event_mask)) | ||
661 | { | ||
662 | if (NULL != c->cc) | ||
663 | c->cc (c->cc_cls, &event); | ||
664 | if (GNUNET_NO == exop_check (event.op)) | ||
665 | return; | ||
666 | } | ||
667 | if (NULL != pcc) | ||
668 | pcc (pcc_cls, NULL); | ||
669 | /* You could have marked the operation as done by now */ | ||
670 | GNUNET_break (GNUNET_NO == exop_check (event.op)); | ||
671 | } | ||
672 | |||
673 | |||
674 | /** | ||
675 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT message from | ||
676 | * controller (testbed service) | ||
677 | * | ||
678 | * @param c the controller handler | ||
679 | * @param msg message received | ||
680 | */ | ||
681 | static void | ||
682 | handle_peer_conevent (void *cls, | ||
683 | const struct GNUNET_TESTBED_ConnectionEventMessage *msg) | ||
684 | { | ||
685 | struct GNUNET_TESTBED_Controller *c = cls; | ||
686 | struct OperationContext *opc; | ||
687 | struct OverlayConnectData *data; | ||
688 | GNUNET_TESTBED_OperationCompletionCallback cb; | ||
689 | void *cb_cls; | ||
690 | struct GNUNET_TESTBED_EventInformation event; | ||
691 | uint64_t op_id; | ||
692 | uint64_t mask; | ||
693 | |||
694 | op_id = GNUNET_ntohll (msg->operation_id); | ||
695 | if (NULL == (opc = find_opc (c, op_id))) | ||
696 | { | ||
697 | LOG_DEBUG ("Operation not found\n"); | ||
698 | return; | ||
699 | } | ||
700 | if (OP_FORWARDED == opc->type) | ||
701 | { | ||
702 | handle_forwarded_operation_msg (c, | ||
703 | opc, | ||
704 | (const struct GNUNET_MessageHeader *) msg); | ||
705 | return; | ||
706 | } | ||
707 | GNUNET_assert (OP_OVERLAY_CONNECT == opc->type); | ||
708 | GNUNET_assert (NULL != (data = opc->data)); | ||
709 | GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) && | ||
710 | (ntohl (msg->peer2) == data->p2->unique_id)); | ||
711 | event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type); | ||
712 | event.op = opc->op; | ||
713 | event.op_cls = opc->op_cls; | ||
714 | switch (event.type) | ||
715 | { | ||
716 | case GNUNET_TESTBED_ET_CONNECT: | ||
717 | event.details.peer_connect.peer1 = data->p1; | ||
718 | event.details.peer_connect.peer2 = data->p2; | ||
719 | break; | ||
720 | |||
721 | case GNUNET_TESTBED_ET_DISCONNECT: | ||
722 | GNUNET_assert (0); /* FIXME: implement */ | ||
723 | break; | ||
724 | |||
725 | default: | ||
726 | GNUNET_assert (0); /* Should never reach here */ | ||
727 | break; | ||
728 | } | ||
729 | cb = data->cb; | ||
730 | cb_cls = data->cb_cls; | ||
731 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
732 | opc->state = OPC_STATE_FINISHED; | ||
733 | exop_insert (event.op); | ||
734 | mask = 1LL << GNUNET_TESTBED_ET_CONNECT; | ||
735 | mask |= 1LL << GNUNET_TESTBED_ET_DISCONNECT; | ||
736 | if (0 != (mask & c->event_mask)) | ||
737 | { | ||
738 | if (NULL != c->cc) | ||
739 | c->cc (c->cc_cls, &event); | ||
740 | if (GNUNET_NO == exop_check (event.op)) | ||
741 | return; | ||
742 | } | ||
743 | if (NULL != cb) | ||
744 | cb (cb_cls, opc->op, NULL); | ||
745 | /* You could have marked the operation as done by now */ | ||
746 | GNUNET_break (GNUNET_NO == exop_check (event.op)); | ||
747 | } | ||
748 | |||
749 | |||
750 | /** | ||
751 | * Validate #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION message from | ||
752 | * controller (testbed service) | ||
753 | * | ||
754 | * @param c the controller handler | ||
755 | * @param msg message received | ||
756 | */ | ||
757 | static int | ||
758 | check_peer_config ( | ||
759 | void *cls, | ||
760 | const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *msg) | ||
761 | { | ||
762 | /* anything goes? */ | ||
763 | return GNUNET_OK; | ||
764 | } | ||
765 | |||
766 | |||
767 | /** | ||
768 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION message from | ||
769 | * controller (testbed service) | ||
770 | * | ||
771 | * @param c the controller handler | ||
772 | * @param msg message received | ||
773 | */ | ||
774 | static void | ||
775 | handle_peer_config ( | ||
776 | void *cls, | ||
777 | const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *msg) | ||
778 | { | ||
779 | struct GNUNET_TESTBED_Controller *c = cls; | ||
780 | struct OperationContext *opc; | ||
781 | struct GNUNET_TESTBED_Peer *peer; | ||
782 | struct PeerInfoData *data; | ||
783 | struct GNUNET_TESTBED_PeerInformation *pinfo; | ||
784 | GNUNET_TESTBED_PeerInfoCallback cb; | ||
785 | void *cb_cls; | ||
786 | uint64_t op_id; | ||
787 | |||
788 | op_id = GNUNET_ntohll (msg->operation_id); | ||
789 | if (NULL == (opc = find_opc (c, op_id))) | ||
790 | { | ||
791 | LOG_DEBUG ("Operation not found\n"); | ||
792 | return; | ||
793 | } | ||
794 | if (OP_FORWARDED == opc->type) | ||
795 | { | ||
796 | handle_forwarded_operation_msg (c, opc, &msg->header); | ||
797 | return; | ||
798 | } | ||
799 | data = opc->data; | ||
800 | GNUNET_assert (NULL != data); | ||
801 | peer = data->peer; | ||
802 | GNUNET_assert (NULL != peer); | ||
803 | GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id); | ||
804 | pinfo = GNUNET_new (struct GNUNET_TESTBED_PeerInformation); | ||
805 | pinfo->pit = data->pit; | ||
806 | cb = data->cb; | ||
807 | cb_cls = data->cb_cls; | ||
808 | GNUNET_assert (NULL != cb); | ||
809 | GNUNET_free (data); | ||
810 | opc->data = NULL; | ||
811 | switch (pinfo->pit) | ||
812 | { | ||
813 | case GNUNET_TESTBED_PIT_IDENTITY: | ||
814 | pinfo->result.id = GNUNET_new (struct GNUNET_PeerIdentity); | ||
815 | GNUNET_memcpy (pinfo->result.id, | ||
816 | &msg->peer_identity, | ||
817 | sizeof(struct GNUNET_PeerIdentity)); | ||
818 | break; | ||
819 | |||
820 | case GNUNET_TESTBED_PIT_CONFIGURATION: | ||
821 | pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */ | ||
822 | GNUNET_TESTBED_extract_config_ (&msg->header); | ||
823 | break; | ||
824 | |||
825 | case GNUNET_TESTBED_PIT_GENERIC: | ||
826 | GNUNET_assert (0); /* never reach here */ | ||
827 | break; | ||
828 | } | ||
829 | opc->data = pinfo; | ||
830 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
831 | opc->state = OPC_STATE_FINISHED; | ||
832 | cb (cb_cls, opc->op, pinfo, NULL); | ||
833 | /* We dont check whether the operation is marked as done here as the | ||
834 | operation contains data (cfg/identify) which will be freed at a later point | ||
835 | */ | ||
836 | } | ||
837 | |||
838 | |||
839 | /** | ||
840 | * Validate #GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT message from | ||
841 | * controller (testbed service) | ||
842 | * | ||
843 | * @param c the controller handler | ||
844 | * @param msg message received | ||
845 | * @return #GNUNET_OK if message is well-formed | ||
846 | */ | ||
847 | static int | ||
848 | check_op_fail_event ( | ||
849 | void *cls, | ||
850 | const struct GNUNET_TESTBED_OperationFailureEventMessage *msg) | ||
851 | { | ||
852 | /* we accept anything as a valid error message */ | ||
853 | return GNUNET_OK; | ||
854 | } | ||
855 | |||
856 | |||
857 | /** | ||
858 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT message from | ||
859 | * controller (testbed service) | ||
860 | * | ||
861 | * @param c the controller handler | ||
862 | * @param msg message received | ||
863 | */ | ||
864 | static void | ||
865 | handle_op_fail_event ( | ||
866 | void *cls, | ||
867 | const struct GNUNET_TESTBED_OperationFailureEventMessage *msg) | ||
868 | { | ||
869 | struct GNUNET_TESTBED_Controller *c = cls; | ||
870 | struct OperationContext *opc; | ||
871 | const char *emsg; | ||
872 | uint64_t op_id; | ||
873 | uint64_t mask; | ||
874 | struct GNUNET_TESTBED_EventInformation event; | ||
875 | |||
876 | op_id = GNUNET_ntohll (msg->operation_id); | ||
877 | if (NULL == (opc = find_opc (c, op_id))) | ||
878 | { | ||
879 | LOG_DEBUG ("Operation not found\n"); | ||
880 | return; | ||
881 | } | ||
882 | if (OP_FORWARDED == opc->type) | ||
883 | { | ||
884 | handle_forwarded_operation_msg (c, | ||
885 | opc, | ||
886 | (const struct GNUNET_MessageHeader *) msg); | ||
887 | return; | ||
888 | } | ||
889 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
890 | opc->state = OPC_STATE_FINISHED; | ||
891 | emsg = GNUNET_TESTBED_parse_error_string_ (msg); | ||
892 | if (NULL == emsg) | ||
893 | emsg = "Unknown error"; | ||
894 | if (OP_PEER_INFO == opc->type) | ||
895 | { | ||
896 | struct PeerInfoData *data; | ||
897 | |||
898 | data = opc->data; | ||
899 | if (NULL != data->cb) | ||
900 | data->cb (data->cb_cls, opc->op, NULL, emsg); | ||
901 | GNUNET_free (data); | ||
902 | return; /* We do not call controller callback for peer info */ | ||
903 | } | ||
904 | event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; | ||
905 | event.op = opc->op; | ||
906 | event.op_cls = opc->op_cls; | ||
907 | event.details.operation_finished.emsg = emsg; | ||
908 | event.details.operation_finished.generic = NULL; | ||
909 | mask = (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
910 | if ((0 != (mask & c->event_mask)) && (NULL != c->cc)) | ||
911 | { | ||
912 | exop_insert (event.op); | ||
913 | c->cc (c->cc_cls, &event); | ||
914 | if (GNUNET_NO == exop_check (event.op)) | ||
915 | return; | ||
916 | } | ||
917 | switch (opc->type) | ||
918 | { | ||
919 | case OP_PEER_CREATE: { | ||
920 | struct PeerCreateData *data; | ||
921 | |||
922 | data = opc->data; | ||
923 | GNUNET_free (data->peer); | ||
924 | if (NULL != data->cb) | ||
925 | data->cb (data->cls, NULL, emsg); | ||
926 | GNUNET_free (data); | ||
927 | } | ||
928 | break; | ||
929 | |||
930 | case OP_PEER_START: | ||
931 | case OP_PEER_STOP: { | ||
932 | struct PeerEventData *data; | ||
933 | |||
934 | data = opc->data; | ||
935 | if (NULL != data->pcc) | ||
936 | data->pcc (data->pcc_cls, emsg); | ||
937 | GNUNET_free (data); | ||
938 | } | ||
939 | break; | ||
940 | |||
941 | case OP_PEER_DESTROY: | ||
942 | break; | ||
943 | |||
944 | case OP_PEER_INFO: | ||
945 | GNUNET_assert (0); | ||
946 | |||
947 | case OP_OVERLAY_CONNECT: { | ||
948 | struct OverlayConnectData *data; | ||
949 | |||
950 | data = opc->data; | ||
951 | GNUNET_TESTBED_operation_mark_failed (opc->op); | ||
952 | if (NULL != data->cb) | ||
953 | data->cb (data->cb_cls, opc->op, emsg); | ||
954 | } | ||
955 | break; | ||
956 | |||
957 | case OP_FORWARDED: | ||
958 | GNUNET_assert (0); | ||
959 | |||
960 | case OP_LINK_CONTROLLERS: /* No secondary callback */ | ||
961 | break; | ||
962 | |||
963 | case OP_SHUTDOWN_PEERS: { | ||
964 | struct ShutdownPeersData *data; | ||
965 | |||
966 | data = opc->data; | ||
967 | GNUNET_free (data); /* FIXME: Decide whether we call data->op_cb */ | ||
968 | opc->data = NULL; | ||
969 | } | ||
970 | break; | ||
971 | |||
972 | case OP_MANAGE_SERVICE: { | ||
973 | struct ManageServiceData *data = opc->data; | ||
974 | GNUNET_TESTBED_OperationCompletionCallback cb; | ||
975 | void *cb_cls; | ||
976 | |||
977 | GNUNET_assert (NULL != data); | ||
978 | cb = data->cb; | ||
979 | cb_cls = data->cb_cls; | ||
980 | GNUNET_free (data); | ||
981 | opc->data = NULL; | ||
982 | exop_insert (event.op); | ||
983 | if (NULL != cb) | ||
984 | cb (cb_cls, opc->op, emsg); | ||
985 | /* You could have marked the operation as done by now */ | ||
986 | GNUNET_break (GNUNET_NO == exop_check (event.op)); | ||
987 | } | ||
988 | break; | ||
989 | |||
990 | default: | ||
991 | GNUNET_break (0); | ||
992 | } | ||
993 | } | ||
994 | |||
995 | |||
996 | /** | ||
997 | * Function to build GET_SLAVE_CONFIG message | ||
998 | * | ||
999 | * @param op_id the id this message should contain in its operation id field | ||
1000 | * @param slave_id the id this message should contain in its slave id field | ||
1001 | * @return newly allocated SlaveGetConfigurationMessage | ||
1002 | */ | ||
1003 | static struct GNUNET_TESTBED_SlaveGetConfigurationMessage * | ||
1004 | GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id) | ||
1005 | { | ||
1006 | struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg; | ||
1007 | uint16_t msize; | ||
1008 | |||
1009 | msize = sizeof(struct GNUNET_TESTBED_SlaveGetConfigurationMessage); | ||
1010 | msg = GNUNET_malloc (msize); | ||
1011 | msg->header.size = htons (msize); | ||
1012 | msg->header.type = | ||
1013 | htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION); | ||
1014 | msg->operation_id = GNUNET_htonll (op_id); | ||
1015 | msg->slave_id = htonl (slave_id); | ||
1016 | return msg; | ||
1017 | } | ||
1018 | |||
1019 | |||
1020 | /** | ||
1021 | * Validate #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_INFORMATION message from | ||
1022 | * controller (testbed service) | ||
1023 | * | ||
1024 | * @param c the controller handler | ||
1025 | * @param msg message received | ||
1026 | */ | ||
1027 | static int | ||
1028 | check_slave_config (void *cls, | ||
1029 | const struct GNUNET_TESTBED_SlaveConfiguration *msg) | ||
1030 | { | ||
1031 | /* anything goes? */ | ||
1032 | return GNUNET_OK; | ||
1033 | } | ||
1034 | |||
1035 | |||
1036 | /** | ||
1037 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION message from controller | ||
1038 | * (testbed service) | ||
1039 | * | ||
1040 | * @param c the controller handler | ||
1041 | * @param msg message received | ||
1042 | */ | ||
1043 | static void | ||
1044 | handle_slave_config (void *cls, | ||
1045 | const struct GNUNET_TESTBED_SlaveConfiguration *msg) | ||
1046 | { | ||
1047 | struct GNUNET_TESTBED_Controller *c = cls; | ||
1048 | struct OperationContext *opc; | ||
1049 | uint64_t op_id; | ||
1050 | uint64_t mask; | ||
1051 | struct GNUNET_TESTBED_EventInformation event; | ||
1052 | |||
1053 | op_id = GNUNET_ntohll (msg->operation_id); | ||
1054 | if (NULL == (opc = find_opc (c, op_id))) | ||
1055 | { | ||
1056 | LOG_DEBUG ("Operation not found\n"); | ||
1057 | return; | ||
1058 | } | ||
1059 | if (OP_GET_SLAVE_CONFIG != opc->type) | ||
1060 | { | ||
1061 | GNUNET_break (0); | ||
1062 | return; | ||
1063 | } | ||
1064 | opc->state = OPC_STATE_FINISHED; | ||
1065 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
1066 | mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED; | ||
1067 | if ((0 != (mask & c->event_mask)) && (NULL != c->cc)) | ||
1068 | { | ||
1069 | opc->data = GNUNET_TESTBED_extract_config_ (&msg->header); | ||
1070 | event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; | ||
1071 | event.op = opc->op; | ||
1072 | event.op_cls = opc->op_cls; | ||
1073 | event.details.operation_finished.generic = opc->data; | ||
1074 | event.details.operation_finished.emsg = NULL; | ||
1075 | c->cc (c->cc_cls, &event); | ||
1076 | } | ||
1077 | } | ||
1078 | |||
1079 | |||
1080 | /** | ||
1081 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT message from controller | ||
1082 | * (testbed service) | ||
1083 | * | ||
1084 | * @param c the controller handler | ||
1085 | * @param msg message received | ||
1086 | * @return #GNUNET_OK if @a msg is well-formed | ||
1087 | */ | ||
1088 | static int | ||
1089 | check_link_controllers_result ( | ||
1090 | void *cls, | ||
1091 | const struct GNUNET_TESTBED_ControllerLinkResponse *msg) | ||
1092 | { | ||
1093 | /* actual check to be implemented */ | ||
1094 | return GNUNET_OK; | ||
1095 | } | ||
1096 | |||
1097 | |||
1098 | /** | ||
1099 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT message from controller | ||
1100 | * (testbed service) | ||
1101 | * | ||
1102 | * @param c the controller handler | ||
1103 | * @param msg message received | ||
1104 | */ | ||
1105 | static void | ||
1106 | handle_link_controllers_result ( | ||
1107 | void *cls, | ||
1108 | const struct GNUNET_TESTBED_ControllerLinkResponse *msg) | ||
1109 | { | ||
1110 | struct GNUNET_TESTBED_Controller *c = cls; | ||
1111 | struct OperationContext *opc; | ||
1112 | struct ControllerLinkData *data; | ||
1113 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
1114 | struct GNUNET_TESTBED_Host *host; | ||
1115 | char *emsg; | ||
1116 | uint64_t op_id; | ||
1117 | struct GNUNET_TESTBED_EventInformation event; | ||
1118 | |||
1119 | op_id = GNUNET_ntohll (msg->operation_id); | ||
1120 | if (NULL == (opc = find_opc (c, op_id))) | ||
1121 | { | ||
1122 | LOG_DEBUG ("Operation not found\n"); | ||
1123 | return; | ||
1124 | } | ||
1125 | if (OP_FORWARDED == opc->type) | ||
1126 | { | ||
1127 | handle_forwarded_operation_msg (c, | ||
1128 | opc, | ||
1129 | (const struct GNUNET_MessageHeader *) msg); | ||
1130 | return; | ||
1131 | } | ||
1132 | if (OP_LINK_CONTROLLERS != opc->type) | ||
1133 | { | ||
1134 | GNUNET_break (0); | ||
1135 | return; | ||
1136 | } | ||
1137 | GNUNET_assert (NULL != (data = opc->data)); | ||
1138 | host = GNUNET_TESTBED_host_lookup_by_id_ (data->host_id); | ||
1139 | GNUNET_assert (NULL != host); | ||
1140 | GNUNET_free (data); | ||
1141 | opc->data = NULL; | ||
1142 | opc->state = OPC_STATE_FINISHED; | ||
1143 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
1144 | event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; | ||
1145 | event.op = opc->op; | ||
1146 | event.op_cls = opc->op_cls; | ||
1147 | event.details.operation_finished.emsg = NULL; | ||
1148 | event.details.operation_finished.generic = NULL; | ||
1149 | emsg = NULL; | ||
1150 | cfg = NULL; | ||
1151 | if (GNUNET_NO == ntohs (msg->success)) | ||
1152 | { | ||
1153 | emsg = | ||
1154 | GNUNET_malloc (ntohs (msg->header.size) | ||
1155 | - sizeof(struct GNUNET_TESTBED_ControllerLinkResponse) | ||
1156 | + 1); | ||
1157 | GNUNET_memcpy (emsg, | ||
1158 | &msg[1], | ||
1159 | ntohs (msg->header.size) | ||
1160 | - sizeof(struct GNUNET_TESTBED_ControllerLinkResponse)); | ||
1161 | event.details.operation_finished.emsg = emsg; | ||
1162 | } | ||
1163 | else | ||
1164 | { | ||
1165 | if (0 != ntohs (msg->config_size)) | ||
1166 | { | ||
1167 | cfg = GNUNET_TESTBED_extract_config_ ( | ||
1168 | (const struct GNUNET_MessageHeader *) msg); | ||
1169 | GNUNET_assert (NULL != cfg); | ||
1170 | GNUNET_TESTBED_host_replace_cfg_ (host, cfg); | ||
1171 | } | ||
1172 | } | ||
1173 | if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED))) | ||
1174 | { | ||
1175 | if (NULL != c->cc) | ||
1176 | c->cc (c->cc_cls, &event); | ||
1177 | } | ||
1178 | else | ||
1179 | LOG_DEBUG ("Not calling callback\n"); | ||
1180 | if (NULL != cfg) | ||
1181 | GNUNET_CONFIGURATION_destroy (cfg); | ||
1182 | GNUNET_free (emsg); | ||
1183 | } | ||
1184 | |||
1185 | |||
1186 | /** | ||
1187 | * Validate #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS message. | ||
1188 | * | ||
1189 | * @param cls the controller handle to determine the connection this message | ||
1190 | * belongs to | ||
1191 | * @param msg the barrier status message | ||
1192 | * @return #GNUNET_OK if the message is valid; #GNUNET_SYSERR to tear it | ||
1193 | * down signalling an error (message malformed) | ||
1194 | */ | ||
1195 | static int | ||
1196 | check_barrier_status (void *cls, | ||
1197 | const struct GNUNET_TESTBED_BarrierStatusMsg *msg) | ||
1198 | { | ||
1199 | uint16_t msize; | ||
1200 | uint16_t name_len; | ||
1201 | int status; | ||
1202 | const char *name; | ||
1203 | size_t emsg_len; | ||
1204 | |||
1205 | msize = ntohs (msg->header.size); | ||
1206 | name = msg->data; | ||
1207 | name_len = ntohs (msg->name_len); | ||
1208 | |||
1209 | if (sizeof(struct GNUNET_TESTBED_BarrierStatusMsg) + name_len + 1 > msize) | ||
1210 | { | ||
1211 | GNUNET_break_op (0); | ||
1212 | return GNUNET_SYSERR; | ||
1213 | } | ||
1214 | if ('\0' != name[name_len]) | ||
1215 | { | ||
1216 | GNUNET_break_op (0); | ||
1217 | return GNUNET_SYSERR; | ||
1218 | } | ||
1219 | status = ntohs (msg->status); | ||
1220 | if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status) | ||
1221 | { | ||
1222 | emsg_len = msize - (sizeof(struct GNUNET_TESTBED_BarrierStatusMsg) | ||
1223 | + name_len + 1); /* +1!? */ | ||
1224 | if (0 == emsg_len) | ||
1225 | { | ||
1226 | GNUNET_break_op (0); | ||
1227 | return GNUNET_SYSERR; | ||
1228 | } | ||
1229 | } | ||
1230 | return GNUNET_OK; | ||
1231 | } | ||
1232 | |||
1233 | |||
1234 | /** | ||
1235 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages | ||
1236 | * | ||
1237 | * @param cls the controller handle to determine the connection this message | ||
1238 | * belongs to | ||
1239 | * @param msg the barrier status message | ||
1240 | */ | ||
1241 | static void | ||
1242 | handle_barrier_status (void *cls, | ||
1243 | const struct GNUNET_TESTBED_BarrierStatusMsg *msg) | ||
1244 | { | ||
1245 | struct GNUNET_TESTBED_Controller *c = cls; | ||
1246 | struct GNUNET_TESTBED_Barrier *barrier; | ||
1247 | char *emsg; | ||
1248 | const char *name; | ||
1249 | struct GNUNET_HashCode key; | ||
1250 | size_t emsg_len; | ||
1251 | int status; | ||
1252 | uint16_t msize; | ||
1253 | uint16_t name_len; | ||
1254 | |||
1255 | emsg = NULL; | ||
1256 | barrier = NULL; | ||
1257 | msize = ntohs (msg->header.size); | ||
1258 | if (msize <= sizeof(struct GNUNET_TESTBED_BarrierStatusMsg)) | ||
1259 | { | ||
1260 | GNUNET_break_op (0); | ||
1261 | goto cleanup; | ||
1262 | } | ||
1263 | name = msg->data; | ||
1264 | name_len = ntohs (msg->name_len); | ||
1265 | if (name_len >= // name_len is strlen(barrier_name) | ||
1266 | (msize - ((sizeof msg->header) + sizeof(msg->status)))) | ||
1267 | { | ||
1268 | GNUNET_break_op (0); | ||
1269 | goto cleanup; | ||
1270 | } | ||
1271 | if ('\0' != name[name_len]) | ||
1272 | { | ||
1273 | GNUNET_break_op (0); | ||
1274 | goto cleanup; | ||
1275 | } | ||
1276 | LOG_DEBUG ("Received BARRIER_STATUS msg\n"); | ||
1277 | status = ntohs (msg->status); | ||
1278 | if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status) | ||
1279 | { | ||
1280 | status = -1; | ||
1281 | // unlike name_len, emsg_len includes the trailing zero | ||
1282 | emsg_len = msize - (sizeof(struct GNUNET_TESTBED_BarrierStatusMsg) | ||
1283 | + (name_len + 1)); | ||
1284 | if (0 == emsg_len) | ||
1285 | { | ||
1286 | GNUNET_break_op (0); | ||
1287 | goto cleanup; | ||
1288 | } | ||
1289 | if ('\0' != (msg->data[(name_len + 1) + (emsg_len - 1)])) | ||
1290 | { | ||
1291 | GNUNET_break_op (0); | ||
1292 | goto cleanup; | ||
1293 | } | ||
1294 | emsg = GNUNET_malloc (emsg_len); | ||
1295 | GNUNET_memcpy (emsg, msg->data + name_len + 1, emsg_len); | ||
1296 | } | ||
1297 | if (NULL == c->barrier_map) | ||
1298 | { | ||
1299 | GNUNET_break_op (0); | ||
1300 | goto cleanup; | ||
1301 | } | ||
1302 | GNUNET_CRYPTO_hash (name, name_len, &key); | ||
1303 | barrier = GNUNET_CONTAINER_multihashmap_get (c->barrier_map, &key); | ||
1304 | if (NULL == barrier) | ||
1305 | { | ||
1306 | GNUNET_break_op (0); | ||
1307 | goto cleanup; | ||
1308 | } | ||
1309 | GNUNET_assert (NULL != barrier->cb); | ||
1310 | if ((GNUNET_YES == barrier->echo) && | ||
1311 | (GNUNET_TESTBED_BARRIERSTATUS_CROSSED == status)) | ||
1312 | GNUNET_TESTBED_queue_message_ (c, GNUNET_copy_message (&msg->header)); | ||
1313 | barrier->cb (barrier->cls, name, barrier, status, emsg); | ||
1314 | if (GNUNET_TESTBED_BARRIERSTATUS_INITIALISED == status) | ||
1315 | return; /* just initialised; skip cleanup */ | ||
1316 | |||
1317 | cleanup: | ||
1318 | GNUNET_free (emsg); | ||
1319 | /** | ||
1320 | * Do not remove the barrier if we did not echo the status back; this is | ||
1321 | * required at the chained testbed controller setup to ensure the only the | ||
1322 | * test-driver echos the status and the controller hierarchy properly | ||
1323 | * propagates the status. | ||
1324 | */if ((NULL != barrier) && (GNUNET_YES == barrier->echo)) | ||
1325 | GNUNET_TESTBED_barrier_remove_ (barrier); | ||
1326 | } | ||
1327 | |||
1328 | |||
1329 | /** | ||
1330 | * Queues a message in send queue for sending to the service | ||
1331 | * | ||
1332 | * @param controller the handle to the controller | ||
1333 | * @param msg the message to queue | ||
1334 | */ | ||
1335 | void | ||
1336 | GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller, | ||
1337 | struct GNUNET_MessageHeader *msg) | ||
1338 | { | ||
1339 | struct GNUNET_MQ_Envelope *env; | ||
1340 | struct GNUNET_MessageHeader *m2; | ||
1341 | uint16_t type; | ||
1342 | uint16_t size; | ||
1343 | |||
1344 | type = ntohs (msg->type); | ||
1345 | size = ntohs (msg->size); | ||
1346 | GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) && | ||
1347 | (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type)); | ||
1348 | env = GNUNET_MQ_msg_extra (m2, size - sizeof(*m2), type); | ||
1349 | GNUNET_memcpy (m2, msg, size); | ||
1350 | GNUNET_free (msg); | ||
1351 | GNUNET_MQ_send (controller->mq, env); | ||
1352 | } | ||
1353 | |||
1354 | |||
1355 | /** | ||
1356 | * Sends the given message as an operation. The given callback is called when a | ||
1357 | * reply for the operation is available. Call | ||
1358 | * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned | ||
1359 | * operation context if the cc hasn't been called | ||
1360 | * | ||
1361 | * @param controller the controller to which the message has to be sent | ||
1362 | * @param operation_id the operation id of the message | ||
1363 | * @param msg the message to send | ||
1364 | * @param cc the callback to call when reply is available | ||
1365 | * @param cc_cls the closure for the above callback | ||
1366 | * @return the operation context which can be used to cancel the forwarded | ||
1367 | * operation | ||
1368 | */ | ||
1369 | struct OperationContext * | ||
1370 | GNUNET_TESTBED_forward_operation_msg_ ( | ||
1371 | struct GNUNET_TESTBED_Controller *controller, | ||
1372 | uint64_t operation_id, | ||
1373 | const struct GNUNET_MessageHeader *msg, | ||
1374 | GNUNET_MQ_MessageCallback cc, | ||
1375 | void *cc_cls) | ||
1376 | { | ||
1377 | struct OperationContext *opc; | ||
1378 | struct ForwardedOperationData *data; | ||
1379 | struct GNUNET_MQ_Envelope *env; | ||
1380 | struct GNUNET_MessageHeader *m2; | ||
1381 | uint16_t type = ntohs (msg->type); | ||
1382 | uint16_t size = ntohs (msg->size); | ||
1383 | |||
1384 | env = GNUNET_MQ_msg_extra (m2, size - sizeof(*m2), type); | ||
1385 | GNUNET_memcpy (m2, msg, size); | ||
1386 | GNUNET_MQ_send (controller->mq, env); | ||
1387 | data = GNUNET_new (struct ForwardedOperationData); | ||
1388 | data->cc = cc; | ||
1389 | data->cc_cls = cc_cls; | ||
1390 | opc = GNUNET_new (struct OperationContext); | ||
1391 | opc->c = controller; | ||
1392 | opc->type = OP_FORWARDED; | ||
1393 | opc->data = data; | ||
1394 | opc->id = operation_id; | ||
1395 | GNUNET_TESTBED_insert_opc_ (controller, opc); | ||
1396 | return opc; | ||
1397 | } | ||
1398 | |||
1399 | |||
1400 | /** | ||
1401 | * Function to cancel an operation created by simply forwarding an operation | ||
1402 | * message. | ||
1403 | * | ||
1404 | * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_() | ||
1405 | */ | ||
1406 | void | ||
1407 | GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc) | ||
1408 | { | ||
1409 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
1410 | GNUNET_free (opc->data); | ||
1411 | GNUNET_free (opc); | ||
1412 | } | ||
1413 | |||
1414 | |||
1415 | /** | ||
1416 | * Function to call to start a link-controllers type operation once all queues | ||
1417 | * the operation is part of declare that the operation can be activated. | ||
1418 | * | ||
1419 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
1420 | */ | ||
1421 | static void | ||
1422 | opstart_link_controllers (void *cls) | ||
1423 | { | ||
1424 | struct OperationContext *opc = cls; | ||
1425 | struct ControllerLinkData *data; | ||
1426 | struct GNUNET_TESTBED_ControllerLinkRequest *msg; | ||
1427 | |||
1428 | GNUNET_assert (NULL != opc->data); | ||
1429 | data = opc->data; | ||
1430 | msg = data->msg; | ||
1431 | data->msg = NULL; | ||
1432 | opc->state = OPC_STATE_STARTED; | ||
1433 | GNUNET_TESTBED_insert_opc_ (opc->c, opc); | ||
1434 | GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); | ||
1435 | } | ||
1436 | |||
1437 | |||
1438 | /** | ||
1439 | * Callback which will be called when link-controllers type operation is released | ||
1440 | * | ||
1441 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
1442 | */ | ||
1443 | static void | ||
1444 | oprelease_link_controllers (void *cls) | ||
1445 | { | ||
1446 | struct OperationContext *opc = cls; | ||
1447 | struct ControllerLinkData *data; | ||
1448 | |||
1449 | data = opc->data; | ||
1450 | switch (opc->state) | ||
1451 | { | ||
1452 | case OPC_STATE_INIT: | ||
1453 | GNUNET_free (data->msg); | ||
1454 | break; | ||
1455 | |||
1456 | case OPC_STATE_STARTED: | ||
1457 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
1458 | break; | ||
1459 | |||
1460 | case OPC_STATE_FINISHED: | ||
1461 | break; | ||
1462 | } | ||
1463 | GNUNET_free (data); | ||
1464 | GNUNET_free (opc); | ||
1465 | } | ||
1466 | |||
1467 | |||
1468 | /** | ||
1469 | * Function to be called when get slave config operation is ready | ||
1470 | * | ||
1471 | * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG | ||
1472 | */ | ||
1473 | static void | ||
1474 | opstart_get_slave_config (void *cls) | ||
1475 | { | ||
1476 | struct OperationContext *opc = cls; | ||
1477 | struct GetSlaveConfigData *data = opc->data; | ||
1478 | struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg; | ||
1479 | |||
1480 | GNUNET_assert (NULL != data); | ||
1481 | msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id); | ||
1482 | GNUNET_free (opc->data); | ||
1483 | data = NULL; | ||
1484 | opc->data = NULL; | ||
1485 | GNUNET_TESTBED_insert_opc_ (opc->c, opc); | ||
1486 | GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); | ||
1487 | opc->state = OPC_STATE_STARTED; | ||
1488 | } | ||
1489 | |||
1490 | |||
1491 | /** | ||
1492 | * Function to be called when get slave config operation is cancelled or finished | ||
1493 | * | ||
1494 | * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG | ||
1495 | */ | ||
1496 | static void | ||
1497 | oprelease_get_slave_config (void *cls) | ||
1498 | { | ||
1499 | struct OperationContext *opc = cls; | ||
1500 | |||
1501 | switch (opc->state) | ||
1502 | { | ||
1503 | case OPC_STATE_INIT: | ||
1504 | GNUNET_free (opc->data); | ||
1505 | break; | ||
1506 | |||
1507 | case OPC_STATE_STARTED: | ||
1508 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
1509 | break; | ||
1510 | |||
1511 | case OPC_STATE_FINISHED: | ||
1512 | if (NULL != opc->data) | ||
1513 | GNUNET_CONFIGURATION_destroy (opc->data); | ||
1514 | break; | ||
1515 | } | ||
1516 | GNUNET_free (opc); | ||
1517 | } | ||
1518 | |||
1519 | |||
1520 | /** | ||
1521 | * Generic error handler, called with the appropriate error code and | ||
1522 | * the same closure specified at the creation of the message queue. | ||
1523 | * Not every message queue implementation supports an error handler. | ||
1524 | * | ||
1525 | * @param cls closure, a `struct GNUNET_TESTBED_Controller *` | ||
1526 | * @param error error code | ||
1527 | */ | ||
1528 | static void | ||
1529 | mq_error_handler (void *cls, enum GNUNET_MQ_Error error) | ||
1530 | { | ||
1531 | /* struct GNUNET_TESTBED_Controller *c = cls; */ | ||
1532 | |||
1533 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Encountered MQ error: %d\n", error); | ||
1534 | /* now what? */ | ||
1535 | GNUNET_SCHEDULER_shutdown (); /* seems most reasonable */ | ||
1536 | } | ||
1537 | |||
1538 | |||
1539 | /** | ||
1540 | * Start a controller process using the given configuration at the | ||
1541 | * given host. | ||
1542 | * | ||
1543 | * @param host host to run the controller on; This should be the same host if | ||
1544 | * the controller was previously started with | ||
1545 | * GNUNET_TESTBED_controller_start() | ||
1546 | * @param event_mask bit mask with set of events to call 'cc' for; | ||
1547 | * or-ed values of "1LL" shifted by the | ||
1548 | * respective 'enum GNUNET_TESTBED_EventType' | ||
1549 | * (e.g. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...") | ||
1550 | * @param cc controller callback to invoke on events | ||
1551 | * @param cc_cls closure for cc | ||
1552 | * @return handle to the controller | ||
1553 | */ | ||
1554 | struct GNUNET_TESTBED_Controller * | ||
1555 | GNUNET_TESTBED_controller_connect (struct GNUNET_TESTBED_Host *host, | ||
1556 | uint64_t event_mask, | ||
1557 | GNUNET_TESTBED_ControllerCallback cc, | ||
1558 | void *cc_cls) | ||
1559 | { | ||
1560 | struct GNUNET_TESTBED_Controller *controller = | ||
1561 | GNUNET_new (struct GNUNET_TESTBED_Controller); | ||
1562 | struct GNUNET_MQ_MessageHandler handlers[] = | ||
1563 | { GNUNET_MQ_hd_var_size (add_host_confirm, | ||
1564 | GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS, | ||
1565 | struct GNUNET_TESTBED_HostConfirmedMessage, | ||
1566 | controller), | ||
1567 | GNUNET_MQ_hd_fixed_size (peer_conevent, | ||
1568 | GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT, | ||
1569 | struct GNUNET_TESTBED_ConnectionEventMessage, | ||
1570 | controller), | ||
1571 | GNUNET_MQ_hd_fixed_size (opsuccess, | ||
1572 | GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS, | ||
1573 | struct | ||
1574 | GNUNET_TESTBED_GenericOperationSuccessEventMessage, | ||
1575 | controller), | ||
1576 | GNUNET_MQ_hd_var_size (op_fail_event, | ||
1577 | GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT, | ||
1578 | struct GNUNET_TESTBED_OperationFailureEventMessage, | ||
1579 | controller), | ||
1580 | GNUNET_MQ_hd_fixed_size (peer_create_success, | ||
1581 | GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS, | ||
1582 | struct | ||
1583 | GNUNET_TESTBED_PeerCreateSuccessEventMessage, | ||
1584 | controller), | ||
1585 | GNUNET_MQ_hd_fixed_size (peer_event, | ||
1586 | GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT, | ||
1587 | struct GNUNET_TESTBED_PeerEventMessage, | ||
1588 | controller), | ||
1589 | GNUNET_MQ_hd_var_size (peer_config, | ||
1590 | GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION, | ||
1591 | struct | ||
1592 | GNUNET_TESTBED_PeerConfigurationInformationMessage, | ||
1593 | controller), | ||
1594 | GNUNET_MQ_hd_var_size (slave_config, | ||
1595 | GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION, | ||
1596 | struct GNUNET_TESTBED_SlaveConfiguration, | ||
1597 | controller), | ||
1598 | GNUNET_MQ_hd_var_size (link_controllers_result, | ||
1599 | GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT, | ||
1600 | struct GNUNET_TESTBED_ControllerLinkResponse, | ||
1601 | controller), | ||
1602 | GNUNET_MQ_hd_var_size (barrier_status, | ||
1603 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, | ||
1604 | struct GNUNET_TESTBED_BarrierStatusMsg, | ||
1605 | controller), | ||
1606 | GNUNET_MQ_handler_end () }; | ||
1607 | struct GNUNET_TESTBED_InitMessage *msg; | ||
1608 | struct GNUNET_MQ_Envelope *env; | ||
1609 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
1610 | const char *controller_hostname; | ||
1611 | unsigned long long max_parallel_operations; | ||
1612 | unsigned long long max_parallel_service_connections; | ||
1613 | unsigned long long max_parallel_topology_config_operations; | ||
1614 | size_t slen; | ||
1615 | |||
1616 | GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host))); | ||
1617 | if (GNUNET_OK != | ||
1618 | GNUNET_CONFIGURATION_get_value_number (cfg, | ||
1619 | "testbed", | ||
1620 | "MAX_PARALLEL_OPERATIONS", | ||
1621 | &max_parallel_operations)) | ||
1622 | { | ||
1623 | GNUNET_break (0); | ||
1624 | GNUNET_free (controller); | ||
1625 | return NULL; | ||
1626 | } | ||
1627 | if (GNUNET_OK != | ||
1628 | GNUNET_CONFIGURATION_get_value_number (cfg, | ||
1629 | "testbed", | ||
1630 | "MAX_PARALLEL_SERVICE_CONNECTIONS", | ||
1631 | &max_parallel_service_connections)) | ||
1632 | { | ||
1633 | GNUNET_break (0); | ||
1634 | GNUNET_free (controller); | ||
1635 | return NULL; | ||
1636 | } | ||
1637 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number ( | ||
1638 | cfg, | ||
1639 | "testbed", | ||
1640 | "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS", | ||
1641 | &max_parallel_topology_config_operations)) | ||
1642 | { | ||
1643 | GNUNET_break (0); | ||
1644 | GNUNET_free (controller); | ||
1645 | return NULL; | ||
1646 | } | ||
1647 | controller->cc = cc; | ||
1648 | controller->cc_cls = cc_cls; | ||
1649 | controller->event_mask = event_mask; | ||
1650 | controller->cfg = GNUNET_CONFIGURATION_dup (cfg); | ||
1651 | controller->mq = GNUNET_CLIENT_connect (controller->cfg, | ||
1652 | "testbed", | ||
1653 | handlers, | ||
1654 | &mq_error_handler, | ||
1655 | controller); | ||
1656 | if (NULL == controller->mq) | ||
1657 | { | ||
1658 | GNUNET_break (0); | ||
1659 | GNUNET_TESTBED_controller_disconnect (controller); | ||
1660 | return NULL; | ||
1661 | } | ||
1662 | GNUNET_TESTBED_mark_host_registered_at_ (host, controller); | ||
1663 | controller->host = host; | ||
1664 | controller->opq_parallel_operations = | ||
1665 | GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, | ||
1666 | (unsigned int) | ||
1667 | max_parallel_operations); | ||
1668 | controller->opq_parallel_service_connections = | ||
1669 | GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, | ||
1670 | (unsigned int) | ||
1671 | max_parallel_service_connections); | ||
1672 | controller->opq_parallel_topology_config_operations = | ||
1673 | GNUNET_TESTBED_operation_queue_create_ ( | ||
1674 | OPERATION_QUEUE_TYPE_FIXED, | ||
1675 | (unsigned int) max_parallel_topology_config_operations); | ||
1676 | controller_hostname = GNUNET_TESTBED_host_get_hostname (host); | ||
1677 | if (NULL == controller_hostname) | ||
1678 | controller_hostname = "127.0.0.1"; | ||
1679 | slen = strlen (controller_hostname) + 1; | ||
1680 | env = GNUNET_MQ_msg_extra (msg, slen, GNUNET_MESSAGE_TYPE_TESTBED_INIT); | ||
1681 | msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host)); | ||
1682 | msg->event_mask = GNUNET_htonll (controller->event_mask); | ||
1683 | GNUNET_memcpy (&msg[1], controller_hostname, slen); | ||
1684 | GNUNET_MQ_send (controller->mq, env); | ||
1685 | return controller; | ||
1686 | } | ||
1687 | |||
1688 | |||
1689 | /** | ||
1690 | * Iterator to free opc map entries | ||
1691 | * | ||
1692 | * @param cls closure | ||
1693 | * @param key current key code | ||
1694 | * @param value value in the hash map | ||
1695 | * @return #GNUNET_YES if we should continue to iterate, | ||
1696 | * #GNUNET_NO if not. | ||
1697 | */ | ||
1698 | static int | ||
1699 | opc_free_iterator (void *cls, uint32_t key, void *value) | ||
1700 | { | ||
1701 | struct GNUNET_CONTAINER_MultiHashMap32 *map = cls; | ||
1702 | struct OperationContext *opc = value; | ||
1703 | |||
1704 | GNUNET_assert (NULL != opc); | ||
1705 | GNUNET_break (0); | ||
1706 | GNUNET_assert (GNUNET_YES == | ||
1707 | GNUNET_CONTAINER_multihashmap32_remove (map, key, value)); | ||
1708 | GNUNET_free (opc); | ||
1709 | return GNUNET_YES; | ||
1710 | } | ||
1711 | |||
1712 | |||
1713 | /** | ||
1714 | * Stop the given controller (also will terminate all peers and | ||
1715 | * controllers dependent on this controller). This function | ||
1716 | * blocks until the testbed has been fully terminated (!). | ||
1717 | * | ||
1718 | * @param c handle to controller to stop | ||
1719 | */ | ||
1720 | void | ||
1721 | GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller *c) | ||
1722 | { | ||
1723 | if (NULL != c->mq) | ||
1724 | { | ||
1725 | GNUNET_MQ_destroy (c->mq); | ||
1726 | c->mq = NULL; | ||
1727 | } | ||
1728 | if (NULL != c->host) | ||
1729 | GNUNET_TESTBED_deregister_host_at_ (c->host, c); | ||
1730 | GNUNET_CONFIGURATION_destroy (c->cfg); | ||
1731 | GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_operations); | ||
1732 | GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_service_connections); | ||
1733 | GNUNET_TESTBED_operation_queue_destroy_ ( | ||
1734 | c->opq_parallel_topology_config_operations); | ||
1735 | if (NULL != c->opc_map) | ||
1736 | { | ||
1737 | GNUNET_assert (GNUNET_SYSERR != | ||
1738 | GNUNET_CONTAINER_multihashmap32_iterate (c->opc_map, | ||
1739 | &opc_free_iterator, | ||
1740 | c->opc_map)); | ||
1741 | GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map)); | ||
1742 | GNUNET_CONTAINER_multihashmap32_destroy (c->opc_map); | ||
1743 | } | ||
1744 | GNUNET_free (c); | ||
1745 | } | ||
1746 | |||
1747 | |||
1748 | /** | ||
1749 | * Compresses given configuration using zlib compress | ||
1750 | * | ||
1751 | * @param config the serialized configuration | ||
1752 | * @param size the size of config | ||
1753 | * @param xconfig will be set to the compressed configuration (memory is fresly | ||
1754 | * allocated) | ||
1755 | * @return the size of the xconfig | ||
1756 | */ | ||
1757 | size_t | ||
1758 | GNUNET_TESTBED_compress_config_ (const char *config, | ||
1759 | size_t size, | ||
1760 | char **xconfig) | ||
1761 | { | ||
1762 | size_t xsize; | ||
1763 | |||
1764 | xsize = compressBound ((uLong) size); | ||
1765 | *xconfig = GNUNET_malloc (xsize); | ||
1766 | GNUNET_assert (Z_OK == compress2 ((Bytef *) *xconfig, | ||
1767 | (uLongf *) &xsize, | ||
1768 | (const Bytef *) config, | ||
1769 | (uLongf) size, | ||
1770 | Z_BEST_SPEED)); | ||
1771 | return xsize; | ||
1772 | } | ||
1773 | |||
1774 | |||
1775 | /** | ||
1776 | * Function to serialize and compress using zlib a configuration through a | ||
1777 | * configuration handle | ||
1778 | * | ||
1779 | * @param cfg the configuration | ||
1780 | * @param size the size of configuration when serialize. Will be set on success. | ||
1781 | * @param xsize the sizeo of the compressed configuration. Will be set on success. | ||
1782 | * @return the serialized and compressed configuration | ||
1783 | */ | ||
1784 | char * | ||
1785 | GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
1786 | size_t *size, | ||
1787 | size_t *xsize) | ||
1788 | { | ||
1789 | char *config; | ||
1790 | char *xconfig; | ||
1791 | size_t size_; | ||
1792 | size_t xsize_; | ||
1793 | |||
1794 | config = GNUNET_CONFIGURATION_serialize (cfg, &size_); | ||
1795 | xsize_ = GNUNET_TESTBED_compress_config_ (config, size_, &xconfig); | ||
1796 | GNUNET_free (config); | ||
1797 | *size = size_; | ||
1798 | *xsize = xsize_; | ||
1799 | return xconfig; | ||
1800 | } | ||
1801 | |||
1802 | |||
1803 | /** | ||
1804 | * Create a link from slave controller to delegated controller. Whenever the | ||
1805 | * master controller is asked to start a peer at the delegated controller the | ||
1806 | * request will be routed towards slave controller (if a route exists). The | ||
1807 | * slave controller will then route it to the delegated controller. The | ||
1808 | * configuration of the delegated controller is given and is used to either | ||
1809 | * create the delegated controller or to connect to an existing controller. Note | ||
1810 | * that while starting the delegated controller the configuration will be | ||
1811 | * modified to accommodate available free ports. the 'is_subordinate' specifies | ||
1812 | * if the given delegated controller should be started and managed by the slave | ||
1813 | * controller, or if the delegated controller already has a master and the slave | ||
1814 | * controller connects to it as a non master controller. The success or failure | ||
1815 | * of this operation will be signalled through the | ||
1816 | * GNUNET_TESTBED_ControllerCallback() with an event of type | ||
1817 | * GNUNET_TESTBED_ET_OPERATION_FINISHED | ||
1818 | * | ||
1819 | * @param op_cls the operation closure for the event which is generated to | ||
1820 | * signal success or failure of this operation | ||
1821 | * @param master handle to the master controller who creates the association | ||
1822 | * @param delegated_host requests to which host should be delegated; cannot be NULL | ||
1823 | * @param slave_host which host is used to run the slave controller; use NULL to | ||
1824 | * make the master controller connect to the delegated host | ||
1825 | * @param is_subordinate GNUNET_YES if the controller at delegated_host should | ||
1826 | * be started by the slave controller; GNUNET_NO if the slave | ||
1827 | * controller has to connect to the already started delegated | ||
1828 | * controller via TCP/IP | ||
1829 | * @return the operation handle | ||
1830 | */ | ||
1831 | struct GNUNET_TESTBED_Operation * | ||
1832 | GNUNET_TESTBED_controller_link (void *op_cls, | ||
1833 | struct GNUNET_TESTBED_Controller *master, | ||
1834 | struct GNUNET_TESTBED_Host *delegated_host, | ||
1835 | struct GNUNET_TESTBED_Host *slave_host, | ||
1836 | int is_subordinate) | ||
1837 | { | ||
1838 | struct OperationContext *opc; | ||
1839 | struct GNUNET_TESTBED_ControllerLinkRequest *msg; | ||
1840 | struct ControllerLinkData *data; | ||
1841 | uint32_t slave_host_id; | ||
1842 | uint32_t delegated_host_id; | ||
1843 | uint16_t msg_size; | ||
1844 | |||
1845 | GNUNET_assert (GNUNET_YES == | ||
1846 | GNUNET_TESTBED_is_host_registered_ (delegated_host, master)); | ||
1847 | slave_host_id = GNUNET_TESTBED_host_get_id_ ( | ||
1848 | (NULL != slave_host) ? slave_host : master->host); | ||
1849 | delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host); | ||
1850 | if ((NULL != slave_host) && (0 != slave_host_id)) | ||
1851 | GNUNET_assert (GNUNET_YES == | ||
1852 | GNUNET_TESTBED_is_host_registered_ (slave_host, master)); | ||
1853 | msg_size = sizeof(struct GNUNET_TESTBED_ControllerLinkRequest); | ||
1854 | msg = GNUNET_malloc (msg_size); | ||
1855 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS); | ||
1856 | msg->header.size = htons (msg_size); | ||
1857 | msg->delegated_host_id = htonl (delegated_host_id); | ||
1858 | msg->slave_host_id = htonl (slave_host_id); | ||
1859 | msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0; | ||
1860 | data = GNUNET_new (struct ControllerLinkData); | ||
1861 | data->msg = msg; | ||
1862 | data->host_id = delegated_host_id; | ||
1863 | opc = GNUNET_new (struct OperationContext); | ||
1864 | opc->c = master; | ||
1865 | opc->data = data; | ||
1866 | opc->type = OP_LINK_CONTROLLERS; | ||
1867 | opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); | ||
1868 | opc->state = OPC_STATE_INIT; | ||
1869 | opc->op_cls = op_cls; | ||
1870 | msg->operation_id = GNUNET_htonll (opc->id); | ||
1871 | opc->op = GNUNET_TESTBED_operation_create_ (opc, | ||
1872 | &opstart_link_controllers, | ||
1873 | &oprelease_link_controllers); | ||
1874 | GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations, | ||
1875 | opc->op); | ||
1876 | GNUNET_TESTBED_operation_begin_wait_ (opc->op); | ||
1877 | return opc->op; | ||
1878 | } | ||
1879 | |||
1880 | |||
1881 | /** | ||
1882 | * Like GNUNET_TESTBED_get_slave_config(), however without the host registration | ||
1883 | * check. Another difference is that this function takes the id of the slave | ||
1884 | * host. | ||
1885 | * | ||
1886 | * @param op_cls the closure for the operation | ||
1887 | * @param master the handle to master controller | ||
1888 | * @param slave_host_id id of the host where the slave controller is running to | ||
1889 | * the slave_host should remain valid until this operation is cancelled | ||
1890 | * or marked as finished | ||
1891 | * @return the operation handle; | ||
1892 | */ | ||
1893 | struct GNUNET_TESTBED_Operation * | ||
1894 | GNUNET_TESTBED_get_slave_config_ (void *op_cls, | ||
1895 | struct GNUNET_TESTBED_Controller *master, | ||
1896 | uint32_t slave_host_id) | ||
1897 | { | ||
1898 | struct OperationContext *opc; | ||
1899 | struct GetSlaveConfigData *data; | ||
1900 | |||
1901 | data = GNUNET_new (struct GetSlaveConfigData); | ||
1902 | data->slave_id = slave_host_id; | ||
1903 | opc = GNUNET_new (struct OperationContext); | ||
1904 | opc->state = OPC_STATE_INIT; | ||
1905 | opc->c = master; | ||
1906 | opc->id = GNUNET_TESTBED_get_next_op_id (master); | ||
1907 | opc->type = OP_GET_SLAVE_CONFIG; | ||
1908 | opc->data = data; | ||
1909 | opc->op_cls = op_cls; | ||
1910 | opc->op = GNUNET_TESTBED_operation_create_ (opc, | ||
1911 | &opstart_get_slave_config, | ||
1912 | &oprelease_get_slave_config); | ||
1913 | GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations, | ||
1914 | opc->op); | ||
1915 | GNUNET_TESTBED_operation_begin_wait_ (opc->op); | ||
1916 | return opc->op; | ||
1917 | } | ||
1918 | |||
1919 | |||
1920 | /** | ||
1921 | * Function to acquire the configuration of a running slave controller. The | ||
1922 | * completion of the operation is signalled through the controller_cb from | ||
1923 | * GNUNET_TESTBED_controller_connect(). If the operation is successful the | ||
1924 | * handle to the configuration is available in the generic pointer of | ||
1925 | * operation_finished field of struct GNUNET_TESTBED_EventInformation. | ||
1926 | * | ||
1927 | * @param op_cls the closure for the operation | ||
1928 | * @param master the handle to master controller | ||
1929 | * @param slave_host the host where the slave controller is running; the handle | ||
1930 | * to the slave_host should remain valid until this operation is | ||
1931 | * cancelled or marked as finished | ||
1932 | * @return the operation handle; NULL if the slave_host is not registered at | ||
1933 | * master | ||
1934 | */ | ||
1935 | struct GNUNET_TESTBED_Operation * | ||
1936 | GNUNET_TESTBED_get_slave_config (void *op_cls, | ||
1937 | struct GNUNET_TESTBED_Controller *master, | ||
1938 | struct GNUNET_TESTBED_Host *slave_host) | ||
1939 | { | ||
1940 | if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master)) | ||
1941 | return NULL; | ||
1942 | return GNUNET_TESTBED_get_slave_config_ (op_cls, | ||
1943 | master, | ||
1944 | GNUNET_TESTBED_host_get_id_ ( | ||
1945 | slave_host)); | ||
1946 | } | ||
1947 | |||
1948 | |||
1949 | /** | ||
1950 | * Ask the testbed controller to write the current overlay topology to | ||
1951 | * a file. Naturally, the file will only contain a snapshot as the | ||
1952 | * topology may evolve all the time. | ||
1953 | * | ||
1954 | * @param controller overlay controller to inspect | ||
1955 | * @param filename name of the file the topology should | ||
1956 | * be written to. | ||
1957 | */ | ||
1958 | void | ||
1959 | GNUNET_TESTBED_overlay_write_topology_to_file ( | ||
1960 | struct GNUNET_TESTBED_Controller *controller, | ||
1961 | const char *filename) | ||
1962 | { | ||
1963 | GNUNET_break (0); | ||
1964 | } | ||
1965 | |||
1966 | |||
1967 | /** | ||
1968 | * Creates a helper initialization message. This function is here because we | ||
1969 | * want to use this in testing | ||
1970 | * | ||
1971 | * @param trusted_ip the ip address of the controller which will be set as TRUSTED | ||
1972 | * HOST(all connections form this ip are permitted by the testbed) when | ||
1973 | * starting testbed controller at host. This can either be a single ip | ||
1974 | * address or a network address in CIDR notation. | ||
1975 | * @param hostname the hostname of the destination this message is intended for | ||
1976 | * @param cfg the configuration that has to used to start the testbed service | ||
1977 | * thru helper | ||
1978 | * @return the initialization message | ||
1979 | */ | ||
1980 | struct GNUNET_TESTBED_HelperInit * | ||
1981 | GNUNET_TESTBED_create_helper_init_msg_ ( | ||
1982 | const char *trusted_ip, | ||
1983 | const char *hostname, | ||
1984 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
1985 | { | ||
1986 | struct GNUNET_TESTBED_HelperInit *msg; | ||
1987 | char *config; | ||
1988 | char *xconfig; | ||
1989 | size_t config_size; | ||
1990 | size_t xconfig_size; | ||
1991 | uint16_t trusted_ip_len; | ||
1992 | uint16_t hostname_len; | ||
1993 | uint16_t msg_size; | ||
1994 | |||
1995 | config = GNUNET_CONFIGURATION_serialize (cfg, &config_size); | ||
1996 | GNUNET_assert (NULL != config); | ||
1997 | xconfig_size = | ||
1998 | GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig); | ||
1999 | GNUNET_free (config); | ||
2000 | trusted_ip_len = strlen (trusted_ip); | ||
2001 | hostname_len = (NULL == hostname) ? 0 : strlen (hostname); | ||
2002 | msg_size = xconfig_size + trusted_ip_len + 1 | ||
2003 | + sizeof(struct GNUNET_TESTBED_HelperInit); | ||
2004 | msg_size += hostname_len; | ||
2005 | msg = GNUNET_realloc (xconfig, msg_size); | ||
2006 | (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, | ||
2007 | msg, | ||
2008 | xconfig_size); | ||
2009 | msg->header.size = htons (msg_size); | ||
2010 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT); | ||
2011 | msg->trusted_ip_size = htons (trusted_ip_len); | ||
2012 | msg->hostname_size = htons (hostname_len); | ||
2013 | msg->config_size = htons (config_size); | ||
2014 | (void) strcpy ((char *) &msg[1], trusted_ip); | ||
2015 | if (0 != hostname_len) | ||
2016 | GNUNET_memcpy ((char *) &msg[1] + trusted_ip_len + 1, | ||
2017 | hostname, | ||
2018 | hostname_len); | ||
2019 | return msg; | ||
2020 | } | ||
2021 | |||
2022 | |||
2023 | /** | ||
2024 | * This function is used to signal that the event information (struct | ||
2025 | * GNUNET_TESTBED_EventInformation) from an operation has been fully processed | ||
2026 | * i.e. if the event callback is ever called for this operation. If the event | ||
2027 | * callback for this operation has not yet been called, calling this function | ||
2028 | * cancels the operation, frees its resources and ensures the no event is | ||
2029 | * generated with respect to this operation. Note that however cancelling an | ||
2030 | * operation does NOT guarantee that the operation will be fully undone (or that | ||
2031 | * nothing ever happened). | ||
2032 | * | ||
2033 | * This function MUST be called for every operation to fully remove the | ||
2034 | * operation from the operation queue. After calling this function, if | ||
2035 | * operation is completed and its event information is of type | ||
2036 | * GNUNET_TESTBED_ET_OPERATION_FINISHED, the 'op_result' becomes invalid (!). | ||
2037 | |||
2038 | * If the operation is generated from GNUNET_TESTBED_service_connect() then | ||
2039 | * calling this function on such as operation calls the disconnect adapter if | ||
2040 | * the connect adapter was ever called. | ||
2041 | * | ||
2042 | * @param operation operation to signal completion or cancellation | ||
2043 | */ | ||
2044 | void | ||
2045 | GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation) | ||
2046 | { | ||
2047 | (void) exop_check (operation); | ||
2048 | GNUNET_TESTBED_operation_release_ (operation); | ||
2049 | } | ||
2050 | |||
2051 | |||
2052 | /** | ||
2053 | * Generates configuration by uncompressing configuration in given message. The | ||
2054 | * given message should be of the following types: | ||
2055 | * #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION, | ||
2056 | * #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION, | ||
2057 | * #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, | ||
2058 | * #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, | ||
2059 | * #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT, | ||
2060 | * | ||
2061 | * FIXME: This API is incredibly ugly. | ||
2062 | * | ||
2063 | * @param msg the message containing compressed configuration | ||
2064 | * @return handle to the parsed configuration; NULL upon error while parsing the message | ||
2065 | */ | ||
2066 | struct GNUNET_CONFIGURATION_Handle * | ||
2067 | GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg) | ||
2068 | { | ||
2069 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
2070 | Bytef *data; | ||
2071 | const Bytef *xdata; | ||
2072 | uLong data_len; | ||
2073 | uLong xdata_len; | ||
2074 | int ret; | ||
2075 | |||
2076 | switch (ntohs (msg->type)) | ||
2077 | { | ||
2078 | case GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION: { | ||
2079 | const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg; | ||
2080 | |||
2081 | imsg = | ||
2082 | (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg; | ||
2083 | data_len = (uLong) ntohs (imsg->config_size); | ||
2084 | xdata_len = | ||
2085 | ntohs (imsg->header.size) | ||
2086 | - sizeof(struct GNUNET_TESTBED_PeerConfigurationInformationMessage); | ||
2087 | xdata = (const Bytef *) &imsg[1]; | ||
2088 | } | ||
2089 | break; | ||
2090 | |||
2091 | case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION: { | ||
2092 | const struct GNUNET_TESTBED_SlaveConfiguration *imsg; | ||
2093 | |||
2094 | imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg; | ||
2095 | data_len = (uLong) ntohs (imsg->config_size); | ||
2096 | xdata_len = ntohs (imsg->header.size) | ||
2097 | - sizeof(struct GNUNET_TESTBED_SlaveConfiguration); | ||
2098 | xdata = (const Bytef *) &imsg[1]; | ||
2099 | } | ||
2100 | break; | ||
2101 | |||
2102 | case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST: { | ||
2103 | const struct GNUNET_TESTBED_AddHostMessage *imsg; | ||
2104 | uint16_t osize; | ||
2105 | |||
2106 | imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg; | ||
2107 | data_len = (uLong) ntohs (imsg->config_size); | ||
2108 | osize = sizeof(struct GNUNET_TESTBED_AddHostMessage) | ||
2109 | + ntohs (imsg->username_length) + ntohs (imsg->hostname_length); | ||
2110 | xdata_len = ntohs (imsg->header.size) - osize; | ||
2111 | xdata = (const Bytef *) ((const void *) imsg + osize); | ||
2112 | } | ||
2113 | break; | ||
2114 | |||
2115 | case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT: { | ||
2116 | const struct GNUNET_TESTBED_ControllerLinkResponse *imsg; | ||
2117 | |||
2118 | imsg = (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg; | ||
2119 | data_len = ntohs (imsg->config_size); | ||
2120 | xdata_len = ntohs (imsg->header.size) | ||
2121 | - sizeof(const struct GNUNET_TESTBED_ControllerLinkResponse); | ||
2122 | xdata = (const Bytef *) &imsg[1]; | ||
2123 | } | ||
2124 | break; | ||
2125 | |||
2126 | case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER: { | ||
2127 | const struct GNUNET_TESTBED_PeerCreateMessage *imsg; | ||
2128 | |||
2129 | imsg = (const struct GNUNET_TESTBED_PeerCreateMessage *) msg; | ||
2130 | data_len = ntohs (imsg->config_size); | ||
2131 | xdata_len = ntohs (imsg->header.size) | ||
2132 | - sizeof(struct GNUNET_TESTBED_PeerCreateMessage); | ||
2133 | xdata = (const Bytef *) &imsg[1]; | ||
2134 | } | ||
2135 | break; | ||
2136 | |||
2137 | case GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER: { | ||
2138 | const struct GNUNET_TESTBED_PeerReconfigureMessage *imsg; | ||
2139 | |||
2140 | imsg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) msg; | ||
2141 | data_len = ntohs (imsg->config_size); | ||
2142 | xdata_len = ntohs (imsg->header.size) | ||
2143 | - sizeof(struct GNUNET_TESTBED_PeerReconfigureMessage); | ||
2144 | xdata = (const Bytef *) &imsg[1]; | ||
2145 | } | ||
2146 | break; | ||
2147 | |||
2148 | default: | ||
2149 | GNUNET_assert (0); | ||
2150 | } | ||
2151 | data = GNUNET_malloc (data_len); | ||
2152 | if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len))) | ||
2153 | { | ||
2154 | GNUNET_free (data); | ||
2155 | GNUNET_break_op (0); /* Un-compression failure */ | ||
2156 | return NULL; | ||
2157 | } | ||
2158 | cfg = GNUNET_CONFIGURATION_create (); | ||
2159 | if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, | ||
2160 | (const char *) data, | ||
2161 | (size_t) data_len, | ||
2162 | NULL)) | ||
2163 | { | ||
2164 | GNUNET_free (data); | ||
2165 | GNUNET_break_op (0); /* De-serialization failure */ | ||
2166 | return NULL; | ||
2167 | } | ||
2168 | GNUNET_free (data); | ||
2169 | return cfg; | ||
2170 | } | ||
2171 | |||
2172 | |||
2173 | /** | ||
2174 | * Checks the integrity of the OperationFailureEventMessage and if good returns | ||
2175 | * the error message it contains. | ||
2176 | * | ||
2177 | * @param msg the OperationFailureEventMessage | ||
2178 | * @return the error message | ||
2179 | */ | ||
2180 | const char * | ||
2181 | GNUNET_TESTBED_parse_error_string_ ( | ||
2182 | const struct GNUNET_TESTBED_OperationFailureEventMessage *msg) | ||
2183 | { | ||
2184 | uint16_t msize; | ||
2185 | const char *emsg; | ||
2186 | |||
2187 | msize = ntohs (msg->header.size); | ||
2188 | if (sizeof(struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize) | ||
2189 | return NULL; | ||
2190 | msize -= sizeof(struct GNUNET_TESTBED_OperationFailureEventMessage); | ||
2191 | emsg = (const char *) &msg[1]; | ||
2192 | if ('\0' != emsg[msize - 1]) | ||
2193 | { | ||
2194 | GNUNET_break (0); | ||
2195 | return NULL; | ||
2196 | } | ||
2197 | return emsg; | ||
2198 | } | ||
2199 | |||
2200 | |||
2201 | /** | ||
2202 | * Function to return the operation id for a controller. The operation id is | ||
2203 | * created from the controllers host id and its internal operation counter. | ||
2204 | * | ||
2205 | * @param controller the handle to the controller whose operation id has to be incremented | ||
2206 | * @return the incremented operation id. | ||
2207 | */ | ||
2208 | uint64_t | ||
2209 | GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller *controller) | ||
2210 | { | ||
2211 | uint64_t op_id; | ||
2212 | |||
2213 | op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host); | ||
2214 | op_id = op_id << 32; | ||
2215 | op_id |= (uint64_t) controller->operation_counter++; | ||
2216 | return op_id; | ||
2217 | } | ||
2218 | |||
2219 | |||
2220 | /** | ||
2221 | * Function called when a shutdown peers operation is ready | ||
2222 | * | ||
2223 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
2224 | */ | ||
2225 | static void | ||
2226 | opstart_shutdown_peers (void *cls) | ||
2227 | { | ||
2228 | struct OperationContext *opc = cls; | ||
2229 | struct GNUNET_MQ_Envelope *env; | ||
2230 | struct GNUNET_TESTBED_ShutdownPeersMessage *msg; | ||
2231 | |||
2232 | opc->state = OPC_STATE_STARTED; | ||
2233 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS); | ||
2234 | msg->operation_id = GNUNET_htonll (opc->id); | ||
2235 | GNUNET_TESTBED_insert_opc_ (opc->c, opc); | ||
2236 | GNUNET_MQ_send (opc->c->mq, env); | ||
2237 | } | ||
2238 | |||
2239 | |||
2240 | /** | ||
2241 | * Callback which will be called when shutdown peers operation is released | ||
2242 | * | ||
2243 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
2244 | */ | ||
2245 | static void | ||
2246 | oprelease_shutdown_peers (void *cls) | ||
2247 | { | ||
2248 | struct OperationContext *opc = cls; | ||
2249 | |||
2250 | switch (opc->state) | ||
2251 | { | ||
2252 | case OPC_STATE_STARTED: | ||
2253 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
2254 | |||
2255 | /* no break; continue */ | ||
2256 | case OPC_STATE_INIT: | ||
2257 | GNUNET_free (opc->data); | ||
2258 | break; | ||
2259 | |||
2260 | case OPC_STATE_FINISHED: | ||
2261 | break; | ||
2262 | } | ||
2263 | GNUNET_free (opc); | ||
2264 | } | ||
2265 | |||
2266 | |||
2267 | /** | ||
2268 | * Stops and destroys all peers. Is equivalent of calling | ||
2269 | * GNUNET_TESTBED_peer_stop() and GNUNET_TESTBED_peer_destroy() on all peers, | ||
2270 | * except that the peer stop event and operation finished event corresponding to | ||
2271 | * the respective functions are not generated. This function should be called | ||
2272 | * when there are no other pending operations. If there are pending operations, | ||
2273 | * it will return NULL | ||
2274 | * | ||
2275 | * @param c the controller to send this message to | ||
2276 | * @param op_cls closure for the operation | ||
2277 | * @param cb the callback to call when all peers are stopped and destroyed | ||
2278 | * @param cb_cls the closure for the callback | ||
2279 | * @return operation handle on success; NULL if any pending operations are | ||
2280 | * present | ||
2281 | */ | ||
2282 | struct GNUNET_TESTBED_Operation * | ||
2283 | GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *c, | ||
2284 | void *op_cls, | ||
2285 | GNUNET_TESTBED_OperationCompletionCallback cb, | ||
2286 | void *cb_cls) | ||
2287 | { | ||
2288 | struct OperationContext *opc; | ||
2289 | struct ShutdownPeersData *data; | ||
2290 | |||
2291 | if (0 != GNUNET_CONTAINER_multihashmap32_size (c->opc_map)) | ||
2292 | return NULL; | ||
2293 | data = GNUNET_new (struct ShutdownPeersData); | ||
2294 | data->cb = cb; | ||
2295 | data->cb_cls = cb_cls; | ||
2296 | opc = GNUNET_new (struct OperationContext); | ||
2297 | opc->c = c; | ||
2298 | opc->op_cls = op_cls; | ||
2299 | opc->data = data; | ||
2300 | opc->id = GNUNET_TESTBED_get_next_op_id (c); | ||
2301 | opc->type = OP_SHUTDOWN_PEERS; | ||
2302 | opc->state = OPC_STATE_INIT; | ||
2303 | opc->op = GNUNET_TESTBED_operation_create_ (opc, | ||
2304 | &opstart_shutdown_peers, | ||
2305 | &oprelease_shutdown_peers); | ||
2306 | GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, | ||
2307 | opc->op); | ||
2308 | GNUNET_TESTBED_operation_begin_wait_ (opc->op); | ||
2309 | return opc->op; | ||
2310 | } | ||
2311 | |||
2312 | |||
2313 | /** | ||
2314 | * Return the index of the peer inside of the total peer array, | ||
2315 | * aka. the peer's "unique ID". | ||
2316 | * | ||
2317 | * @param peer Peer handle. | ||
2318 | * | ||
2319 | * @return The peer's unique ID. | ||
2320 | */ | ||
2321 | uint32_t | ||
2322 | GNUNET_TESTBED_get_index (const struct GNUNET_TESTBED_Peer *peer) | ||
2323 | { | ||
2324 | return peer->unique_id; | ||
2325 | } | ||
2326 | |||
2327 | |||
2328 | /** | ||
2329 | * Remove a barrier and it was the last one in the barrier hash map, destroy the | ||
2330 | * hash map | ||
2331 | * | ||
2332 | * @param barrier the barrier to remove | ||
2333 | */ | ||
2334 | void | ||
2335 | GNUNET_TESTBED_barrier_remove_ (struct GNUNET_TESTBED_Barrier *barrier) | ||
2336 | { | ||
2337 | struct GNUNET_TESTBED_Controller *c = barrier->c; | ||
2338 | |||
2339 | GNUNET_assert (NULL != c->barrier_map); /* No barriers present */ | ||
2340 | GNUNET_assert (GNUNET_OK == | ||
2341 | GNUNET_CONTAINER_multihashmap_remove (c->barrier_map, | ||
2342 | &barrier->key, | ||
2343 | barrier)); | ||
2344 | GNUNET_free (barrier->name); | ||
2345 | GNUNET_free (barrier); | ||
2346 | if (0 == GNUNET_CONTAINER_multihashmap_size (c->barrier_map)) | ||
2347 | { | ||
2348 | GNUNET_CONTAINER_multihashmap_destroy (c->barrier_map); | ||
2349 | c->barrier_map = NULL; | ||
2350 | } | ||
2351 | } | ||
2352 | |||
2353 | |||
2354 | /** | ||
2355 | * Initialise a barrier and call the given callback when the required percentage | ||
2356 | * of peers (quorum) reach the barrier OR upon error. | ||
2357 | * | ||
2358 | * @param controller the handle to the controller | ||
2359 | * @param name identification name of the barrier | ||
2360 | * @param quorum the percentage of peers that is required to reach the barrier. | ||
2361 | * Peers signal reaching a barrier by calling | ||
2362 | * GNUNET_TESTBED_barrier_reached(). | ||
2363 | * @param cb the callback to call when the barrier is reached or upon error. | ||
2364 | * Cannot be NULL. | ||
2365 | * @param cls closure for the above callback | ||
2366 | * @param echo GNUNET_YES to echo the barrier crossed status message back to the | ||
2367 | * controller | ||
2368 | * @return barrier handle; NULL upon error | ||
2369 | */ | ||
2370 | struct GNUNET_TESTBED_Barrier * | ||
2371 | GNUNET_TESTBED_barrier_init_ (struct GNUNET_TESTBED_Controller *controller, | ||
2372 | const char *name, | ||
2373 | unsigned int quorum, | ||
2374 | GNUNET_TESTBED_barrier_status_cb cb, | ||
2375 | void *cls, | ||
2376 | int echo) | ||
2377 | { | ||
2378 | struct GNUNET_TESTBED_BarrierInit *msg; | ||
2379 | struct GNUNET_MQ_Envelope *env; | ||
2380 | struct GNUNET_TESTBED_Barrier *barrier; | ||
2381 | struct GNUNET_HashCode key; | ||
2382 | size_t name_len; | ||
2383 | |||
2384 | GNUNET_assert (quorum <= 100); | ||
2385 | GNUNET_assert (NULL != cb); | ||
2386 | name_len = strlen (name); | ||
2387 | GNUNET_assert (0 < name_len); | ||
2388 | GNUNET_CRYPTO_hash (name, name_len, &key); | ||
2389 | if (NULL == controller->barrier_map) | ||
2390 | controller->barrier_map = | ||
2391 | GNUNET_CONTAINER_multihashmap_create (3, GNUNET_YES); | ||
2392 | if (GNUNET_YES == | ||
2393 | GNUNET_CONTAINER_multihashmap_contains (controller->barrier_map, &key)) | ||
2394 | { | ||
2395 | GNUNET_break (0); | ||
2396 | return NULL; | ||
2397 | } | ||
2398 | LOG_DEBUG ("Initialising barrier `%s'\n", name); | ||
2399 | barrier = GNUNET_new (struct GNUNET_TESTBED_Barrier); | ||
2400 | barrier->c = controller; | ||
2401 | barrier->name = GNUNET_strdup (name); | ||
2402 | barrier->cb = cb; | ||
2403 | barrier->cls = cls; | ||
2404 | barrier->echo = echo; | ||
2405 | GNUNET_memcpy (&barrier->key, &key, sizeof(struct GNUNET_HashCode)); | ||
2406 | GNUNET_assert (GNUNET_OK == | ||
2407 | GNUNET_CONTAINER_multihashmap_put ( | ||
2408 | controller->barrier_map, | ||
2409 | &barrier->key, | ||
2410 | barrier, | ||
2411 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); | ||
2412 | |||
2413 | env = GNUNET_MQ_msg_extra (msg, | ||
2414 | name_len, | ||
2415 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT); | ||
2416 | msg->quorum = (uint8_t) quorum; | ||
2417 | GNUNET_memcpy (msg->name, barrier->name, name_len); | ||
2418 | GNUNET_MQ_send (barrier->c->mq, env); | ||
2419 | return barrier; | ||
2420 | } | ||
2421 | |||
2422 | |||
2423 | /** | ||
2424 | * Initialise a barrier and call the given callback when the required percentage | ||
2425 | * of peers (quorum) reach the barrier OR upon error. | ||
2426 | * | ||
2427 | * @param controller the handle to the controller | ||
2428 | * @param name identification name of the barrier | ||
2429 | * @param quorum the percentage of peers that is required to reach the barrier. | ||
2430 | * Peers signal reaching a barrier by calling | ||
2431 | * GNUNET_TESTBED_barrier_reached(). | ||
2432 | * @param cb the callback to call when the barrier is reached or upon error. | ||
2433 | * Cannot be NULL. | ||
2434 | * @param cls closure for the above callback | ||
2435 | * @return barrier handle; NULL upon error | ||
2436 | */ | ||
2437 | struct GNUNET_TESTBED_Barrier * | ||
2438 | GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller, | ||
2439 | const char *name, | ||
2440 | unsigned int quorum, | ||
2441 | GNUNET_TESTBED_barrier_status_cb cb, | ||
2442 | void *cls) | ||
2443 | { | ||
2444 | return GNUNET_TESTBED_barrier_init_ (controller, | ||
2445 | name, | ||
2446 | quorum, | ||
2447 | cb, | ||
2448 | cls, | ||
2449 | GNUNET_YES); | ||
2450 | } | ||
2451 | |||
2452 | |||
2453 | /** | ||
2454 | * Cancel a barrier. | ||
2455 | * | ||
2456 | * @param barrier the barrier handle | ||
2457 | */ | ||
2458 | void | ||
2459 | GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier) | ||
2460 | { | ||
2461 | struct GNUNET_MQ_Envelope *env; | ||
2462 | struct GNUNET_TESTBED_BarrierCancel *msg; | ||
2463 | size_t slen; | ||
2464 | |||
2465 | slen = strlen (barrier->name); | ||
2466 | env = | ||
2467 | GNUNET_MQ_msg_extra (msg, slen, GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL); | ||
2468 | GNUNET_memcpy (msg->name, barrier->name, slen); | ||
2469 | GNUNET_MQ_send (barrier->c->mq, env); | ||
2470 | GNUNET_TESTBED_barrier_remove_ (barrier); | ||
2471 | } | ||
2472 | |||
2473 | |||
2474 | /* end of testbed_api.c */ | ||
diff --git a/src/testbed/testbed_api.h b/src/testbed/testbed_api.h deleted file mode 100644 index d4ef832ad..000000000 --- a/src/testbed/testbed_api.h +++ /dev/null | |||
@@ -1,521 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api.h | ||
23 | * @brief Interface for functions internally exported from testbed_api.c | ||
24 | * @author Sree Harsha Totakura | ||
25 | */ | ||
26 | |||
27 | #ifndef TESTBED_API_H | ||
28 | #define TESTBED_API_H | ||
29 | |||
30 | #include "gnunet_util_lib.h" | ||
31 | #include "gnunet_testbed_service.h" | ||
32 | #include "testbed.h" | ||
33 | #include "testbed_helper.h" | ||
34 | |||
35 | /** | ||
36 | * Testbed Helper binary name | ||
37 | */ | ||
38 | #define HELPER_TESTBED_BINARY "gnunet-helper-testbed" | ||
39 | |||
40 | |||
41 | /** | ||
42 | * Enumeration of operations | ||
43 | */ | ||
44 | enum OperationType | ||
45 | { | ||
46 | /** | ||
47 | * Peer create operation | ||
48 | */ | ||
49 | OP_PEER_CREATE, | ||
50 | |||
51 | /** | ||
52 | * Peer start operation | ||
53 | */ | ||
54 | OP_PEER_START, | ||
55 | |||
56 | /** | ||
57 | * Peer stop operation | ||
58 | */ | ||
59 | OP_PEER_STOP, | ||
60 | |||
61 | /** | ||
62 | * Peer destroy operation | ||
63 | */ | ||
64 | OP_PEER_DESTROY, | ||
65 | |||
66 | /** | ||
67 | * Get peer information operation | ||
68 | */ | ||
69 | OP_PEER_INFO, | ||
70 | |||
71 | /** | ||
72 | * Reconfigure a peer | ||
73 | */ | ||
74 | OP_PEER_RECONFIGURE, | ||
75 | |||
76 | /** | ||
77 | * Overlay connection operation | ||
78 | */ | ||
79 | OP_OVERLAY_CONNECT, | ||
80 | |||
81 | /** | ||
82 | * Forwarded operation | ||
83 | */ | ||
84 | OP_FORWARDED, | ||
85 | |||
86 | /** | ||
87 | * Link controllers operation | ||
88 | */ | ||
89 | OP_LINK_CONTROLLERS, | ||
90 | |||
91 | /** | ||
92 | * Get slave config operation | ||
93 | */ | ||
94 | OP_GET_SLAVE_CONFIG, | ||
95 | |||
96 | /** | ||
97 | * Stop and destroy all peers | ||
98 | */ | ||
99 | OP_SHUTDOWN_PEERS, | ||
100 | |||
101 | /** | ||
102 | * Start/stop service at a peer | ||
103 | */ | ||
104 | OP_MANAGE_SERVICE | ||
105 | }; | ||
106 | |||
107 | |||
108 | /** | ||
109 | * Enumeration of states of OperationContext | ||
110 | */ | ||
111 | enum OperationContextState | ||
112 | { | ||
113 | /** | ||
114 | * The initial state where the associated operation has just been created | ||
115 | * and is waiting in the operation queues to be started | ||
116 | */ | ||
117 | OPC_STATE_INIT = 0, | ||
118 | |||
119 | /** | ||
120 | * The operation has been started. It may occupy some resources which are to | ||
121 | * be freed if cancelled. | ||
122 | */ | ||
123 | OPC_STATE_STARTED, | ||
124 | |||
125 | /** | ||
126 | * The operation has finished. The end results of this operation may occupy | ||
127 | * some resources which are to be freed by operation_done | ||
128 | */ | ||
129 | OPC_STATE_FINISHED | ||
130 | }; | ||
131 | |||
132 | |||
133 | /** | ||
134 | * Context information for GNUNET_TESTBED_Operation | ||
135 | */ | ||
136 | struct OperationContext | ||
137 | { | ||
138 | /** | ||
139 | * The controller to which this operation context belongs to | ||
140 | */ | ||
141 | struct GNUNET_TESTBED_Controller *c; | ||
142 | |||
143 | /** | ||
144 | * The operation | ||
145 | */ | ||
146 | struct GNUNET_TESTBED_Operation *op; | ||
147 | |||
148 | /** | ||
149 | * The operation closure | ||
150 | */ | ||
151 | void *op_cls; | ||
152 | |||
153 | /** | ||
154 | * Data relevant to the operation | ||
155 | */ | ||
156 | void *data; | ||
157 | |||
158 | /** | ||
159 | * The id of the operation | ||
160 | */ | ||
161 | uint64_t id; | ||
162 | |||
163 | /** | ||
164 | * The type of operation | ||
165 | */ | ||
166 | enum OperationType type; | ||
167 | |||
168 | /** | ||
169 | * The state of the operation | ||
170 | */ | ||
171 | enum OperationContextState state; | ||
172 | }; | ||
173 | |||
174 | |||
175 | /** | ||
176 | * Operation empty callback | ||
177 | * | ||
178 | * @param cls closure | ||
179 | */ | ||
180 | typedef void | ||
181 | (*TESTBED_opcq_empty_cb) (void *cls); | ||
182 | |||
183 | |||
184 | /** | ||
185 | * Handle to interact with a GNUnet testbed controller. Each | ||
186 | * controller has at least one master handle which is created when the | ||
187 | * controller is created; this master handle interacts with the | ||
188 | * controller process, destroying it destroys the controller (by | ||
189 | * closing stdin of the controller process). Additionally, | ||
190 | * controllers can interact with each other (in a P2P fashion); those | ||
191 | * links are established via TCP/IP on the controller's service port. | ||
192 | */ | ||
193 | struct GNUNET_TESTBED_Controller | ||
194 | { | ||
195 | /** | ||
196 | * The host where the controller is running | ||
197 | */ | ||
198 | struct GNUNET_TESTBED_Host *host; | ||
199 | |||
200 | /** | ||
201 | * The controller callback | ||
202 | */ | ||
203 | GNUNET_TESTBED_ControllerCallback cc; | ||
204 | |||
205 | /** | ||
206 | * The closure for controller callback | ||
207 | */ | ||
208 | void *cc_cls; | ||
209 | |||
210 | /** | ||
211 | * The configuration to use while connecting to controller | ||
212 | */ | ||
213 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
214 | |||
215 | /** | ||
216 | * The message queue to the controller service | ||
217 | */ | ||
218 | struct GNUNET_MQ_Handle *mq; | ||
219 | |||
220 | /** | ||
221 | * The host registration handle; NULL if no current registration requests are | ||
222 | * present | ||
223 | */ | ||
224 | struct GNUNET_TESTBED_HostRegistrationHandle *rh; | ||
225 | |||
226 | /** | ||
227 | * The map of active operation contexts | ||
228 | */ | ||
229 | struct GNUNET_CONTAINER_MultiHashMap32 *opc_map; | ||
230 | |||
231 | /** | ||
232 | * If this callback is not NULL, schedule it as a task when opc_map gets empty | ||
233 | */ | ||
234 | TESTBED_opcq_empty_cb opcq_empty_cb; | ||
235 | |||
236 | /** | ||
237 | * Closure for the above task | ||
238 | */ | ||
239 | void *opcq_empty_cls; | ||
240 | |||
241 | /** | ||
242 | * Operation queue for simultaneous operations | ||
243 | */ | ||
244 | struct OperationQueue *opq_parallel_operations; | ||
245 | |||
246 | /** | ||
247 | * Operation queue for simultaneous service connections | ||
248 | */ | ||
249 | struct OperationQueue *opq_parallel_service_connections; | ||
250 | |||
251 | /** | ||
252 | * Operation queue for simultaneous topology configuration operations | ||
253 | */ | ||
254 | struct OperationQueue *opq_parallel_topology_config_operations; | ||
255 | |||
256 | /** | ||
257 | * handle for hashtable of barrier handles, values are | ||
258 | * of type `struct GNUNET_TESTBED_Barrier`. | ||
259 | */ | ||
260 | struct GNUNET_CONTAINER_MultiHashMap *barrier_map; | ||
261 | |||
262 | /** | ||
263 | * The controller event mask | ||
264 | */ | ||
265 | uint64_t event_mask; | ||
266 | |||
267 | /** | ||
268 | * The operation id counter. use current value and increment | ||
269 | */ | ||
270 | uint32_t operation_counter; | ||
271 | }; | ||
272 | |||
273 | |||
274 | /** | ||
275 | * Handle for barrier | ||
276 | */ | ||
277 | struct GNUNET_TESTBED_Barrier | ||
278 | { | ||
279 | /** | ||
280 | * hashcode identifying this barrier in the hashmap | ||
281 | */ | ||
282 | struct GNUNET_HashCode key; | ||
283 | |||
284 | /** | ||
285 | * The controller handle given while initialising this barrier | ||
286 | */ | ||
287 | struct GNUNET_TESTBED_Controller *c; | ||
288 | |||
289 | /** | ||
290 | * The name of the barrier | ||
291 | */ | ||
292 | char *name; | ||
293 | |||
294 | /** | ||
295 | * The continuation callback to call when we have a status update on this | ||
296 | */ | ||
297 | GNUNET_TESTBED_barrier_status_cb cb; | ||
298 | |||
299 | /** | ||
300 | * the closure for the above callback | ||
301 | */ | ||
302 | void *cls; | ||
303 | |||
304 | /** | ||
305 | * Should the barrier crossed status message be echoed back to the controller? | ||
306 | */ | ||
307 | int echo; | ||
308 | }; | ||
309 | |||
310 | |||
311 | /** | ||
312 | * Queues a message in send queue for sending to the service | ||
313 | * | ||
314 | * @param controller the handle to the controller | ||
315 | * @param msg the message to queue | ||
316 | * @deprecated | ||
317 | */ | ||
318 | void | ||
319 | GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller, | ||
320 | struct GNUNET_MessageHeader *msg); | ||
321 | |||
322 | |||
323 | /** | ||
324 | * Inserts the given operation context into the operation context map of the | ||
325 | * given controller. Creates the operation context map if one does not exist | ||
326 | * for the controller | ||
327 | * | ||
328 | * @param c the controller | ||
329 | * @param opc the operation context to be inserted | ||
330 | */ | ||
331 | void | ||
332 | GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c, | ||
333 | struct OperationContext *opc); | ||
334 | |||
335 | |||
336 | /** | ||
337 | * Removes the given operation context from the operation context map of the | ||
338 | * given controller | ||
339 | * | ||
340 | * @param c the controller | ||
341 | * @param opc the operation context to remove | ||
342 | */ | ||
343 | void | ||
344 | GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c, | ||
345 | struct OperationContext *opc); | ||
346 | |||
347 | |||
348 | /** | ||
349 | * Compresses given configuration using zlib compress | ||
350 | * | ||
351 | * @param config the serialized configuration | ||
352 | * @param size the size of config | ||
353 | * @param xconfig will be set to the compressed configuration (memory is fresly | ||
354 | * allocated) | ||
355 | * @return the size of the xconfig | ||
356 | */ | ||
357 | size_t | ||
358 | GNUNET_TESTBED_compress_config_ (const char *config, | ||
359 | size_t size, | ||
360 | char **xconfig); | ||
361 | |||
362 | |||
363 | /** | ||
364 | * Function to serialize and compress using zlib a configuration through a | ||
365 | * configuration handle | ||
366 | * | ||
367 | * @param cfg the configuration | ||
368 | * @param size the size of configuration when serialize. Will be set on success. | ||
369 | * @param xsize the sizeo of the compressed configuration. Will be set on success. | ||
370 | * @return the serialized and compressed configuration | ||
371 | */ | ||
372 | char * | ||
373 | GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
374 | size_t *size, | ||
375 | size_t *xsize); | ||
376 | |||
377 | |||
378 | /** | ||
379 | * Creates a helper initialization message. This function is here because we | ||
380 | * want to use this in testing | ||
381 | * | ||
382 | * @param trusted_ip the ip address of the controller which will be set as TRUSTED | ||
383 | * HOST(all connections form this ip are permitted by the testbed) when | ||
384 | * starting testbed controller at host. This can either be a single ip | ||
385 | * address or a network address in CIDR notation. | ||
386 | * @param hostname the hostname of the destination this message is intended for | ||
387 | * @param cfg the configuration that has to used to start the testbed service | ||
388 | * thru helper | ||
389 | * @return the initialization message | ||
390 | */ | ||
391 | struct GNUNET_TESTBED_HelperInit * | ||
392 | GNUNET_TESTBED_create_helper_init_msg_ (const char *cname, | ||
393 | const char *hostname, | ||
394 | const struct | ||
395 | GNUNET_CONFIGURATION_Handle *cfg); | ||
396 | |||
397 | |||
398 | /** | ||
399 | * Sends the given message as an operation. The given callback is called when a | ||
400 | * reply for the operation is available. Call | ||
401 | * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned | ||
402 | * operation context if the cc hasn't been called | ||
403 | * | ||
404 | * @param controller the controller to which the message has to be sent | ||
405 | * @param operation_id the operation id of the message | ||
406 | * @param msg the message to send | ||
407 | * @param cc the callback to call when reply is available | ||
408 | * @param cc_cls the closure for the above callback | ||
409 | * @return the operation context which can be used to cancel the forwarded | ||
410 | * operation | ||
411 | */ | ||
412 | struct OperationContext * | ||
413 | GNUNET_TESTBED_forward_operation_msg_ (struct | ||
414 | GNUNET_TESTBED_Controller *controller, | ||
415 | uint64_t operation_id, | ||
416 | const struct GNUNET_MessageHeader *msg, | ||
417 | GNUNET_MQ_MessageCallback cc, | ||
418 | void *cc_cls); | ||
419 | |||
420 | /** | ||
421 | * Function to cancel an operation created by simply forwarding an operation | ||
422 | * message. | ||
423 | * | ||
424 | * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_() | ||
425 | */ | ||
426 | void | ||
427 | GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc); | ||
428 | |||
429 | |||
430 | /** | ||
431 | * Generates configuration by uncompressing configuration in given message. The | ||
432 | * given message should be of the following types: | ||
433 | * #GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG, | ||
434 | * #GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG | ||
435 | * | ||
436 | * @param msg the message containing compressed configuration | ||
437 | * @return handle to the parsed configuration | ||
438 | */ | ||
439 | struct GNUNET_CONFIGURATION_Handle * | ||
440 | GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg); | ||
441 | |||
442 | |||
443 | /** | ||
444 | * Checks the integrity of the OpeationFailureEventMessage and if good returns | ||
445 | * the error message it contains. | ||
446 | * | ||
447 | * @param msg the OperationFailureEventMessage | ||
448 | * @return the error message | ||
449 | */ | ||
450 | const char * | ||
451 | GNUNET_TESTBED_parse_error_string_ (const struct | ||
452 | GNUNET_TESTBED_OperationFailureEventMessage | ||
453 | *msg); | ||
454 | |||
455 | |||
456 | /** | ||
457 | * Function to return the operation id for a controller. The operation id is | ||
458 | * created from the controllers host id and its internal operation counter. | ||
459 | * | ||
460 | * @param controller the handle to the controller whose operation id has to be incremented | ||
461 | * @return the incremented operation id. | ||
462 | */ | ||
463 | uint64_t | ||
464 | GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller *controller); | ||
465 | |||
466 | |||
467 | /** | ||
468 | * Like GNUNET_TESTBED_get_slave_config(), however without the host registration | ||
469 | * check. Another difference is that this function takes the id of the slave | ||
470 | * host. | ||
471 | * | ||
472 | * @param op_cls the closure for the operation | ||
473 | * @param master the handle to master controller | ||
474 | * @param slave_host_id id of the host where the slave controller is running to | ||
475 | * the slave_host should remain valid until this operation is cancelled | ||
476 | * or marked as finished | ||
477 | * @return the operation handle; | ||
478 | */ | ||
479 | struct GNUNET_TESTBED_Operation * | ||
480 | GNUNET_TESTBED_get_slave_config_ (void *op_cls, | ||
481 | struct GNUNET_TESTBED_Controller *master, | ||
482 | uint32_t slave_host_id); | ||
483 | |||
484 | |||
485 | /** | ||
486 | * Initialise a barrier and call the given callback when the required percentage | ||
487 | * of peers (quorum) reach the barrier OR upon error. | ||
488 | * | ||
489 | * @param controller the handle to the controller | ||
490 | * @param name identification name of the barrier | ||
491 | * @param quorum the percentage of peers that is required to reach the barrier. | ||
492 | * Peers signal reaching a barrier by calling | ||
493 | * GNUNET_TESTBED_barrier_reached(). | ||
494 | * @param cb the callback to call when the barrier is reached or upon error. | ||
495 | * Cannot be NULL. | ||
496 | * @param cls closure for the above callback | ||
497 | * @param echo #GNUNET_YES to echo the barrier crossed status message back to the | ||
498 | * controller | ||
499 | * @return barrier handle; NULL upon error | ||
500 | */ | ||
501 | struct GNUNET_TESTBED_Barrier * | ||
502 | GNUNET_TESTBED_barrier_init_ (struct GNUNET_TESTBED_Controller *controller, | ||
503 | const char *name, | ||
504 | unsigned int quorum, | ||
505 | GNUNET_TESTBED_barrier_status_cb cb, | ||
506 | void *cls, | ||
507 | int echo); | ||
508 | |||
509 | |||
510 | /** | ||
511 | * Remove a barrier and it was the last one in the barrier hash map, destroy the | ||
512 | * hash map | ||
513 | * | ||
514 | * @param barrier the barrier to remove | ||
515 | */ | ||
516 | void | ||
517 | GNUNET_TESTBED_barrier_remove_ (struct GNUNET_TESTBED_Barrier *barrier); | ||
518 | |||
519 | |||
520 | #endif | ||
521 | /* end of testbed_api.h */ | ||
diff --git a/src/testbed/testbed_api_barriers.c b/src/testbed/testbed_api_barriers.c deleted file mode 100644 index 61578c1e6..000000000 --- a/src/testbed/testbed_api_barriers.c +++ /dev/null | |||
@@ -1,264 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2013, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_barriers.c | ||
23 | * @brief API implementation for testbed barriers | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_testbed_service.h" | ||
28 | #include "testbed_api.h" | ||
29 | |||
30 | /** | ||
31 | * Logging shorthand | ||
32 | */ | ||
33 | #define LOG(type, ...) \ | ||
34 | GNUNET_log_from (type, "testbed-api-barriers", __VA_ARGS__); | ||
35 | |||
36 | /** | ||
37 | * Debug logging shorthand | ||
38 | */ | ||
39 | #define LOG_DEBUG(...) \ | ||
40 | LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__); | ||
41 | |||
42 | |||
43 | /** | ||
44 | * Barrier wait handle | ||
45 | */ | ||
46 | struct GNUNET_TESTBED_BarrierWaitHandle | ||
47 | { | ||
48 | /** | ||
49 | * The name of the barrier | ||
50 | */ | ||
51 | char *name; | ||
52 | |||
53 | /** | ||
54 | * Then configuration used for the client connection | ||
55 | */ | ||
56 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
57 | |||
58 | /** | ||
59 | * The testbed-barrier service message queue. | ||
60 | */ | ||
61 | struct GNUNET_MQ_Handle *mq; | ||
62 | |||
63 | /** | ||
64 | * The barrier wait callback | ||
65 | */ | ||
66 | GNUNET_TESTBED_barrier_wait_cb cb; | ||
67 | |||
68 | /** | ||
69 | * The closure for @e cb. | ||
70 | */ | ||
71 | void *cb_cls; | ||
72 | }; | ||
73 | |||
74 | |||
75 | /** | ||
76 | * Check if barrier status message is well-formed. | ||
77 | * | ||
78 | * @param cls closure | ||
79 | * @param msg received message | ||
80 | * @return #GNUNET_OK if the message is well-formed. | ||
81 | */ | ||
82 | static int | ||
83 | check_status (void *cls, | ||
84 | const struct GNUNET_TESTBED_BarrierStatusMsg *msg) | ||
85 | { | ||
86 | /* FIXME: this fails to actually check that the message | ||
87 | follows the protocol spec (0-terminations!). However, | ||
88 | not critical as #handle_status() doesn't interpret the | ||
89 | variable-size part anyway right now. */ | ||
90 | return GNUNET_OK; | ||
91 | } | ||
92 | |||
93 | |||
94 | /** | ||
95 | * Type of a function to call when we receive a message | ||
96 | * from the service. | ||
97 | * | ||
98 | * @param cls closure | ||
99 | * @param msg received message | ||
100 | */ | ||
101 | static void | ||
102 | handle_status (void *cls, | ||
103 | const struct GNUNET_TESTBED_BarrierStatusMsg *msg) | ||
104 | { | ||
105 | struct GNUNET_TESTBED_BarrierWaitHandle *h = cls; | ||
106 | |||
107 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
108 | "Got barrier status %d\n", | ||
109 | (int) ntohs (msg->status)); | ||
110 | switch (ntohs (msg->status)) | ||
111 | { | ||
112 | case GNUNET_TESTBED_BARRIERSTATUS_ERROR: | ||
113 | h->cb (h->cb_cls, | ||
114 | h->name, | ||
115 | GNUNET_SYSERR); | ||
116 | break; | ||
117 | |||
118 | case GNUNET_TESTBED_BARRIERSTATUS_INITIALISED: | ||
119 | h->cb (h->cb_cls, | ||
120 | h->name, | ||
121 | GNUNET_SYSERR); | ||
122 | GNUNET_break (0); | ||
123 | break; | ||
124 | |||
125 | case GNUNET_TESTBED_BARRIERSTATUS_CROSSED: | ||
126 | h->cb (h->cb_cls, | ||
127 | h->name, | ||
128 | GNUNET_OK); | ||
129 | break; | ||
130 | |||
131 | default: | ||
132 | GNUNET_break_op (0); | ||
133 | h->cb (h->cb_cls, | ||
134 | h->name, | ||
135 | GNUNET_SYSERR); | ||
136 | break; | ||
137 | } | ||
138 | GNUNET_TESTBED_barrier_wait_cancel (h); | ||
139 | } | ||
140 | |||
141 | |||
142 | /** | ||
143 | * Generic error handler, called with the appropriate error code and | ||
144 | * the same closure specified at the creation of the message queue. | ||
145 | * Not every message queue implementation supports an error handler. | ||
146 | * | ||
147 | * @param cls closure with the `struct GNUNET_TESTBED_BarrierWaitHandle *` | ||
148 | * @param error error code | ||
149 | */ | ||
150 | static void | ||
151 | mq_error_handler (void *cls, | ||
152 | enum GNUNET_MQ_Error error) | ||
153 | { | ||
154 | struct GNUNET_TESTBED_BarrierWaitHandle *h = cls; | ||
155 | |||
156 | h->cb (h->cb_cls, | ||
157 | h->name, | ||
158 | GNUNET_SYSERR); | ||
159 | GNUNET_TESTBED_barrier_wait_cancel (h); | ||
160 | } | ||
161 | |||
162 | |||
163 | /** | ||
164 | * Wait for a barrier to be crossed. This function should be called by the | ||
165 | * peers which have been started by the testbed. If the peer is not started by | ||
166 | * testbed this function may return error | ||
167 | * | ||
168 | * @param name the name of the barrier | ||
169 | * @param cb the barrier wait callback | ||
170 | * @param cb_cls the closure for @a cb | ||
171 | * @return barrier wait handle which can be used to cancel the waiting at | ||
172 | * anytime before the callback is called. NULL upon error. | ||
173 | */ | ||
174 | struct GNUNET_TESTBED_BarrierWaitHandle * | ||
175 | GNUNET_TESTBED_barrier_wait (const char *name, | ||
176 | GNUNET_TESTBED_barrier_wait_cb cb, | ||
177 | void *cb_cls) | ||
178 | { | ||
179 | struct GNUNET_TESTBED_BarrierWaitHandle *h | ||
180 | = GNUNET_new (struct GNUNET_TESTBED_BarrierWaitHandle); | ||
181 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
182 | GNUNET_MQ_hd_var_size (status, | ||
183 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, | ||
184 | struct GNUNET_TESTBED_BarrierStatusMsg, | ||
185 | h), | ||
186 | GNUNET_MQ_handler_end () | ||
187 | }; | ||
188 | struct GNUNET_MQ_Envelope *env; | ||
189 | struct GNUNET_TESTBED_BarrierWait *msg; | ||
190 | const char *cfg_filename; | ||
191 | size_t name_len; | ||
192 | |||
193 | GNUNET_assert (NULL != cb); | ||
194 | cfg_filename = getenv (ENV_TESTBED_CONFIG); | ||
195 | if (NULL == cfg_filename) | ||
196 | { | ||
197 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
198 | "Are you running under testbed?\n"); | ||
199 | GNUNET_free (h); | ||
200 | return NULL; | ||
201 | } | ||
202 | h->cfg = GNUNET_CONFIGURATION_create (); | ||
203 | if (GNUNET_OK != | ||
204 | GNUNET_CONFIGURATION_load (h->cfg, | ||
205 | cfg_filename)) | ||
206 | { | ||
207 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
208 | "Unable to load configuration from file `%s'\n", | ||
209 | cfg_filename); | ||
210 | GNUNET_CONFIGURATION_destroy (h->cfg); | ||
211 | GNUNET_free (h); | ||
212 | return NULL; | ||
213 | } | ||
214 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
215 | "Waiting on barrier `%s'\n", | ||
216 | name); | ||
217 | h->name = GNUNET_strdup (name); | ||
218 | h->cb = cb; | ||
219 | h->cb_cls = cb_cls; | ||
220 | h->mq = GNUNET_CLIENT_connect (h->cfg, | ||
221 | "testbed-barrier", | ||
222 | handlers, | ||
223 | &mq_error_handler, | ||
224 | h); | ||
225 | if (NULL == h->mq) | ||
226 | { | ||
227 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
228 | "Unable to connect to local testbed-barrier service\n"); | ||
229 | GNUNET_TESTBED_barrier_wait_cancel (h); | ||
230 | return NULL; | ||
231 | } | ||
232 | name_len = strlen (name); /* NOTE: unusual to not have 0-termination, change? */ | ||
233 | env = GNUNET_MQ_msg_extra (msg, | ||
234 | name_len, | ||
235 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT); | ||
236 | GNUNET_memcpy (msg->name, | ||
237 | name, | ||
238 | name_len); | ||
239 | GNUNET_MQ_send (h->mq, | ||
240 | env); | ||
241 | return h; | ||
242 | } | ||
243 | |||
244 | |||
245 | /** | ||
246 | * Cancel a barrier wait handle | ||
247 | * | ||
248 | * @param h the barrier wait handle | ||
249 | */ | ||
250 | void | ||
251 | GNUNET_TESTBED_barrier_wait_cancel (struct GNUNET_TESTBED_BarrierWaitHandle *h) | ||
252 | { | ||
253 | if (NULL != h->mq) | ||
254 | { | ||
255 | GNUNET_MQ_destroy (h->mq); | ||
256 | h->mq = NULL; | ||
257 | } | ||
258 | GNUNET_free (h->name); | ||
259 | GNUNET_CONFIGURATION_destroy (h->cfg); | ||
260 | GNUNET_free (h); | ||
261 | } | ||
262 | |||
263 | |||
264 | /* end of testbed_api_barriers.c */ | ||
diff --git a/src/testbed/testbed_api_hosts.c b/src/testbed/testbed_api_hosts.c deleted file mode 100644 index 8dd0a4893..000000000 --- a/src/testbed/testbed_api_hosts.c +++ /dev/null | |||
@@ -1,1539 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_hosts.c | ||
23 | * @brief API for manipulating 'hosts' controlled by the GNUnet testing service; | ||
24 | * allows parsing hosts files, starting, stopping and communicating (via | ||
25 | * SSH/stdin/stdout) with the remote (or local) processes | ||
26 | * @author Christian Grothoff | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_testbed_service.h" | ||
31 | #include "gnunet_core_service.h" | ||
32 | #include "gnunet_transport_service.h" | ||
33 | |||
34 | #include "testbed_api.h" | ||
35 | #include "testbed_api_hosts.h" | ||
36 | #include "testbed_helper.h" | ||
37 | #include "testbed_api_operations.h" | ||
38 | |||
39 | #include <zlib.h> | ||
40 | #include <regex.h> | ||
41 | |||
42 | /** | ||
43 | * Generic logging shorthand | ||
44 | */ | ||
45 | #define LOG(kind, ...) GNUNET_log_from (kind, "testbed-api-hosts", __VA_ARGS__); | ||
46 | |||
47 | /** | ||
48 | * Debug logging shorthand | ||
49 | */ | ||
50 | #define LOG_DEBUG(...) LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__); | ||
51 | |||
52 | /** | ||
53 | * Prints API violation message | ||
54 | */ | ||
55 | #define API_VIOLATION(cond, errstr) \ | ||
56 | do \ | ||
57 | { \ | ||
58 | if (cond) \ | ||
59 | break; \ | ||
60 | LOG (GNUNET_ERROR_TYPE_ERROR, "API violation detected: %s\n", errstr); \ | ||
61 | GNUNET_assert (0); \ | ||
62 | } while (0) | ||
63 | |||
64 | /** | ||
65 | * Log an error message at log-level 'level' that indicates a failure of the | ||
66 | * command 'cmd' with the message given by gai_strerror(rc). | ||
67 | */ | ||
68 | #define LOG_GAI(level, cmd, rc) \ | ||
69 | do \ | ||
70 | { \ | ||
71 | LOG (level, \ | ||
72 | _ ("`%s' failed at %s:%d with error: %s\n"), \ | ||
73 | cmd, \ | ||
74 | __FILE__, \ | ||
75 | __LINE__, \ | ||
76 | gai_strerror (rc)); \ | ||
77 | } while (0) | ||
78 | |||
79 | /** | ||
80 | * Number of extra elements we create space for when we grow host list | ||
81 | */ | ||
82 | #define HOST_LIST_GROW_STEP 10 | ||
83 | |||
84 | |||
85 | /** | ||
86 | * A list entry for registered controllers list | ||
87 | */ | ||
88 | struct RegisteredController | ||
89 | { | ||
90 | /** | ||
91 | * The controller at which this host is registered | ||
92 | */ | ||
93 | const struct GNUNET_TESTBED_Controller *controller; | ||
94 | |||
95 | /** | ||
96 | * The next ptr for DLL | ||
97 | */ | ||
98 | struct RegisteredController *next; | ||
99 | |||
100 | /** | ||
101 | * The prev ptr for DLL | ||
102 | */ | ||
103 | struct RegisteredController *prev; | ||
104 | }; | ||
105 | |||
106 | |||
107 | /** | ||
108 | * Opaque handle to a host running experiments managed by the testing framework. | ||
109 | * The master process must be able to SSH to this host without password (via | ||
110 | * ssh-agent). | ||
111 | */ | ||
112 | struct GNUNET_TESTBED_Host | ||
113 | { | ||
114 | /** | ||
115 | * The hostname of the host; NULL for localhost | ||
116 | */ | ||
117 | const char *hostname; | ||
118 | |||
119 | /** | ||
120 | * The username to be used for SSH login | ||
121 | */ | ||
122 | const char *username; | ||
123 | |||
124 | /** | ||
125 | * the configuration to use as a template while starting a controller on this | ||
126 | * host. Operation queue size specific to a host are also read from this | ||
127 | * configuration handle. After starting the controller, it points to the actual | ||
128 | * configuration with which the controller is running | ||
129 | */ | ||
130 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
131 | |||
132 | /** | ||
133 | * The head for the list of controllers where this host is registered | ||
134 | */ | ||
135 | struct RegisteredController *rc_head; | ||
136 | |||
137 | /** | ||
138 | * The tail for the list of controllers where this host is registered | ||
139 | */ | ||
140 | struct RegisteredController *rc_tail; | ||
141 | |||
142 | /** | ||
143 | * Operation queue for simultaneous overlay connect operations target at this | ||
144 | * host | ||
145 | */ | ||
146 | struct OperationQueue *opq_parallel_overlay_connect_operations; | ||
147 | |||
148 | /** | ||
149 | * Is a controller started on this host? FIXME: Is this needed? | ||
150 | */ | ||
151 | int controller_started; | ||
152 | |||
153 | /** | ||
154 | * Is this host locked by GNUNET_TESTBED_controller_start()? | ||
155 | */ | ||
156 | int locked; | ||
157 | |||
158 | /** | ||
159 | * Global ID we use to refer to a host on the network | ||
160 | */ | ||
161 | uint32_t id; | ||
162 | |||
163 | /** | ||
164 | * The port which is to be used for SSH | ||
165 | */ | ||
166 | uint16_t port; | ||
167 | }; | ||
168 | |||
169 | |||
170 | /** | ||
171 | * Array of available hosts | ||
172 | */ | ||
173 | static struct GNUNET_TESTBED_Host **host_list; | ||
174 | |||
175 | /** | ||
176 | * The size of the available hosts list | ||
177 | */ | ||
178 | static unsigned int host_list_size; | ||
179 | |||
180 | |||
181 | /** | ||
182 | * Lookup a host by ID. | ||
183 | * | ||
184 | * @param id global host ID assigned to the host; 0 is | ||
185 | * reserved to always mean 'localhost' | ||
186 | * @return handle to the host, NULL if host not found | ||
187 | */ | ||
188 | struct GNUNET_TESTBED_Host * | ||
189 | GNUNET_TESTBED_host_lookup_by_id_ (uint32_t id) | ||
190 | { | ||
191 | if (host_list_size <= id) | ||
192 | return NULL; | ||
193 | return host_list[id]; | ||
194 | } | ||
195 | |||
196 | |||
197 | /** | ||
198 | * Create a host by ID; given this host handle, we could not | ||
199 | * run peers at the host, but we can talk about the host | ||
200 | * internally. | ||
201 | * | ||
202 | * @param id global host ID assigned to the host; 0 is | ||
203 | * reserved to always mean 'localhost' | ||
204 | * @param cfg the configuration to use as a template while starting a controller | ||
205 | * on this host. Operation queue sizes specific to a host are also | ||
206 | * read from this configuration handle | ||
207 | * @return handle to the host, NULL on error | ||
208 | */ | ||
209 | struct GNUNET_TESTBED_Host * | ||
210 | GNUNET_TESTBED_host_create_by_id_ ( | ||
211 | uint32_t id, | ||
212 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
213 | { | ||
214 | return GNUNET_TESTBED_host_create_with_id (id, NULL, NULL, cfg, 0); | ||
215 | } | ||
216 | |||
217 | |||
218 | /** | ||
219 | * Obtain the host's unique global ID. | ||
220 | * | ||
221 | * @param host handle to the host, NULL means 'localhost' | ||
222 | * @return id global host ID assigned to the host (0 is | ||
223 | * 'localhost', but then obviously not globally unique) | ||
224 | */ | ||
225 | uint32_t | ||
226 | GNUNET_TESTBED_host_get_id_ (const struct GNUNET_TESTBED_Host *host) | ||
227 | { | ||
228 | return host->id; | ||
229 | } | ||
230 | |||
231 | |||
232 | /** | ||
233 | * Obtain the host's hostname. | ||
234 | * | ||
235 | * @param host handle to the host, NULL means 'localhost' | ||
236 | * @return hostname of the host | ||
237 | */ | ||
238 | const char * | ||
239 | GNUNET_TESTBED_host_get_hostname (const struct GNUNET_TESTBED_Host *host) | ||
240 | { | ||
241 | return host->hostname; | ||
242 | } | ||
243 | |||
244 | |||
245 | /** | ||
246 | * Obtain the host's username | ||
247 | * | ||
248 | * @param host handle to the host, NULL means 'localhost' | ||
249 | * @return username to login to the host | ||
250 | */ | ||
251 | const char * | ||
252 | GNUNET_TESTBED_host_get_username_ (const struct GNUNET_TESTBED_Host *host) | ||
253 | { | ||
254 | return host->username; | ||
255 | } | ||
256 | |||
257 | |||
258 | /** | ||
259 | * Obtain the host's ssh port | ||
260 | * | ||
261 | * @param host handle to the host, NULL means 'localhost' | ||
262 | * @return username to login to the host | ||
263 | */ | ||
264 | uint16_t | ||
265 | GNUNET_TESTBED_host_get_ssh_port_ (const struct GNUNET_TESTBED_Host *host) | ||
266 | { | ||
267 | return host->port; | ||
268 | } | ||
269 | |||
270 | |||
271 | /** | ||
272 | * Check whether a controller is already started on the given host | ||
273 | * | ||
274 | * @param host the handle to the host | ||
275 | * @return GNUNET_YES if the controller is already started; GNUNET_NO if not | ||
276 | */ | ||
277 | int | ||
278 | GNUNET_TESTBED_host_controller_started (const struct GNUNET_TESTBED_Host *host) | ||
279 | { | ||
280 | return host->controller_started; | ||
281 | } | ||
282 | |||
283 | |||
284 | /** | ||
285 | * Obtain the host's configuration template | ||
286 | * | ||
287 | * @param host handle to the host | ||
288 | * @return the host's configuration template | ||
289 | */ | ||
290 | const struct GNUNET_CONFIGURATION_Handle * | ||
291 | GNUNET_TESTBED_host_get_cfg_ (const struct GNUNET_TESTBED_Host *host) | ||
292 | { | ||
293 | return host->cfg; | ||
294 | } | ||
295 | |||
296 | |||
297 | /** | ||
298 | * Function to replace host's configuration | ||
299 | * | ||
300 | * @param host the host handle | ||
301 | * @param new_cfg the new configuration to replace the old one | ||
302 | */ | ||
303 | void | ||
304 | GNUNET_TESTBED_host_replace_cfg_ ( | ||
305 | struct GNUNET_TESTBED_Host *host, | ||
306 | const struct GNUNET_CONFIGURATION_Handle *new_cfg) | ||
307 | { | ||
308 | GNUNET_CONFIGURATION_destroy (host->cfg); | ||
309 | host->cfg = GNUNET_CONFIGURATION_dup (new_cfg); | ||
310 | } | ||
311 | |||
312 | |||
313 | /** | ||
314 | * Create a host to run peers and controllers on. | ||
315 | * | ||
316 | * @param id global host ID assigned to the host; 0 is | ||
317 | * reserved to always mean 'localhost' | ||
318 | * @param hostname name of the host, use "NULL" for localhost | ||
319 | * @param username username to use for the login; may be NULL | ||
320 | * @param cfg the configuration to use as a template while starting a controller | ||
321 | * on this host. Operation queue sizes specific to a host are also | ||
322 | * read from this configuration handle | ||
323 | * @param port port number to use for ssh; use 0 to let ssh decide | ||
324 | * @return handle to the host, NULL on error | ||
325 | */ | ||
326 | struct GNUNET_TESTBED_Host * | ||
327 | GNUNET_TESTBED_host_create_with_id ( | ||
328 | uint32_t id, | ||
329 | const char *hostname, | ||
330 | const char *username, | ||
331 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
332 | uint16_t port) | ||
333 | { | ||
334 | struct GNUNET_TESTBED_Host *host; | ||
335 | unsigned int new_size; | ||
336 | |||
337 | if ((id < host_list_size) && (NULL != host_list[id])) | ||
338 | { | ||
339 | LOG (GNUNET_ERROR_TYPE_WARNING, "Host with id: %u already created\n", id); | ||
340 | return NULL; | ||
341 | } | ||
342 | host = GNUNET_new (struct GNUNET_TESTBED_Host); | ||
343 | host->hostname = (NULL != hostname) ? GNUNET_strdup (hostname) : NULL; | ||
344 | host->username = (NULL != username) ? GNUNET_strdup (username) : NULL; | ||
345 | host->id = id; | ||
346 | host->port = (0 == port) ? 22 : port; | ||
347 | host->cfg = GNUNET_CONFIGURATION_dup (cfg); | ||
348 | host->opq_parallel_overlay_connect_operations = | ||
349 | GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_ADAPTIVE, | ||
350 | UINT_MAX); | ||
351 | new_size = host_list_size; | ||
352 | while (id >= new_size) | ||
353 | new_size += HOST_LIST_GROW_STEP; | ||
354 | if (new_size != host_list_size) | ||
355 | GNUNET_array_grow (host_list, host_list_size, new_size); | ||
356 | GNUNET_assert (id < host_list_size); | ||
357 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding host with id: %u\n", host->id); | ||
358 | host_list[id] = host; | ||
359 | return host; | ||
360 | } | ||
361 | |||
362 | |||
363 | /** | ||
364 | * Create a host to run peers and controllers on. | ||
365 | * | ||
366 | * @param hostname name of the host, use "NULL" for localhost | ||
367 | * @param username username to use for the login; may be NULL | ||
368 | * @param cfg the configuration to use as a template while starting a controller | ||
369 | * on this host. Operation queue sizes specific to a host are also | ||
370 | * read from this configuration handle | ||
371 | * @param port port number to use for ssh; use 0 to let ssh decide | ||
372 | * @return handle to the host, NULL on error | ||
373 | */ | ||
374 | struct GNUNET_TESTBED_Host * | ||
375 | GNUNET_TESTBED_host_create (const char *hostname, | ||
376 | const char *username, | ||
377 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
378 | uint16_t port) | ||
379 | { | ||
380 | static uint32_t uid_generator; | ||
381 | |||
382 | if (NULL == hostname) | ||
383 | return GNUNET_TESTBED_host_create_with_id (0, | ||
384 | hostname, | ||
385 | username, | ||
386 | cfg, | ||
387 | port); | ||
388 | return GNUNET_TESTBED_host_create_with_id (++uid_generator, | ||
389 | hostname, | ||
390 | username, | ||
391 | cfg, | ||
392 | port); | ||
393 | } | ||
394 | |||
395 | |||
396 | /** | ||
397 | * Load a set of hosts from a configuration file. | ||
398 | * | ||
399 | * @param filename file with the host specification | ||
400 | * @param cfg the configuration to use as a template while starting a controller | ||
401 | * on any of the loaded hosts. Operation queue sizes specific to a host | ||
402 | * are also read from this configuration handle | ||
403 | * @param hosts set to the hosts found in the file; caller must free this if | ||
404 | * number of hosts returned is greater than 0 | ||
405 | * @return number of hosts returned in 'hosts', 0 on error | ||
406 | */ | ||
407 | unsigned int | ||
408 | GNUNET_TESTBED_hosts_load_from_file ( | ||
409 | const char *filename, | ||
410 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
411 | struct GNUNET_TESTBED_Host ***hosts) | ||
412 | { | ||
413 | struct GNUNET_TESTBED_Host *starting_host; | ||
414 | char *data; | ||
415 | char *buf; | ||
416 | char *username; | ||
417 | char *hostname; | ||
418 | regex_t rex; | ||
419 | regmatch_t pmatch[6]; | ||
420 | uint64_t fs; | ||
421 | short int port; | ||
422 | unsigned int offset; | ||
423 | unsigned int count; | ||
424 | |||
425 | |||
426 | GNUNET_assert (NULL != filename); | ||
427 | if (GNUNET_YES != GNUNET_DISK_file_test (filename)) | ||
428 | { | ||
429 | LOG (GNUNET_ERROR_TYPE_WARNING, _ ("Hosts file %s not found\n"), filename); | ||
430 | return 0; | ||
431 | } | ||
432 | if (GNUNET_OK != | ||
433 | GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES)) | ||
434 | fs = 0; | ||
435 | if (0 == fs) | ||
436 | { | ||
437 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
438 | _ ("Hosts file %s has no data\n"), | ||
439 | filename); | ||
440 | return 0; | ||
441 | } | ||
442 | data = GNUNET_malloc (fs); | ||
443 | if (fs != GNUNET_DISK_fn_read (filename, data, fs)) | ||
444 | { | ||
445 | GNUNET_free (data); | ||
446 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
447 | _ ("Hosts file %s cannot be read\n"), | ||
448 | filename); | ||
449 | return 0; | ||
450 | } | ||
451 | buf = data; | ||
452 | offset = 0; | ||
453 | starting_host = NULL; | ||
454 | count = 0; | ||
455 | /* refer RFC 952 and RFC 1123 for valid hostnames */ | ||
456 | GNUNET_assert (0 == regcomp (&rex, | ||
457 | "^(([[:alnum:]]+)@)?" /* username */ | ||
458 | "([[:alnum:]]+[-[:alnum:]_\\.]+)" /* hostname */ | ||
459 | "(:([[:digit:]]{1,5}))?", /* port */ | ||
460 | REG_EXTENDED | REG_ICASE)); | ||
461 | while (offset < (fs - 1)) | ||
462 | { | ||
463 | offset++; | ||
464 | if (((data[offset] == '\n')) && (buf != &data[offset])) | ||
465 | { | ||
466 | unsigned int size; | ||
467 | |||
468 | data[offset] = '\0'; | ||
469 | username = NULL; | ||
470 | hostname = NULL; | ||
471 | port = 0; | ||
472 | if ((REG_NOMATCH == regexec (&rex, buf, 6, pmatch, 0)) || | ||
473 | (-1 == pmatch[3].rm_so)) | ||
474 | { | ||
475 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
476 | "Error reading line `%s' in hostfile\n", | ||
477 | buf); | ||
478 | buf = &data[offset + 1]; | ||
479 | continue; | ||
480 | } | ||
481 | if (-1 != pmatch[2].rm_so) | ||
482 | { | ||
483 | size = pmatch[2].rm_eo - pmatch[2].rm_so; | ||
484 | username = GNUNET_malloc (size + 1); | ||
485 | GNUNET_assert ( | ||
486 | 0 != GNUNET_strlcpy (username, buf + pmatch[2].rm_so, size + 1)); | ||
487 | } | ||
488 | if (-1 != pmatch[5].rm_so) | ||
489 | { | ||
490 | (void) sscanf (buf + pmatch[5].rm_so, "%5hd", &port); | ||
491 | } | ||
492 | size = pmatch[3].rm_eo - pmatch[3].rm_so; | ||
493 | hostname = GNUNET_malloc (size + 1); | ||
494 | GNUNET_assert ( | ||
495 | 0 != GNUNET_strlcpy (hostname, buf + pmatch[3].rm_so, size + 1)); | ||
496 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
497 | "Successfully read host %s, port %d and user %s from file\n", | ||
498 | (NULL == hostname) ? "NULL" : hostname, | ||
499 | port, | ||
500 | (NULL == username) ? "NULL" : username); | ||
501 | /* We store hosts in a static list; hence we only require the starting | ||
502 | * host pointer in that list to access the newly created list of hosts */ | ||
503 | if (NULL == starting_host) | ||
504 | starting_host = | ||
505 | GNUNET_TESTBED_host_create (hostname, username, cfg, port); | ||
506 | else | ||
507 | (void) GNUNET_TESTBED_host_create (hostname, username, cfg, port); | ||
508 | count++; | ||
509 | GNUNET_free (username); | ||
510 | GNUNET_free (hostname); | ||
511 | buf = &data[offset + 1]; | ||
512 | } | ||
513 | else if ((data[offset] == '\n') || (data[offset] == '\0')) | ||
514 | buf = &data[offset + 1]; | ||
515 | } | ||
516 | regfree (&rex); | ||
517 | GNUNET_free (data); | ||
518 | if (NULL == starting_host) | ||
519 | return 0; | ||
520 | *hosts = GNUNET_malloc (sizeof(struct GNUNET_TESTBED_Host *) * count); | ||
521 | GNUNET_memcpy (*hosts, | ||
522 | &host_list[GNUNET_TESTBED_host_get_id_ (starting_host)], | ||
523 | sizeof(struct GNUNET_TESTBED_Host *) * count); | ||
524 | return count; | ||
525 | } | ||
526 | |||
527 | |||
528 | /** | ||
529 | * Resolves a hostname using getaddrinfo | ||
530 | * | ||
531 | * @param host the hostname | ||
532 | * @return the string representing the IPv4 address of the given host; NULL upon error | ||
533 | */ | ||
534 | const char * | ||
535 | simple_resolve (const char *host) | ||
536 | { | ||
537 | struct addrinfo *res; | ||
538 | const struct sockaddr_in *in_addr; | ||
539 | char *hostip; | ||
540 | struct addrinfo hint; | ||
541 | unsigned int rc; | ||
542 | |||
543 | hint.ai_family = AF_INET; /* IPv4 */ | ||
544 | hint.ai_socktype = 0; | ||
545 | hint.ai_protocol = 0; | ||
546 | hint.ai_addrlen = 0; | ||
547 | hint.ai_addr = NULL; | ||
548 | hint.ai_canonname = NULL; | ||
549 | hint.ai_next = NULL; | ||
550 | hint.ai_flags = AI_NUMERICSERV; | ||
551 | res = NULL; | ||
552 | LOG_DEBUG ("Resolving [%s]\n", host); | ||
553 | if (0 != (rc = getaddrinfo (host, "22", &hint, &res))) | ||
554 | { | ||
555 | LOG_GAI (GNUNET_ERROR_TYPE_ERROR, "getaddrinfo", rc); | ||
556 | return NULL; | ||
557 | } | ||
558 | GNUNET_assert (NULL != res); | ||
559 | GNUNET_assert (NULL != res->ai_addr); | ||
560 | GNUNET_assert (sizeof(struct sockaddr_in) == res->ai_addrlen); | ||
561 | in_addr = (const struct sockaddr_in *) res->ai_addr; | ||
562 | hostip = inet_ntoa (in_addr->sin_addr); | ||
563 | GNUNET_assert (NULL != hostip); | ||
564 | freeaddrinfo (res); | ||
565 | LOG_DEBUG ("Resolved [%s] to [%s]\n", host, hostip); | ||
566 | return hostip; | ||
567 | } | ||
568 | |||
569 | |||
570 | /** | ||
571 | * Destroy a host handle. Must only be called once everything | ||
572 | * running on that host has been stopped. | ||
573 | * | ||
574 | * @param host handle to destroy | ||
575 | */ | ||
576 | void | ||
577 | GNUNET_TESTBED_host_destroy (struct GNUNET_TESTBED_Host *host) | ||
578 | { | ||
579 | GNUNET_assert (host->id < host_list_size); | ||
580 | GNUNET_assert (host_list[host->id] == host); | ||
581 | host_list[host->id] = NULL; | ||
582 | /* clear registered controllers list */ | ||
583 | for (struct RegisteredController *rc = host->rc_head; | ||
584 | NULL != rc; | ||
585 | rc = host->rc_head) | ||
586 | { | ||
587 | GNUNET_CONTAINER_DLL_remove (host->rc_head, host->rc_tail, rc); | ||
588 | GNUNET_free (rc); | ||
589 | } | ||
590 | GNUNET_free_nz ((char *) host->username); | ||
591 | GNUNET_free_nz ((char *) host->hostname); | ||
592 | GNUNET_TESTBED_operation_queue_destroy_ ( | ||
593 | host->opq_parallel_overlay_connect_operations); | ||
594 | GNUNET_CONFIGURATION_destroy (host->cfg); | ||
595 | GNUNET_free (host); | ||
596 | while (host_list_size >= HOST_LIST_GROW_STEP) | ||
597 | { | ||
598 | uint32_t id; | ||
599 | |||
600 | for (id = host_list_size - 1; id > host_list_size - HOST_LIST_GROW_STEP; | ||
601 | id--) | ||
602 | if (NULL != host_list[id]) | ||
603 | break; | ||
604 | if (id != host_list_size - HOST_LIST_GROW_STEP) | ||
605 | break; | ||
606 | if (NULL != host_list[id]) | ||
607 | break; | ||
608 | host_list_size -= HOST_LIST_GROW_STEP; | ||
609 | } | ||
610 | host_list = | ||
611 | GNUNET_realloc (host_list, | ||
612 | sizeof(struct GNUNET_TESTBED_Host *) * host_list_size); | ||
613 | } | ||
614 | |||
615 | |||
616 | /** | ||
617 | * Marks a host as registered with a controller | ||
618 | * | ||
619 | * @param host the host to mark | ||
620 | * @param controller the controller at which this host is registered | ||
621 | */ | ||
622 | void | ||
623 | GNUNET_TESTBED_mark_host_registered_at_ ( | ||
624 | struct GNUNET_TESTBED_Host *host, | ||
625 | const struct GNUNET_TESTBED_Controller *const controller) | ||
626 | { | ||
627 | struct RegisteredController *rc; | ||
628 | |||
629 | for (rc = host->rc_head; NULL != rc; rc = rc->next) | ||
630 | { | ||
631 | if (controller == rc->controller) /* already registered at controller */ | ||
632 | { | ||
633 | GNUNET_break (0); | ||
634 | return; | ||
635 | } | ||
636 | } | ||
637 | rc = GNUNET_new (struct RegisteredController); | ||
638 | rc->controller = controller; | ||
639 | GNUNET_CONTAINER_DLL_insert_tail (host->rc_head, host->rc_tail, rc); | ||
640 | } | ||
641 | |||
642 | |||
643 | /** | ||
644 | * Unmarks a host registered at a controller | ||
645 | * | ||
646 | * @param host the host to unmark | ||
647 | * @param controller the controller at which this host has to be unmarked | ||
648 | */ | ||
649 | void | ||
650 | GNUNET_TESTBED_deregister_host_at_ ( | ||
651 | struct GNUNET_TESTBED_Host *host, | ||
652 | const struct GNUNET_TESTBED_Controller *const controller) | ||
653 | { | ||
654 | struct RegisteredController *rc; | ||
655 | |||
656 | for (rc = host->rc_head; NULL != rc; rc = rc->next) | ||
657 | if (controller == rc->controller) | ||
658 | break; | ||
659 | if (NULL == rc) | ||
660 | { | ||
661 | GNUNET_break (0); | ||
662 | return; | ||
663 | } | ||
664 | GNUNET_CONTAINER_DLL_remove (host->rc_head, host->rc_tail, rc); | ||
665 | GNUNET_free (rc); | ||
666 | } | ||
667 | |||
668 | |||
669 | /** | ||
670 | * Checks whether a host has been registered | ||
671 | * | ||
672 | * @param host the host to check | ||
673 | * @param controller the controller at which host's registration is checked | ||
674 | * @return GNUNET_YES if registered; GNUNET_NO if not | ||
675 | */ | ||
676 | int | ||
677 | GNUNET_TESTBED_is_host_registered_ ( | ||
678 | const struct GNUNET_TESTBED_Host *host, | ||
679 | const struct GNUNET_TESTBED_Controller *const controller) | ||
680 | { | ||
681 | struct RegisteredController *rc; | ||
682 | |||
683 | for (rc = host->rc_head; NULL != rc; rc = rc->next) | ||
684 | { | ||
685 | if (controller == rc->controller) /* already registered at controller */ | ||
686 | { | ||
687 | return GNUNET_YES; | ||
688 | } | ||
689 | } | ||
690 | return GNUNET_NO; | ||
691 | } | ||
692 | |||
693 | |||
694 | /** | ||
695 | * Handle for controller process | ||
696 | */ | ||
697 | struct GNUNET_TESTBED_ControllerProc | ||
698 | { | ||
699 | /** | ||
700 | * The process handle | ||
701 | */ | ||
702 | struct GNUNET_HELPER_Handle *helper; | ||
703 | |||
704 | /** | ||
705 | * The arguments used to start the helper | ||
706 | */ | ||
707 | char **helper_argv; | ||
708 | |||
709 | /** | ||
710 | * The host where the helper is run | ||
711 | */ | ||
712 | struct GNUNET_TESTBED_Host *host; | ||
713 | |||
714 | /** | ||
715 | * The controller error callback | ||
716 | */ | ||
717 | GNUNET_TESTBED_ControllerStatusCallback cb; | ||
718 | |||
719 | /** | ||
720 | * The closure for the above callback | ||
721 | */ | ||
722 | void *cls; | ||
723 | |||
724 | /** | ||
725 | * The send handle for the helper | ||
726 | */ | ||
727 | struct GNUNET_HELPER_SendHandle *shandle; | ||
728 | |||
729 | /** | ||
730 | * The message corresponding to send handle | ||
731 | */ | ||
732 | struct GNUNET_MessageHeader *msg; | ||
733 | }; | ||
734 | |||
735 | |||
736 | /** | ||
737 | * Function to copy NULL terminated list of arguments | ||
738 | * | ||
739 | * @param argv the NULL terminated list of arguments. Cannot be NULL. | ||
740 | * @return the copied NULL terminated arguments | ||
741 | */ | ||
742 | static char ** | ||
743 | copy_argv (const char *const *argv) | ||
744 | { | ||
745 | char **argv_dup; | ||
746 | unsigned int argp; | ||
747 | |||
748 | GNUNET_assert (NULL != argv); | ||
749 | for (argp = 0; NULL != argv[argp]; argp++) | ||
750 | ; | ||
751 | argv_dup = GNUNET_malloc (sizeof(char *) * (argp + 1)); | ||
752 | for (argp = 0; NULL != argv[argp]; argp++) | ||
753 | argv_dup[argp] = GNUNET_strdup (argv[argp]); | ||
754 | return argv_dup; | ||
755 | } | ||
756 | |||
757 | |||
758 | /** | ||
759 | * Function to join NULL terminated list of arguments | ||
760 | * | ||
761 | * @param argv1 the NULL terminated list of arguments. Cannot be NULL. | ||
762 | * @param argv2 the NULL terminated list of arguments. Cannot be NULL. | ||
763 | * @return the joined NULL terminated arguments | ||
764 | */ | ||
765 | static char ** | ||
766 | join_argv (const char *const *argv1, const char *const *argv2) | ||
767 | { | ||
768 | char **argvj; | ||
769 | char *argv; | ||
770 | unsigned int carg; | ||
771 | unsigned int cnt; | ||
772 | |||
773 | carg = 0; | ||
774 | argvj = NULL; | ||
775 | for (cnt = 0; NULL != argv1[cnt]; cnt++) | ||
776 | { | ||
777 | argv = GNUNET_strdup (argv1[cnt]); | ||
778 | GNUNET_array_append (argvj, carg, argv); | ||
779 | } | ||
780 | for (cnt = 0; NULL != argv2[cnt]; cnt++) | ||
781 | { | ||
782 | argv = GNUNET_strdup (argv2[cnt]); | ||
783 | GNUNET_array_append (argvj, carg, argv); | ||
784 | } | ||
785 | GNUNET_array_append (argvj, carg, NULL); | ||
786 | return argvj; | ||
787 | } | ||
788 | |||
789 | |||
790 | /** | ||
791 | * Frees the given NULL terminated arguments | ||
792 | * | ||
793 | * @param argv the NULL terminated list of arguments | ||
794 | */ | ||
795 | static void | ||
796 | free_argv (char **argv) | ||
797 | { | ||
798 | unsigned int argp; | ||
799 | |||
800 | for (argp = 0; NULL != argv[argp]; argp++) | ||
801 | GNUNET_free (argv[argp]); | ||
802 | GNUNET_free (argv); | ||
803 | } | ||
804 | |||
805 | |||
806 | /** | ||
807 | * Generates arguments for opening a remote shell. Builds up the arguments | ||
808 | * from the environment variable GNUNET_TESTBED_RSH_CMD. The variable | ||
809 | * should not mention `-p' (port) option and destination address as these will | ||
810 | * be set locally in the function from its parameteres. If the environmental | ||
811 | * variable is not found then it defaults to `ssh -o BatchMode=yes -o | ||
812 | * NoHostAuthenticationForLocalhost=yes -o StrictHostkeyChecking=no -o | ||
813 | * PasswordAuthentication=noc' | ||
814 | * | ||
815 | * @param port the destination port number | ||
816 | * @param hostname the hostname of the target host | ||
817 | * @param username the username to use while connecting to target host | ||
818 | * @return NULL terminated list of arguments | ||
819 | */ | ||
820 | static char ** | ||
821 | gen_rsh_args (const char *port, const char *hostname, const char *username) | ||
822 | { | ||
823 | static const char *default_ssh_args[] = | ||
824 | { "ssh", | ||
825 | "-o", | ||
826 | "BatchMode=yes", | ||
827 | "-o", | ||
828 | "NoHostAuthenticationForLocalhost=yes", | ||
829 | "-o", | ||
830 | "StrictHostKeyChecking=no", | ||
831 | "-o", | ||
832 | "PasswordAuthentication=no", | ||
833 | "%h", | ||
834 | NULL }; | ||
835 | char **ssh_args; | ||
836 | char *ssh_cmd; | ||
837 | char *ssh_cmd_cp; | ||
838 | char *arg; | ||
839 | const char *new_arg; | ||
840 | unsigned int size; | ||
841 | unsigned int cnt; | ||
842 | |||
843 | ssh_args = NULL; | ||
844 | if (NULL != (ssh_cmd = getenv ("GNUNET_TESTBED_RSH_CMD"))) | ||
845 | { | ||
846 | ssh_cmd = GNUNET_strdup (ssh_cmd); | ||
847 | ssh_cmd_cp = ssh_cmd; | ||
848 | for (size = 0; NULL != (arg = strtok (ssh_cmd, " ")); ssh_cmd = NULL) | ||
849 | GNUNET_array_append (ssh_args, size, GNUNET_strdup (arg)); | ||
850 | GNUNET_free (ssh_cmd_cp); | ||
851 | } | ||
852 | else | ||
853 | { | ||
854 | ssh_args = copy_argv (default_ssh_args); | ||
855 | size = (sizeof(default_ssh_args)) / (sizeof(const char *)); | ||
856 | GNUNET_array_grow (ssh_args, size, size - 1); | ||
857 | } | ||
858 | for (cnt = 0; cnt < size; cnt++) | ||
859 | { | ||
860 | arg = ssh_args[cnt]; | ||
861 | if ('%' != arg[0]) | ||
862 | continue; | ||
863 | switch (arg[1]) | ||
864 | { | ||
865 | case 'p': | ||
866 | new_arg = port; | ||
867 | break; | ||
868 | |||
869 | case 'u': | ||
870 | new_arg = username; | ||
871 | break; | ||
872 | |||
873 | case 'h': | ||
874 | new_arg = hostname; | ||
875 | break; | ||
876 | |||
877 | default: | ||
878 | continue; | ||
879 | } | ||
880 | if (NULL == new_arg) | ||
881 | continue; | ||
882 | GNUNET_free (arg); | ||
883 | ssh_args[cnt] = GNUNET_strdup (new_arg); | ||
884 | } | ||
885 | GNUNET_array_append (ssh_args, size, NULL); | ||
886 | return ssh_args; | ||
887 | } | ||
888 | |||
889 | |||
890 | /** | ||
891 | * Generates the arguments needed for executing the given binary in a remote | ||
892 | * shell. Builds the arguments from the environmental variable | ||
893 | * GNUNET_TETSBED_RSH_CMD_SUFFIX. If the environmental variable is not found, | ||
894 | * only the given binary name will be present in the returned arguments | ||
895 | * | ||
896 | * @param append_args the arguments to append after generating the suffix | ||
897 | * arguments. Can be NULL; if not must be NULL terminated 'char *' array | ||
898 | * @return NULL-terminated args | ||
899 | */ | ||
900 | static char ** | ||
901 | gen_rsh_suffix_args (const char *const *append_args) | ||
902 | { | ||
903 | char **rshell_args; | ||
904 | char *rshell_cmd; | ||
905 | char *rshell_cmd_cp; | ||
906 | char *arg; | ||
907 | unsigned int cnt; | ||
908 | unsigned int append_cnt; | ||
909 | |||
910 | rshell_args = NULL; | ||
911 | cnt = 0; | ||
912 | if (NULL != (rshell_cmd = getenv ("GNUNET_TESTBED_RSH_CMD_SUFFIX"))) | ||
913 | { | ||
914 | rshell_cmd = GNUNET_strdup (rshell_cmd); | ||
915 | rshell_cmd_cp = rshell_cmd; | ||
916 | for (; NULL != (arg = strtok (rshell_cmd, " ")); rshell_cmd = NULL) | ||
917 | GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (arg)); | ||
918 | GNUNET_free (rshell_cmd_cp); | ||
919 | } | ||
920 | if (NULL != append_args) | ||
921 | { | ||
922 | for (append_cnt = 0; NULL != append_args[append_cnt]; append_cnt++) | ||
923 | GNUNET_array_append (rshell_args, | ||
924 | cnt, | ||
925 | GNUNET_strdup (append_args[append_cnt])); | ||
926 | } | ||
927 | GNUNET_array_append (rshell_args, cnt, NULL); | ||
928 | return rshell_args; | ||
929 | } | ||
930 | |||
931 | |||
932 | /** | ||
933 | * Functions with this signature are called whenever a | ||
934 | * complete message is received by the tokenizer. | ||
935 | * | ||
936 | * Do not call GNUNET_SERVER_mst_destroy in callback | ||
937 | * | ||
938 | * @param cls closure | ||
939 | * @param client identification of the client | ||
940 | * @param message the actual message | ||
941 | * | ||
942 | * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing | ||
943 | */ | ||
944 | static int | ||
945 | helper_mst (void *cls, const struct GNUNET_MessageHeader *message) | ||
946 | { | ||
947 | struct GNUNET_TESTBED_ControllerProc *cp = cls; | ||
948 | const struct GNUNET_TESTBED_HelperReply *msg; | ||
949 | const char *hostname; | ||
950 | char *config; | ||
951 | uLongf config_size; | ||
952 | uLongf xconfig_size; | ||
953 | |||
954 | msg = (const struct GNUNET_TESTBED_HelperReply *) message; | ||
955 | GNUNET_assert (sizeof(struct GNUNET_TESTBED_HelperReply) < | ||
956 | ntohs (msg->header.size)); | ||
957 | GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY == | ||
958 | ntohs (msg->header.type)); | ||
959 | config_size = (uLongf) ntohs (msg->config_size); | ||
960 | xconfig_size = (uLongf) (ntohs (msg->header.size) | ||
961 | - sizeof(struct GNUNET_TESTBED_HelperReply)); | ||
962 | config = GNUNET_malloc (config_size); | ||
963 | GNUNET_assert (Z_OK == uncompress ((Bytef *) config, | ||
964 | &config_size, | ||
965 | (const Bytef *) &msg[1], | ||
966 | xconfig_size)); | ||
967 | /* Replace the configuration template present in the host with the | ||
968 | controller's running configuration */ | ||
969 | GNUNET_CONFIGURATION_destroy (cp->host->cfg); | ||
970 | cp->host->cfg = GNUNET_CONFIGURATION_create (); | ||
971 | GNUNET_assert (GNUNET_CONFIGURATION_deserialize (cp->host->cfg, | ||
972 | config, | ||
973 | config_size, | ||
974 | NULL)); | ||
975 | GNUNET_free (config); | ||
976 | if (NULL == (hostname = GNUNET_TESTBED_host_get_hostname (cp->host))) | ||
977 | hostname = "localhost"; | ||
978 | /* Change the hostname so that we can connect to it */ | ||
979 | GNUNET_CONFIGURATION_set_value_string (cp->host->cfg, | ||
980 | "testbed", | ||
981 | "hostname", | ||
982 | hostname); | ||
983 | cp->host->locked = GNUNET_NO; | ||
984 | cp->host->controller_started = GNUNET_YES; | ||
985 | cp->cb (cp->cls, cp->host->cfg, GNUNET_OK); | ||
986 | return GNUNET_OK; | ||
987 | } | ||
988 | |||
989 | |||
990 | /** | ||
991 | * Continuation function from GNUNET_HELPER_send() | ||
992 | * | ||
993 | * @param cls closure | ||
994 | * @param result GNUNET_OK on success, | ||
995 | * GNUNET_NO if helper process died | ||
996 | * GNUNET_SYSERR during GNUNET_HELPER_stop | ||
997 | */ | ||
998 | static void | ||
999 | clear_msg (void *cls, int result) | ||
1000 | { | ||
1001 | struct GNUNET_TESTBED_ControllerProc *cp = cls; | ||
1002 | |||
1003 | GNUNET_assert (NULL != cp->shandle); | ||
1004 | cp->shandle = NULL; | ||
1005 | GNUNET_free (cp->msg); | ||
1006 | cp->msg = NULL; | ||
1007 | } | ||
1008 | |||
1009 | |||
1010 | /** | ||
1011 | * Callback that will be called when the helper process dies. This is not called | ||
1012 | * when the helper process is stopped using GNUNET_HELPER_stop() | ||
1013 | * | ||
1014 | * @param cls the closure from GNUNET_HELPER_start() | ||
1015 | */ | ||
1016 | static void | ||
1017 | helper_exp_cb (void *cls) | ||
1018 | { | ||
1019 | struct GNUNET_TESTBED_ControllerProc *cp = cls; | ||
1020 | GNUNET_TESTBED_ControllerStatusCallback cb; | ||
1021 | void *cb_cls; | ||
1022 | |||
1023 | cb = cp->cb; | ||
1024 | cb_cls = cp->cls; | ||
1025 | cp->helper = NULL; | ||
1026 | GNUNET_TESTBED_controller_stop (cp); | ||
1027 | if (NULL != cb) | ||
1028 | cb (cb_cls, NULL, GNUNET_SYSERR); | ||
1029 | } | ||
1030 | |||
1031 | |||
1032 | /** | ||
1033 | * Starts a controller process at the given host. The given host's configuration | ||
1034 | * is used as a Template configuration to use for the remote controller; the | ||
1035 | * remote controller will be started with a slightly modified configuration | ||
1036 | * (port numbers, unix domain sockets and service home values are changed as per | ||
1037 | * TESTING library on the remote host). The modified configuration replaces the | ||
1038 | * host's existing configuration before signalling success through the | ||
1039 | * GNUNET_TESTBED_ControllerStatusCallback() | ||
1040 | * | ||
1041 | * @param trusted_ip the ip address of the controller which will be set as TRUSTED | ||
1042 | * HOST(all connections form this ip are permitted by the testbed) when | ||
1043 | * starting testbed controller at host. This can either be a single ip | ||
1044 | * address or a network address in CIDR notation. | ||
1045 | * @param host the host where the controller has to be started. CANNOT be NULL. | ||
1046 | * @param cb function called when the controller is successfully started or | ||
1047 | * dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be | ||
1048 | * called if cb is called with GNUNET_SYSERR as status. Will never be | ||
1049 | * called in the same task as 'GNUNET_TESTBED_controller_start' | ||
1050 | * (synchronous errors will be signalled by returning NULL). This | ||
1051 | * parameter cannot be NULL. | ||
1052 | * @param cls closure for above callbacks | ||
1053 | * @return the controller process handle, NULL on errors | ||
1054 | */ | ||
1055 | struct GNUNET_TESTBED_ControllerProc * | ||
1056 | GNUNET_TESTBED_controller_start (const char *trusted_ip, | ||
1057 | struct GNUNET_TESTBED_Host *host, | ||
1058 | GNUNET_TESTBED_ControllerStatusCallback cb, | ||
1059 | void *cls) | ||
1060 | { | ||
1061 | struct GNUNET_TESTBED_ControllerProc *cp; | ||
1062 | struct GNUNET_TESTBED_HelperInit *msg; | ||
1063 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
1064 | const char *hostname; | ||
1065 | static char *const binary_argv[] = { HELPER_TESTBED_BINARY, NULL }; | ||
1066 | |||
1067 | GNUNET_assert (NULL != host); | ||
1068 | GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host))); | ||
1069 | hostname = NULL; | ||
1070 | API_VIOLATION ( | ||
1071 | GNUNET_NO == host->locked, | ||
1072 | "Host is already locked by a previous call to GNUNET_TESTBED_controller_start()"); | ||
1073 | host->locked = GNUNET_YES; | ||
1074 | API_VIOLATION ( | ||
1075 | GNUNET_NO == host->controller_started, | ||
1076 | "Attempting to start a controller on a host which is already started a controller"); | ||
1077 | cp = GNUNET_new (struct GNUNET_TESTBED_ControllerProc); | ||
1078 | if (0 == GNUNET_TESTBED_host_get_id_ (host)) | ||
1079 | { | ||
1080 | cp->helper = GNUNET_HELPER_start (GNUNET_YES, | ||
1081 | HELPER_TESTBED_BINARY, | ||
1082 | binary_argv, | ||
1083 | &helper_mst, | ||
1084 | &helper_exp_cb, | ||
1085 | cp); | ||
1086 | } | ||
1087 | else | ||
1088 | { | ||
1089 | char *helper_binary_path_args[2]; | ||
1090 | char **rsh_args; | ||
1091 | char **rsh_suffix_args; | ||
1092 | const char *username; | ||
1093 | char *port; | ||
1094 | char *argstr; | ||
1095 | char *aux; | ||
1096 | unsigned int cnt; | ||
1097 | |||
1098 | username = host->username; | ||
1099 | hostname = host->hostname; | ||
1100 | GNUNET_asprintf (&port, "%u", host->port); | ||
1101 | LOG_DEBUG ("Starting remote connection to destination %s\n", hostname); | ||
1102 | if (GNUNET_OK != | ||
1103 | GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
1104 | "testbed", | ||
1105 | "HELPER_BINARY_PATH", | ||
1106 | &helper_binary_path_args[0])) | ||
1107 | helper_binary_path_args[0] = | ||
1108 | GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY); | ||
1109 | helper_binary_path_args[1] = NULL; | ||
1110 | rsh_args = gen_rsh_args (port, hostname, username); | ||
1111 | rsh_suffix_args = | ||
1112 | gen_rsh_suffix_args ((const char **) helper_binary_path_args); | ||
1113 | cp->helper_argv = | ||
1114 | join_argv ((const char **) rsh_args, (const char **) rsh_suffix_args); | ||
1115 | free_argv (rsh_args); | ||
1116 | free_argv (rsh_suffix_args); | ||
1117 | GNUNET_free (port); | ||
1118 | argstr = GNUNET_strdup (""); | ||
1119 | for (cnt = 0; NULL != cp->helper_argv[cnt]; cnt++) | ||
1120 | { | ||
1121 | aux = argstr; | ||
1122 | GNUNET_assert ( | ||
1123 | 0 < GNUNET_asprintf (&argstr, "%s %s", aux, cp->helper_argv[cnt])); | ||
1124 | GNUNET_free (aux); | ||
1125 | } | ||
1126 | LOG_DEBUG ("Helper cmd str: %s\n", argstr); | ||
1127 | GNUNET_free (argstr); | ||
1128 | cp->helper = GNUNET_HELPER_start (GNUNET_NO, | ||
1129 | cp->helper_argv[0], | ||
1130 | cp->helper_argv, | ||
1131 | &helper_mst, | ||
1132 | &helper_exp_cb, | ||
1133 | cp); | ||
1134 | GNUNET_free (helper_binary_path_args[0]); | ||
1135 | } | ||
1136 | if (NULL == cp->helper) | ||
1137 | { | ||
1138 | if (NULL != cp->helper_argv) | ||
1139 | free_argv (cp->helper_argv); | ||
1140 | GNUNET_free (cp); | ||
1141 | return NULL; | ||
1142 | } | ||
1143 | cp->host = host; | ||
1144 | cp->cb = cb; | ||
1145 | cp->cls = cls; | ||
1146 | msg = GNUNET_TESTBED_create_helper_init_msg_ (trusted_ip, hostname, cfg); | ||
1147 | cp->msg = &msg->header; | ||
1148 | cp->shandle = | ||
1149 | GNUNET_HELPER_send (cp->helper, &msg->header, GNUNET_NO, &clear_msg, cp); | ||
1150 | if (NULL == cp->shandle) | ||
1151 | { | ||
1152 | GNUNET_free (msg); | ||
1153 | GNUNET_TESTBED_controller_stop (cp); | ||
1154 | return NULL; | ||
1155 | } | ||
1156 | return cp; | ||
1157 | } | ||
1158 | |||
1159 | |||
1160 | /** | ||
1161 | * Sends termination signal to the controller's helper process | ||
1162 | * | ||
1163 | * @param cproc the handle to the controller's helper process | ||
1164 | */ | ||
1165 | void | ||
1166 | GNUNET_TESTBED_controller_kill_ (struct GNUNET_TESTBED_ControllerProc *cproc) | ||
1167 | { | ||
1168 | if (NULL != cproc->shandle) | ||
1169 | GNUNET_HELPER_send_cancel (cproc->shandle); | ||
1170 | if (NULL != cproc->helper) | ||
1171 | GNUNET_HELPER_kill (cproc->helper, GNUNET_YES); | ||
1172 | } | ||
1173 | |||
1174 | |||
1175 | /** | ||
1176 | * Cleans-up the controller's helper process handle | ||
1177 | * | ||
1178 | * @param cproc the handle to the controller's helper process | ||
1179 | */ | ||
1180 | void | ||
1181 | GNUNET_TESTBED_controller_destroy_ (struct GNUNET_TESTBED_ControllerProc *cproc) | ||
1182 | { | ||
1183 | if (NULL != cproc->helper) | ||
1184 | { | ||
1185 | GNUNET_break (GNUNET_OK == GNUNET_HELPER_wait (cproc->helper)); | ||
1186 | GNUNET_HELPER_destroy (cproc->helper); | ||
1187 | } | ||
1188 | if (NULL != cproc->helper_argv) | ||
1189 | free_argv (cproc->helper_argv); | ||
1190 | cproc->host->controller_started = GNUNET_NO; | ||
1191 | cproc->host->locked = GNUNET_NO; | ||
1192 | GNUNET_free (cproc->msg); | ||
1193 | GNUNET_free (cproc); | ||
1194 | } | ||
1195 | |||
1196 | |||
1197 | /** | ||
1198 | * Stop the controller process (also will terminate all peers and controllers | ||
1199 | * dependent on this controller). This function blocks until the testbed has | ||
1200 | * been fully terminated (!). The controller status cb from | ||
1201 | * GNUNET_TESTBED_controller_start() will not be called. | ||
1202 | * | ||
1203 | * @param cproc the controller process handle | ||
1204 | */ | ||
1205 | void | ||
1206 | GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc) | ||
1207 | { | ||
1208 | GNUNET_TESTBED_controller_kill_ (cproc); | ||
1209 | GNUNET_TESTBED_controller_destroy_ (cproc); | ||
1210 | } | ||
1211 | |||
1212 | |||
1213 | /** | ||
1214 | * The handle for whether a host is habitable or not | ||
1215 | */ | ||
1216 | struct GNUNET_TESTBED_HostHabitableCheckHandle | ||
1217 | { | ||
1218 | /** | ||
1219 | * The host to check | ||
1220 | */ | ||
1221 | const struct GNUNET_TESTBED_Host *host; | ||
1222 | |||
1223 | /** | ||
1224 | * The callback to call once we have the status | ||
1225 | */ | ||
1226 | GNUNET_TESTBED_HostHabitableCallback cb; | ||
1227 | |||
1228 | /** | ||
1229 | * The callback closure | ||
1230 | */ | ||
1231 | void *cb_cls; | ||
1232 | |||
1233 | /** | ||
1234 | * The process handle for the SSH process | ||
1235 | */ | ||
1236 | struct GNUNET_OS_Process *auxp; | ||
1237 | |||
1238 | /** | ||
1239 | * The arguments used to start the helper | ||
1240 | */ | ||
1241 | char **helper_argv; | ||
1242 | |||
1243 | /** | ||
1244 | * Task id for the habitability check task | ||
1245 | */ | ||
1246 | struct GNUNET_SCHEDULER_Task *habitability_check_task; | ||
1247 | |||
1248 | /** | ||
1249 | * How long we wait before checking the process status. Should grow | ||
1250 | * exponentially | ||
1251 | */ | ||
1252 | struct GNUNET_TIME_Relative wait_time; | ||
1253 | }; | ||
1254 | |||
1255 | |||
1256 | /** | ||
1257 | * Task for checking whether a host is habitable or not | ||
1258 | * | ||
1259 | * @param cls GNUNET_TESTBED_HostHabitableCheckHandle | ||
1260 | */ | ||
1261 | static void | ||
1262 | habitability_check (void *cls) | ||
1263 | { | ||
1264 | struct GNUNET_TESTBED_HostHabitableCheckHandle *h = cls; | ||
1265 | void *cb_cls; | ||
1266 | GNUNET_TESTBED_HostHabitableCallback cb; | ||
1267 | const struct GNUNET_TESTBED_Host *host; | ||
1268 | unsigned long code; | ||
1269 | enum GNUNET_OS_ProcessStatusType type; | ||
1270 | int ret; | ||
1271 | |||
1272 | h->habitability_check_task = NULL; | ||
1273 | ret = GNUNET_OS_process_status (h->auxp, &type, &code); | ||
1274 | if (GNUNET_SYSERR == ret) | ||
1275 | { | ||
1276 | GNUNET_break (0); | ||
1277 | ret = GNUNET_NO; | ||
1278 | goto call_cb; | ||
1279 | } | ||
1280 | if (GNUNET_NO == ret) | ||
1281 | { | ||
1282 | h->wait_time = GNUNET_TIME_STD_BACKOFF (h->wait_time); | ||
1283 | h->habitability_check_task = | ||
1284 | GNUNET_SCHEDULER_add_delayed (h->wait_time, &habitability_check, h); | ||
1285 | return; | ||
1286 | } | ||
1287 | GNUNET_OS_process_destroy (h->auxp); | ||
1288 | h->auxp = NULL; | ||
1289 | ret = (0 != code) ? GNUNET_NO : GNUNET_YES; | ||
1290 | |||
1291 | call_cb: | ||
1292 | if (NULL != h->auxp) | ||
1293 | GNUNET_OS_process_destroy (h->auxp); | ||
1294 | cb = h->cb; | ||
1295 | cb_cls = h->cb_cls; | ||
1296 | host = h->host; | ||
1297 | free_argv (h->helper_argv); | ||
1298 | GNUNET_free (h); | ||
1299 | if (NULL != cb) | ||
1300 | cb (cb_cls, host, ret); | ||
1301 | } | ||
1302 | |||
1303 | |||
1304 | /** | ||
1305 | * Checks whether a host can be used to start testbed service | ||
1306 | * | ||
1307 | * @param host the host to check | ||
1308 | * @param config the configuration handle to lookup the path of the testbed | ||
1309 | * helper | ||
1310 | * @param cb the callback to call to inform about habitability of the given host | ||
1311 | * @param cb_cls the closure for the callback | ||
1312 | * @return NULL upon any error or a handle which can be passed to | ||
1313 | * GNUNET_TESTBED_is_host_habitable_cancel() | ||
1314 | */ | ||
1315 | struct GNUNET_TESTBED_HostHabitableCheckHandle * | ||
1316 | GNUNET_TESTBED_is_host_habitable ( | ||
1317 | const struct GNUNET_TESTBED_Host *host, | ||
1318 | const struct GNUNET_CONFIGURATION_Handle *config, | ||
1319 | GNUNET_TESTBED_HostHabitableCallback cb, | ||
1320 | void *cb_cls) | ||
1321 | { | ||
1322 | struct GNUNET_TESTBED_HostHabitableCheckHandle *h; | ||
1323 | char **rsh_args; | ||
1324 | char **rsh_suffix_args; | ||
1325 | char *stat_args[3]; | ||
1326 | const char *hostname; | ||
1327 | char *port; | ||
1328 | |||
1329 | h = GNUNET_new (struct GNUNET_TESTBED_HostHabitableCheckHandle); | ||
1330 | h->cb = cb; | ||
1331 | h->cb_cls = cb_cls; | ||
1332 | h->host = host; | ||
1333 | hostname = (NULL == host->hostname) ? "127.0.0.1" : host->hostname; | ||
1334 | if (GNUNET_OK != | ||
1335 | GNUNET_CONFIGURATION_get_value_filename (config, | ||
1336 | "testbed", | ||
1337 | "HELPER_BINARY_PATH", | ||
1338 | &stat_args[1])) | ||
1339 | stat_args[1] = GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY); | ||
1340 | GNUNET_asprintf (&port, "%u", host->port); | ||
1341 | rsh_args = gen_rsh_args (port, hostname, host->username); | ||
1342 | GNUNET_free (port); | ||
1343 | port = NULL; | ||
1344 | stat_args[0] = "stat"; | ||
1345 | stat_args[2] = NULL; | ||
1346 | rsh_suffix_args = gen_rsh_suffix_args ((const char **) stat_args); | ||
1347 | GNUNET_free (stat_args[1]); | ||
1348 | h->helper_argv = | ||
1349 | join_argv ((const char **) rsh_args, (const char **) rsh_suffix_args); | ||
1350 | free_argv (rsh_suffix_args); | ||
1351 | free_argv (rsh_args); | ||
1352 | h->auxp = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR, | ||
1353 | NULL, | ||
1354 | NULL, | ||
1355 | NULL, | ||
1356 | h->helper_argv[0], | ||
1357 | h->helper_argv); | ||
1358 | if (NULL == h->auxp) | ||
1359 | { | ||
1360 | GNUNET_break (0); /* Cannot exec SSH? */ | ||
1361 | GNUNET_free (h); | ||
1362 | return NULL; | ||
1363 | } | ||
1364 | h->wait_time = GNUNET_TIME_STD_BACKOFF (h->wait_time); | ||
1365 | h->habitability_check_task = | ||
1366 | GNUNET_SCHEDULER_add_delayed (h->wait_time, &habitability_check, h); | ||
1367 | return h; | ||
1368 | } | ||
1369 | |||
1370 | |||
1371 | /** | ||
1372 | * Function to cancel a request started using GNUNET_TESTBED_is_host_habitable() | ||
1373 | * | ||
1374 | * @param handle the habitability check handle | ||
1375 | */ | ||
1376 | void | ||
1377 | GNUNET_TESTBED_is_host_habitable_cancel ( | ||
1378 | struct GNUNET_TESTBED_HostHabitableCheckHandle *handle) | ||
1379 | { | ||
1380 | GNUNET_SCHEDULER_cancel (handle->habitability_check_task); | ||
1381 | (void) GNUNET_OS_process_kill (handle->auxp, GNUNET_TERM_SIG); | ||
1382 | (void) GNUNET_OS_process_wait (handle->auxp); | ||
1383 | GNUNET_OS_process_destroy (handle->auxp); | ||
1384 | free_argv (handle->helper_argv); | ||
1385 | GNUNET_free (handle); | ||
1386 | } | ||
1387 | |||
1388 | |||
1389 | /** | ||
1390 | * Register a host with the controller | ||
1391 | * | ||
1392 | * @param controller the controller handle | ||
1393 | * @param host the host to register | ||
1394 | * @param cc the completion callback to call to inform the status of | ||
1395 | * registration. After calling this callback the registration handle | ||
1396 | * will be invalid. Cannot be NULL. | ||
1397 | * @param cc_cls the closure for the cc | ||
1398 | * @return handle to the host registration which can be used to cancel the | ||
1399 | * registration | ||
1400 | */ | ||
1401 | struct GNUNET_TESTBED_HostRegistrationHandle * | ||
1402 | GNUNET_TESTBED_register_host (struct GNUNET_TESTBED_Controller *controller, | ||
1403 | struct GNUNET_TESTBED_Host *host, | ||
1404 | GNUNET_TESTBED_HostRegistrationCompletion cc, | ||
1405 | void *cc_cls) | ||
1406 | { | ||
1407 | struct GNUNET_TESTBED_HostRegistrationHandle *rh; | ||
1408 | struct GNUNET_TESTBED_AddHostMessage *msg; | ||
1409 | const char *username; | ||
1410 | const char *hostname; | ||
1411 | char *config; | ||
1412 | char *cconfig; | ||
1413 | void *ptr; | ||
1414 | size_t cc_size; | ||
1415 | size_t config_size; | ||
1416 | uint16_t msg_size; | ||
1417 | uint16_t username_length; | ||
1418 | uint16_t hostname_length; | ||
1419 | |||
1420 | if (NULL != controller->rh) | ||
1421 | return NULL; | ||
1422 | hostname = GNUNET_TESTBED_host_get_hostname (host); | ||
1423 | if (GNUNET_YES == GNUNET_TESTBED_is_host_registered_ (host, controller)) | ||
1424 | { | ||
1425 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1426 | "Host hostname: %s already registered\n", | ||
1427 | (NULL == hostname) ? "localhost" : hostname); | ||
1428 | return NULL; | ||
1429 | } | ||
1430 | rh = GNUNET_new (struct GNUNET_TESTBED_HostRegistrationHandle); | ||
1431 | rh->host = host; | ||
1432 | rh->c = controller; | ||
1433 | GNUNET_assert (NULL != cc); | ||
1434 | rh->cc = cc; | ||
1435 | rh->cc_cls = cc_cls; | ||
1436 | controller->rh = rh; | ||
1437 | username = GNUNET_TESTBED_host_get_username_ (host); | ||
1438 | username_length = 0; | ||
1439 | if (NULL != username) | ||
1440 | username_length = strlen (username); | ||
1441 | GNUNET_assert (NULL != hostname); /* Hostname must be present */ | ||
1442 | hostname_length = strlen (hostname); | ||
1443 | GNUNET_assert (NULL != host->cfg); | ||
1444 | config = GNUNET_CONFIGURATION_serialize (host->cfg, &config_size); | ||
1445 | cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig); | ||
1446 | GNUNET_free (config); | ||
1447 | msg_size = (sizeof(struct GNUNET_TESTBED_AddHostMessage)); | ||
1448 | msg_size += username_length; | ||
1449 | msg_size += hostname_length; | ||
1450 | msg_size += cc_size; | ||
1451 | msg = GNUNET_malloc (msg_size); | ||
1452 | msg->header.size = htons (msg_size); | ||
1453 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST); | ||
1454 | msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host)); | ||
1455 | msg->ssh_port = htons (GNUNET_TESTBED_host_get_ssh_port_ (host)); | ||
1456 | ptr = &msg[1]; | ||
1457 | if (NULL != username) | ||
1458 | { | ||
1459 | msg->username_length = htons (username_length); | ||
1460 | GNUNET_memcpy (ptr, username, username_length); | ||
1461 | ptr += username_length; | ||
1462 | } | ||
1463 | msg->hostname_length = htons (hostname_length); | ||
1464 | GNUNET_memcpy (ptr, hostname, hostname_length); | ||
1465 | ptr += hostname_length; | ||
1466 | msg->config_size = htons (config_size); | ||
1467 | GNUNET_memcpy (ptr, cconfig, cc_size); | ||
1468 | ptr += cc_size; | ||
1469 | GNUNET_assert ((ptr - (void *) msg) == msg_size); | ||
1470 | GNUNET_free (cconfig); | ||
1471 | GNUNET_TESTBED_queue_message_ (controller, | ||
1472 | (struct GNUNET_MessageHeader *) msg); | ||
1473 | return rh; | ||
1474 | } | ||
1475 | |||
1476 | |||
1477 | /** | ||
1478 | * Cancel the pending registration. Note that if the registration message is | ||
1479 | * already sent to the service the cancellation has only the effect that the | ||
1480 | * registration completion callback for the registration is never called. | ||
1481 | * | ||
1482 | * @param handle the registration handle to cancel | ||
1483 | */ | ||
1484 | void | ||
1485 | GNUNET_TESTBED_cancel_registration ( | ||
1486 | struct GNUNET_TESTBED_HostRegistrationHandle *handle) | ||
1487 | { | ||
1488 | if (handle != handle->c->rh) | ||
1489 | { | ||
1490 | GNUNET_break (0); | ||
1491 | return; | ||
1492 | } | ||
1493 | handle->c->rh = NULL; | ||
1494 | GNUNET_free (handle); | ||
1495 | } | ||
1496 | |||
1497 | |||
1498 | /** | ||
1499 | * Queues the given operation in the queue for parallel overlay connects of the | ||
1500 | * given host | ||
1501 | * | ||
1502 | * @param h the host handle | ||
1503 | * @param op the operation to queue in the given host's parally overlay connect | ||
1504 | * queue | ||
1505 | */ | ||
1506 | void | ||
1507 | GNUNET_TESTBED_host_queue_oc_ (struct GNUNET_TESTBED_Host *h, | ||
1508 | struct GNUNET_TESTBED_Operation *op) | ||
1509 | { | ||
1510 | GNUNET_TESTBED_operation_queue_insert_ ( | ||
1511 | h->opq_parallel_overlay_connect_operations, | ||
1512 | op); | ||
1513 | } | ||
1514 | |||
1515 | |||
1516 | /** | ||
1517 | * Resolves the hostname of the host to an ip address | ||
1518 | * | ||
1519 | * @param host the host whose hostname is to be resolved | ||
1520 | */ | ||
1521 | void | ||
1522 | GNUNET_TESTBED_host_resolve_ (struct GNUNET_TESTBED_Host *host) | ||
1523 | { | ||
1524 | char *hostname; | ||
1525 | |||
1526 | hostname = (char *) host->hostname; | ||
1527 | host->hostname = simple_resolve (hostname); | ||
1528 | if (NULL == host->hostname) | ||
1529 | { | ||
1530 | GNUNET_break (0); | ||
1531 | host->hostname = hostname; | ||
1532 | return; | ||
1533 | } | ||
1534 | GNUNET_free (hostname); | ||
1535 | host->hostname = GNUNET_strdup (host->hostname); | ||
1536 | } | ||
1537 | |||
1538 | |||
1539 | /* end of testbed_api_hosts.c */ | ||
diff --git a/src/testbed/testbed_api_hosts.h b/src/testbed/testbed_api_hosts.h deleted file mode 100644 index ab7dd8808..000000000 --- a/src/testbed/testbed_api_hosts.h +++ /dev/null | |||
@@ -1,227 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_hosts.h | ||
23 | * @brief internal API to access the 'hosts' subsystem | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | |||
27 | #ifndef TESTBED_API_HOSTS_H | ||
28 | #define TESTBED_API_HOSTS_H | ||
29 | |||
30 | // #include "gnunet_testbed_service.h" | ||
31 | // #include "testbed_helper.h" | ||
32 | #include "testbed.h" | ||
33 | |||
34 | |||
35 | /** | ||
36 | * handle for host registration | ||
37 | */ | ||
38 | struct GNUNET_TESTBED_HostRegistrationHandle | ||
39 | { | ||
40 | /** | ||
41 | * The host being registered | ||
42 | */ | ||
43 | struct GNUNET_TESTBED_Host *host; | ||
44 | |||
45 | /** | ||
46 | * The controller at which this host is being registered | ||
47 | */ | ||
48 | struct GNUNET_TESTBED_Controller *c; | ||
49 | |||
50 | /** | ||
51 | * The Registration completion callback | ||
52 | */ | ||
53 | GNUNET_TESTBED_HostRegistrationCompletion cc; | ||
54 | |||
55 | /** | ||
56 | * The closure for above callback | ||
57 | */ | ||
58 | void *cc_cls; | ||
59 | }; | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Lookup a host by ID. | ||
64 | * | ||
65 | * @param id global host ID assigned to the host; 0 is | ||
66 | * reserved to always mean 'localhost' | ||
67 | * @return handle to the host, NULL on error | ||
68 | */ | ||
69 | struct GNUNET_TESTBED_Host * | ||
70 | GNUNET_TESTBED_host_lookup_by_id_ (uint32_t id); | ||
71 | |||
72 | |||
73 | /** | ||
74 | * Create a host by ID; given this host handle, we could not | ||
75 | * run peers at the host, but we can talk about the host | ||
76 | * internally. | ||
77 | * | ||
78 | * @param id global host ID assigned to the host; 0 is | ||
79 | * reserved to always mean 'localhost' | ||
80 | * @param cfg the configuration to use as a template while starting a controller | ||
81 | * on this host. Operation queue sizes specific to a host are also | ||
82 | * read from this configuration handle | ||
83 | * @return handle to the host, NULL on error | ||
84 | */ | ||
85 | struct GNUNET_TESTBED_Host * | ||
86 | GNUNET_TESTBED_host_create_by_id_ (uint32_t id, | ||
87 | const struct GNUNET_CONFIGURATION_Handle | ||
88 | *cfg); | ||
89 | |||
90 | |||
91 | /** | ||
92 | * Obtain a host's unique global ID. | ||
93 | * | ||
94 | * @param host handle to the host, NULL means 'localhost' | ||
95 | * @return id global host ID assigned to the host (0 is | ||
96 | * 'localhost', but then obviously not globally unique) | ||
97 | */ | ||
98 | uint32_t | ||
99 | GNUNET_TESTBED_host_get_id_ (const struct GNUNET_TESTBED_Host *host); | ||
100 | |||
101 | |||
102 | /** | ||
103 | * Obtain the host's username | ||
104 | * | ||
105 | * @param host handle to the host, NULL means 'localhost' | ||
106 | * @return username to login to the host | ||
107 | */ | ||
108 | const char * | ||
109 | GNUNET_TESTBED_host_get_username_ (const struct GNUNET_TESTBED_Host *host); | ||
110 | |||
111 | |||
112 | /** | ||
113 | * Obtain the host's ssh port | ||
114 | * | ||
115 | * @param host handle to the host, NULL means 'localhost' | ||
116 | * @return username to login to the host | ||
117 | */ | ||
118 | uint16_t | ||
119 | GNUNET_TESTBED_host_get_ssh_port_ (const struct GNUNET_TESTBED_Host *host); | ||
120 | |||
121 | |||
122 | /** | ||
123 | * Obtain the host's configuration template | ||
124 | * | ||
125 | * @param host handle to the host | ||
126 | * @return the host's configuration template | ||
127 | */ | ||
128 | const struct GNUNET_CONFIGURATION_Handle * | ||
129 | GNUNET_TESTBED_host_get_cfg_ (const struct GNUNET_TESTBED_Host *host); | ||
130 | |||
131 | |||
132 | /** | ||
133 | * Function to replace host's configuration | ||
134 | * | ||
135 | * @param host the host handle | ||
136 | * @param new_cfg the new configuration to replace the old one | ||
137 | */ | ||
138 | void | ||
139 | GNUNET_TESTBED_host_replace_cfg_ (struct GNUNET_TESTBED_Host *host, | ||
140 | const struct | ||
141 | GNUNET_CONFIGURATION_Handle *new_cfg); | ||
142 | |||
143 | |||
144 | /** | ||
145 | * Marks a host as registered with a controller | ||
146 | * | ||
147 | * @param host the host to mark | ||
148 | * @param controller the controller at which this host is registered | ||
149 | */ | ||
150 | void | ||
151 | GNUNET_TESTBED_mark_host_registered_at_ (struct GNUNET_TESTBED_Host *host, | ||
152 | const struct GNUNET_TESTBED_Controller | ||
153 | *controller); | ||
154 | |||
155 | |||
156 | /** | ||
157 | * Unmarks a host registered at a controller | ||
158 | * | ||
159 | * @param host the host to unmark | ||
160 | * @param controller the controller at which this host has to be unmarked | ||
161 | */ | ||
162 | void | ||
163 | GNUNET_TESTBED_deregister_host_at_ (struct GNUNET_TESTBED_Host *host, | ||
164 | const struct GNUNET_TESTBED_Controller | ||
165 | *const controller); | ||
166 | |||
167 | |||
168 | /** | ||
169 | * Checks whether a host has been registered with the given controller | ||
170 | * | ||
171 | * @param host the host to check | ||
172 | * @param controller the controller at which host's registration is checked | ||
173 | * @return GNUNET_YES if registered; GNUNET_NO if not | ||
174 | */ | ||
175 | int | ||
176 | GNUNET_TESTBED_is_host_registered_ (const struct GNUNET_TESTBED_Host *host, | ||
177 | const struct GNUNET_TESTBED_Controller | ||
178 | *controller); | ||
179 | |||
180 | |||
181 | /** | ||
182 | * Queues the given operation in the queue for parallel overlay connects of the | ||
183 | * given host | ||
184 | * | ||
185 | * @param h the host handle | ||
186 | * @param op the operation to queue in the given host's parally overlay connect | ||
187 | * queue | ||
188 | */ | ||
189 | void | ||
190 | GNUNET_TESTBED_host_queue_oc_ (struct GNUNET_TESTBED_Host *h, | ||
191 | struct GNUNET_TESTBED_Operation *op); | ||
192 | |||
193 | |||
194 | /** | ||
195 | * Sends termination signal to the controller's helper process | ||
196 | * | ||
197 | * @param cproc the handle to the controller's helper process | ||
198 | */ | ||
199 | void | ||
200 | GNUNET_TESTBED_controller_kill_ (struct GNUNET_TESTBED_ControllerProc *cproc); | ||
201 | |||
202 | |||
203 | /** | ||
204 | * Cleans-up the controller's helper process handle | ||
205 | * | ||
206 | * @param cproc the handle to the controller's helper process | ||
207 | */ | ||
208 | void | ||
209 | GNUNET_TESTBED_controller_destroy_ (struct GNUNET_TESTBED_ControllerProc | ||
210 | *cproc); | ||
211 | |||
212 | |||
213 | /** | ||
214 | * Resolves the hostname of the host to an ip address | ||
215 | * | ||
216 | * @param host the host whose hostname is to be resolved | ||
217 | */ | ||
218 | void | ||
219 | GNUNET_TESTBED_host_resolve_ (struct GNUNET_TESTBED_Host *host); | ||
220 | |||
221 | void | ||
222 | GNUNET_TESTBED_extract_cfg (struct GNUNET_TESTBED_Host *host, const struct | ||
223 | GNUNET_MessageHeader *message); | ||
224 | |||
225 | |||
226 | #endif | ||
227 | /* end of testbed_api_hosts.h */ | ||
diff --git a/src/testbed/testbed_api_operations.c b/src/testbed/testbed_api_operations.c deleted file mode 100644 index a23f8c666..000000000 --- a/src/testbed/testbed_api_operations.c +++ /dev/null | |||
@@ -1,1387 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_operations.c | ||
23 | * @brief functions to manage operation queues | ||
24 | * @author Christian Grothoff | ||
25 | * @author Sree Harsha Totakura | ||
26 | */ | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "testbed_api_operations.h" | ||
30 | #include "testbed_api_sd.h" | ||
31 | |||
32 | /** | ||
33 | * The number of readings containing past operation's timing information that we | ||
34 | * keep track of for adaptive queues | ||
35 | */ | ||
36 | #define ADAPTIVE_QUEUE_DEFAULT_HISTORY 40 | ||
37 | |||
38 | /** | ||
39 | * The number of parallel operations we start with by default for adaptive | ||
40 | * queues | ||
41 | */ | ||
42 | #define ADAPTIVE_QUEUE_DEFAULT_MAX_ACTIVE 4 | ||
43 | |||
44 | /** | ||
45 | * An entry in the operation queue | ||
46 | */ | ||
47 | struct QueueEntry | ||
48 | { | ||
49 | /** | ||
50 | * The next DLL pointer | ||
51 | */ | ||
52 | struct QueueEntry *next; | ||
53 | |||
54 | /** | ||
55 | * The prev DLL pointer | ||
56 | */ | ||
57 | struct QueueEntry *prev; | ||
58 | |||
59 | /** | ||
60 | * The operation this entry holds | ||
61 | */ | ||
62 | struct GNUNET_TESTBED_Operation *op; | ||
63 | |||
64 | /** | ||
65 | * How many units of resources does the operation need | ||
66 | */ | ||
67 | unsigned int nres; | ||
68 | }; | ||
69 | |||
70 | |||
71 | /** | ||
72 | * Queue of operations where we can only support a certain | ||
73 | * number of concurrent operations of a particular type. | ||
74 | */ | ||
75 | struct OperationQueue; | ||
76 | |||
77 | |||
78 | /** | ||
79 | * A slot to record time taken by an operation | ||
80 | */ | ||
81 | struct TimeSlot | ||
82 | { | ||
83 | /** | ||
84 | * DLL next pointer | ||
85 | */ | ||
86 | struct TimeSlot *next; | ||
87 | |||
88 | /** | ||
89 | * DLL prev pointer | ||
90 | */ | ||
91 | struct TimeSlot *prev; | ||
92 | |||
93 | /** | ||
94 | * This operation queue to which this time slot belongs to | ||
95 | */ | ||
96 | struct OperationQueue *queue; | ||
97 | |||
98 | /** | ||
99 | * The operation to which this timeslot is currently allocated to | ||
100 | */ | ||
101 | struct GNUNET_TESTBED_Operation *op; | ||
102 | |||
103 | /** | ||
104 | * Accumulated time | ||
105 | */ | ||
106 | struct GNUNET_TIME_Relative tsum; | ||
107 | |||
108 | /** | ||
109 | * Number of timing values accumulated | ||
110 | */ | ||
111 | unsigned int nvals; | ||
112 | }; | ||
113 | |||
114 | |||
115 | /** | ||
116 | * Context for operation queues of type OPERATION_QUEUE_TYPE_ADAPTIVE | ||
117 | */ | ||
118 | struct FeedbackCtx | ||
119 | { | ||
120 | /** | ||
121 | * Handle for calculating standard deviation | ||
122 | */ | ||
123 | struct SDHandle *sd; | ||
124 | |||
125 | /** | ||
126 | * Head for DLL of time slots which are free to be allocated to operations | ||
127 | */ | ||
128 | struct TimeSlot *alloc_head; | ||
129 | |||
130 | /** | ||
131 | * Tail for DLL of time slots which are free to be allocated to operations | ||
132 | */ | ||
133 | struct TimeSlot *alloc_tail; | ||
134 | |||
135 | /** | ||
136 | * Pointer to the chunk of time slots. Free all time slots at a time using | ||
137 | * this pointer. | ||
138 | */ | ||
139 | struct TimeSlot *tslots_freeptr; | ||
140 | |||
141 | /** | ||
142 | * Number of time slots filled so far | ||
143 | */ | ||
144 | unsigned int tslots_filled; | ||
145 | |||
146 | /** | ||
147 | * Bound on the maximum number of operations which can be active | ||
148 | */ | ||
149 | unsigned int max_active_bound; | ||
150 | |||
151 | /** | ||
152 | * Number of operations that have failed | ||
153 | */ | ||
154 | unsigned int nfailed; | ||
155 | }; | ||
156 | |||
157 | |||
158 | /** | ||
159 | * Queue of operations where we can only support a certain | ||
160 | * number of concurrent operations of a particular type. | ||
161 | */ | ||
162 | struct OperationQueue | ||
163 | { | ||
164 | /** | ||
165 | * DLL head for the wait queue. Operations which are waiting for this | ||
166 | * operation queue are put here | ||
167 | */ | ||
168 | struct QueueEntry *wq_head; | ||
169 | |||
170 | /** | ||
171 | * DLL tail for the wait queue. | ||
172 | */ | ||
173 | struct QueueEntry *wq_tail; | ||
174 | |||
175 | /** | ||
176 | * DLL head for the ready queue. Operations which are in this operation queue | ||
177 | * and are in ready state are put here | ||
178 | */ | ||
179 | struct QueueEntry *rq_head; | ||
180 | |||
181 | /** | ||
182 | * DLL tail for the ready queue | ||
183 | */ | ||
184 | struct QueueEntry *rq_tail; | ||
185 | |||
186 | /** | ||
187 | * DLL head for the active queue. Operations which are in this operation | ||
188 | * queue and are currently active are put here | ||
189 | */ | ||
190 | struct QueueEntry *aq_head; | ||
191 | |||
192 | /** | ||
193 | * DLL tail for the active queue. | ||
194 | */ | ||
195 | struct QueueEntry *aq_tail; | ||
196 | |||
197 | /** | ||
198 | * DLL head for the inactive queue. Operations which are inactive and can be | ||
199 | * evicted if the queues it holds are maxed out and another operation begins | ||
200 | * to wait on them. | ||
201 | */ | ||
202 | struct QueueEntry *nq_head; | ||
203 | |||
204 | /** | ||
205 | * DLL tail for the inactive queue. | ||
206 | */ | ||
207 | struct QueueEntry *nq_tail; | ||
208 | |||
209 | /** | ||
210 | * Feedback context; only relevant for adaptive operation queues. NULL for | ||
211 | * fixed operation queues | ||
212 | */ | ||
213 | struct FeedbackCtx *fctx; | ||
214 | |||
215 | /** | ||
216 | * The type of this operation queue | ||
217 | */ | ||
218 | enum OperationQueueType type; | ||
219 | |||
220 | /** | ||
221 | * Number of operations that are currently active in this queue. | ||
222 | */ | ||
223 | unsigned int active; | ||
224 | |||
225 | /** | ||
226 | * Max number of operations which can be active at any time in this queue. | ||
227 | * This value can be changed either by calling | ||
228 | * GNUNET_TESTBED_operation_queue_reset_max_active_() or by the adaptive | ||
229 | * algorithm if this operation queue is of type #OPERATION_QUEUE_TYPE_ADAPTIVE | ||
230 | */ | ||
231 | unsigned int max_active; | ||
232 | |||
233 | /** | ||
234 | * The number of resources occupied by failed operations in the current shot. | ||
235 | * This is only relevant if the operation queue is of type | ||
236 | * #OPERATION_QUEUE_TYPE_ADAPTIVE | ||
237 | */ | ||
238 | unsigned int overload; | ||
239 | |||
240 | /** | ||
241 | * Is this queue marked for expiry? | ||
242 | */ | ||
243 | unsigned int expired; | ||
244 | }; | ||
245 | |||
246 | |||
247 | /** | ||
248 | * Operation state | ||
249 | */ | ||
250 | enum OperationState | ||
251 | { | ||
252 | /** | ||
253 | * The operation is just created and is in initial state | ||
254 | */ | ||
255 | OP_STATE_INIT, | ||
256 | |||
257 | /** | ||
258 | * The operation is currently waiting for resources | ||
259 | */ | ||
260 | OP_STATE_WAITING, | ||
261 | |||
262 | /** | ||
263 | * The operation is ready to be started | ||
264 | */ | ||
265 | OP_STATE_READY, | ||
266 | |||
267 | /** | ||
268 | * The operation has started and is active | ||
269 | */ | ||
270 | OP_STATE_ACTIVE, | ||
271 | |||
272 | /** | ||
273 | * The operation is inactive. It still holds resources on the operation | ||
274 | * queues. However, this operation will be evicted when another operation | ||
275 | * requires resources from the maxed out queues this operation is holding | ||
276 | * resources from. | ||
277 | */ | ||
278 | OP_STATE_INACTIVE | ||
279 | }; | ||
280 | |||
281 | |||
282 | /** | ||
283 | * An entry in the ready queue (implemented as DLL) | ||
284 | */ | ||
285 | struct ReadyQueueEntry | ||
286 | { | ||
287 | /** | ||
288 | * next ptr for DLL | ||
289 | */ | ||
290 | struct ReadyQueueEntry *next; | ||
291 | |||
292 | /** | ||
293 | * prev ptr for DLL | ||
294 | */ | ||
295 | struct ReadyQueueEntry *prev; | ||
296 | |||
297 | /** | ||
298 | * The operation associated with this entry | ||
299 | */ | ||
300 | struct GNUNET_TESTBED_Operation *op; | ||
301 | }; | ||
302 | |||
303 | |||
304 | /** | ||
305 | * Opaque handle to an abstract operation to be executed by the testing framework. | ||
306 | */ | ||
307 | struct GNUNET_TESTBED_Operation | ||
308 | { | ||
309 | /** | ||
310 | * Function to call when we have the resources to begin the operation. | ||
311 | */ | ||
312 | OperationStart start; | ||
313 | |||
314 | /** | ||
315 | * Function to call to clean up after the operation (which may or may | ||
316 | * not have been started yet). | ||
317 | */ | ||
318 | OperationRelease release; | ||
319 | |||
320 | /** | ||
321 | * Closure for callbacks. | ||
322 | */ | ||
323 | void *cb_cls; | ||
324 | |||
325 | /** | ||
326 | * Array of operation queues this Operation belongs to. | ||
327 | */ | ||
328 | struct OperationQueue **queues; | ||
329 | |||
330 | /** | ||
331 | * Array of operation queue entries corresponding to this operation in | ||
332 | * operation queues for this operation | ||
333 | */ | ||
334 | struct QueueEntry **qentries; | ||
335 | |||
336 | /** | ||
337 | * Array of number of resources an operation need from each queue. The numbers | ||
338 | * in this array should correspond to the queues array | ||
339 | */ | ||
340 | unsigned int *nres; | ||
341 | |||
342 | /** | ||
343 | * Entry corresponding to this operation in ready queue. Will be NULL if the | ||
344 | * operation is not marked as READY | ||
345 | */ | ||
346 | struct ReadyQueueEntry *rq_entry; | ||
347 | |||
348 | /** | ||
349 | * Head pointer for DLL of tslots allocated to this operation | ||
350 | */ | ||
351 | struct TimeSlot *tslots_head; | ||
352 | |||
353 | /** | ||
354 | * Tail pointer for DLL of tslots allocated to this operation | ||
355 | */ | ||
356 | struct TimeSlot *tslots_tail; | ||
357 | |||
358 | /** | ||
359 | * The time at which the operation is started | ||
360 | */ | ||
361 | struct GNUNET_TIME_Absolute tstart; | ||
362 | |||
363 | /** | ||
364 | * Number of queues in the operation queues array | ||
365 | */ | ||
366 | unsigned int nqueues; | ||
367 | |||
368 | /** | ||
369 | * The state of the operation | ||
370 | */ | ||
371 | enum OperationState state; | ||
372 | |||
373 | /** | ||
374 | * Is this a failed operation? | ||
375 | */ | ||
376 | int failed; | ||
377 | }; | ||
378 | |||
379 | /** | ||
380 | * DLL head for the ready queue | ||
381 | */ | ||
382 | static struct ReadyQueueEntry *rq_head; | ||
383 | |||
384 | /** | ||
385 | * DLL tail for the ready queue | ||
386 | */ | ||
387 | static struct ReadyQueueEntry *rq_tail; | ||
388 | |||
389 | /** | ||
390 | * Array of operation queues which are to be destroyed | ||
391 | */ | ||
392 | static struct OperationQueue **expired_opqs; | ||
393 | |||
394 | /** | ||
395 | * Number of expired operation queues in the above array | ||
396 | */ | ||
397 | static unsigned int n_expired_opqs; | ||
398 | |||
399 | /** | ||
400 | * The id of the task to process the ready queue | ||
401 | */ | ||
402 | struct GNUNET_SCHEDULER_Task *process_rq_task_id; | ||
403 | |||
404 | |||
405 | /** | ||
406 | * Assigns the given operation a time slot from the given operation queue | ||
407 | * | ||
408 | * @param op the operation | ||
409 | * @param queue the operation queue | ||
410 | * @return the timeslot | ||
411 | */ | ||
412 | static void | ||
413 | assign_timeslot (struct GNUNET_TESTBED_Operation *op, | ||
414 | struct OperationQueue *queue) | ||
415 | { | ||
416 | struct FeedbackCtx *fctx = queue->fctx; | ||
417 | struct TimeSlot *tslot; | ||
418 | |||
419 | GNUNET_assert (OPERATION_QUEUE_TYPE_ADAPTIVE == queue->type); | ||
420 | tslot = fctx->alloc_head; | ||
421 | GNUNET_assert (NULL != tslot); | ||
422 | GNUNET_CONTAINER_DLL_remove (fctx->alloc_head, fctx->alloc_tail, tslot); | ||
423 | GNUNET_CONTAINER_DLL_insert_tail (op->tslots_head, op->tslots_tail, tslot); | ||
424 | tslot->op = op; | ||
425 | } | ||
426 | |||
427 | |||
428 | /** | ||
429 | * Removes a queue entry of an operation from one of the operation queues' lists | ||
430 | * depending on the state of the operation | ||
431 | * | ||
432 | * @param op the operation whose entry has to be removed | ||
433 | * @param index the index of the entry in the operation's array of queue entries | ||
434 | */ | ||
435 | static void | ||
436 | remove_queue_entry (struct GNUNET_TESTBED_Operation *op, unsigned int index) | ||
437 | { | ||
438 | struct OperationQueue *opq; | ||
439 | struct QueueEntry *entry; | ||
440 | |||
441 | opq = op->queues[index]; | ||
442 | entry = op->qentries[index]; | ||
443 | switch (op->state) | ||
444 | { | ||
445 | case OP_STATE_INIT: | ||
446 | GNUNET_assert (0); | ||
447 | break; | ||
448 | |||
449 | case OP_STATE_WAITING: | ||
450 | GNUNET_CONTAINER_DLL_remove (opq->wq_head, opq->wq_tail, entry); | ||
451 | break; | ||
452 | |||
453 | case OP_STATE_READY: | ||
454 | GNUNET_CONTAINER_DLL_remove (opq->rq_head, opq->rq_tail, entry); | ||
455 | break; | ||
456 | |||
457 | case OP_STATE_ACTIVE: | ||
458 | GNUNET_CONTAINER_DLL_remove (opq->aq_head, opq->aq_tail, entry); | ||
459 | break; | ||
460 | |||
461 | case OP_STATE_INACTIVE: | ||
462 | GNUNET_CONTAINER_DLL_remove (opq->nq_head, opq->nq_tail, entry); | ||
463 | break; | ||
464 | } | ||
465 | } | ||
466 | |||
467 | |||
468 | /** | ||
469 | * Changes the state of the operation while moving its associated queue entries | ||
470 | * in the operation's operation queues | ||
471 | * | ||
472 | * @param op the operation whose state has to be changed | ||
473 | * @param state the state the operation should have. It cannot be OP_STATE_INIT | ||
474 | */ | ||
475 | static void | ||
476 | change_state (struct GNUNET_TESTBED_Operation *op, enum OperationState state) | ||
477 | { | ||
478 | struct QueueEntry *entry; | ||
479 | struct OperationQueue *opq; | ||
480 | unsigned int cnt; | ||
481 | unsigned int s; | ||
482 | |||
483 | GNUNET_assert (OP_STATE_INIT != state); | ||
484 | GNUNET_assert (NULL != op->queues); | ||
485 | GNUNET_assert (NULL != op->nres); | ||
486 | GNUNET_assert ((OP_STATE_INIT == op->state) || (NULL != op->qentries)); | ||
487 | GNUNET_assert (op->state != state); | ||
488 | for (cnt = 0; cnt < op->nqueues; cnt++) | ||
489 | { | ||
490 | if (OP_STATE_INIT == op->state) | ||
491 | { | ||
492 | entry = GNUNET_new (struct QueueEntry); | ||
493 | entry->op = op; | ||
494 | entry->nres = op->nres[cnt]; | ||
495 | s = cnt; | ||
496 | GNUNET_array_append (op->qentries, s, entry); | ||
497 | } | ||
498 | else | ||
499 | { | ||
500 | entry = op->qentries[cnt]; | ||
501 | remove_queue_entry (op, cnt); | ||
502 | } | ||
503 | opq = op->queues[cnt]; | ||
504 | switch (state) | ||
505 | { | ||
506 | case OP_STATE_INIT: | ||
507 | GNUNET_assert (0); | ||
508 | break; | ||
509 | |||
510 | case OP_STATE_WAITING: | ||
511 | GNUNET_CONTAINER_DLL_insert_tail (opq->wq_head, opq->wq_tail, entry); | ||
512 | break; | ||
513 | |||
514 | case OP_STATE_READY: | ||
515 | GNUNET_CONTAINER_DLL_insert_tail (opq->rq_head, opq->rq_tail, entry); | ||
516 | break; | ||
517 | |||
518 | case OP_STATE_ACTIVE: | ||
519 | GNUNET_CONTAINER_DLL_insert_tail (opq->aq_head, opq->aq_tail, entry); | ||
520 | break; | ||
521 | |||
522 | case OP_STATE_INACTIVE: | ||
523 | GNUNET_CONTAINER_DLL_insert_tail (opq->nq_head, opq->nq_tail, entry); | ||
524 | break; | ||
525 | } | ||
526 | } | ||
527 | op->state = state; | ||
528 | } | ||
529 | |||
530 | |||
531 | /** | ||
532 | * Removes an operation from the ready queue. Also stops the 'process_rq_task' | ||
533 | * if the given operation is the last one in the queue. | ||
534 | * | ||
535 | * @param op the operation to be removed | ||
536 | */ | ||
537 | static void | ||
538 | rq_remove (struct GNUNET_TESTBED_Operation *op) | ||
539 | { | ||
540 | GNUNET_assert (NULL != op->rq_entry); | ||
541 | GNUNET_CONTAINER_DLL_remove (rq_head, rq_tail, op->rq_entry); | ||
542 | GNUNET_free (op->rq_entry); | ||
543 | op->rq_entry = NULL; | ||
544 | if ((NULL == rq_head) && (NULL != process_rq_task_id)) | ||
545 | { | ||
546 | GNUNET_SCHEDULER_cancel (process_rq_task_id); | ||
547 | process_rq_task_id = NULL; | ||
548 | } | ||
549 | } | ||
550 | |||
551 | |||
552 | /** | ||
553 | * Processes the ready queue by calling the operation start callback of the | ||
554 | * operation at the head. The operation is then removed from the queue. The | ||
555 | * task is scheduled to run again immediately until no more operations are in | ||
556 | * the ready queue. | ||
557 | * | ||
558 | * @param cls NULL | ||
559 | */ | ||
560 | static void | ||
561 | process_rq_task (void *cls) | ||
562 | { | ||
563 | struct GNUNET_TESTBED_Operation *op; | ||
564 | struct OperationQueue *queue; | ||
565 | unsigned int cnt; | ||
566 | |||
567 | process_rq_task_id = NULL; | ||
568 | GNUNET_assert (NULL != rq_head); | ||
569 | GNUNET_assert (NULL != (op = rq_head->op)); | ||
570 | rq_remove (op); | ||
571 | if (NULL != rq_head) | ||
572 | process_rq_task_id = GNUNET_SCHEDULER_add_now (&process_rq_task, NULL); | ||
573 | change_state (op, OP_STATE_ACTIVE); | ||
574 | for (cnt = 0; cnt < op->nqueues; cnt++) | ||
575 | { | ||
576 | queue = op->queues[cnt]; | ||
577 | if (OPERATION_QUEUE_TYPE_ADAPTIVE == queue->type) | ||
578 | assign_timeslot (op, queue); | ||
579 | } | ||
580 | op->tstart = GNUNET_TIME_absolute_get (); | ||
581 | if (NULL != op->start) | ||
582 | op->start (op->cb_cls); | ||
583 | } | ||
584 | |||
585 | |||
586 | /** | ||
587 | * Adds the operation to the ready queue and starts the 'process_rq_task' | ||
588 | * | ||
589 | * @param op the operation to be queued | ||
590 | */ | ||
591 | static void | ||
592 | rq_add (struct GNUNET_TESTBED_Operation *op) | ||
593 | { | ||
594 | struct ReadyQueueEntry *rq_entry; | ||
595 | |||
596 | GNUNET_assert (NULL == op->rq_entry); | ||
597 | rq_entry = GNUNET_new (struct ReadyQueueEntry); | ||
598 | rq_entry->op = op; | ||
599 | GNUNET_CONTAINER_DLL_insert_tail (rq_head, rq_tail, rq_entry); | ||
600 | op->rq_entry = rq_entry; | ||
601 | if (NULL == process_rq_task_id) | ||
602 | process_rq_task_id = GNUNET_SCHEDULER_add_now (&process_rq_task, NULL); | ||
603 | } | ||
604 | |||
605 | |||
606 | /** | ||
607 | * Checks if the given operation queue is empty or not | ||
608 | * | ||
609 | * @param opq the operation queue | ||
610 | * @return GNUNET_YES if the given operation queue has no operations; GNUNET_NO | ||
611 | * otherwise | ||
612 | */ | ||
613 | static int | ||
614 | is_queue_empty (struct OperationQueue *opq) | ||
615 | { | ||
616 | if ((NULL != opq->wq_head) | ||
617 | || (NULL != opq->rq_head) | ||
618 | || (NULL != opq->aq_head) | ||
619 | || (NULL != opq->nq_head)) | ||
620 | return GNUNET_NO; | ||
621 | return GNUNET_YES; | ||
622 | } | ||
623 | |||
624 | |||
625 | /** | ||
626 | * Checks if the given operation queue has enough resources to provide for the | ||
627 | * operation of the given queue entry. It also checks if any inactive | ||
628 | * operations are to be released in order to accommodate the needed resources | ||
629 | * and returns them as an array. | ||
630 | * | ||
631 | * @param opq the operation queue to check for resource accommodation | ||
632 | * @param entry the operation queue entry whose operation's resources are to be | ||
633 | * accommodated | ||
634 | * @param ops_ pointer to return the array of operations which are to be released | ||
635 | * in order to accommodate the new operation. Can be NULL | ||
636 | * @param n_ops_ the number of operations in ops_ | ||
637 | * @return GNUNET_YES if the given entry's operation can be accommodated in this | ||
638 | * queue. GNUNET_NO if it cannot be accommodated; ops_ and n_ops_ will | ||
639 | * be set to NULL and 0 respectively. | ||
640 | */ | ||
641 | static int | ||
642 | decide_capacity (struct OperationQueue *opq, | ||
643 | struct QueueEntry *entry, | ||
644 | struct GNUNET_TESTBED_Operation ***ops_, | ||
645 | unsigned int *n_ops_) | ||
646 | { | ||
647 | struct QueueEntry **evict_entries; | ||
648 | struct GNUNET_TESTBED_Operation **ops; | ||
649 | struct GNUNET_TESTBED_Operation *op; | ||
650 | unsigned int n_ops; | ||
651 | unsigned int n_evict_entries; | ||
652 | unsigned int need; | ||
653 | unsigned int max; | ||
654 | int deficit; | ||
655 | int rval; | ||
656 | |||
657 | GNUNET_assert (NULL != (op = entry->op)); | ||
658 | GNUNET_assert (0 < (need = entry->nres)); | ||
659 | ops = NULL; | ||
660 | n_ops = 0; | ||
661 | evict_entries = NULL; | ||
662 | n_evict_entries = 0; | ||
663 | rval = GNUNET_YES; | ||
664 | if (OPERATION_QUEUE_TYPE_ADAPTIVE == opq->type) | ||
665 | { | ||
666 | GNUNET_assert (NULL != opq->fctx); | ||
667 | GNUNET_assert (opq->max_active >= opq->overload); | ||
668 | max = opq->max_active - opq->overload; | ||
669 | } | ||
670 | else | ||
671 | max = opq->max_active; | ||
672 | if (opq->active > max) | ||
673 | { | ||
674 | rval = GNUNET_NO; | ||
675 | goto ret; | ||
676 | } | ||
677 | if ((opq->active + need) <= max) | ||
678 | goto ret; | ||
679 | deficit = need - (max - opq->active); | ||
680 | for (entry = opq->nq_head; | ||
681 | (0 < deficit) && (NULL != entry); | ||
682 | entry = entry->next) | ||
683 | { | ||
684 | GNUNET_array_append (evict_entries, n_evict_entries, entry); | ||
685 | deficit -= entry->nres; | ||
686 | } | ||
687 | if (0 < deficit) | ||
688 | { | ||
689 | rval = GNUNET_NO; | ||
690 | goto ret; | ||
691 | } | ||
692 | for (n_ops = 0; n_ops < n_evict_entries;) | ||
693 | { | ||
694 | op = evict_entries[n_ops]->op; | ||
695 | GNUNET_array_append (ops, n_ops, op); /* increments n-ops */ | ||
696 | } | ||
697 | |||
698 | ret: | ||
699 | GNUNET_free (evict_entries); | ||
700 | if (NULL != ops_) | ||
701 | *ops_ = ops; | ||
702 | else | ||
703 | GNUNET_free (ops); | ||
704 | if (NULL != n_ops_) | ||
705 | *n_ops_ = n_ops; | ||
706 | return rval; | ||
707 | } | ||
708 | |||
709 | |||
710 | /** | ||
711 | * Merges an array of operations into another, eliminating duplicates. No | ||
712 | * ordering is guaranteed. | ||
713 | * | ||
714 | * @param old the array into which the merging is done. | ||
715 | * @param n_old the number of operations in old array | ||
716 | * @param new the array from which operations are to be merged | ||
717 | * @param n_new the number of operations in new array | ||
718 | */ | ||
719 | static void | ||
720 | merge_ops (struct GNUNET_TESTBED_Operation ***old, | ||
721 | unsigned int *n_old, | ||
722 | struct GNUNET_TESTBED_Operation **new, | ||
723 | unsigned int n_new) | ||
724 | { | ||
725 | struct GNUNET_TESTBED_Operation **cur; | ||
726 | unsigned int i; | ||
727 | unsigned int j; | ||
728 | unsigned int n_cur; | ||
729 | |||
730 | GNUNET_assert (NULL != old); | ||
731 | n_cur = *n_old; | ||
732 | cur = *old; | ||
733 | for (i = 0; i < n_new; i++) | ||
734 | { | ||
735 | for (j = 0; j < *n_old; j++) | ||
736 | { | ||
737 | if (new[i] == cur[j]) | ||
738 | break; | ||
739 | } | ||
740 | if (j < *n_old) | ||
741 | continue; | ||
742 | GNUNET_array_append (cur, n_cur, new[j]); | ||
743 | } | ||
744 | *old = cur; | ||
745 | *n_old = n_cur; | ||
746 | } | ||
747 | |||
748 | |||
749 | /** | ||
750 | * Checks for the readiness of an operation and schedules a operation start task | ||
751 | * | ||
752 | * @param op the operation | ||
753 | */ | ||
754 | static int | ||
755 | check_readiness (struct GNUNET_TESTBED_Operation *op) | ||
756 | { | ||
757 | struct GNUNET_TESTBED_Operation **evict_ops; | ||
758 | struct GNUNET_TESTBED_Operation **ops; | ||
759 | unsigned int n_ops; | ||
760 | unsigned int n_evict_ops; | ||
761 | unsigned int i; | ||
762 | |||
763 | GNUNET_assert (NULL == op->rq_entry); | ||
764 | GNUNET_assert (OP_STATE_WAITING == op->state); | ||
765 | evict_ops = NULL; | ||
766 | n_evict_ops = 0; | ||
767 | for (i = 0; i < op->nqueues; i++) | ||
768 | { | ||
769 | ops = NULL; | ||
770 | n_ops = 0; | ||
771 | if (GNUNET_NO == decide_capacity (op->queues[i], op->qentries[i], | ||
772 | &ops, &n_ops)) | ||
773 | { | ||
774 | GNUNET_free (evict_ops); | ||
775 | return GNUNET_NO; | ||
776 | } | ||
777 | if (NULL == ops) | ||
778 | continue; | ||
779 | merge_ops (&evict_ops, &n_evict_ops, ops, n_ops); | ||
780 | GNUNET_free (ops); | ||
781 | } | ||
782 | if (NULL != evict_ops) | ||
783 | { | ||
784 | for (i = 0; i < n_evict_ops; i++) | ||
785 | GNUNET_TESTBED_operation_release_ (evict_ops[i]); | ||
786 | GNUNET_free (evict_ops); | ||
787 | evict_ops = NULL; | ||
788 | /* Evicting the operations should schedule this operation */ | ||
789 | GNUNET_assert (OP_STATE_READY == op->state); | ||
790 | return GNUNET_YES; | ||
791 | } | ||
792 | for (i = 0; i < op->nqueues; i++) | ||
793 | op->queues[i]->active += op->nres[i]; | ||
794 | change_state (op, OP_STATE_READY); | ||
795 | rq_add (op); | ||
796 | return GNUNET_YES; | ||
797 | } | ||
798 | |||
799 | |||
800 | /** | ||
801 | * Defers a ready to be executed operation back to waiting | ||
802 | * | ||
803 | * @param op the operation to defer | ||
804 | */ | ||
805 | static void | ||
806 | defer (struct GNUNET_TESTBED_Operation *op) | ||
807 | { | ||
808 | unsigned int i; | ||
809 | |||
810 | GNUNET_assert (OP_STATE_READY == op->state); | ||
811 | rq_remove (op); | ||
812 | for (i = 0; i < op->nqueues; i++) | ||
813 | { | ||
814 | GNUNET_assert (op->queues[i]->active >= op->nres[i]); | ||
815 | op->queues[i]->active -= op->nres[i]; | ||
816 | } | ||
817 | change_state (op, OP_STATE_WAITING); | ||
818 | } | ||
819 | |||
820 | |||
821 | /** | ||
822 | * Cleanups the array of timeslots of an operation queue. For each time slot in | ||
823 | * the array, if it is allocated to an operation, it will be deallocated from | ||
824 | * the operation | ||
825 | * | ||
826 | * @param queue the operation queue | ||
827 | */ | ||
828 | static void | ||
829 | cleanup_tslots (struct OperationQueue *queue) | ||
830 | { | ||
831 | struct FeedbackCtx *fctx = queue->fctx; | ||
832 | struct TimeSlot *tslot; | ||
833 | struct GNUNET_TESTBED_Operation *op; | ||
834 | unsigned int cnt; | ||
835 | |||
836 | GNUNET_assert (NULL != fctx); | ||
837 | for (cnt = 0; cnt < queue->max_active; cnt++) | ||
838 | { | ||
839 | tslot = &fctx->tslots_freeptr[cnt]; | ||
840 | op = tslot->op; | ||
841 | if (NULL == op) | ||
842 | continue; | ||
843 | GNUNET_CONTAINER_DLL_remove (op->tslots_head, op->tslots_tail, tslot); | ||
844 | } | ||
845 | GNUNET_free (fctx->tslots_freeptr); | ||
846 | fctx->tslots_freeptr = NULL; | ||
847 | fctx->alloc_head = NULL; | ||
848 | fctx->alloc_tail = NULL; | ||
849 | fctx->tslots_filled = 0; | ||
850 | } | ||
851 | |||
852 | |||
853 | /** | ||
854 | * Cleansup the existing timing slots and sets new timing slots in the given | ||
855 | * queue to accommodate given number of max active operations. | ||
856 | * | ||
857 | * @param queue the queue | ||
858 | * @param n the number of maximum active operations. If n is greater than the | ||
859 | * maximum limit set while creating the queue, then the minimum of these two | ||
860 | * will be selected as n | ||
861 | */ | ||
862 | static void | ||
863 | adaptive_queue_set_max_active (struct OperationQueue *queue, unsigned int n) | ||
864 | { | ||
865 | struct FeedbackCtx *fctx = queue->fctx; | ||
866 | struct TimeSlot *tslot; | ||
867 | unsigned int cnt; | ||
868 | |||
869 | cleanup_tslots (queue); | ||
870 | n = GNUNET_MIN (n, fctx->max_active_bound); | ||
871 | fctx->tslots_freeptr = GNUNET_malloc (n * sizeof(struct TimeSlot)); | ||
872 | fctx->nfailed = 0; | ||
873 | for (cnt = 0; cnt < n; cnt++) | ||
874 | { | ||
875 | tslot = &fctx->tslots_freeptr[cnt]; | ||
876 | tslot->queue = queue; | ||
877 | GNUNET_CONTAINER_DLL_insert_tail (fctx->alloc_head, fctx->alloc_tail, | ||
878 | tslot); | ||
879 | } | ||
880 | GNUNET_TESTBED_operation_queue_reset_max_active_ (queue, n); | ||
881 | } | ||
882 | |||
883 | |||
884 | /** | ||
885 | * Adapts parallelism in an adaptive queue by using the statistical data from | ||
886 | * the feedback context. | ||
887 | * | ||
888 | * @param queue the queue | ||
889 | */ | ||
890 | static void | ||
891 | adapt_parallelism (struct OperationQueue *queue) | ||
892 | { | ||
893 | struct GNUNET_TIME_Relative avg; | ||
894 | struct FeedbackCtx *fctx; | ||
895 | struct TimeSlot *tslot; | ||
896 | int sd; | ||
897 | unsigned int nvals; | ||
898 | unsigned int cnt; | ||
899 | unsigned int parallelism; | ||
900 | |||
901 | avg = GNUNET_TIME_UNIT_ZERO; | ||
902 | nvals = 0; | ||
903 | fctx = queue->fctx; | ||
904 | for (cnt = 0; cnt < queue->max_active; cnt++) | ||
905 | { | ||
906 | tslot = &fctx->tslots_freeptr[cnt]; | ||
907 | avg = GNUNET_TIME_relative_add (avg, tslot->tsum); | ||
908 | nvals += tslot->nvals; | ||
909 | } | ||
910 | GNUNET_assert (nvals >= queue->max_active); | ||
911 | GNUNET_assert (fctx->nfailed <= nvals); | ||
912 | nvals -= fctx->nfailed; | ||
913 | if (0 == nvals) | ||
914 | { | ||
915 | if (1 == queue->max_active) | ||
916 | adaptive_queue_set_max_active (queue, 1); | ||
917 | else | ||
918 | adaptive_queue_set_max_active (queue, queue->max_active / 2); | ||
919 | return; | ||
920 | } | ||
921 | avg = GNUNET_TIME_relative_divide (avg, nvals); | ||
922 | GNUNET_TESTBED_SD_add_data_ (fctx->sd, (unsigned int) avg.rel_value_us); | ||
923 | if (GNUNET_SYSERR == | ||
924 | GNUNET_TESTBED_SD_deviation_factor_ (fctx->sd, | ||
925 | (unsigned int) avg.rel_value_us, | ||
926 | &sd)) | ||
927 | { | ||
928 | adaptive_queue_set_max_active (queue, queue->max_active); /* no change */ | ||
929 | return; | ||
930 | } | ||
931 | |||
932 | parallelism = 0; | ||
933 | if (-1 == sd) | ||
934 | parallelism = queue->max_active + 1; | ||
935 | if (sd <= -2) | ||
936 | parallelism = queue->max_active * 2; | ||
937 | if (1 == sd) | ||
938 | parallelism = queue->max_active - 1; | ||
939 | if (2 <= sd) | ||
940 | parallelism = queue->max_active / 2; | ||
941 | parallelism = GNUNET_MAX (parallelism, ADAPTIVE_QUEUE_DEFAULT_MAX_ACTIVE); | ||
942 | adaptive_queue_set_max_active (queue, parallelism); | ||
943 | |||
944 | #if 0 | ||
945 | /* old algorithm */ | ||
946 | if (sd < 0) | ||
947 | sd = 0; | ||
948 | GNUNET_assert (0 <= sd); | ||
949 | // GNUNET_TESTBED_SD_add_data_ (fctx->sd, (unsigned int) avg.rel_value_us); | ||
950 | if (0 == sd) | ||
951 | { | ||
952 | adaptive_queue_set_max_active (queue, queue->max_active * 2); | ||
953 | return; | ||
954 | } | ||
955 | if (1 == sd) | ||
956 | { | ||
957 | adaptive_queue_set_max_active (queue, queue->max_active + 1); | ||
958 | return; | ||
959 | } | ||
960 | if (1 == queue->max_active) | ||
961 | { | ||
962 | adaptive_queue_set_max_active (queue, 1); | ||
963 | return; | ||
964 | } | ||
965 | if (2 == sd) | ||
966 | { | ||
967 | adaptive_queue_set_max_active (queue, queue->max_active - 1); | ||
968 | return; | ||
969 | } | ||
970 | adaptive_queue_set_max_active (queue, queue->max_active / 2); | ||
971 | #endif | ||
972 | } | ||
973 | |||
974 | |||
975 | /** | ||
976 | * update tslots with the operation's completion time. Additionally, if | ||
977 | * updating a timeslot makes all timeslots filled in an adaptive operation | ||
978 | * queue, call adapt_parallelism() for that queue. | ||
979 | * | ||
980 | * @param op the operation | ||
981 | */ | ||
982 | static void | ||
983 | update_tslots (struct GNUNET_TESTBED_Operation *op) | ||
984 | { | ||
985 | struct OperationQueue *queue; | ||
986 | struct GNUNET_TIME_Relative t; | ||
987 | struct TimeSlot *tslot; | ||
988 | struct FeedbackCtx *fctx; | ||
989 | unsigned int i; | ||
990 | |||
991 | t = GNUNET_TIME_absolute_get_duration (op->tstart); | ||
992 | while (NULL != (tslot = op->tslots_head)) /* update time slots */ | ||
993 | { | ||
994 | queue = tslot->queue; | ||
995 | fctx = queue->fctx; | ||
996 | GNUNET_CONTAINER_DLL_remove (op->tslots_head, op->tslots_tail, tslot); | ||
997 | tslot->op = NULL; | ||
998 | GNUNET_CONTAINER_DLL_insert_tail (fctx->alloc_head, fctx->alloc_tail, | ||
999 | tslot); | ||
1000 | if (op->failed) | ||
1001 | { | ||
1002 | fctx->nfailed++; | ||
1003 | for (i = 0; i < op->nqueues; i++) | ||
1004 | if (queue == op->queues[i]) | ||
1005 | break; | ||
1006 | GNUNET_assert (i != op->nqueues); | ||
1007 | op->queues[i]->overload += op->nres[i]; | ||
1008 | } | ||
1009 | tslot->tsum = GNUNET_TIME_relative_add (tslot->tsum, t); | ||
1010 | if (0 != tslot->nvals++) | ||
1011 | continue; | ||
1012 | fctx->tslots_filled++; | ||
1013 | if (queue->max_active == fctx->tslots_filled) | ||
1014 | adapt_parallelism (queue); | ||
1015 | } | ||
1016 | } | ||
1017 | |||
1018 | |||
1019 | /** | ||
1020 | * Create an 'operation' to be performed. | ||
1021 | * | ||
1022 | * @param cls closure for the callbacks | ||
1023 | * @param start function to call to start the operation | ||
1024 | * @param release function to call to close down the operation | ||
1025 | * @return handle to the operation | ||
1026 | */ | ||
1027 | struct GNUNET_TESTBED_Operation * | ||
1028 | GNUNET_TESTBED_operation_create_ (void *cls, OperationStart start, | ||
1029 | OperationRelease release) | ||
1030 | { | ||
1031 | struct GNUNET_TESTBED_Operation *op; | ||
1032 | |||
1033 | op = GNUNET_new (struct GNUNET_TESTBED_Operation); | ||
1034 | op->start = start; | ||
1035 | op->state = OP_STATE_INIT; | ||
1036 | op->release = release; | ||
1037 | op->cb_cls = cls; | ||
1038 | return op; | ||
1039 | } | ||
1040 | |||
1041 | |||
1042 | /** | ||
1043 | * Create an operation queue. | ||
1044 | * | ||
1045 | * @param type the type of operation queue | ||
1046 | * @param max_active maximum number of operations in this | ||
1047 | * queue that can be active in parallel at the same time | ||
1048 | * @return handle to the queue | ||
1049 | */ | ||
1050 | struct OperationQueue * | ||
1051 | GNUNET_TESTBED_operation_queue_create_ (enum OperationQueueType type, | ||
1052 | unsigned int max_active) | ||
1053 | { | ||
1054 | struct OperationQueue *queue; | ||
1055 | struct FeedbackCtx *fctx; | ||
1056 | |||
1057 | queue = GNUNET_new (struct OperationQueue); | ||
1058 | queue->type = type; | ||
1059 | if (OPERATION_QUEUE_TYPE_FIXED == type) | ||
1060 | { | ||
1061 | queue->max_active = max_active; | ||
1062 | } | ||
1063 | else | ||
1064 | { | ||
1065 | fctx = GNUNET_new (struct FeedbackCtx); | ||
1066 | fctx->max_active_bound = max_active; | ||
1067 | fctx->sd = GNUNET_TESTBED_SD_init_ (ADAPTIVE_QUEUE_DEFAULT_HISTORY); | ||
1068 | queue->fctx = fctx; | ||
1069 | adaptive_queue_set_max_active (queue, ADAPTIVE_QUEUE_DEFAULT_MAX_ACTIVE); | ||
1070 | } | ||
1071 | return queue; | ||
1072 | } | ||
1073 | |||
1074 | |||
1075 | /** | ||
1076 | * Cleanup the given operation queue. | ||
1077 | * | ||
1078 | * @param queue the operation queue to destroy | ||
1079 | */ | ||
1080 | static void | ||
1081 | queue_destroy (struct OperationQueue *queue) | ||
1082 | { | ||
1083 | struct FeedbackCtx *fctx; | ||
1084 | |||
1085 | if (OPERATION_QUEUE_TYPE_ADAPTIVE == queue->type) | ||
1086 | { | ||
1087 | cleanup_tslots (queue); | ||
1088 | fctx = queue->fctx; | ||
1089 | GNUNET_TESTBED_SD_destroy_ (fctx->sd); | ||
1090 | GNUNET_free (fctx); | ||
1091 | } | ||
1092 | GNUNET_free (queue); | ||
1093 | } | ||
1094 | |||
1095 | |||
1096 | /** | ||
1097 | * Destroys an operation queue. If the queue is still in use by operations it | ||
1098 | * is marked as expired and its resources are released in the destructor | ||
1099 | * GNUNET_TESTBED_operations_fini(). | ||
1100 | * | ||
1101 | * @param queue queue to destroy | ||
1102 | */ | ||
1103 | void | ||
1104 | GNUNET_TESTBED_operation_queue_destroy_ (struct OperationQueue *queue) | ||
1105 | { | ||
1106 | if (GNUNET_YES != is_queue_empty (queue)) | ||
1107 | { | ||
1108 | GNUNET_assert (0 == queue->expired); /* Are you calling twice on same queue? */ | ||
1109 | queue->expired = 1; | ||
1110 | GNUNET_array_append (expired_opqs, n_expired_opqs, queue); | ||
1111 | return; | ||
1112 | } | ||
1113 | queue_destroy (queue); | ||
1114 | } | ||
1115 | |||
1116 | |||
1117 | /** | ||
1118 | * Destroys the operation queue if it is empty. If not empty return GNUNET_NO. | ||
1119 | * | ||
1120 | * @param queue the queue to destroy if empty | ||
1121 | * @return GNUNET_YES if the queue is destroyed. GNUNET_NO if not (because it | ||
1122 | * is not empty) | ||
1123 | */ | ||
1124 | int | ||
1125 | GNUNET_TESTBED_operation_queue_destroy_empty_ (struct OperationQueue *queue) | ||
1126 | { | ||
1127 | if (GNUNET_NO == is_queue_empty (queue)) | ||
1128 | return GNUNET_NO; | ||
1129 | GNUNET_TESTBED_operation_queue_destroy_ (queue); | ||
1130 | return GNUNET_YES; | ||
1131 | } | ||
1132 | |||
1133 | |||
1134 | /** | ||
1135 | * Rechecks if any of the operations in the given operation queue's waiting list | ||
1136 | * can be made active | ||
1137 | * | ||
1138 | * @param opq the operation queue | ||
1139 | */ | ||
1140 | static void | ||
1141 | recheck_waiting (struct OperationQueue *opq) | ||
1142 | { | ||
1143 | struct QueueEntry *entry; | ||
1144 | struct QueueEntry *entry2; | ||
1145 | |||
1146 | entry = opq->wq_head; | ||
1147 | while (NULL != entry) | ||
1148 | { | ||
1149 | entry2 = entry->next; | ||
1150 | if (GNUNET_NO == check_readiness (entry->op)) | ||
1151 | break; | ||
1152 | entry = entry2; | ||
1153 | } | ||
1154 | } | ||
1155 | |||
1156 | |||
1157 | /** | ||
1158 | * Function to reset the maximum number of operations in the given queue. If | ||
1159 | * max_active is lesser than the number of currently active operations, the | ||
1160 | * active operations are not stopped immediately. | ||
1161 | * | ||
1162 | * @param queue the operation queue which has to be modified | ||
1163 | * @param max_active the new maximum number of active operations | ||
1164 | */ | ||
1165 | void | ||
1166 | GNUNET_TESTBED_operation_queue_reset_max_active_ (struct OperationQueue *queue, | ||
1167 | unsigned int max_active) | ||
1168 | { | ||
1169 | struct QueueEntry *entry; | ||
1170 | |||
1171 | queue->max_active = max_active; | ||
1172 | queue->overload = 0; | ||
1173 | while ((queue->active > queue->max_active) | ||
1174 | && (NULL != (entry = queue->rq_head))) | ||
1175 | defer (entry->op); | ||
1176 | recheck_waiting (queue); | ||
1177 | } | ||
1178 | |||
1179 | |||
1180 | /** | ||
1181 | * Add an operation to a queue. An operation can be in multiple queues at | ||
1182 | * once. Once the operation is inserted into all the queues | ||
1183 | * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start | ||
1184 | * waiting for the operation to become active. | ||
1185 | * | ||
1186 | * @param queue queue to add the operation to | ||
1187 | * @param op operation to add to the queue | ||
1188 | * @param nres the number of units of the resources of queue needed by the | ||
1189 | * operation. Should be greater than 0. | ||
1190 | */ | ||
1191 | void | ||
1192 | GNUNET_TESTBED_operation_queue_insert2_ (struct OperationQueue *queue, | ||
1193 | struct GNUNET_TESTBED_Operation *op, | ||
1194 | unsigned int nres) | ||
1195 | { | ||
1196 | unsigned int qsize; | ||
1197 | |||
1198 | GNUNET_assert (0 < nres); | ||
1199 | qsize = op->nqueues; | ||
1200 | GNUNET_array_append (op->queues, op->nqueues, queue); | ||
1201 | GNUNET_array_append (op->nres, qsize, nres); | ||
1202 | GNUNET_assert (qsize == op->nqueues); | ||
1203 | } | ||
1204 | |||
1205 | |||
1206 | /** | ||
1207 | * Add an operation to a queue. An operation can be in multiple queues at | ||
1208 | * once. Once the operation is inserted into all the queues | ||
1209 | * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start | ||
1210 | * waiting for the operation to become active. The operation is assumed to take | ||
1211 | * 1 queue resource. Use GNUNET_TESTBED_operation_queue_insert2_() if it | ||
1212 | * requires more than 1 | ||
1213 | * | ||
1214 | * @param queue queue to add the operation to | ||
1215 | * @param op operation to add to the queue | ||
1216 | */ | ||
1217 | void | ||
1218 | GNUNET_TESTBED_operation_queue_insert_ (struct OperationQueue *queue, | ||
1219 | struct GNUNET_TESTBED_Operation *op) | ||
1220 | { | ||
1221 | return GNUNET_TESTBED_operation_queue_insert2_ (queue, op, 1); | ||
1222 | } | ||
1223 | |||
1224 | |||
1225 | /** | ||
1226 | * Marks the given operation as waiting on the queues. Once all queues permit | ||
1227 | * the operation to become active, the operation will be activated. The actual | ||
1228 | * activation will occur in a separate task (thus allowing multiple queue | ||
1229 | * insertions to be made without having the first one instantly trigger the | ||
1230 | * operation if the first queue has sufficient resources). | ||
1231 | * | ||
1232 | * @param op the operation to marks as waiting | ||
1233 | */ | ||
1234 | void | ||
1235 | GNUNET_TESTBED_operation_begin_wait_ (struct GNUNET_TESTBED_Operation *op) | ||
1236 | { | ||
1237 | GNUNET_assert (NULL == op->rq_entry); | ||
1238 | change_state (op, OP_STATE_WAITING); | ||
1239 | (void) check_readiness (op); | ||
1240 | } | ||
1241 | |||
1242 | |||
1243 | /** | ||
1244 | * Marks an active operation as inactive - the operation will be kept in a | ||
1245 | * ready-to-be-released state and continues to hold resources until another | ||
1246 | * operation contents for them. | ||
1247 | * | ||
1248 | * @param op the operation to be marked as inactive. The operation start | ||
1249 | * callback should have been called before for this operation to mark | ||
1250 | * it as inactive. | ||
1251 | */ | ||
1252 | void | ||
1253 | GNUNET_TESTBED_operation_inactivate_ (struct GNUNET_TESTBED_Operation *op) | ||
1254 | { | ||
1255 | struct OperationQueue **queues; | ||
1256 | size_t ms; | ||
1257 | unsigned int nqueues; | ||
1258 | unsigned int i; | ||
1259 | |||
1260 | GNUNET_assert (OP_STATE_ACTIVE == op->state); | ||
1261 | change_state (op, OP_STATE_INACTIVE); | ||
1262 | nqueues = op->nqueues; | ||
1263 | ms = sizeof(struct OperationQueue *) * nqueues; | ||
1264 | queues = GNUNET_malloc (ms); | ||
1265 | /* Cloning is needed as the operation be released by waiting operations and | ||
1266 | hence its nqueues memory ptr will be freed */ | ||
1267 | GNUNET_memcpy (queues, op->queues, ms); | ||
1268 | for (i = 0; i < nqueues; i++) | ||
1269 | recheck_waiting (queues[i]); | ||
1270 | GNUNET_free (queues); | ||
1271 | } | ||
1272 | |||
1273 | |||
1274 | /** | ||
1275 | * Marks and inactive operation as active. This function should be called to | ||
1276 | * ensure that the oprelease callback will not be called until it is either | ||
1277 | * marked as inactive or released. | ||
1278 | * | ||
1279 | * @param op the operation to be marked as active | ||
1280 | */ | ||
1281 | void | ||
1282 | GNUNET_TESTBED_operation_activate_ (struct GNUNET_TESTBED_Operation *op) | ||
1283 | { | ||
1284 | GNUNET_assert (OP_STATE_INACTIVE == op->state); | ||
1285 | change_state (op, OP_STATE_ACTIVE); | ||
1286 | } | ||
1287 | |||
1288 | |||
1289 | /** | ||
1290 | * An operation is 'done' (was cancelled or finished); remove | ||
1291 | * it from the queues and release associated resources. | ||
1292 | * | ||
1293 | * @param op operation that finished | ||
1294 | */ | ||
1295 | void | ||
1296 | GNUNET_TESTBED_operation_release_ (struct GNUNET_TESTBED_Operation *op) | ||
1297 | { | ||
1298 | struct QueueEntry *entry; | ||
1299 | struct OperationQueue *opq; | ||
1300 | unsigned int i; | ||
1301 | |||
1302 | if (OP_STATE_INIT == op->state) | ||
1303 | { | ||
1304 | GNUNET_free (op); | ||
1305 | return; | ||
1306 | } | ||
1307 | if (OP_STATE_READY == op->state) | ||
1308 | rq_remove (op); | ||
1309 | if (OP_STATE_INACTIVE == op->state) /* Activate the operation if inactive */ | ||
1310 | GNUNET_TESTBED_operation_activate_ (op); | ||
1311 | if (OP_STATE_ACTIVE == op->state) | ||
1312 | update_tslots (op); | ||
1313 | GNUNET_assert (NULL != op->queues); | ||
1314 | GNUNET_assert (NULL != op->qentries); | ||
1315 | for (i = 0; i < op->nqueues; i++) | ||
1316 | { | ||
1317 | entry = op->qentries[i]; | ||
1318 | remove_queue_entry (op, i); | ||
1319 | opq = op->queues[i]; | ||
1320 | switch (op->state) | ||
1321 | { | ||
1322 | case OP_STATE_INIT: | ||
1323 | case OP_STATE_INACTIVE: | ||
1324 | GNUNET_assert (0); | ||
1325 | break; | ||
1326 | |||
1327 | case OP_STATE_WAITING: | ||
1328 | break; | ||
1329 | |||
1330 | case OP_STATE_ACTIVE: | ||
1331 | case OP_STATE_READY: | ||
1332 | GNUNET_assert (0 != opq->active); | ||
1333 | GNUNET_assert (opq->active >= entry->nres); | ||
1334 | opq->active -= entry->nres; | ||
1335 | recheck_waiting (opq); | ||
1336 | break; | ||
1337 | } | ||
1338 | GNUNET_free (entry); | ||
1339 | } | ||
1340 | GNUNET_free (op->qentries); | ||
1341 | GNUNET_free (op->queues); | ||
1342 | GNUNET_free (op->nres); | ||
1343 | if (NULL != op->release) | ||
1344 | op->release (op->cb_cls); | ||
1345 | GNUNET_free (op); | ||
1346 | } | ||
1347 | |||
1348 | |||
1349 | /** | ||
1350 | * Marks an operation as failed | ||
1351 | * | ||
1352 | * @param op the operation to be marked as failed | ||
1353 | */ | ||
1354 | void | ||
1355 | GNUNET_TESTBED_operation_mark_failed (struct GNUNET_TESTBED_Operation *op) | ||
1356 | { | ||
1357 | op->failed = GNUNET_YES; | ||
1358 | } | ||
1359 | |||
1360 | |||
1361 | /** | ||
1362 | * Cleanup expired operation queues. While doing so, also check for any | ||
1363 | * operations which are not completed and warn about them. | ||
1364 | */ | ||
1365 | void __attribute__ ((destructor)) | ||
1366 | GNUNET_TESTBED_operations_fini () | ||
1367 | { | ||
1368 | struct OperationQueue *queue; | ||
1369 | unsigned int i; | ||
1370 | int warn = 0; | ||
1371 | |||
1372 | for (i = 0; i < n_expired_opqs; i++) | ||
1373 | { | ||
1374 | queue = expired_opqs[i]; | ||
1375 | if (GNUNET_NO == is_queue_empty (queue)) | ||
1376 | warn = 1; | ||
1377 | queue_destroy (queue); | ||
1378 | } | ||
1379 | GNUNET_free (expired_opqs); | ||
1380 | n_expired_opqs = 0; | ||
1381 | if (warn) | ||
1382 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1383 | "Be disciplined. Some operations were not marked as done.\n"); | ||
1384 | } | ||
1385 | |||
1386 | |||
1387 | /* end of testbed_api_operations.c */ | ||
diff --git a/src/testbed/testbed_api_operations.h b/src/testbed/testbed_api_operations.h deleted file mode 100644 index d9de5c011..000000000 --- a/src/testbed/testbed_api_operations.h +++ /dev/null | |||
@@ -1,233 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_operations.h | ||
23 | * @brief internal API to access the 'operations' subsystem | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #ifndef NEW_TESTING_API_OPERATIONS_H | ||
27 | #define NEW_TESTING_API_OPERATIONS_H | ||
28 | |||
29 | #include "gnunet_testbed_service.h" | ||
30 | #include "gnunet_helper_lib.h" | ||
31 | |||
32 | |||
33 | /** | ||
34 | * Queue of operations where we can only support a certain | ||
35 | * number of concurrent operations of a particular type. | ||
36 | */ | ||
37 | struct OperationQueue; | ||
38 | |||
39 | |||
40 | /** | ||
41 | * The type of operation queue | ||
42 | */ | ||
43 | enum OperationQueueType | ||
44 | { | ||
45 | /** | ||
46 | * Operation queue which permits a fixed maximum number of operations to be | ||
47 | * active at any time | ||
48 | */ | ||
49 | OPERATION_QUEUE_TYPE_FIXED, | ||
50 | |||
51 | /** | ||
52 | * Operation queue which adapts the number of operations to be active based on | ||
53 | * the operation completion times of previously executed operation in it | ||
54 | */ | ||
55 | OPERATION_QUEUE_TYPE_ADAPTIVE | ||
56 | }; | ||
57 | |||
58 | |||
59 | /** | ||
60 | * Create an operation queue. | ||
61 | * | ||
62 | * @param type the type of operation queue | ||
63 | * @param max_active maximum number of operations in this queue that can be | ||
64 | * active in parallel at the same time. | ||
65 | * @return handle to the queue | ||
66 | */ | ||
67 | struct OperationQueue * | ||
68 | GNUNET_TESTBED_operation_queue_create_ (enum OperationQueueType type, | ||
69 | unsigned int max_active); | ||
70 | |||
71 | |||
72 | /** | ||
73 | * Destroy an operation queue. The queue MUST be empty | ||
74 | * at this time. | ||
75 | * | ||
76 | * @param queue queue to destroy | ||
77 | */ | ||
78 | void | ||
79 | GNUNET_TESTBED_operation_queue_destroy_ (struct OperationQueue *queue); | ||
80 | |||
81 | |||
82 | /** | ||
83 | * Destroys the operation queue if it is empty. If not empty return GNUNET_NO. | ||
84 | * | ||
85 | * @param queue the queue to destroy if empty | ||
86 | * @return GNUNET_YES if the queue is destroyed. GNUNET_NO if not (because it | ||
87 | * is not empty) | ||
88 | */ | ||
89 | int | ||
90 | GNUNET_TESTBED_operation_queue_destroy_empty_ (struct OperationQueue *queue); | ||
91 | |||
92 | |||
93 | /** | ||
94 | * Function to reset the maximum number of operations in the given queue. If | ||
95 | * max_active is lesser than the number of currently active operations, the | ||
96 | * active operations are not stopped immediately. | ||
97 | * | ||
98 | * @param queue the operation queue which has to be modified | ||
99 | * @param max_active the new maximum number of active operations | ||
100 | */ | ||
101 | void | ||
102 | GNUNET_TESTBED_operation_queue_reset_max_active_ (struct OperationQueue *queue, | ||
103 | unsigned int max_active); | ||
104 | |||
105 | |||
106 | /** | ||
107 | * Add an operation to a queue. An operation can be in multiple queues at | ||
108 | * once. Once the operation is inserted into all the queues | ||
109 | * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start | ||
110 | * waiting for the operation to become active. | ||
111 | * | ||
112 | * @param queue queue to add the operation to | ||
113 | * @param op operation to add to the queue | ||
114 | * @param nres the number of units of the resources of queue needed by the | ||
115 | * operation. Should be greater than 0. | ||
116 | */ | ||
117 | void | ||
118 | GNUNET_TESTBED_operation_queue_insert2_ (struct OperationQueue *queue, | ||
119 | struct GNUNET_TESTBED_Operation *op, | ||
120 | unsigned int nres); | ||
121 | |||
122 | |||
123 | /** | ||
124 | * Add an operation to a queue. An operation can be in multiple queues at | ||
125 | * once. Once the operation is inserted into all the queues | ||
126 | * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start | ||
127 | * waiting for the operation to become active. | ||
128 | * | ||
129 | * @param queue queue to add the operation to | ||
130 | * @param op operation to add to the queue | ||
131 | */ | ||
132 | void | ||
133 | GNUNET_TESTBED_operation_queue_insert_ (struct OperationQueue *queue, | ||
134 | struct GNUNET_TESTBED_Operation *op); | ||
135 | |||
136 | |||
137 | /** | ||
138 | * Marks the given operation as waiting on the queues. Once all queues permit | ||
139 | * the operation to become active, the operation will be activated. The actual | ||
140 | * activation will occur in a separate task (thus allowing multiple queue | ||
141 | * insertions to be made without having the first one instantly trigger the | ||
142 | * operation if the first queue has sufficient resources). | ||
143 | * | ||
144 | * @param op the operation to marks as waiting | ||
145 | */ | ||
146 | void | ||
147 | GNUNET_TESTBED_operation_begin_wait_ (struct GNUNET_TESTBED_Operation *op); | ||
148 | |||
149 | |||
150 | /** | ||
151 | * Function to call to start an operation once all | ||
152 | * queues the operation is part of declare that the | ||
153 | * operation can be activated. | ||
154 | * | ||
155 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
156 | */ | ||
157 | typedef void (*OperationStart) (void *cls); | ||
158 | |||
159 | |||
160 | /** | ||
161 | * Function to call to cancel an operation (release all associated | ||
162 | * resources). This can be because of a call to | ||
163 | * "GNUNET_TESTBED_operation_cancel" (before the operation generated | ||
164 | * an event) or AFTER the operation generated an event due to a call | ||
165 | * to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that | ||
166 | * a callback to the 'OperationStart' precedes the call to | ||
167 | * 'OperationRelease'. Implementations of this function are expected | ||
168 | * to clean up whatever state is in 'cls' and release all resources | ||
169 | * associated with the operation. | ||
170 | * | ||
171 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
172 | */ | ||
173 | typedef void (*OperationRelease) (void *cls); | ||
174 | |||
175 | |||
176 | /** | ||
177 | * Create an 'operation' to be performed. | ||
178 | * | ||
179 | * @param cls closure for the callbacks | ||
180 | * @param start function to call to start the operation | ||
181 | * @param release function to call to close down the operation | ||
182 | * @return handle to the operation | ||
183 | */ | ||
184 | struct GNUNET_TESTBED_Operation * | ||
185 | GNUNET_TESTBED_operation_create_ (void *cls, OperationStart start, | ||
186 | OperationRelease release); | ||
187 | |||
188 | |||
189 | /** | ||
190 | * An operation is 'done' (was cancelled or finished); remove | ||
191 | * it from the queues and release associated resources. | ||
192 | * | ||
193 | * @param op operation that finished | ||
194 | */ | ||
195 | void | ||
196 | GNUNET_TESTBED_operation_release_ (struct GNUNET_TESTBED_Operation *op); | ||
197 | |||
198 | |||
199 | /** | ||
200 | * Marks an active operation as inactive - the operation will be kept in a | ||
201 | * ready-to-be-released state and continues to hold resources until another | ||
202 | * operation contents for them. | ||
203 | * | ||
204 | * @param op the operation to be marked as inactive. The operation start | ||
205 | * callback should have been called before for this operation to mark | ||
206 | * it as inactive. | ||
207 | */ | ||
208 | void | ||
209 | GNUNET_TESTBED_operation_inactivate_ (struct GNUNET_TESTBED_Operation *op); | ||
210 | |||
211 | |||
212 | /** | ||
213 | * Marks and inactive operation as active. This function should be called to | ||
214 | * ensure that the oprelease callback will not be called until it is either | ||
215 | * marked as inactive or released. | ||
216 | * | ||
217 | * @param op the operation to be marked as active | ||
218 | */ | ||
219 | void | ||
220 | GNUNET_TESTBED_operation_activate_ (struct GNUNET_TESTBED_Operation *op); | ||
221 | |||
222 | |||
223 | /** | ||
224 | * Marks an operation as failed | ||
225 | * | ||
226 | * @param op the operation to be marked as failed | ||
227 | */ | ||
228 | void | ||
229 | GNUNET_TESTBED_operation_mark_failed (struct GNUNET_TESTBED_Operation *op); | ||
230 | |||
231 | |||
232 | #endif | ||
233 | /* end of testbed_api_operations.h */ | ||
diff --git a/src/testbed/testbed_api_peers.c b/src/testbed/testbed_api_peers.c deleted file mode 100644 index 99d30e85b..000000000 --- a/src/testbed/testbed_api_peers.c +++ /dev/null | |||
@@ -1,1016 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_peers.c | ||
23 | * @brief management of the knowledge about peers in this library | ||
24 | * (we know the peer ID, its host, pending operations, etc.) | ||
25 | * @author Christian Grothoff | ||
26 | * @author Sree Harsha Totakura | ||
27 | */ | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "testbed_api_peers.h" | ||
31 | #include "testbed_api.h" | ||
32 | #include "testbed.h" | ||
33 | #include "testbed_api_hosts.h" | ||
34 | #include "testbed_api_operations.h" | ||
35 | |||
36 | |||
37 | /** | ||
38 | * Peer list DLL head | ||
39 | */ | ||
40 | static struct GNUNET_TESTBED_Peer *peer_list_head; | ||
41 | |||
42 | /** | ||
43 | * Peer list DLL tail | ||
44 | */ | ||
45 | static struct GNUNET_TESTBED_Peer *peer_list_tail; | ||
46 | |||
47 | |||
48 | /** | ||
49 | * Adds a peer to the peer list | ||
50 | * | ||
51 | * @param peer the peer to add to the peer list | ||
52 | */ | ||
53 | void | ||
54 | GNUNET_TESTBED_peer_register_ (struct GNUNET_TESTBED_Peer *peer) | ||
55 | { | ||
56 | GNUNET_CONTAINER_DLL_insert_tail (peer_list_head, peer_list_tail, peer); | ||
57 | } | ||
58 | |||
59 | |||
60 | /** | ||
61 | * Removes a peer from the peer list | ||
62 | * | ||
63 | * @param peer the peer to remove | ||
64 | */ | ||
65 | void | ||
66 | GNUNET_TESTBED_peer_deregister_ (struct GNUNET_TESTBED_Peer *peer) | ||
67 | { | ||
68 | GNUNET_CONTAINER_DLL_remove (peer_list_head, peer_list_tail, peer); | ||
69 | } | ||
70 | |||
71 | |||
72 | /** | ||
73 | * Frees all peers | ||
74 | */ | ||
75 | void | ||
76 | GNUNET_TESTBED_cleanup_peers_ (void) | ||
77 | { | ||
78 | struct GNUNET_TESTBED_Peer *peer; | ||
79 | |||
80 | while (NULL != (peer = peer_list_head)) | ||
81 | { | ||
82 | GNUNET_TESTBED_peer_deregister_ (peer); | ||
83 | GNUNET_free (peer); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | |||
88 | /** | ||
89 | * Function to call to start a peer_create type operation once all | ||
90 | * queues the operation is part of declare that the | ||
91 | * operation can be activated. | ||
92 | * | ||
93 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
94 | */ | ||
95 | static void | ||
96 | opstart_peer_create (void *cls) | ||
97 | { | ||
98 | struct OperationContext *opc = cls; | ||
99 | struct PeerCreateData *data = opc->data; | ||
100 | struct GNUNET_TESTBED_PeerCreateMessage *msg; | ||
101 | struct GNUNET_MQ_Envelope *env; | ||
102 | char *config; | ||
103 | char *xconfig; | ||
104 | size_t c_size; | ||
105 | size_t xc_size; | ||
106 | |||
107 | GNUNET_assert (OP_PEER_CREATE == opc->type); | ||
108 | GNUNET_assert (NULL != data); | ||
109 | GNUNET_assert (NULL != data->peer); | ||
110 | opc->state = OPC_STATE_STARTED; | ||
111 | config = GNUNET_CONFIGURATION_serialize (data->cfg, | ||
112 | &c_size); | ||
113 | xc_size = GNUNET_TESTBED_compress_config_ (config, | ||
114 | c_size, | ||
115 | &xconfig); | ||
116 | GNUNET_free (config); | ||
117 | env = GNUNET_MQ_msg_extra (msg, | ||
118 | xc_size, | ||
119 | GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER); | ||
120 | msg->operation_id = GNUNET_htonll (opc->id); | ||
121 | msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->peer->host)); | ||
122 | msg->peer_id = htonl (data->peer->unique_id); | ||
123 | msg->config_size = htons ((uint16_t) c_size); | ||
124 | GNUNET_memcpy (&msg[1], | ||
125 | xconfig, | ||
126 | xc_size); | ||
127 | GNUNET_MQ_send (opc->c->mq, | ||
128 | env); | ||
129 | GNUNET_free (xconfig); | ||
130 | GNUNET_TESTBED_insert_opc_ (opc->c, opc); | ||
131 | } | ||
132 | |||
133 | |||
134 | /** | ||
135 | * Callback which will be called when peer_create type operation is released | ||
136 | * | ||
137 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
138 | */ | ||
139 | static void | ||
140 | oprelease_peer_create (void *cls) | ||
141 | { | ||
142 | struct OperationContext *opc = cls; | ||
143 | |||
144 | switch (opc->state) | ||
145 | { | ||
146 | case OPC_STATE_STARTED: | ||
147 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
148 | |||
149 | /* No break we continue flow */ | ||
150 | case OPC_STATE_INIT: | ||
151 | GNUNET_free (((struct PeerCreateData *) opc->data)->peer); | ||
152 | GNUNET_free (opc->data); | ||
153 | break; | ||
154 | |||
155 | case OPC_STATE_FINISHED: | ||
156 | break; | ||
157 | } | ||
158 | GNUNET_free (opc); | ||
159 | } | ||
160 | |||
161 | |||
162 | /** | ||
163 | * Function called when a peer destroy operation is ready | ||
164 | * | ||
165 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
166 | */ | ||
167 | static void | ||
168 | opstart_peer_destroy (void *cls) | ||
169 | { | ||
170 | struct OperationContext *opc = cls; | ||
171 | struct GNUNET_TESTBED_Peer *peer = opc->data; | ||
172 | struct GNUNET_TESTBED_PeerDestroyMessage *msg; | ||
173 | struct GNUNET_MQ_Envelope *env; | ||
174 | |||
175 | GNUNET_assert (OP_PEER_DESTROY == opc->type); | ||
176 | GNUNET_assert (NULL != peer); | ||
177 | opc->state = OPC_STATE_STARTED; | ||
178 | env = GNUNET_MQ_msg (msg, | ||
179 | GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER); | ||
180 | msg->peer_id = htonl (peer->unique_id); | ||
181 | msg->operation_id = GNUNET_htonll (opc->id); | ||
182 | GNUNET_TESTBED_insert_opc_ (opc->c, opc); | ||
183 | GNUNET_MQ_send (peer->controller->mq, | ||
184 | env); | ||
185 | } | ||
186 | |||
187 | |||
188 | /** | ||
189 | * Callback which will be called when peer_create type operation is released | ||
190 | * | ||
191 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
192 | */ | ||
193 | static void | ||
194 | oprelease_peer_destroy (void *cls) | ||
195 | { | ||
196 | struct OperationContext *opc = cls; | ||
197 | |||
198 | switch (opc->state) | ||
199 | { | ||
200 | case OPC_STATE_STARTED: | ||
201 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
202 | |||
203 | /* no break; continue */ | ||
204 | case OPC_STATE_INIT: | ||
205 | break; | ||
206 | |||
207 | case OPC_STATE_FINISHED: | ||
208 | break; | ||
209 | } | ||
210 | GNUNET_free (opc); | ||
211 | } | ||
212 | |||
213 | |||
214 | /** | ||
215 | * Function called when a peer start operation is ready | ||
216 | * | ||
217 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
218 | */ | ||
219 | static void | ||
220 | opstart_peer_start (void *cls) | ||
221 | { | ||
222 | struct OperationContext *opc = cls; | ||
223 | struct GNUNET_TESTBED_PeerStartMessage *msg; | ||
224 | struct GNUNET_MQ_Envelope *env; | ||
225 | struct PeerEventData *data; | ||
226 | struct GNUNET_TESTBED_Peer *peer; | ||
227 | |||
228 | GNUNET_assert (OP_PEER_START == opc->type); | ||
229 | GNUNET_assert (NULL != (data = opc->data)); | ||
230 | GNUNET_assert (NULL != (peer = data->peer)); | ||
231 | GNUNET_assert ((TESTBED_PS_CREATED == peer->state) || (TESTBED_PS_STOPPED == | ||
232 | peer->state)); | ||
233 | opc->state = OPC_STATE_STARTED; | ||
234 | env = GNUNET_MQ_msg (msg, | ||
235 | GNUNET_MESSAGE_TYPE_TESTBED_START_PEER); | ||
236 | msg->peer_id = htonl (peer->unique_id); | ||
237 | msg->operation_id = GNUNET_htonll (opc->id); | ||
238 | GNUNET_TESTBED_insert_opc_ (opc->c, opc); | ||
239 | GNUNET_MQ_send (peer->controller->mq, | ||
240 | env); | ||
241 | } | ||
242 | |||
243 | |||
244 | /** | ||
245 | * Callback which will be called when peer start type operation is released | ||
246 | * | ||
247 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
248 | */ | ||
249 | static void | ||
250 | oprelease_peer_start (void *cls) | ||
251 | { | ||
252 | struct OperationContext *opc = cls; | ||
253 | |||
254 | switch (opc->state) | ||
255 | { | ||
256 | case OPC_STATE_STARTED: | ||
257 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
258 | |||
259 | /* no break; continue */ | ||
260 | case OPC_STATE_INIT: | ||
261 | GNUNET_free (opc->data); | ||
262 | break; | ||
263 | |||
264 | case OPC_STATE_FINISHED: | ||
265 | break; | ||
266 | } | ||
267 | GNUNET_free (opc); | ||
268 | } | ||
269 | |||
270 | |||
271 | /** | ||
272 | * Function called when a peer stop operation is ready | ||
273 | * | ||
274 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
275 | */ | ||
276 | static void | ||
277 | opstart_peer_stop (void *cls) | ||
278 | { | ||
279 | struct OperationContext *opc = cls; | ||
280 | struct GNUNET_TESTBED_PeerStopMessage *msg; | ||
281 | struct PeerEventData *data; | ||
282 | struct GNUNET_TESTBED_Peer *peer; | ||
283 | struct GNUNET_MQ_Envelope *env; | ||
284 | |||
285 | GNUNET_assert (NULL != (data = opc->data)); | ||
286 | GNUNET_assert (NULL != (peer = data->peer)); | ||
287 | GNUNET_assert (TESTBED_PS_STARTED == peer->state); | ||
288 | opc->state = OPC_STATE_STARTED; | ||
289 | env = GNUNET_MQ_msg (msg, | ||
290 | GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER); | ||
291 | msg->peer_id = htonl (peer->unique_id); | ||
292 | msg->operation_id = GNUNET_htonll (opc->id); | ||
293 | GNUNET_TESTBED_insert_opc_ (opc->c, opc); | ||
294 | GNUNET_MQ_send (peer->controller->mq, | ||
295 | env); | ||
296 | } | ||
297 | |||
298 | |||
299 | /** | ||
300 | * Callback which will be called when peer stop type operation is released | ||
301 | * | ||
302 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
303 | */ | ||
304 | static void | ||
305 | oprelease_peer_stop (void *cls) | ||
306 | { | ||
307 | struct OperationContext *opc = cls; | ||
308 | |||
309 | switch (opc->state) | ||
310 | { | ||
311 | case OPC_STATE_STARTED: | ||
312 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
313 | |||
314 | /* no break; continue */ | ||
315 | case OPC_STATE_INIT: | ||
316 | GNUNET_free (opc->data); | ||
317 | break; | ||
318 | |||
319 | case OPC_STATE_FINISHED: | ||
320 | break; | ||
321 | } | ||
322 | GNUNET_free (opc); | ||
323 | } | ||
324 | |||
325 | |||
326 | /** | ||
327 | * Generate PeerGetConfigurationMessage | ||
328 | * | ||
329 | * @param peer_id the id of the peer whose information we have to get | ||
330 | * @param operation_id the ip of the operation that should be represented in the | ||
331 | * message | ||
332 | * @return the PeerGetConfigurationMessage | ||
333 | */ | ||
334 | struct GNUNET_TESTBED_PeerGetConfigurationMessage * | ||
335 | GNUNET_TESTBED_generate_peergetconfig_msg_ (uint32_t peer_id, | ||
336 | uint64_t operation_id) | ||
337 | { | ||
338 | struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; | ||
339 | |||
340 | msg = | ||
341 | GNUNET_malloc (sizeof | ||
342 | (struct GNUNET_TESTBED_PeerGetConfigurationMessage)); | ||
343 | msg->header.size = | ||
344 | htons (sizeof(struct GNUNET_TESTBED_PeerGetConfigurationMessage)); | ||
345 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION); | ||
346 | msg->peer_id = htonl (peer_id); | ||
347 | msg->operation_id = GNUNET_htonll (operation_id); | ||
348 | return msg; | ||
349 | } | ||
350 | |||
351 | |||
352 | /** | ||
353 | * Function called when a peer get information operation is ready | ||
354 | * | ||
355 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
356 | */ | ||
357 | static void | ||
358 | opstart_peer_getinfo (void *cls) | ||
359 | { | ||
360 | struct OperationContext *opc = cls; | ||
361 | struct PeerInfoData *data = opc->data; | ||
362 | struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; | ||
363 | |||
364 | GNUNET_assert (NULL != data); | ||
365 | opc->state = OPC_STATE_STARTED; | ||
366 | msg = | ||
367 | GNUNET_TESTBED_generate_peergetconfig_msg_ (data->peer->unique_id, | ||
368 | opc->id); | ||
369 | GNUNET_TESTBED_insert_opc_ (opc->c, opc); | ||
370 | GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); | ||
371 | } | ||
372 | |||
373 | |||
374 | /** | ||
375 | * Callback which will be called when peer stop type operation is released | ||
376 | * | ||
377 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
378 | */ | ||
379 | static void | ||
380 | oprelease_peer_getinfo (void *cls) | ||
381 | { | ||
382 | struct OperationContext *opc = cls; | ||
383 | struct GNUNET_TESTBED_PeerInformation *data; | ||
384 | |||
385 | switch (opc->state) | ||
386 | { | ||
387 | case OPC_STATE_STARTED: | ||
388 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
389 | |||
390 | /* no break; continue */ | ||
391 | case OPC_STATE_INIT: | ||
392 | GNUNET_free (opc->data); | ||
393 | break; | ||
394 | |||
395 | case OPC_STATE_FINISHED: | ||
396 | data = opc->data; | ||
397 | GNUNET_assert (NULL != data); | ||
398 | switch (data->pit) | ||
399 | { | ||
400 | case GNUNET_TESTBED_PIT_CONFIGURATION: | ||
401 | if (NULL != data->result.cfg) | ||
402 | GNUNET_CONFIGURATION_destroy (data->result.cfg); | ||
403 | break; | ||
404 | |||
405 | case GNUNET_TESTBED_PIT_IDENTITY: | ||
406 | GNUNET_free (data->result.id); | ||
407 | break; | ||
408 | |||
409 | default: | ||
410 | GNUNET_assert (0); /* We should never reach here */ | ||
411 | } | ||
412 | GNUNET_free (data); | ||
413 | break; | ||
414 | } | ||
415 | GNUNET_free (opc); | ||
416 | } | ||
417 | |||
418 | |||
419 | /** | ||
420 | * Function called when a overlay connect operation is ready | ||
421 | * | ||
422 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
423 | */ | ||
424 | static void | ||
425 | opstart_overlay_connect (void *cls) | ||
426 | { | ||
427 | struct OperationContext *opc = cls; | ||
428 | struct GNUNET_MQ_Envelope *env; | ||
429 | struct GNUNET_TESTBED_OverlayConnectMessage *msg; | ||
430 | struct OverlayConnectData *data; | ||
431 | |||
432 | opc->state = OPC_STATE_STARTED; | ||
433 | data = opc->data; | ||
434 | GNUNET_assert (NULL != data); | ||
435 | env = GNUNET_MQ_msg (msg, | ||
436 | GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT); | ||
437 | msg->peer1 = htonl (data->p1->unique_id); | ||
438 | msg->peer2 = htonl (data->p2->unique_id); | ||
439 | msg->operation_id = GNUNET_htonll (opc->id); | ||
440 | msg->peer2_host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->p2->host)); | ||
441 | GNUNET_TESTBED_insert_opc_ (opc->c, | ||
442 | opc); | ||
443 | GNUNET_MQ_send (opc->c->mq, | ||
444 | env); | ||
445 | } | ||
446 | |||
447 | |||
448 | /** | ||
449 | * Callback which will be called when overlay connect operation is released | ||
450 | * | ||
451 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
452 | */ | ||
453 | static void | ||
454 | oprelease_overlay_connect (void *cls) | ||
455 | { | ||
456 | struct OperationContext *opc = cls; | ||
457 | struct OverlayConnectData *data; | ||
458 | |||
459 | data = opc->data; | ||
460 | switch (opc->state) | ||
461 | { | ||
462 | case OPC_STATE_INIT: | ||
463 | break; | ||
464 | |||
465 | case OPC_STATE_STARTED: | ||
466 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
467 | break; | ||
468 | |||
469 | case OPC_STATE_FINISHED: | ||
470 | break; | ||
471 | } | ||
472 | GNUNET_free (data); | ||
473 | GNUNET_free (opc); | ||
474 | } | ||
475 | |||
476 | |||
477 | /** | ||
478 | * Function called when a peer reconfigure operation is ready | ||
479 | * | ||
480 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
481 | */ | ||
482 | static void | ||
483 | opstart_peer_reconfigure (void *cls) | ||
484 | { | ||
485 | struct OperationContext *opc = cls; | ||
486 | struct PeerReconfigureData *data = opc->data; | ||
487 | struct GNUNET_MQ_Envelope *env; | ||
488 | struct GNUNET_TESTBED_PeerReconfigureMessage *msg; | ||
489 | char *xconfig; | ||
490 | size_t xc_size; | ||
491 | |||
492 | opc->state = OPC_STATE_STARTED; | ||
493 | GNUNET_assert (NULL != data); | ||
494 | xc_size = GNUNET_TESTBED_compress_config_ (data->config, | ||
495 | data->cfg_size, | ||
496 | &xconfig); | ||
497 | GNUNET_free (data->config); | ||
498 | data->config = NULL; | ||
499 | GNUNET_assert (xc_size < UINT16_MAX - sizeof(*msg)); | ||
500 | env = GNUNET_MQ_msg_extra (msg, | ||
501 | xc_size, | ||
502 | GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER); | ||
503 | msg->peer_id = htonl (data->peer->unique_id); | ||
504 | msg->operation_id = GNUNET_htonll (opc->id); | ||
505 | msg->config_size = htons (data->cfg_size); | ||
506 | GNUNET_memcpy (&msg[1], | ||
507 | xconfig, | ||
508 | xc_size); | ||
509 | GNUNET_free (xconfig); | ||
510 | GNUNET_free (data); | ||
511 | opc->data = NULL; | ||
512 | GNUNET_TESTBED_insert_opc_ (opc->c, opc); | ||
513 | GNUNET_MQ_send (opc->c->mq, | ||
514 | env); | ||
515 | } | ||
516 | |||
517 | |||
518 | /** | ||
519 | * Callback which will be called when a peer reconfigure operation is released | ||
520 | * | ||
521 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
522 | */ | ||
523 | static void | ||
524 | oprelease_peer_reconfigure (void *cls) | ||
525 | { | ||
526 | struct OperationContext *opc = cls; | ||
527 | struct PeerReconfigureData *data = opc->data; | ||
528 | |||
529 | switch (opc->state) | ||
530 | { | ||
531 | case OPC_STATE_INIT: | ||
532 | GNUNET_free (data->config); | ||
533 | GNUNET_free (data); | ||
534 | break; | ||
535 | |||
536 | case OPC_STATE_STARTED: | ||
537 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
538 | break; | ||
539 | |||
540 | case OPC_STATE_FINISHED: | ||
541 | break; | ||
542 | } | ||
543 | GNUNET_free (opc); | ||
544 | } | ||
545 | |||
546 | |||
547 | /** | ||
548 | * Lookup a peer by ID. | ||
549 | * | ||
550 | * @param id global peer ID assigned to the peer | ||
551 | * @return handle to the host, NULL on error | ||
552 | */ | ||
553 | struct GNUNET_TESTBED_Peer * | ||
554 | GNUNET_TESTBED_peer_lookup_by_id_ (uint32_t id) | ||
555 | { | ||
556 | GNUNET_break (0); | ||
557 | return NULL; | ||
558 | } | ||
559 | |||
560 | |||
561 | /** | ||
562 | * Create the given peer at the specified host using the given | ||
563 | * controller. If the given controller is not running on the target | ||
564 | * host, it should find or create a controller at the target host and | ||
565 | * delegate creating the peer. Explicit delegation paths can be setup | ||
566 | * using 'GNUNET_TESTBED_controller_link'. If no explicit delegation | ||
567 | * path exists, a direct link with a subordinate controller is setup | ||
568 | * for the first delegated peer to a particular host; the subordinate | ||
569 | * controller is then destroyed once the last peer that was delegated | ||
570 | * to the remote host is stopped. | ||
571 | * | ||
572 | * Creating the peer only creates the handle to manipulate and further | ||
573 | * configure the peer; use "GNUNET_TESTBED_peer_start" and | ||
574 | * "GNUNET_TESTBED_peer_stop" to actually start/stop the peer's | ||
575 | * processes. | ||
576 | * | ||
577 | * Note that the given configuration will be adjusted by the | ||
578 | * controller to avoid port/path conflicts with other peers. | ||
579 | * The "final" configuration can be obtained using | ||
580 | * 'GNUNET_TESTBED_peer_get_information'. | ||
581 | * | ||
582 | * @param controller controller process to use | ||
583 | * @param host host to run the peer on; cannot be NULL | ||
584 | * @param cfg Template configuration to use for the peer. Should exist until | ||
585 | * operation is cancelled or GNUNET_TESTBED_operation_done() is called | ||
586 | * @param cb the callback to call when the peer has been created | ||
587 | * @param cls the closure to the above callback | ||
588 | * @return the operation handle | ||
589 | */ | ||
590 | struct GNUNET_TESTBED_Operation * | ||
591 | GNUNET_TESTBED_peer_create (struct GNUNET_TESTBED_Controller *controller, | ||
592 | struct GNUNET_TESTBED_Host *host, | ||
593 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
594 | GNUNET_TESTBED_PeerCreateCallback cb, void *cls) | ||
595 | { | ||
596 | struct GNUNET_TESTBED_Peer *peer; | ||
597 | struct PeerCreateData *data; | ||
598 | struct OperationContext *opc; | ||
599 | static uint32_t id_gen; | ||
600 | |||
601 | peer = GNUNET_new (struct GNUNET_TESTBED_Peer); | ||
602 | peer->controller = controller; | ||
603 | peer->host = host; | ||
604 | peer->unique_id = id_gen++; | ||
605 | peer->state = TESTBED_PS_INVALID; | ||
606 | data = GNUNET_new (struct PeerCreateData); | ||
607 | data->host = host; | ||
608 | data->cfg = cfg; | ||
609 | data->cb = cb; | ||
610 | data->cls = cls; | ||
611 | data->peer = peer; | ||
612 | opc = GNUNET_new (struct OperationContext); | ||
613 | opc->c = controller; | ||
614 | opc->data = data; | ||
615 | opc->id = GNUNET_TESTBED_get_next_op_id (controller); | ||
616 | opc->type = OP_PEER_CREATE; | ||
617 | opc->op = | ||
618 | GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_create, | ||
619 | &oprelease_peer_create); | ||
620 | GNUNET_TESTBED_operation_queue_insert_ (controller->opq_parallel_operations, | ||
621 | opc->op); | ||
622 | GNUNET_TESTBED_operation_begin_wait_ (opc->op); | ||
623 | return opc->op; | ||
624 | } | ||
625 | |||
626 | |||
627 | /** | ||
628 | * Start the given peer. | ||
629 | * | ||
630 | * @param op_cls the closure for this operation; will be set in | ||
631 | * event->details.operation_finished.op_cls when this operation fails. | ||
632 | * @param peer peer to start | ||
633 | * @param pcc function to call upon completion | ||
634 | * @param pcc_cls closure for 'pcc' | ||
635 | * @return handle to the operation | ||
636 | */ | ||
637 | struct GNUNET_TESTBED_Operation * | ||
638 | GNUNET_TESTBED_peer_start (void *op_cls, struct GNUNET_TESTBED_Peer *peer, | ||
639 | GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls) | ||
640 | { | ||
641 | struct OperationContext *opc; | ||
642 | struct PeerEventData *data; | ||
643 | |||
644 | data = GNUNET_new (struct PeerEventData); | ||
645 | data->peer = peer; | ||
646 | data->pcc = pcc; | ||
647 | data->pcc_cls = pcc_cls; | ||
648 | opc = GNUNET_new (struct OperationContext); | ||
649 | opc->c = peer->controller; | ||
650 | opc->data = data; | ||
651 | opc->op_cls = op_cls; | ||
652 | opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); | ||
653 | opc->type = OP_PEER_START; | ||
654 | opc->op = | ||
655 | GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_start, | ||
656 | &oprelease_peer_start); | ||
657 | GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, | ||
658 | opc->op); | ||
659 | GNUNET_TESTBED_operation_begin_wait_ (opc->op); | ||
660 | return opc->op; | ||
661 | } | ||
662 | |||
663 | |||
664 | /** | ||
665 | * Stop the given peer. The handle remains valid (use | ||
666 | * "GNUNET_TESTBED_peer_destroy" to fully clean up the | ||
667 | * state of the peer). | ||
668 | * | ||
669 | * @param op_cls the closure for this operation; will be set in the event | ||
670 | * information | ||
671 | * @param peer peer to stop | ||
672 | * @param pcc function to call upon completion | ||
673 | * @param pcc_cls closure for 'pcc' | ||
674 | * @return handle to the operation | ||
675 | */ | ||
676 | struct GNUNET_TESTBED_Operation * | ||
677 | GNUNET_TESTBED_peer_stop (void *op_cls, | ||
678 | struct GNUNET_TESTBED_Peer *peer, | ||
679 | GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls) | ||
680 | { | ||
681 | struct OperationContext *opc; | ||
682 | struct PeerEventData *data; | ||
683 | |||
684 | data = GNUNET_new (struct PeerEventData); | ||
685 | data->peer = peer; | ||
686 | data->pcc = pcc; | ||
687 | data->pcc_cls = pcc_cls; | ||
688 | opc = GNUNET_new (struct OperationContext); | ||
689 | opc->c = peer->controller; | ||
690 | opc->data = data; | ||
691 | opc->op_cls = op_cls; | ||
692 | opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); | ||
693 | opc->type = OP_PEER_STOP; | ||
694 | opc->op = | ||
695 | GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_stop, | ||
696 | &oprelease_peer_stop); | ||
697 | GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, | ||
698 | opc->op); | ||
699 | GNUNET_TESTBED_operation_begin_wait_ (opc->op); | ||
700 | return opc->op; | ||
701 | } | ||
702 | |||
703 | |||
704 | /** | ||
705 | * Request information about a peer. The controller callback will not be called | ||
706 | * with event type GNUNET_TESTBED_ET_OPERATION_FINISHED when result for this | ||
707 | * operation is available. Instead, the GNUNET_TESTBED_PeerInfoCallback() will | ||
708 | * be called. | ||
709 | * The peer information in the callback is valid until the operation is canceled. | ||
710 | * | ||
711 | * @param peer peer to request information about | ||
712 | * @param pit desired information | ||
713 | * @param cb the convenience callback to be called when results for this | ||
714 | * operation are available | ||
715 | * @param cb_cls the closure for the above callback | ||
716 | * @return handle to the operation | ||
717 | */ | ||
718 | struct GNUNET_TESTBED_Operation * | ||
719 | GNUNET_TESTBED_peer_get_information (struct GNUNET_TESTBED_Peer *peer, | ||
720 | enum GNUNET_TESTBED_PeerInformationType | ||
721 | pit, GNUNET_TESTBED_PeerInfoCallback cb, | ||
722 | void *cb_cls) | ||
723 | { | ||
724 | struct OperationContext *opc; | ||
725 | struct PeerInfoData *data; | ||
726 | |||
727 | GNUNET_assert (GNUNET_TESTBED_PIT_GENERIC != pit); | ||
728 | GNUNET_assert (NULL != cb); | ||
729 | data = GNUNET_new (struct PeerInfoData); | ||
730 | data->peer = peer; | ||
731 | data->pit = pit; | ||
732 | data->cb = cb; | ||
733 | data->cb_cls = cb_cls; | ||
734 | opc = GNUNET_new (struct OperationContext); | ||
735 | opc->c = peer->controller; | ||
736 | opc->data = data; | ||
737 | opc->type = OP_PEER_INFO; | ||
738 | opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); | ||
739 | opc->op = | ||
740 | GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_getinfo, | ||
741 | &oprelease_peer_getinfo); | ||
742 | GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, | ||
743 | opc->op); | ||
744 | GNUNET_TESTBED_operation_begin_wait_ (opc->op); | ||
745 | return opc->op; | ||
746 | } | ||
747 | |||
748 | |||
749 | /** | ||
750 | * Change peer configuration. Must only be called while the | ||
751 | * peer is stopped. Ports and paths cannot be changed this | ||
752 | * way. | ||
753 | * | ||
754 | * @param peer peer to change configuration for | ||
755 | * @param cfg new configuration (differences to existing | ||
756 | * configuration only) | ||
757 | * @return handle to the operation | ||
758 | */ | ||
759 | struct GNUNET_TESTBED_Operation * | ||
760 | GNUNET_TESTBED_peer_update_configuration (struct GNUNET_TESTBED_Peer *peer, | ||
761 | const struct | ||
762 | GNUNET_CONFIGURATION_Handle *cfg) | ||
763 | { | ||
764 | struct OperationContext *opc; | ||
765 | struct PeerReconfigureData *data; | ||
766 | size_t csize; | ||
767 | |||
768 | data = GNUNET_new (struct PeerReconfigureData); | ||
769 | data->peer = peer; | ||
770 | data->config = GNUNET_CONFIGURATION_serialize (cfg, &csize); | ||
771 | if (NULL == data->config) | ||
772 | { | ||
773 | GNUNET_free (data); | ||
774 | return NULL; | ||
775 | } | ||
776 | if (csize > UINT16_MAX) | ||
777 | { | ||
778 | GNUNET_break (0); | ||
779 | GNUNET_free (data->config); | ||
780 | GNUNET_free (data); | ||
781 | return NULL; | ||
782 | } | ||
783 | data->cfg_size = (uint16_t) csize; | ||
784 | opc = GNUNET_new (struct OperationContext); | ||
785 | opc->c = peer->controller; | ||
786 | opc->data = data; | ||
787 | opc->type = OP_PEER_RECONFIGURE; | ||
788 | opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); | ||
789 | opc->op = | ||
790 | GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_reconfigure, | ||
791 | &oprelease_peer_reconfigure); | ||
792 | GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, | ||
793 | opc->op); | ||
794 | GNUNET_TESTBED_operation_begin_wait_ (opc->op); | ||
795 | return opc->op; | ||
796 | } | ||
797 | |||
798 | |||
799 | /** | ||
800 | * Destroy the given peer; the peer should have been | ||
801 | * stopped first (if it was started). | ||
802 | * | ||
803 | * @param peer peer to stop | ||
804 | * @return handle to the operation | ||
805 | */ | ||
806 | struct GNUNET_TESTBED_Operation * | ||
807 | GNUNET_TESTBED_peer_destroy (struct GNUNET_TESTBED_Peer *peer) | ||
808 | { | ||
809 | struct OperationContext *opc; | ||
810 | |||
811 | opc = GNUNET_new (struct OperationContext); | ||
812 | opc->data = peer; | ||
813 | opc->c = peer->controller; | ||
814 | opc->id = GNUNET_TESTBED_get_next_op_id (peer->controller); | ||
815 | opc->type = OP_PEER_DESTROY; | ||
816 | opc->op = | ||
817 | GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_destroy, | ||
818 | &oprelease_peer_destroy); | ||
819 | GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, | ||
820 | opc->op); | ||
821 | GNUNET_TESTBED_operation_begin_wait_ (opc->op); | ||
822 | return opc->op; | ||
823 | } | ||
824 | |||
825 | |||
826 | /** | ||
827 | * Manipulate the P2P underlay topology by configuring a link | ||
828 | * between two peers. | ||
829 | * | ||
830 | * @param op_cls closure argument to give with the operation event | ||
831 | * @param p1 first peer | ||
832 | * @param p2 second peer | ||
833 | * @param co option to change | ||
834 | * @param ... option-specific values | ||
835 | * @return handle to the operation, NULL if configuring the link at this | ||
836 | * time is not allowed | ||
837 | */ | ||
838 | struct GNUNET_TESTBED_Operation * | ||
839 | GNUNET_TESTBED_underlay_configure_link (void *op_cls, | ||
840 | struct GNUNET_TESTBED_Peer *p1, | ||
841 | struct GNUNET_TESTBED_Peer *p2, | ||
842 | enum GNUNET_TESTBED_ConnectOption co, | ||
843 | ...) | ||
844 | { | ||
845 | GNUNET_break (0); | ||
846 | return NULL; | ||
847 | } | ||
848 | |||
849 | |||
850 | /** | ||
851 | * Both peers must have been started before calling this function. | ||
852 | * This function then obtains a HELLO from 'p1', gives it to 'p2' | ||
853 | * and asks 'p2' to connect to 'p1'. | ||
854 | * | ||
855 | * @param op_cls closure argument to give with the operation event | ||
856 | * @param cb the callback to call when this operation has finished | ||
857 | * @param cb_cls the closure for the above callback | ||
858 | * @param p1 first peer | ||
859 | * @param p2 second peer | ||
860 | * @return handle to the operation, NULL if connecting these two | ||
861 | * peers is fundamentally not possible at this time (peers | ||
862 | * not running or underlay disallows) | ||
863 | */ | ||
864 | struct GNUNET_TESTBED_Operation * | ||
865 | GNUNET_TESTBED_overlay_connect (void *op_cls, | ||
866 | GNUNET_TESTBED_OperationCompletionCallback cb, | ||
867 | void *cb_cls, struct GNUNET_TESTBED_Peer *p1, | ||
868 | struct GNUNET_TESTBED_Peer *p2) | ||
869 | { | ||
870 | struct OperationContext *opc; | ||
871 | struct OverlayConnectData *data; | ||
872 | |||
873 | GNUNET_assert ((TESTBED_PS_STARTED == p1->state) && (TESTBED_PS_STARTED == | ||
874 | p2->state)); | ||
875 | data = GNUNET_new (struct OverlayConnectData); | ||
876 | data->p1 = p1; | ||
877 | data->p2 = p2; | ||
878 | data->cb = cb; | ||
879 | data->cb_cls = cb_cls; | ||
880 | opc = GNUNET_new (struct OperationContext); | ||
881 | opc->data = data; | ||
882 | opc->c = p1->controller; | ||
883 | opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); | ||
884 | opc->type = OP_OVERLAY_CONNECT; | ||
885 | opc->op_cls = op_cls; | ||
886 | opc->op = | ||
887 | GNUNET_TESTBED_operation_create_ (opc, &opstart_overlay_connect, | ||
888 | &oprelease_overlay_connect); | ||
889 | GNUNET_TESTBED_host_queue_oc_ (p1->host, opc->op); | ||
890 | GNUNET_TESTBED_operation_begin_wait_ (opc->op); | ||
891 | return opc->op; | ||
892 | } | ||
893 | |||
894 | |||
895 | /** | ||
896 | * Function called when a peer manage service operation is ready | ||
897 | * | ||
898 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
899 | */ | ||
900 | static void | ||
901 | opstart_manage_service (void *cls) | ||
902 | { | ||
903 | struct OperationContext *opc = cls; | ||
904 | struct ManageServiceData *data = opc->data; | ||
905 | struct GNUNET_MQ_Envelope *env; | ||
906 | struct GNUNET_TESTBED_ManagePeerServiceMessage *msg; | ||
907 | size_t xlen; | ||
908 | |||
909 | GNUNET_assert (NULL != data); | ||
910 | xlen = data->msize - sizeof(struct GNUNET_TESTBED_ManagePeerServiceMessage); | ||
911 | env = GNUNET_MQ_msg_extra (msg, | ||
912 | xlen, | ||
913 | GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE); | ||
914 | msg->peer_id = htonl (data->peer->unique_id); | ||
915 | msg->operation_id = GNUNET_htonll (opc->id); | ||
916 | msg->start = (uint8_t) data->start; | ||
917 | GNUNET_memcpy (&msg[1], | ||
918 | data->service_name, | ||
919 | xlen); | ||
920 | GNUNET_free (data->service_name); | ||
921 | data->service_name = NULL; | ||
922 | opc->state = OPC_STATE_STARTED; | ||
923 | GNUNET_TESTBED_insert_opc_ (opc->c, opc); | ||
924 | GNUNET_MQ_send (opc->c->mq, | ||
925 | env); | ||
926 | } | ||
927 | |||
928 | |||
929 | /** | ||
930 | * Callback which will be called when peer manage server operation is released | ||
931 | * | ||
932 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
933 | */ | ||
934 | static void | ||
935 | oprelease_manage_service (void *cls) | ||
936 | { | ||
937 | struct OperationContext *opc = cls; | ||
938 | struct ManageServiceData *data; | ||
939 | |||
940 | data = opc->data; | ||
941 | switch (opc->state) | ||
942 | { | ||
943 | case OPC_STATE_STARTED: | ||
944 | GNUNET_TESTBED_remove_opc_ (opc->c, opc); | ||
945 | break; | ||
946 | |||
947 | case OPC_STATE_INIT: | ||
948 | GNUNET_assert (NULL != data); | ||
949 | GNUNET_free (data->service_name); | ||
950 | break; | ||
951 | |||
952 | case OPC_STATE_FINISHED: | ||
953 | break; | ||
954 | } | ||
955 | GNUNET_free (data); | ||
956 | GNUNET_free (opc); | ||
957 | } | ||
958 | |||
959 | |||
960 | /** | ||
961 | * Start or stop given service at a peer. This should not be called to | ||
962 | * start/stop the peer's ARM service. Use GNUNET_TESTBED_peer_start(), | ||
963 | * GNUNET_TESTBED_peer_stop() for starting/stopping peer's ARM service. Success | ||
964 | * or failure of the generated operation is signalled through the controller | ||
965 | * event callback and/or operation completion callback. | ||
966 | * | ||
967 | * @param op_cls the closure for the operation | ||
968 | * @param peer the peer whose service is to be started/stopped | ||
969 | * @param service_name the name of the service | ||
970 | * @param cb the operation completion callback | ||
971 | * @param cb_cls the closure for the operation completion callback | ||
972 | * @param start 1 to start the service; 0 to stop the service | ||
973 | * @return an operation handle; NULL upon error (peer not running) | ||
974 | */ | ||
975 | struct GNUNET_TESTBED_Operation * | ||
976 | GNUNET_TESTBED_peer_manage_service (void *op_cls, | ||
977 | struct GNUNET_TESTBED_Peer *peer, | ||
978 | const char *service_name, | ||
979 | GNUNET_TESTBED_OperationCompletionCallback | ||
980 | cb, | ||
981 | void *cb_cls, | ||
982 | unsigned int start) | ||
983 | { | ||
984 | struct ManageServiceData *data; | ||
985 | struct OperationContext *opc; | ||
986 | size_t msize; | ||
987 | |||
988 | GNUNET_assert (TESTBED_PS_STARTED == peer->state); /* peer is not running? */ | ||
989 | msize = strlen (service_name) + 1; | ||
990 | msize += sizeof(struct GNUNET_TESTBED_ManagePeerServiceMessage); | ||
991 | if (GNUNET_MAX_MESSAGE_SIZE < msize) | ||
992 | return NULL; | ||
993 | data = GNUNET_new (struct ManageServiceData); | ||
994 | data->cb = cb; | ||
995 | data->cb_cls = cb_cls; | ||
996 | data->peer = peer; | ||
997 | data->service_name = GNUNET_strdup (service_name); | ||
998 | data->start = start; | ||
999 | data->msize = (uint16_t) msize; | ||
1000 | opc = GNUNET_new (struct OperationContext); | ||
1001 | opc->data = data; | ||
1002 | opc->c = peer->controller; | ||
1003 | opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); | ||
1004 | opc->type = OP_MANAGE_SERVICE; | ||
1005 | opc->op_cls = op_cls; | ||
1006 | opc->op = | ||
1007 | GNUNET_TESTBED_operation_create_ (opc, &opstart_manage_service, | ||
1008 | &oprelease_manage_service); | ||
1009 | GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, | ||
1010 | opc->op); | ||
1011 | GNUNET_TESTBED_operation_begin_wait_ (opc->op); | ||
1012 | return opc->op; | ||
1013 | } | ||
1014 | |||
1015 | |||
1016 | /* end of testbed_api_peers.c */ | ||
diff --git a/src/testbed/testbed_api_peers.h b/src/testbed/testbed_api_peers.h deleted file mode 100644 index db8ec9881..000000000 --- a/src/testbed/testbed_api_peers.h +++ /dev/null | |||
@@ -1,311 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_peers.h | ||
23 | * @brief internal API to access the 'peers' subsystem | ||
24 | * @author Christian Grothoff | ||
25 | * @author Sree Harsha Totakura | ||
26 | */ | ||
27 | |||
28 | #ifndef NEW_TESTING_API_PEERS_H | ||
29 | #define NEW_TESTING_API_PEERS_H | ||
30 | |||
31 | #include "gnunet_testbed_service.h" | ||
32 | #include "gnunet_helper_lib.h" | ||
33 | |||
34 | |||
35 | /** | ||
36 | * Enumeration of possible states a peer could be in | ||
37 | */ | ||
38 | enum PeerState | ||
39 | { | ||
40 | /** | ||
41 | * State to signify that this peer is invalid | ||
42 | */ | ||
43 | TESTBED_PS_INVALID, | ||
44 | |||
45 | /** | ||
46 | * The peer has been created | ||
47 | */ | ||
48 | TESTBED_PS_CREATED, | ||
49 | |||
50 | /** | ||
51 | * The peer is running | ||
52 | */ | ||
53 | TESTBED_PS_STARTED, | ||
54 | |||
55 | /** | ||
56 | * The peer is stopped | ||
57 | */ | ||
58 | TESTBED_PS_STOPPED, | ||
59 | }; | ||
60 | |||
61 | |||
62 | /** | ||
63 | * A peer controlled by the testing framework. A peer runs | ||
64 | * at a particular host. | ||
65 | */ | ||
66 | struct GNUNET_TESTBED_Peer | ||
67 | { | ||
68 | /** | ||
69 | * peer list DLL | ||
70 | */ | ||
71 | struct GNUNET_TESTBED_Peer *next; | ||
72 | |||
73 | /** | ||
74 | * peer list DLL | ||
75 | */ | ||
76 | struct GNUNET_TESTBED_Peer *prev; | ||
77 | |||
78 | /** | ||
79 | * Our controller context (not necessarily the controller | ||
80 | * that is responsible for starting/running the peer!). | ||
81 | */ | ||
82 | struct GNUNET_TESTBED_Controller *controller; | ||
83 | |||
84 | /** | ||
85 | * Which host does this peer run on? | ||
86 | */ | ||
87 | struct GNUNET_TESTBED_Host *host; | ||
88 | |||
89 | /** | ||
90 | * Globally unique ID of the peer. | ||
91 | */ | ||
92 | uint32_t unique_id; | ||
93 | |||
94 | /** | ||
95 | * Peer's state | ||
96 | */ | ||
97 | enum PeerState state; | ||
98 | |||
99 | /** | ||
100 | * Has an underlay model already set for this peer? | ||
101 | */ | ||
102 | uint8_t underlay_model_exists; | ||
103 | }; | ||
104 | |||
105 | |||
106 | /** | ||
107 | * Data for the OperationType OP_PEER_CREATE | ||
108 | */ | ||
109 | struct PeerCreateData | ||
110 | { | ||
111 | /** | ||
112 | * The host where the peer has to be created | ||
113 | */ | ||
114 | struct GNUNET_TESTBED_Host *host; | ||
115 | |||
116 | /** | ||
117 | * The template configuration of the peer | ||
118 | */ | ||
119 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
120 | |||
121 | /** | ||
122 | * The call back to call when we receive peer create success message | ||
123 | */ | ||
124 | GNUNET_TESTBED_PeerCreateCallback cb; | ||
125 | |||
126 | /** | ||
127 | * The closure for the above callback | ||
128 | */ | ||
129 | void *cls; | ||
130 | |||
131 | /** | ||
132 | * The peer structure to return when we get success message | ||
133 | */ | ||
134 | struct GNUNET_TESTBED_Peer *peer; | ||
135 | }; | ||
136 | |||
137 | |||
138 | /** | ||
139 | * Data for OperationType OP_PEER_START and OP_PEER_STOP | ||
140 | */ | ||
141 | struct PeerEventData | ||
142 | { | ||
143 | /** | ||
144 | * The handle of the peer to start | ||
145 | */ | ||
146 | struct GNUNET_TESTBED_Peer *peer; | ||
147 | |||
148 | /** | ||
149 | * The Peer churn callback to call when this operation is completed | ||
150 | */ | ||
151 | GNUNET_TESTBED_PeerChurnCallback pcc; | ||
152 | |||
153 | /** | ||
154 | * Closure for the above callback | ||
155 | */ | ||
156 | void *pcc_cls; | ||
157 | }; | ||
158 | |||
159 | |||
160 | /** | ||
161 | * Data for the OperationType OP_PEER_DESTROY; | ||
162 | */ | ||
163 | struct PeerDestroyData | ||
164 | { | ||
165 | /** | ||
166 | * The peer structure | ||
167 | */ | ||
168 | struct GNUNET_TESTBED_Peer *peer; | ||
169 | |||
170 | // PEERDESTROYDATA | ||
171 | }; | ||
172 | |||
173 | |||
174 | /** | ||
175 | * Data for the OperationType OP_PEER_INFO | ||
176 | */ | ||
177 | struct PeerInfoData | ||
178 | { | ||
179 | /** | ||
180 | * The peer whose information has been requested | ||
181 | */ | ||
182 | struct GNUNET_TESTBED_Peer *peer; | ||
183 | |||
184 | /** | ||
185 | * The Peer info callback to call when this operation has completed | ||
186 | */ | ||
187 | GNUNET_TESTBED_PeerInfoCallback cb; | ||
188 | |||
189 | /** | ||
190 | * The closure for peer info callback | ||
191 | */ | ||
192 | void *cb_cls; | ||
193 | |||
194 | /** | ||
195 | * The type of peer information requested | ||
196 | */ | ||
197 | enum GNUNET_TESTBED_PeerInformationType pit; | ||
198 | }; | ||
199 | |||
200 | |||
201 | /** | ||
202 | * Data for the operations of type OP_PEER_RECONFIGURE | ||
203 | */ | ||
204 | struct PeerReconfigureData | ||
205 | { | ||
206 | /** | ||
207 | * The peer whose information has been requested | ||
208 | */ | ||
209 | struct GNUNET_TESTBED_Peer *peer; | ||
210 | |||
211 | /** | ||
212 | * The serialized new configuration template | ||
213 | */ | ||
214 | char *config; | ||
215 | |||
216 | /** | ||
217 | * the size of the serialized configuration | ||
218 | */ | ||
219 | uint16_t cfg_size; | ||
220 | }; | ||
221 | |||
222 | |||
223 | /** | ||
224 | * Data structure for OperationType OP_OVERLAY_CONNECT | ||
225 | */ | ||
226 | struct OverlayConnectData | ||
227 | { | ||
228 | /** | ||
229 | * Peer A to connect to peer B | ||
230 | */ | ||
231 | struct GNUNET_TESTBED_Peer *p1; | ||
232 | |||
233 | /** | ||
234 | * Peer B | ||
235 | */ | ||
236 | struct GNUNET_TESTBED_Peer *p2; | ||
237 | |||
238 | /** | ||
239 | * The operation completion callback to call once this operation is done | ||
240 | */ | ||
241 | GNUNET_TESTBED_OperationCompletionCallback cb; | ||
242 | |||
243 | /** | ||
244 | * The closure for the above callback | ||
245 | */ | ||
246 | void *cb_cls; | ||
247 | |||
248 | /** | ||
249 | * OperationContext for forwarded operations generated when peer1's controller doesn't have the | ||
250 | * configuration of peer2's controller for linking laterally to attempt an | ||
251 | * overlay connection between peer 1 and peer 2. | ||
252 | */ | ||
253 | struct OperationContext *sub_opc; | ||
254 | }; | ||
255 | |||
256 | |||
257 | struct ManageServiceData | ||
258 | { | ||
259 | GNUNET_TESTBED_OperationCompletionCallback cb; | ||
260 | |||
261 | void *cb_cls; | ||
262 | |||
263 | struct GNUNET_TESTBED_Peer *peer; | ||
264 | |||
265 | char *service_name; | ||
266 | |||
267 | unsigned int start; | ||
268 | |||
269 | uint16_t msize; | ||
270 | }; | ||
271 | |||
272 | |||
273 | /** | ||
274 | * Generate PeerGetConfigurationMessage | ||
275 | * | ||
276 | * @param peer_id the id of the peer whose information we have to get | ||
277 | * @param operation_id the ip of the operation that should be represented in | ||
278 | * the message | ||
279 | * @return the PeerGetConfigurationMessage | ||
280 | */ | ||
281 | struct GNUNET_TESTBED_PeerGetConfigurationMessage * | ||
282 | GNUNET_TESTBED_generate_peergetconfig_msg_ (uint32_t peer_id, | ||
283 | uint64_t operation_id); | ||
284 | |||
285 | |||
286 | /** | ||
287 | * Adds a peer to the peer list | ||
288 | * | ||
289 | * @param peer the peer to add to the peer list | ||
290 | */ | ||
291 | void | ||
292 | GNUNET_TESTBED_peer_register_ (struct GNUNET_TESTBED_Peer *peer); | ||
293 | |||
294 | |||
295 | /** | ||
296 | * Removes a peer from the peer list | ||
297 | * | ||
298 | * @param peer the peer to remove | ||
299 | */ | ||
300 | void | ||
301 | GNUNET_TESTBED_peer_deregister_ (struct GNUNET_TESTBED_Peer *peer); | ||
302 | |||
303 | |||
304 | /** | ||
305 | * Frees all peers | ||
306 | */ | ||
307 | void | ||
308 | GNUNET_TESTBED_cleanup_peers_ (void); | ||
309 | |||
310 | #endif | ||
311 | /* end of testbed_api_peers.h */ | ||
diff --git a/src/testbed/testbed_api_sd.c b/src/testbed/testbed_api_sd.c deleted file mode 100644 index 59c7a3ebd..000000000 --- a/src/testbed/testbed_api_sd.c +++ /dev/null | |||
@@ -1,213 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_sd.c | ||
23 | * @brief functions to calculate standard deviation | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "testbed_api_sd.h" | ||
30 | |||
31 | /** | ||
32 | * An entry to hold data which will be used to calculate SD | ||
33 | */ | ||
34 | struct SDEntry | ||
35 | { | ||
36 | /** | ||
37 | * DLL next pointer | ||
38 | */ | ||
39 | struct SDEntry *next; | ||
40 | |||
41 | /** | ||
42 | * DLL prev pointer | ||
43 | */ | ||
44 | struct SDEntry *prev; | ||
45 | |||
46 | /** | ||
47 | * The value to store | ||
48 | */ | ||
49 | unsigned int amount; | ||
50 | }; | ||
51 | |||
52 | |||
53 | /** | ||
54 | * Opaque handle for calculating SD | ||
55 | */ | ||
56 | struct SDHandle | ||
57 | { | ||
58 | /** | ||
59 | * DLL head for storing entries | ||
60 | */ | ||
61 | struct SDEntry *head; | ||
62 | |||
63 | /** | ||
64 | * DLL tail for storing entries | ||
65 | */ | ||
66 | struct SDEntry *tail; | ||
67 | |||
68 | /** | ||
69 | * Squared sum of data values | ||
70 | */ | ||
71 | unsigned long long sqsum; | ||
72 | |||
73 | /** | ||
74 | * Sum of the data values | ||
75 | */ | ||
76 | unsigned long sum; | ||
77 | |||
78 | /** | ||
79 | * The average of data amounts | ||
80 | */ | ||
81 | float avg; | ||
82 | |||
83 | /** | ||
84 | * The variance | ||
85 | */ | ||
86 | double vr; | ||
87 | |||
88 | /** | ||
89 | * Number of data values; also the length of DLL containing SDEntries | ||
90 | */ | ||
91 | unsigned int cnt; | ||
92 | |||
93 | /** | ||
94 | * max number of entries we can have in the DLL | ||
95 | */ | ||
96 | unsigned int max_cnt; | ||
97 | }; | ||
98 | |||
99 | |||
100 | /** | ||
101 | * Initialize standard deviation calculation handle | ||
102 | * | ||
103 | * @param max_cnt the maximum number of readings to keep | ||
104 | * @return the initialized handle | ||
105 | */ | ||
106 | struct SDHandle * | ||
107 | GNUNET_TESTBED_SD_init_ (unsigned int max_cnt) | ||
108 | { | ||
109 | struct SDHandle *h; | ||
110 | |||
111 | GNUNET_assert (1 < max_cnt); | ||
112 | h = GNUNET_new (struct SDHandle); | ||
113 | h->max_cnt = max_cnt; | ||
114 | return h; | ||
115 | } | ||
116 | |||
117 | |||
118 | /** | ||
119 | * Frees the memory allocated to the SD handle | ||
120 | * | ||
121 | * @param h the SD handle | ||
122 | */ | ||
123 | void | ||
124 | GNUNET_TESTBED_SD_destroy_ (struct SDHandle *h) | ||
125 | { | ||
126 | struct SDEntry *entry; | ||
127 | |||
128 | while (NULL != (entry = h->head)) | ||
129 | { | ||
130 | GNUNET_CONTAINER_DLL_remove (h->head, h->tail, entry); | ||
131 | GNUNET_free (entry); | ||
132 | } | ||
133 | GNUNET_free (h); | ||
134 | } | ||
135 | |||
136 | |||
137 | /** | ||
138 | * Add a reading to SD | ||
139 | * | ||
140 | * @param h the SD handle | ||
141 | * @param amount the reading value | ||
142 | */ | ||
143 | void | ||
144 | GNUNET_TESTBED_SD_add_data_ (struct SDHandle *h, unsigned int amount) | ||
145 | { | ||
146 | struct SDEntry *entry; | ||
147 | double sqavg; | ||
148 | double sqsum_avg; | ||
149 | |||
150 | entry = NULL; | ||
151 | if (h->cnt == h->max_cnt) | ||
152 | { | ||
153 | entry = h->head; | ||
154 | GNUNET_CONTAINER_DLL_remove (h->head, h->tail, entry); | ||
155 | h->sum -= entry->amount; | ||
156 | h->sqsum -= | ||
157 | ((unsigned long) entry->amount) * ((unsigned long) entry->amount); | ||
158 | h->cnt--; | ||
159 | } | ||
160 | GNUNET_assert (h->cnt < h->max_cnt); | ||
161 | if (NULL == entry) | ||
162 | entry = GNUNET_new (struct SDEntry); | ||
163 | entry->amount = amount; | ||
164 | GNUNET_CONTAINER_DLL_insert_tail (h->head, h->tail, entry); | ||
165 | h->sum += amount; | ||
166 | h->cnt++; | ||
167 | h->avg = ((float) h->sum) / ((float) h->cnt); | ||
168 | h->sqsum += ((unsigned long) amount) * ((unsigned long) amount); | ||
169 | sqsum_avg = ((double) h->sqsum) / ((double) h->cnt); | ||
170 | sqavg = ((double) h->avg) * ((double) h->avg); | ||
171 | h->vr = sqsum_avg - sqavg; | ||
172 | } | ||
173 | |||
174 | |||
175 | /** | ||
176 | * Calculates the factor by which the given amount differs | ||
177 | * | ||
178 | * @param h the SDhandle | ||
179 | * @param amount the value for which the deviation is returned | ||
180 | * @param factor the factor by which the given amont differs | ||
181 | * @return GNUNET_SYSERR if the deviation cannot | ||
182 | * be calculated; GNUNET_OK if the deviation is returned through factor | ||
183 | */ | ||
184 | int | ||
185 | GNUNET_TESTBED_SD_deviation_factor_ (struct SDHandle *h, unsigned int amount, | ||
186 | int *factor) | ||
187 | { | ||
188 | double diff; | ||
189 | int f; | ||
190 | int n; | ||
191 | |||
192 | if (h->cnt < 2) | ||
193 | return GNUNET_SYSERR; | ||
194 | if (((float) amount) > h->avg) | ||
195 | { | ||
196 | diff = ((float) amount) - h->avg; | ||
197 | f = 1; | ||
198 | } | ||
199 | else | ||
200 | { | ||
201 | diff = h->avg - ((float) amount); | ||
202 | f = -1; | ||
203 | } | ||
204 | diff *= diff; | ||
205 | for (n = 1; n < 4; n++) | ||
206 | if (diff < (((double) (n * n)) * h->vr)) | ||
207 | break; | ||
208 | *factor = f * n; | ||
209 | return GNUNET_OK; | ||
210 | } | ||
211 | |||
212 | |||
213 | /* end of testbed_api_sd.c */ | ||
diff --git a/src/testbed/testbed_api_sd.h b/src/testbed/testbed_api_sd.h deleted file mode 100644 index 2872051e0..000000000 --- a/src/testbed/testbed_api_sd.h +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_sd.h | ||
23 | * @brief functions to calculate standard deviation | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #ifndef TESTBED_API_SD_H | ||
28 | #define TESTBED_API_SD_H | ||
29 | |||
30 | |||
31 | /** | ||
32 | * Opaque handle for calculating SD | ||
33 | */ | ||
34 | struct SDHandle; | ||
35 | |||
36 | |||
37 | /** | ||
38 | * Initialize standard deviation calculation handle | ||
39 | * | ||
40 | * @param max_cnt the maximum number of readings to keep | ||
41 | * @return the initialized handle | ||
42 | */ | ||
43 | struct SDHandle * | ||
44 | GNUNET_TESTBED_SD_init_ (unsigned int max_cnt); | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Frees the memory allocated to the SD handle | ||
49 | * | ||
50 | * @param h the SD handle | ||
51 | */ | ||
52 | void | ||
53 | GNUNET_TESTBED_SD_destroy_ (struct SDHandle *h); | ||
54 | |||
55 | |||
56 | /** | ||
57 | * Add a reading to SD | ||
58 | * | ||
59 | * @param h the SD handle | ||
60 | * @param amount the reading value | ||
61 | */ | ||
62 | void | ||
63 | GNUNET_TESTBED_SD_add_data_ (struct SDHandle *h, unsigned int amount); | ||
64 | |||
65 | |||
66 | /** | ||
67 | * Returns the factor by which the given amount differs from the standard deviation | ||
68 | * | ||
69 | * @param h the SDhandle | ||
70 | * @param amount the value for which the deviation is returned | ||
71 | * @param factor the factor by which the given amont differs | ||
72 | * @return the deviation from the average; GNUNET_SYSERR if the deviation cannot | ||
73 | * be calculated OR 0 if the deviation is less than the average; a | ||
74 | * maximum of 4 is returned for deviations equal to or larger than 4 | ||
75 | */ | ||
76 | int | ||
77 | GNUNET_TESTBED_SD_deviation_factor_ (struct SDHandle *h, unsigned int amount, | ||
78 | int *factor); | ||
79 | |||
80 | #endif | ||
81 | /* end of testbed_api.h */ | ||
diff --git a/src/testbed/testbed_api_services.c b/src/testbed/testbed_api_services.c deleted file mode 100644 index 2c9a90fd4..000000000 --- a/src/testbed/testbed_api_services.c +++ /dev/null | |||
@@ -1,291 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_services.c | ||
23 | * @brief convenience functions for accessing services | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "testbed_api.h" | ||
28 | #include "testbed_api_peers.h" | ||
29 | #include "testbed_api_operations.h" | ||
30 | |||
31 | |||
32 | /** | ||
33 | * States for Service connect operations | ||
34 | */ | ||
35 | enum State | ||
36 | { | ||
37 | /** | ||
38 | * Initial state | ||
39 | */ | ||
40 | INIT, | ||
41 | |||
42 | /** | ||
43 | * The configuration request has been sent | ||
44 | */ | ||
45 | CFG_REQUEST_QUEUED, | ||
46 | |||
47 | /** | ||
48 | * connected to service | ||
49 | */ | ||
50 | SERVICE_CONNECTED | ||
51 | }; | ||
52 | |||
53 | |||
54 | /** | ||
55 | * Data accessed during service connections | ||
56 | */ | ||
57 | struct ServiceConnectData | ||
58 | { | ||
59 | /** | ||
60 | * helper function callback to establish the connection | ||
61 | */ | ||
62 | GNUNET_TESTBED_ConnectAdapter ca; | ||
63 | |||
64 | /** | ||
65 | * helper function callback to close the connection | ||
66 | */ | ||
67 | GNUNET_TESTBED_DisconnectAdapter da; | ||
68 | |||
69 | /** | ||
70 | * Closure to the above callbacks | ||
71 | */ | ||
72 | void *cada_cls; | ||
73 | |||
74 | /** | ||
75 | * Service name | ||
76 | */ | ||
77 | char *service_name; | ||
78 | |||
79 | /** | ||
80 | * Closure for operation event | ||
81 | */ | ||
82 | void *op_cls; | ||
83 | |||
84 | /** | ||
85 | * The operation which created this structure | ||
86 | */ | ||
87 | struct GNUNET_TESTBED_Operation *operation; | ||
88 | |||
89 | /** | ||
90 | * The operation context from GNUNET_TESTBED_forward_operation_msg_() | ||
91 | */ | ||
92 | struct OperationContext *opc; | ||
93 | |||
94 | /** | ||
95 | * The peer handle | ||
96 | */ | ||
97 | struct GNUNET_TESTBED_Peer *peer; | ||
98 | |||
99 | /** | ||
100 | * The acquired configuration of the peer | ||
101 | */ | ||
102 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
103 | |||
104 | /** | ||
105 | * The op_result pointer from ConnectAdapter | ||
106 | */ | ||
107 | void *op_result; | ||
108 | |||
109 | /** | ||
110 | * The operation completion callback | ||
111 | */ | ||
112 | GNUNET_TESTBED_ServiceConnectCompletionCallback cb; | ||
113 | |||
114 | /** | ||
115 | * The closure for operation completion callback | ||
116 | */ | ||
117 | void *cb_cls; | ||
118 | |||
119 | /** | ||
120 | * State information | ||
121 | */ | ||
122 | enum State state; | ||
123 | }; | ||
124 | |||
125 | |||
126 | /** | ||
127 | * Type of a function to call when we receive a message | ||
128 | * from the service. | ||
129 | * | ||
130 | * @param cls ServiceConnectData | ||
131 | * @param msg message received, NULL on timeout or fatal error | ||
132 | */ | ||
133 | static void | ||
134 | configuration_receiver (void *cls, const struct GNUNET_MessageHeader *msg) | ||
135 | { | ||
136 | struct ServiceConnectData *data = cls; | ||
137 | struct GNUNET_TESTBED_Controller *c; | ||
138 | const char *emsg; | ||
139 | struct GNUNET_TESTBED_EventInformation info; | ||
140 | uint16_t mtype; | ||
141 | |||
142 | c = data->peer->controller; | ||
143 | mtype = ntohs (msg->type); | ||
144 | emsg = NULL; | ||
145 | info.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; | ||
146 | info.op = data->operation; | ||
147 | info.op_cls = data->op_cls; | ||
148 | if (GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT == mtype) | ||
149 | { | ||
150 | emsg = | ||
151 | GNUNET_TESTBED_parse_error_string_ ((const struct | ||
152 | GNUNET_TESTBED_OperationFailureEventMessage | ||
153 | *) msg); | ||
154 | if (NULL == emsg) | ||
155 | emsg = "Unknown error"; | ||
156 | info.details.operation_finished.emsg = emsg; | ||
157 | info.details.operation_finished.generic = NULL; | ||
158 | goto call_cb; | ||
159 | } | ||
160 | data->cfg = GNUNET_TESTBED_extract_config_ (msg); | ||
161 | GNUNET_assert (NULL == data->op_result); | ||
162 | data->op_result = data->ca (data->cada_cls, data->cfg); | ||
163 | info.details.operation_finished.emsg = NULL; | ||
164 | info.details.operation_finished.generic = data->op_result; | ||
165 | data->state = SERVICE_CONNECTED; | ||
166 | |||
167 | call_cb: | ||
168 | if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) && | ||
169 | (NULL != c->cc)) | ||
170 | c->cc (c->cc_cls, &info); | ||
171 | if (NULL != data->cb) | ||
172 | data->cb (data->cb_cls, data->operation, data->op_result, emsg); | ||
173 | } | ||
174 | |||
175 | |||
176 | /** | ||
177 | * Function called when a service connect operation is ready | ||
178 | * | ||
179 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
180 | */ | ||
181 | static void | ||
182 | opstart_service_connect (void *cls) | ||
183 | { | ||
184 | struct ServiceConnectData *data = cls; | ||
185 | struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; | ||
186 | struct GNUNET_TESTBED_Controller *c; | ||
187 | uint64_t op_id; | ||
188 | |||
189 | GNUNET_assert (NULL != data); | ||
190 | GNUNET_assert (NULL != data->peer); | ||
191 | c = data->peer->controller; | ||
192 | op_id = GNUNET_TESTBED_get_next_op_id (c); | ||
193 | msg = | ||
194 | GNUNET_TESTBED_generate_peergetconfig_msg_ (data->peer->unique_id, op_id); | ||
195 | data->opc = | ||
196 | GNUNET_TESTBED_forward_operation_msg_ (c, op_id, &msg->header, | ||
197 | &configuration_receiver, data); | ||
198 | GNUNET_free (msg); | ||
199 | data->state = CFG_REQUEST_QUEUED; | ||
200 | } | ||
201 | |||
202 | |||
203 | /** | ||
204 | * Callback which will be called when service connect type operation is | ||
205 | * released | ||
206 | * | ||
207 | * @param cls the closure from GNUNET_TESTBED_operation_create_() | ||
208 | */ | ||
209 | static void | ||
210 | oprelease_service_connect (void *cls) | ||
211 | { | ||
212 | struct ServiceConnectData *data = cls; | ||
213 | |||
214 | switch (data->state) | ||
215 | { | ||
216 | case INIT: | ||
217 | break; | ||
218 | |||
219 | case CFG_REQUEST_QUEUED: | ||
220 | GNUNET_assert (NULL != data->opc); | ||
221 | GNUNET_TESTBED_forward_operation_msg_cancel_ (data->opc); | ||
222 | break; | ||
223 | |||
224 | case SERVICE_CONNECTED: | ||
225 | GNUNET_assert (NULL != data->cfg); | ||
226 | GNUNET_CONFIGURATION_destroy (data->cfg); | ||
227 | if (NULL != data->da) | ||
228 | data->da (data->cada_cls, data->op_result); | ||
229 | break; | ||
230 | } | ||
231 | GNUNET_free (data); | ||
232 | } | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Connect to a service offered by the given peer. Will ensure that | ||
237 | * the request is queued to not overwhelm our ability to create and | ||
238 | * maintain connections with other systems. The actual service | ||
239 | * handle is then returned via the 'op_result' member in the event | ||
240 | * callback. The 'ca' callback is used to create the connection | ||
241 | * when the time is right; the 'da' callback will be used to | ||
242 | * destroy the connection (upon 'GNUNET_TESTBED_operation_done'). | ||
243 | * 'GNUNET_TESTBED_operation_done' can be used to abort this | ||
244 | * operation until the event callback has been called. | ||
245 | * | ||
246 | * @param op_cls closure to pass in operation event | ||
247 | * @param peer peer that runs the service | ||
248 | * @param service_name name of the service to connect to | ||
249 | * @param cb the callback to call when this operation finishes | ||
250 | * @param cb_cls closure for the above callback | ||
251 | * @param ca helper function to establish the connection | ||
252 | * @param da helper function to close the connection | ||
253 | * @param cada_cls closure for ca and da | ||
254 | * @return handle for the operation | ||
255 | */ | ||
256 | struct GNUNET_TESTBED_Operation * | ||
257 | GNUNET_TESTBED_service_connect (void *op_cls, struct GNUNET_TESTBED_Peer *peer, | ||
258 | const char *service_name, | ||
259 | GNUNET_TESTBED_ServiceConnectCompletionCallback | ||
260 | cb, void *cb_cls, | ||
261 | GNUNET_TESTBED_ConnectAdapter ca, | ||
262 | GNUNET_TESTBED_DisconnectAdapter da, | ||
263 | void *cada_cls) | ||
264 | { | ||
265 | struct ServiceConnectData *data; | ||
266 | |||
267 | data = GNUNET_new (struct ServiceConnectData); | ||
268 | data->ca = ca; | ||
269 | data->da = da; | ||
270 | data->cada_cls = cada_cls; | ||
271 | data->op_cls = op_cls; | ||
272 | data->peer = peer; | ||
273 | data->state = INIT; | ||
274 | data->cb = cb; | ||
275 | data->cb_cls = cb_cls; | ||
276 | data->operation = | ||
277 | GNUNET_TESTBED_operation_create_ (data, &opstart_service_connect, | ||
278 | &oprelease_service_connect); | ||
279 | GNUNET_TESTBED_operation_queue_insert_ (peer-> | ||
280 | controller-> | ||
281 | opq_parallel_service_connections, | ||
282 | data->operation); | ||
283 | GNUNET_TESTBED_operation_queue_insert_ (peer-> | ||
284 | controller->opq_parallel_operations, | ||
285 | data->operation); | ||
286 | GNUNET_TESTBED_operation_begin_wait_ (data->operation); | ||
287 | return data->operation; | ||
288 | } | ||
289 | |||
290 | |||
291 | /* end of testbed_api_services.c */ | ||
diff --git a/src/testbed/testbed_api_statistics.c b/src/testbed/testbed_api_statistics.c deleted file mode 100644 index e800baa73..000000000 --- a/src/testbed/testbed_api_statistics.c +++ /dev/null | |||
@@ -1,435 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_statistics.c | ||
23 | * @brief high-level statistics function | ||
24 | * @author Christian Grothoff | ||
25 | * @author Sree Harsha Totakura | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | |||
31 | #include "testbed_api_operations.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Generic logging shorthand | ||
36 | */ | ||
37 | #define LOG(kind, ...) \ | ||
38 | GNUNET_log_from (kind, "testbed-api-statistics", __VA_ARGS__) | ||
39 | |||
40 | /** | ||
41 | * Debug logging shorthand | ||
42 | */ | ||
43 | #define LOG_DEBUG(...) \ | ||
44 | LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Context information for use in GNUNET_TESTBED_get_statistics() | ||
49 | */ | ||
50 | struct GetStatsContext | ||
51 | { | ||
52 | /** | ||
53 | * The main operation we generate while creating this context | ||
54 | */ | ||
55 | struct GNUNET_TESTBED_Operation *main_op; | ||
56 | |||
57 | /** | ||
58 | * The service connect operations we create to open connection to the | ||
59 | * statistics service of each given peer | ||
60 | */ | ||
61 | struct GNUNET_TESTBED_Operation **ops; | ||
62 | |||
63 | /** | ||
64 | * The array of peers whose statistics services are to be accessed | ||
65 | */ | ||
66 | struct GNUNET_TESTBED_Peer **peers; | ||
67 | |||
68 | /** | ||
69 | * The subsystem of peers for which statistics are requested | ||
70 | */ | ||
71 | char *subsystem; | ||
72 | |||
73 | /** | ||
74 | * The particular statistics value of interest | ||
75 | */ | ||
76 | char *name; | ||
77 | |||
78 | /** | ||
79 | * The iterator to call with statistics information | ||
80 | */ | ||
81 | GNUNET_TESTBED_StatisticsIterator proc; | ||
82 | |||
83 | /** | ||
84 | * The callback to call when we are done iterating through all peers' | ||
85 | * statistics services | ||
86 | */ | ||
87 | GNUNET_TESTBED_OperationCompletionCallback cont; | ||
88 | |||
89 | /** | ||
90 | * The closure for the above callbacks | ||
91 | */ | ||
92 | void *cb_cls; | ||
93 | |||
94 | /** | ||
95 | * The task for calling the continuation callback | ||
96 | */ | ||
97 | struct GNUNET_SCHEDULER_Task *call_completion_task_id; | ||
98 | |||
99 | /** | ||
100 | * The number of peers present in the peers array. This number also | ||
101 | * represents the number of service connect operations in the ops array | ||
102 | */ | ||
103 | unsigned int num_peers; | ||
104 | |||
105 | /** | ||
106 | * How many peers' statistics have we iterated through | ||
107 | */ | ||
108 | unsigned int num_completed; | ||
109 | }; | ||
110 | |||
111 | |||
112 | /** | ||
113 | * Context information with respect to a particular peer | ||
114 | */ | ||
115 | struct PeerGetStatsContext | ||
116 | { | ||
117 | /** | ||
118 | * The GetStatsContext which is associated with this context | ||
119 | */ | ||
120 | struct GetStatsContext *sc; | ||
121 | |||
122 | /** | ||
123 | * The handle from GNUNET_STATISTICS_get() | ||
124 | */ | ||
125 | struct GNUNET_STATISTICS_GetHandle *get_handle; | ||
126 | |||
127 | /** | ||
128 | * Task to mark the statistics service connect operation as done | ||
129 | */ | ||
130 | struct GNUNET_SCHEDULER_Task *op_done_task_id; | ||
131 | |||
132 | /** | ||
133 | * The index of this peer in the peers array of GetStatsContext | ||
134 | */ | ||
135 | unsigned int peer_index; | ||
136 | }; | ||
137 | |||
138 | |||
139 | /** | ||
140 | * A no-wait operation queue | ||
141 | */ | ||
142 | static struct OperationQueue *no_wait_queue; | ||
143 | |||
144 | |||
145 | /** | ||
146 | * Call statistics operation completion. We call it in a separate task because | ||
147 | * the iteration_completion_cb() cannot destroy statistics handle which will be | ||
148 | * the case if the user calls GNUNET_TESTBED_operation_done() on the | ||
149 | * get_statistics operation. | ||
150 | * | ||
151 | * @param cls the GetStatsContext | ||
152 | */ | ||
153 | static void | ||
154 | call_completion_task (void *cls) | ||
155 | { | ||
156 | struct GetStatsContext *sc = cls; | ||
157 | |||
158 | GNUNET_assert (sc->call_completion_task_id != NULL); | ||
159 | sc->call_completion_task_id = NULL; | ||
160 | LOG_DEBUG ("Calling get_statistics() continuation callback\n"); | ||
161 | sc->cont (sc->cb_cls, sc->main_op, NULL); | ||
162 | } | ||
163 | |||
164 | |||
165 | /** | ||
166 | * Task to mark statistics service connect operation as done. We call it here | ||
167 | * as we cannot destroy the statistics handle in iteration_completion_cb() | ||
168 | * | ||
169 | * @param cls the PeerGetStatsContext | ||
170 | */ | ||
171 | static void | ||
172 | op_done_task (void *cls) | ||
173 | { | ||
174 | struct PeerGetStatsContext *peer_sc = cls; | ||
175 | struct GetStatsContext *sc; | ||
176 | struct GNUNET_TESTBED_Operation **op; | ||
177 | |||
178 | sc = peer_sc->sc; | ||
179 | peer_sc->op_done_task_id = NULL; | ||
180 | op = &sc->ops[peer_sc->peer_index]; | ||
181 | GNUNET_assert (NULL != *op); | ||
182 | GNUNET_TESTBED_operation_done (*op); | ||
183 | *op = NULL; | ||
184 | } | ||
185 | |||
186 | |||
187 | /** | ||
188 | * Continuation called by the "get_all" and "get" functions. | ||
189 | * | ||
190 | * @param cls the PeerGetStatsContext | ||
191 | * @param success GNUNET_OK if statistics were | ||
192 | * successfully obtained, GNUNET_SYSERR if not. | ||
193 | */ | ||
194 | static void | ||
195 | iteration_completion_cb (void *cls, int success) | ||
196 | { | ||
197 | struct PeerGetStatsContext *peer_sc = cls; | ||
198 | struct GetStatsContext *sc; | ||
199 | |||
200 | GNUNET_break (GNUNET_OK == success); | ||
201 | sc = peer_sc->sc; | ||
202 | peer_sc->get_handle = NULL; | ||
203 | sc->num_completed++; | ||
204 | peer_sc->op_done_task_id = GNUNET_SCHEDULER_add_now (&op_done_task, peer_sc); | ||
205 | if (sc->num_completed == sc->num_peers) | ||
206 | { | ||
207 | LOG_DEBUG ("Scheduling to call iteration completion callback\n"); | ||
208 | sc->call_completion_task_id = | ||
209 | GNUNET_SCHEDULER_add_now (&call_completion_task, sc); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | |||
214 | /** | ||
215 | * Callback function to process statistic values. | ||
216 | * | ||
217 | * @param cls the PeerGetStatsContext | ||
218 | * @param subsystem name of subsystem that created the statistic | ||
219 | * @param name the name of the datum | ||
220 | * @param value the current value | ||
221 | * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not | ||
222 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | ||
223 | */ | ||
224 | static int | ||
225 | iterator_cb (void *cls, const char *subsystem, | ||
226 | const char *name, uint64_t value, | ||
227 | int is_persistent) | ||
228 | { | ||
229 | struct PeerGetStatsContext *peer_sc = cls; | ||
230 | struct GetStatsContext *sc; | ||
231 | struct GNUNET_TESTBED_Peer *peer; | ||
232 | int ret; | ||
233 | |||
234 | sc = peer_sc->sc; | ||
235 | peer = sc->peers[peer_sc->peer_index]; | ||
236 | LOG_DEBUG ("Peer %u: [%s,%s] -> %lu\n", peer_sc->peer_index, | ||
237 | subsystem, name, (unsigned long) value); | ||
238 | ret = sc->proc (sc->cb_cls, peer, | ||
239 | subsystem, name, value, is_persistent); | ||
240 | if (GNUNET_SYSERR == ret) | ||
241 | LOG_DEBUG ("Aborting iteration for peer %u\n", peer_sc->peer_index); | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | |||
246 | /** | ||
247 | * Called after opening a connection to the statistics service of a peer | ||
248 | * | ||
249 | * @param cls the PeerGetStatsContext | ||
250 | * @param op the operation that has been finished | ||
251 | * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() | ||
252 | * @param emsg error message in case the operation has failed; will be NULL if | ||
253 | * operation has executed successfully. | ||
254 | */ | ||
255 | static void | ||
256 | service_connect_comp (void *cls, | ||
257 | struct GNUNET_TESTBED_Operation *op, | ||
258 | void *ca_result, | ||
259 | const char *emsg) | ||
260 | { | ||
261 | struct PeerGetStatsContext *peer_sc = cls; | ||
262 | struct GNUNET_STATISTICS_Handle *h = ca_result; | ||
263 | |||
264 | LOG_DEBUG ("Retrieving statistics of peer %u\n", | ||
265 | peer_sc->peer_index); | ||
266 | peer_sc->get_handle = | ||
267 | GNUNET_STATISTICS_get (h, peer_sc->sc->subsystem, | ||
268 | peer_sc->sc->name, | ||
269 | &iteration_completion_cb, | ||
270 | iterator_cb, peer_sc); | ||
271 | } | ||
272 | |||
273 | |||
274 | /** | ||
275 | * Adapter function called to establish a connection to the statistics service | ||
276 | * of a peer. | ||
277 | * | ||
278 | * @param cls the PeerGetStatsContext | ||
279 | * @param cfg configuration of the peer to connect to; will be available until | ||
280 | * GNUNET_TESTBED_operation_done() is called on the operation returned | ||
281 | * from GNUNET_TESTBED_service_connect() | ||
282 | * @return service handle to return in 'op_result', NULL on error | ||
283 | */ | ||
284 | static void * | ||
285 | statistics_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
286 | { | ||
287 | struct PeerGetStatsContext *peer_sc = cls; | ||
288 | |||
289 | LOG_DEBUG ("Connecting to statistics service of peer %u\n", | ||
290 | peer_sc->peer_index); | ||
291 | return GNUNET_STATISTICS_create ("<testbed-api>", cfg); | ||
292 | } | ||
293 | |||
294 | |||
295 | /** | ||
296 | * Adapter function called to destroy statistics connection | ||
297 | * | ||
298 | * @param cls the PeerGetStatsContext | ||
299 | * @param op_result service handle returned from the connect adapter | ||
300 | */ | ||
301 | static void | ||
302 | statistics_da (void *cls, void *op_result) | ||
303 | { | ||
304 | struct PeerGetStatsContext *peer_sc = cls; | ||
305 | struct GNUNET_STATISTICS_Handle *sh = op_result; | ||
306 | |||
307 | if (NULL != peer_sc->get_handle) | ||
308 | { | ||
309 | GNUNET_STATISTICS_get_cancel (peer_sc->get_handle); | ||
310 | peer_sc->get_handle = NULL; | ||
311 | } | ||
312 | GNUNET_STATISTICS_destroy (sh, GNUNET_NO); | ||
313 | if (NULL != peer_sc->op_done_task_id) | ||
314 | GNUNET_SCHEDULER_cancel (peer_sc->op_done_task_id); | ||
315 | GNUNET_free (peer_sc); | ||
316 | } | ||
317 | |||
318 | |||
319 | /** | ||
320 | * Function called when get_statistics operation is ready | ||
321 | * | ||
322 | * @param cls the GetStatsContext | ||
323 | */ | ||
324 | static void | ||
325 | opstart_get_stats (void *cls) | ||
326 | { | ||
327 | struct GetStatsContext *sc = cls; | ||
328 | struct PeerGetStatsContext *peer_sc; | ||
329 | unsigned int peer; | ||
330 | |||
331 | LOG_DEBUG ("Starting get_statistics operation\n"); | ||
332 | sc->ops = GNUNET_malloc (sc->num_peers | ||
333 | * sizeof(struct GNUNET_TESTBED_Operation *)); | ||
334 | for (peer = 0; peer < sc->num_peers; peer++) | ||
335 | { | ||
336 | if (NULL == sc->peers[peer]) | ||
337 | { | ||
338 | GNUNET_break (0); | ||
339 | continue; | ||
340 | } | ||
341 | peer_sc = GNUNET_new (struct PeerGetStatsContext); | ||
342 | peer_sc->sc = sc; | ||
343 | peer_sc->peer_index = peer; | ||
344 | sc->ops[peer] = | ||
345 | GNUNET_TESTBED_service_connect (sc, sc->peers[peer], "statistics", | ||
346 | &service_connect_comp, | ||
347 | peer_sc, | ||
348 | &statistics_ca, | ||
349 | &statistics_da, | ||
350 | peer_sc); | ||
351 | } | ||
352 | } | ||
353 | |||
354 | |||
355 | /** | ||
356 | * Function called when get_statistics operation is cancelled or marked as done | ||
357 | * | ||
358 | * @param cls the GetStatsContext | ||
359 | */ | ||
360 | static void | ||
361 | oprelease_get_stats (void *cls) | ||
362 | { | ||
363 | struct GetStatsContext *sc = cls; | ||
364 | unsigned int peer; | ||
365 | |||
366 | LOG_DEBUG ("Cleaning up get_statistics operation\n"); | ||
367 | if (NULL != sc->call_completion_task_id) | ||
368 | GNUNET_SCHEDULER_cancel (sc->call_completion_task_id); | ||
369 | if (NULL != sc->ops) | ||
370 | { | ||
371 | for (peer = 0; peer < sc->num_peers; peer++) | ||
372 | { | ||
373 | if (NULL != sc->ops[peer]) | ||
374 | { | ||
375 | GNUNET_TESTBED_operation_done (sc->ops[peer]); | ||
376 | sc->ops[peer] = NULL; | ||
377 | } | ||
378 | } | ||
379 | GNUNET_free (sc->ops); | ||
380 | } | ||
381 | GNUNET_free (sc->subsystem); | ||
382 | GNUNET_free (sc->name); | ||
383 | GNUNET_free (sc); | ||
384 | if (GNUNET_YES == | ||
385 | GNUNET_TESTBED_operation_queue_destroy_empty_ (no_wait_queue)) | ||
386 | no_wait_queue = NULL; | ||
387 | } | ||
388 | |||
389 | |||
390 | /** | ||
391 | * Convenience method that iterates over all (running) peers | ||
392 | * and retrieves all statistics from each peer. | ||
393 | * | ||
394 | * @param num_peers number of peers to iterate over | ||
395 | * @param peers array of peers to iterate over | ||
396 | * @param subsystem limit to the specified subsystem, NULL for all subsystems | ||
397 | * @param name name of the statistic value, NULL for all values | ||
398 | * @param proc processing function for each statistic retrieved | ||
399 | * @param cont continuation to call once call is completed(?) | ||
400 | * @param cls closure to pass to proc and cont | ||
401 | * @return operation handle to cancel the operation | ||
402 | */ | ||
403 | struct GNUNET_TESTBED_Operation * | ||
404 | GNUNET_TESTBED_get_statistics (unsigned int num_peers, | ||
405 | struct GNUNET_TESTBED_Peer **peers, | ||
406 | const char *subsystem, const char *name, | ||
407 | GNUNET_TESTBED_StatisticsIterator proc, | ||
408 | GNUNET_TESTBED_OperationCompletionCallback cont, | ||
409 | void *cls) | ||
410 | { | ||
411 | struct GetStatsContext *sc; | ||
412 | |||
413 | GNUNET_assert (NULL != proc); | ||
414 | GNUNET_assert (NULL != cont); | ||
415 | if (NULL == no_wait_queue) | ||
416 | no_wait_queue = GNUNET_TESTBED_operation_queue_create_ | ||
417 | (OPERATION_QUEUE_TYPE_FIXED, UINT_MAX); | ||
418 | sc = GNUNET_new (struct GetStatsContext); | ||
419 | sc->peers = peers; | ||
420 | sc->subsystem = (NULL == subsystem) ? NULL : GNUNET_strdup (subsystem); | ||
421 | sc->name = (NULL == name) ? NULL : GNUNET_strdup (name); | ||
422 | sc->proc = proc; | ||
423 | sc->cont = cont; | ||
424 | sc->cb_cls = cls; | ||
425 | sc->num_peers = num_peers; | ||
426 | sc->main_op = | ||
427 | GNUNET_TESTBED_operation_create_ (sc, &opstart_get_stats, | ||
428 | &oprelease_get_stats); | ||
429 | GNUNET_TESTBED_operation_queue_insert_ (no_wait_queue, sc->main_op); | ||
430 | GNUNET_TESTBED_operation_begin_wait_ (sc->main_op); | ||
431 | return sc->main_op; | ||
432 | } | ||
433 | |||
434 | |||
435 | /* end of testbed_api_statistics.c */ | ||
diff --git a/src/testbed/testbed_api_test.c b/src/testbed/testbed_api_test.c deleted file mode 100644 index d9eb384ba..000000000 --- a/src/testbed/testbed_api_test.c +++ /dev/null | |||
@@ -1,175 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_test.c | ||
23 | * @brief high-level test function | ||
24 | * @author Christian Grothoff | ||
25 | * @author Sree Harsha Totakura | ||
26 | * @author Tobias Frisch | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | #include "testbed.h" | ||
31 | |||
32 | |||
33 | /** | ||
34 | * Context information for test run | ||
35 | */ | ||
36 | struct TestRunContext | ||
37 | { | ||
38 | /** | ||
39 | * Test master callback | ||
40 | */ | ||
41 | GNUNET_TESTBED_TestMaster test_master; | ||
42 | |||
43 | /** | ||
44 | * Closure for test master | ||
45 | */ | ||
46 | void *test_master_cls; | ||
47 | |||
48 | /** | ||
49 | * The controller event callback | ||
50 | */ | ||
51 | GNUNET_TESTBED_ControllerCallback cc; | ||
52 | |||
53 | /** | ||
54 | * Closure for the above callback | ||
55 | */ | ||
56 | void *cc_cls; | ||
57 | |||
58 | /** | ||
59 | * event mask for the controller callback | ||
60 | */ | ||
61 | uint64_t event_mask; | ||
62 | |||
63 | /** | ||
64 | * Number of peers to start | ||
65 | */ | ||
66 | unsigned int num_peers; | ||
67 | }; | ||
68 | |||
69 | |||
70 | /** | ||
71 | * Main run function. | ||
72 | * | ||
73 | * @param cls NULL | ||
74 | * @param args arguments passed to GNUNET_PROGRAM_run | ||
75 | * @param cfgfile the path to configuration file | ||
76 | * @param config the configuration file handle | ||
77 | */ | ||
78 | static void | ||
79 | run (void *cls, char *const *args, const char *cfgfile, | ||
80 | const struct GNUNET_CONFIGURATION_Handle *config) | ||
81 | { | ||
82 | struct TestRunContext *rc = cls; | ||
83 | |||
84 | GNUNET_TESTBED_run (NULL, config, rc->num_peers, rc->event_mask, rc->cc, | ||
85 | rc->cc_cls, rc->test_master, rc->test_master_cls); | ||
86 | } | ||
87 | |||
88 | |||
89 | /** | ||
90 | * Convenience method for running a "simple" test on the local system | ||
91 | * with a single call from 'main'. Underlay and overlay topology are | ||
92 | * configured using the "UNDERLAY" and "OVERLAY" options in the | ||
93 | * "[testbed]" section of the configuration (with possible options | ||
94 | * given in "UNDERLAY_XXX" and/or "OVERLAY_XXX"). | ||
95 | * | ||
96 | * The test is to be terminated using a call to | ||
97 | * "GNUNET_SCHEDULER_shutdown". If starting the test fails, | ||
98 | * the program is stopped without 'master' ever being run. | ||
99 | * | ||
100 | * NOTE: this function should be called from 'main', NOT from | ||
101 | * within a GNUNET_SCHEDULER-loop. This function will initialize | ||
102 | * the scheduler loop, the testbed and then pass control to | ||
103 | * 'master'. | ||
104 | * | ||
105 | * @param testname name of the testcase (to configure logging, etc.) | ||
106 | * @param cfg_filename configuration filename to use | ||
107 | * (for testbed, controller and peers) | ||
108 | * @param num_peers number of peers to start | ||
109 | * @param event_mask bit mask with set of events to call 'cc' for; | ||
110 | * or-ed values of "1LL" shifted by the | ||
111 | * respective 'enum GNUNET_TESTBED_EventType' | ||
112 | * (e.g. "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...") | ||
113 | * @param cc controller callback to invoke on events; This callback is called | ||
114 | * for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't | ||
115 | * set in the event_mask as this is the only way get access to the | ||
116 | * handle of each peer | ||
117 | * @param cc_cls closure for cc | ||
118 | * @param test_master task to run once the test is ready | ||
119 | * @param test_master_cls closure for @a test_master | ||
120 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
121 | */ | ||
122 | int | ||
123 | GNUNET_TESTBED_test_run (const char *testname, | ||
124 | const char *cfg_filename, | ||
125 | unsigned int num_peers, | ||
126 | uint64_t event_mask, | ||
127 | GNUNET_TESTBED_ControllerCallback cc, | ||
128 | void *cc_cls, | ||
129 | GNUNET_TESTBED_TestMaster test_master, | ||
130 | void *test_master_cls) | ||
131 | { | ||
132 | char *argv2[] = { | ||
133 | NULL, | ||
134 | "-c", | ||
135 | NULL, | ||
136 | NULL | ||
137 | }; | ||
138 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
139 | GNUNET_GETOPT_OPTION_END | ||
140 | }; | ||
141 | struct TestRunContext *rc; | ||
142 | int ret; | ||
143 | |||
144 | argv2[0] = GNUNET_strdup (testname); | ||
145 | argv2[2] = GNUNET_strdup (cfg_filename); | ||
146 | GNUNET_assert (NULL != test_master); | ||
147 | GNUNET_assert (num_peers > 0); | ||
148 | |||
149 | char* envcfg = getenv(ENV_TESTBED_CONFIG); | ||
150 | setenv(ENV_TESTBED_CONFIG, cfg_filename, 1); | ||
151 | |||
152 | rc = GNUNET_malloc (sizeof(struct TestRunContext) | ||
153 | + (num_peers * sizeof(struct GNUNET_TESTBED_Peer *))); | ||
154 | rc->test_master = test_master; | ||
155 | rc->test_master_cls = test_master_cls; | ||
156 | rc->num_peers = num_peers; | ||
157 | rc->event_mask = event_mask; | ||
158 | rc->cc = cc; | ||
159 | rc->cc_cls = cc_cls; | ||
160 | ret = GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, | ||
161 | testname, "nohelp", options, &run, rc); | ||
162 | |||
163 | if (envcfg) | ||
164 | setenv(ENV_TESTBED_CONFIG, envcfg, 1); | ||
165 | else | ||
166 | unsetenv(ENV_TESTBED_CONFIG); | ||
167 | |||
168 | GNUNET_free (rc); | ||
169 | GNUNET_free (argv2[0]); | ||
170 | GNUNET_free (argv2[2]); | ||
171 | return ret; | ||
172 | } | ||
173 | |||
174 | |||
175 | /* end of testbed_api_test.c */ | ||
diff --git a/src/testbed/testbed_api_testbed.c b/src/testbed/testbed_api_testbed.c deleted file mode 100644 index e0b76ad78..000000000 --- a/src/testbed/testbed_api_testbed.c +++ /dev/null | |||
@@ -1,1472 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_testbed.c | ||
23 | * @brief high-level testbed management | ||
24 | * @author Christian Grothoff | ||
25 | * @author Sree Harsha Totakura | ||
26 | */ | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_testbed_service.h" | ||
31 | #include "testbed_api.h" | ||
32 | #include "testbed_api_peers.h" | ||
33 | #include "testbed_api_hosts.h" | ||
34 | #include "testbed_api_topology.h" | ||
35 | |||
36 | /** | ||
37 | * Generic loggins shorthand | ||
38 | */ | ||
39 | #define LOG(kind, ...) \ | ||
40 | GNUNET_log_from (kind, "testbed-api-testbed", __VA_ARGS__) | ||
41 | |||
42 | /** | ||
43 | * Debug logging shortcut | ||
44 | */ | ||
45 | #define DEBUG(...) \ | ||
46 | LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) | ||
47 | |||
48 | /** | ||
49 | * The default setup timeout in seconds | ||
50 | */ | ||
51 | #define DEFAULT_SETUP_TIMEOUT 300 | ||
52 | |||
53 | |||
54 | /** | ||
55 | * Configuration section for testbed | ||
56 | */ | ||
57 | #define TESTBED_CONFIG_SECTION "testbed" | ||
58 | |||
59 | /** | ||
60 | * Option string for the maximum number of edges a peer is permitted to have | ||
61 | * while generating scale free topology | ||
62 | */ | ||
63 | #define SCALE_FREE_CAP "SCALE_FREE_TOPOLOGY_CAP" | ||
64 | |||
65 | /** | ||
66 | * Option string for the number of edges to be established when adding a new | ||
67 | * node to the scale free network | ||
68 | */ | ||
69 | #define SCALE_FREE_M "SCALE_FREE_TOPOLOGY_M" | ||
70 | |||
71 | /** | ||
72 | * Context information for the operation we start | ||
73 | */ | ||
74 | struct RunContextOperation | ||
75 | { | ||
76 | /** | ||
77 | * The testbed operation handle | ||
78 | */ | ||
79 | struct GNUNET_TESTBED_Operation *op; | ||
80 | |||
81 | /** | ||
82 | * Context information for GNUNET_TESTBED_run() | ||
83 | */ | ||
84 | struct GNUNET_TESTBED_RunHandle *rc; | ||
85 | |||
86 | /** | ||
87 | * Closure | ||
88 | */ | ||
89 | void *cls; | ||
90 | }; | ||
91 | |||
92 | |||
93 | /** | ||
94 | * States of RunContext | ||
95 | */ | ||
96 | enum State | ||
97 | { | ||
98 | /** | ||
99 | * Initial state | ||
100 | */ | ||
101 | RC_INIT = 0, | ||
102 | |||
103 | /** | ||
104 | * Controllers on given hosts started and linked | ||
105 | */ | ||
106 | RC_LINKED, | ||
107 | |||
108 | /** | ||
109 | * Peers are created | ||
110 | */ | ||
111 | RC_PEERS_CREATED, | ||
112 | |||
113 | /** | ||
114 | * The testbed run is ready and the master callback can be called now. At this | ||
115 | * time the peers are all started and if a topology is provided in the | ||
116 | * configuration the topology would have been attempted | ||
117 | */ | ||
118 | RC_READY, | ||
119 | |||
120 | /* /\** */ | ||
121 | /* * Peers are stopped */ | ||
122 | /* *\/ */ | ||
123 | /* RC_PEERS_STOPPED, */ | ||
124 | |||
125 | /* /\** */ | ||
126 | /* * Peers are destroyed */ | ||
127 | /* *\/ */ | ||
128 | /* RC_PEERS_DESTROYED */ | ||
129 | |||
130 | /** | ||
131 | * All peers shutdown (stopped and destroyed) | ||
132 | */ | ||
133 | RC_PEERS_SHUTDOWN | ||
134 | }; | ||
135 | |||
136 | |||
137 | /** | ||
138 | * Context for host compatibility checks | ||
139 | */ | ||
140 | struct CompatibilityCheckContext | ||
141 | { | ||
142 | /** | ||
143 | * The run context | ||
144 | */ | ||
145 | struct GNUNET_TESTBED_RunHandle *rc; | ||
146 | |||
147 | /** | ||
148 | * Handle for the compatibility check | ||
149 | */ | ||
150 | struct GNUNET_TESTBED_HostHabitableCheckHandle *h; | ||
151 | |||
152 | /** | ||
153 | * Index of the host in the run context's hosts array | ||
154 | */ | ||
155 | unsigned int index; | ||
156 | }; | ||
157 | |||
158 | |||
159 | /** | ||
160 | * Testbed Run Handle | ||
161 | */ | ||
162 | struct GNUNET_TESTBED_RunHandle | ||
163 | { | ||
164 | /** | ||
165 | * The controller handle | ||
166 | */ | ||
167 | struct GNUNET_TESTBED_Controller *c; | ||
168 | |||
169 | /** | ||
170 | * The configuration of the controller. This is based on the cfg given to the | ||
171 | * function GNUNET_TESTBED_run(). We also use this config as a template while | ||
172 | * for peers | ||
173 | */ | ||
174 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
175 | |||
176 | /** | ||
177 | * Handle to the host on which the controller runs | ||
178 | */ | ||
179 | struct GNUNET_TESTBED_Host *h; | ||
180 | |||
181 | /** | ||
182 | * The handle to the controller process | ||
183 | */ | ||
184 | struct GNUNET_TESTBED_ControllerProc *cproc; | ||
185 | |||
186 | /** | ||
187 | * The callback to use as controller callback | ||
188 | */ | ||
189 | GNUNET_TESTBED_ControllerCallback cc; | ||
190 | |||
191 | /** | ||
192 | * The pointer to the controller callback | ||
193 | */ | ||
194 | void *cc_cls; | ||
195 | |||
196 | /** | ||
197 | * The trusted IP string | ||
198 | */ | ||
199 | char *trusted_ip; | ||
200 | |||
201 | /** | ||
202 | * TestMaster callback to call when testbed initialization is done | ||
203 | */ | ||
204 | GNUNET_TESTBED_TestMaster test_master; | ||
205 | |||
206 | /** | ||
207 | * The closure for the TestMaster callback | ||
208 | */ | ||
209 | void *test_master_cls; | ||
210 | |||
211 | /** | ||
212 | * A hashmap for operations started by us | ||
213 | */ | ||
214 | struct GNUNET_CONTAINER_MultiHashMap32 *rcop_map; | ||
215 | |||
216 | /** | ||
217 | * An array of hosts loaded from the hostkeys file | ||
218 | */ | ||
219 | struct GNUNET_TESTBED_Host **hosts; | ||
220 | |||
221 | /** | ||
222 | * Array of compatibility check contexts | ||
223 | */ | ||
224 | struct CompatibilityCheckContext *hclist; | ||
225 | |||
226 | /** | ||
227 | * Array of peers which we create | ||
228 | */ | ||
229 | struct GNUNET_TESTBED_Peer **peers; | ||
230 | |||
231 | /** | ||
232 | * The topology generation operation. Will be null if no topology is set in | ||
233 | * the configuration | ||
234 | */ | ||
235 | struct GNUNET_TESTBED_Operation *topology_operation; | ||
236 | |||
237 | /** | ||
238 | * The file containing topology data. Only used if the topology is set to 'FROM_FILE' | ||
239 | */ | ||
240 | char *topo_file; | ||
241 | |||
242 | /** | ||
243 | * Host registration handle | ||
244 | */ | ||
245 | struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle; | ||
246 | |||
247 | /** | ||
248 | * Profiling start time | ||
249 | */ | ||
250 | struct GNUNET_TIME_Absolute pstart_time; | ||
251 | |||
252 | /** | ||
253 | * Host registration task | ||
254 | */ | ||
255 | struct GNUNET_SCHEDULER_Task *register_hosts_task; | ||
256 | |||
257 | /** | ||
258 | * Task to be run of a timeout | ||
259 | */ | ||
260 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
261 | |||
262 | /** | ||
263 | * Task run upon shutdown interrupts | ||
264 | */ | ||
265 | struct GNUNET_SCHEDULER_Task *interrupt_task; | ||
266 | |||
267 | /** | ||
268 | * The event mask for the controller | ||
269 | */ | ||
270 | uint64_t event_mask; | ||
271 | |||
272 | /** | ||
273 | * State of this context | ||
274 | */ | ||
275 | enum State state; | ||
276 | |||
277 | /** | ||
278 | * The topology which has to be achieved with the peers started in this context | ||
279 | */ | ||
280 | enum GNUNET_TESTBED_TopologyOption topology; | ||
281 | |||
282 | /** | ||
283 | * Have we already shutdown | ||
284 | */ | ||
285 | int shutdown; | ||
286 | |||
287 | /** | ||
288 | * Number of hosts in the given host file | ||
289 | */ | ||
290 | unsigned int num_hosts; | ||
291 | |||
292 | /** | ||
293 | * Number of registered hosts. Also used as a counter while checking | ||
294 | * habitabillity of hosts | ||
295 | */ | ||
296 | unsigned int reg_hosts; | ||
297 | |||
298 | /** | ||
299 | * Current peer count for an operation; Set this to 0 and increment for each | ||
300 | * successful operation on a peer | ||
301 | */ | ||
302 | unsigned int peer_count; | ||
303 | |||
304 | /** | ||
305 | * number of peers to start | ||
306 | */ | ||
307 | unsigned int num_peers; | ||
308 | |||
309 | /** | ||
310 | * Expected overlay connects. Should be zero if no topology is relevant | ||
311 | */ | ||
312 | unsigned int num_oc; | ||
313 | |||
314 | /** | ||
315 | * Number of random links to established | ||
316 | */ | ||
317 | unsigned int random_links; | ||
318 | |||
319 | /** | ||
320 | * the number of overlay link connection attempts that succeeded | ||
321 | */ | ||
322 | unsigned int links_succeeded; | ||
323 | |||
324 | /** | ||
325 | * the number of overlay link connection attempts that failed | ||
326 | */ | ||
327 | unsigned int links_failed; | ||
328 | }; | ||
329 | |||
330 | |||
331 | /** | ||
332 | * Return a 32-bit key from a pointer | ||
333 | * | ||
334 | * @param rcop the pointer | ||
335 | * @return 32-bit key | ||
336 | */ | ||
337 | static uint32_t | ||
338 | rcop_key (void *rcop) | ||
339 | { | ||
340 | return *((uint32_t *) &rcop); | ||
341 | } | ||
342 | |||
343 | |||
344 | /** | ||
345 | * Context information used for finding a pointer in the rcop_map | ||
346 | */ | ||
347 | struct SearchContext | ||
348 | { | ||
349 | /** | ||
350 | * The operation pointer to look for | ||
351 | */ | ||
352 | struct GNUNET_TESTBED_Operation *query; | ||
353 | |||
354 | /** | ||
355 | * The Run context operation which has the operation being queried | ||
356 | */ | ||
357 | struct RunContextOperation *result; | ||
358 | }; | ||
359 | |||
360 | |||
361 | /** | ||
362 | * Iterator for searching over the elements matching a given query | ||
363 | * | ||
364 | * @param cls the SearchContext | ||
365 | * @param key the 32-bit key | ||
366 | * @param value the RunContextOperation element | ||
367 | * @return GNUNET_YES to continue iteration; GNUNET_NO to cancel it | ||
368 | */ | ||
369 | static int | ||
370 | search_iterator (void *cls, uint32_t key, void *value) | ||
371 | { | ||
372 | struct RunContextOperation *rcop = value; | ||
373 | struct SearchContext *sc = cls; | ||
374 | |||
375 | GNUNET_assert (NULL != rcop); | ||
376 | if (sc->query == rcop->op) | ||
377 | { | ||
378 | GNUNET_assert (NULL == sc->result); | ||
379 | sc->result = rcop; | ||
380 | return GNUNET_NO; | ||
381 | } | ||
382 | return GNUNET_YES; | ||
383 | } | ||
384 | |||
385 | |||
386 | /** | ||
387 | * Initiate a search for the given operation in the rcop_map | ||
388 | * | ||
389 | * @param rc the RunContext whose rcop_map will be searched for the given | ||
390 | * operation | ||
391 | * @param op the given operation to search for | ||
392 | * @return the matching RunContextOperation if found; NULL if not | ||
393 | */ | ||
394 | static struct RunContextOperation * | ||
395 | search_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct | ||
396 | GNUNET_TESTBED_Operation *op) | ||
397 | { | ||
398 | struct SearchContext sc; | ||
399 | |||
400 | sc.query = op; | ||
401 | sc.result = NULL; | ||
402 | if (GNUNET_SYSERR == | ||
403 | GNUNET_CONTAINER_multihashmap32_get_multiple (rc->rcop_map, | ||
404 | rcop_key (op), | ||
405 | &search_iterator, | ||
406 | &sc)) | ||
407 | { | ||
408 | GNUNET_assert (NULL != sc.result); | ||
409 | return sc.result; | ||
410 | } | ||
411 | return NULL; | ||
412 | } | ||
413 | |||
414 | |||
415 | /** | ||
416 | * Insert an RunContextOperation into the rcop_map of the given RunContext | ||
417 | * | ||
418 | * @param rc the RunContext into whose map is to be used for insertion | ||
419 | * @param rcop the RunContextOperation to insert | ||
420 | */ | ||
421 | static void | ||
422 | insert_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct | ||
423 | RunContextOperation *rcop) | ||
424 | { | ||
425 | GNUNET_assert (GNUNET_OK == | ||
426 | GNUNET_CONTAINER_multihashmap32_put (rc->rcop_map, | ||
427 | rcop_key (rcop->op), rcop, | ||
428 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); | ||
429 | } | ||
430 | |||
431 | |||
432 | /** | ||
433 | * Remove a RunContextOperation from the rcop_map of the given RunContext | ||
434 | * | ||
435 | * @param rc the RunContext from whose map the given RunContextOperaton has to | ||
436 | * be removed | ||
437 | * @param rcop the RunContextOperation | ||
438 | */ | ||
439 | static void | ||
440 | remove_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct | ||
441 | RunContextOperation *rcop) | ||
442 | { | ||
443 | GNUNET_assert (GNUNET_YES == | ||
444 | GNUNET_CONTAINER_multihashmap32_remove (rc->rcop_map, | ||
445 | rcop_key (rcop->op), | ||
446 | rcop)); | ||
447 | } | ||
448 | |||
449 | |||
450 | /** | ||
451 | * Assuming all peers have been destroyed cleanup run handle | ||
452 | * | ||
453 | * @param rc the run context | ||
454 | */ | ||
455 | static void | ||
456 | cleanup (struct GNUNET_TESTBED_RunHandle *rc) | ||
457 | { | ||
458 | unsigned int hid; | ||
459 | |||
460 | GNUNET_assert (NULL == rc->register_hosts_task); | ||
461 | GNUNET_assert (NULL == rc->reg_handle); | ||
462 | GNUNET_assert (NULL == rc->peers); | ||
463 | GNUNET_assert (NULL == rc->hclist); | ||
464 | GNUNET_assert (RC_PEERS_SHUTDOWN == rc->state); | ||
465 | GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (rc->rcop_map)); | ||
466 | GNUNET_CONTAINER_multihashmap32_destroy (rc->rcop_map); | ||
467 | if (NULL != rc->c) | ||
468 | GNUNET_TESTBED_controller_disconnect (rc->c); | ||
469 | if (NULL != rc->cproc) | ||
470 | GNUNET_TESTBED_controller_stop (rc->cproc); | ||
471 | if (NULL != rc->h) | ||
472 | GNUNET_TESTBED_host_destroy (rc->h); | ||
473 | for (hid = 0; hid < rc->num_hosts; hid++) | ||
474 | GNUNET_TESTBED_host_destroy (rc->hosts[hid]); | ||
475 | GNUNET_free (rc->hosts); | ||
476 | if (NULL != rc->cfg) | ||
477 | GNUNET_CONFIGURATION_destroy (rc->cfg); | ||
478 | GNUNET_free (rc->topo_file); | ||
479 | GNUNET_free (rc->trusted_ip); | ||
480 | GNUNET_free (rc); | ||
481 | } | ||
482 | |||
483 | |||
484 | /** | ||
485 | * Iterator for cleaning up elements from rcop_map | ||
486 | * | ||
487 | * @param cls the RunContext | ||
488 | * @param key the 32-bit key | ||
489 | * @param value the RunContextOperation element | ||
490 | * @return always GNUNET_YES | ||
491 | */ | ||
492 | static int | ||
493 | rcop_cleanup_iterator (void *cls, uint32_t key, void *value) | ||
494 | { | ||
495 | struct GNUNET_TESTBED_RunHandle *rc = cls; | ||
496 | struct RunContextOperation *rcop = value; | ||
497 | |||
498 | GNUNET_assert (rc == rcop->rc); | ||
499 | remove_rcop (rc, rcop); | ||
500 | GNUNET_TESTBED_operation_done (rcop->op); | ||
501 | GNUNET_free (rcop); | ||
502 | return GNUNET_YES; | ||
503 | } | ||
504 | |||
505 | |||
506 | /** | ||
507 | * Cancels operations and tasks which are assigned to the given run context | ||
508 | * | ||
509 | * @param rc the RunContext | ||
510 | */ | ||
511 | static void | ||
512 | rc_cleanup_operations (struct GNUNET_TESTBED_RunHandle *rc) | ||
513 | { | ||
514 | struct CompatibilityCheckContext *hc; | ||
515 | unsigned int nhost; | ||
516 | |||
517 | if (NULL != rc->hclist) | ||
518 | { | ||
519 | for (nhost = 0; nhost < rc->num_hosts; nhost++) | ||
520 | { | ||
521 | hc = &rc->hclist[nhost]; | ||
522 | if (NULL != hc->h) | ||
523 | GNUNET_TESTBED_is_host_habitable_cancel (hc->h); | ||
524 | } | ||
525 | GNUNET_free (rc->hclist); | ||
526 | rc->hclist = NULL; | ||
527 | } | ||
528 | /* Stop register hosts task if it is running */ | ||
529 | if (NULL != rc->register_hosts_task) | ||
530 | { | ||
531 | GNUNET_SCHEDULER_cancel (rc->register_hosts_task); | ||
532 | rc->register_hosts_task = NULL; | ||
533 | } | ||
534 | if (NULL != rc->timeout_task) | ||
535 | { | ||
536 | GNUNET_SCHEDULER_cancel (rc->timeout_task); | ||
537 | rc->timeout_task = NULL; | ||
538 | } | ||
539 | if (NULL != rc->reg_handle) | ||
540 | { | ||
541 | GNUNET_TESTBED_cancel_registration (rc->reg_handle); | ||
542 | rc->reg_handle = NULL; | ||
543 | } | ||
544 | if (NULL != rc->topology_operation) | ||
545 | { | ||
546 | GNUNET_TESTBED_operation_done (rc->topology_operation); | ||
547 | rc->topology_operation = NULL; | ||
548 | } | ||
549 | /* cancel any exiting operations */ | ||
550 | GNUNET_assert (GNUNET_SYSERR != | ||
551 | GNUNET_CONTAINER_multihashmap32_iterate (rc->rcop_map, | ||
552 | &rcop_cleanup_iterator, | ||
553 | rc)); | ||
554 | } | ||
555 | |||
556 | |||
557 | /** | ||
558 | * Cancels the scheduled interrupt task | ||
559 | * | ||
560 | * @param rc the run context | ||
561 | */ | ||
562 | static void | ||
563 | cancel_interrupt_task (struct GNUNET_TESTBED_RunHandle *rc) | ||
564 | { | ||
565 | GNUNET_SCHEDULER_cancel (rc->interrupt_task); | ||
566 | rc->interrupt_task = NULL; | ||
567 | } | ||
568 | |||
569 | |||
570 | /** | ||
571 | * This callback will be called when all the operations are completed | ||
572 | * (done/cancelled) | ||
573 | * | ||
574 | * @param cls run context | ||
575 | */ | ||
576 | static void | ||
577 | wait_op_completion (void *cls) | ||
578 | { | ||
579 | struct GNUNET_TESTBED_RunHandle *rc = cls; | ||
580 | struct RunContextOperation *rcop; | ||
581 | |||
582 | if ((NULL == rc->cproc) | ||
583 | || (NULL == rc->c) | ||
584 | || (GNUNET_YES == rc->shutdown)) | ||
585 | { | ||
586 | if (NULL != rc->peers) | ||
587 | { | ||
588 | GNUNET_free (rc->peers); | ||
589 | rc->peers = NULL; | ||
590 | } | ||
591 | goto cleanup_; | ||
592 | } | ||
593 | if (NULL == rc->peers) | ||
594 | goto cleanup_; | ||
595 | rc->shutdown = GNUNET_YES; | ||
596 | rcop = GNUNET_new (struct RunContextOperation); | ||
597 | rcop->rc = rc; | ||
598 | rcop->op = GNUNET_TESTBED_shutdown_peers (rc->c, rcop, NULL, NULL); | ||
599 | GNUNET_assert (NULL != rcop->op); | ||
600 | DEBUG ("Shutting down peers\n"); | ||
601 | rc->pstart_time = GNUNET_TIME_absolute_get (); | ||
602 | insert_rcop (rc, rcop); | ||
603 | return; | ||
604 | |||
605 | cleanup_: | ||
606 | rc->state = RC_PEERS_SHUTDOWN; | ||
607 | cancel_interrupt_task (rc); | ||
608 | cleanup (rc); | ||
609 | } | ||
610 | |||
611 | |||
612 | /** | ||
613 | * Task run upon interrupts (SIGINT, SIGTERM) and upon scheduler shutdown. | ||
614 | * | ||
615 | * @param cls the RunContext which has to be acted upon | ||
616 | */ | ||
617 | static void | ||
618 | interrupt (void *cls) | ||
619 | { | ||
620 | struct GNUNET_TESTBED_RunHandle *rc = cls; | ||
621 | struct GNUNET_TESTBED_Controller *c = rc->c; | ||
622 | unsigned int size; | ||
623 | |||
624 | /* reschedule */ | ||
625 | rc->interrupt_task = GNUNET_SCHEDULER_add_shutdown (&interrupt, rc); | ||
626 | rc_cleanup_operations (rc); | ||
627 | if ((GNUNET_NO == rc->shutdown) && | ||
628 | (NULL != c) && | ||
629 | (NULL != c->opc_map) && | ||
630 | (0 != (size = GNUNET_CONTAINER_multihashmap32_size (c->opc_map)))) | ||
631 | { | ||
632 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
633 | "Shutdown postponed as there are %u operations currently active\n", | ||
634 | size); | ||
635 | c->opcq_empty_cb = &wait_op_completion; | ||
636 | c->opcq_empty_cls = rc; | ||
637 | return; | ||
638 | } | ||
639 | wait_op_completion (rc); | ||
640 | } | ||
641 | |||
642 | |||
643 | /** | ||
644 | * Function to return the string representation of the duration between current | ||
645 | * time and `pstart_time' in `RunContext' | ||
646 | * | ||
647 | * @param rc the RunContext | ||
648 | * @return the representation string; this is NOT reentrant | ||
649 | */ | ||
650 | static const char * | ||
651 | prof_time (struct GNUNET_TESTBED_RunHandle *rc) | ||
652 | { | ||
653 | struct GNUNET_TIME_Relative ptime; | ||
654 | |||
655 | ptime = GNUNET_TIME_absolute_get_duration (rc->pstart_time); | ||
656 | return GNUNET_STRINGS_relative_time_to_string (ptime, GNUNET_YES); | ||
657 | } | ||
658 | |||
659 | |||
660 | /** | ||
661 | * Task for starting peers | ||
662 | * | ||
663 | * @param cls the RunHandle | ||
664 | */ | ||
665 | static void | ||
666 | start_peers_task (void *cls) | ||
667 | { | ||
668 | struct GNUNET_TESTBED_RunHandle *rc = cls; | ||
669 | struct RunContextOperation *rcop; | ||
670 | unsigned int peer; | ||
671 | |||
672 | DEBUG ("Starting Peers\n"); | ||
673 | rc->pstart_time = GNUNET_TIME_absolute_get (); | ||
674 | for (peer = 0; peer < rc->num_peers; peer++) | ||
675 | { | ||
676 | rcop = GNUNET_new (struct RunContextOperation); | ||
677 | rcop->rc = rc; | ||
678 | rcop->op = GNUNET_TESTBED_peer_start (NULL, rc->peers[peer], NULL, NULL); | ||
679 | GNUNET_assert (NULL != rcop->op); | ||
680 | rcop->cls = rc->peers[peer]; | ||
681 | insert_rcop (rc, rcop); | ||
682 | } | ||
683 | rc->peer_count = 0; | ||
684 | } | ||
685 | |||
686 | |||
687 | /** | ||
688 | * Functions of this signature are called when a peer has been successfully | ||
689 | * created | ||
690 | * | ||
691 | * @param cls the closure from GNUNET_TESTBED_peer_create() | ||
692 | * @param peer the handle for the created peer; NULL on any error during | ||
693 | * creation | ||
694 | * @param emsg NULL if peer is not NULL; else MAY contain the error description | ||
695 | */ | ||
696 | static void | ||
697 | peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) | ||
698 | { | ||
699 | struct RunContextOperation *rcop = cls; | ||
700 | struct GNUNET_TESTBED_RunHandle *rc; | ||
701 | |||
702 | GNUNET_assert (NULL != rcop); | ||
703 | GNUNET_assert (NULL != (rc = rcop->rc)); | ||
704 | remove_rcop (rc, rcop); | ||
705 | GNUNET_TESTBED_operation_done (rcop->op); | ||
706 | GNUNET_free (rcop); | ||
707 | if (NULL == peer) | ||
708 | { | ||
709 | if (NULL != emsg) | ||
710 | LOG (GNUNET_ERROR_TYPE_ERROR, "Error while creating a peer: %s\n", | ||
711 | emsg); | ||
712 | GNUNET_SCHEDULER_shutdown (); | ||
713 | return; | ||
714 | } | ||
715 | rc->peers[rc->peer_count] = peer; | ||
716 | rc->peer_count++; | ||
717 | if (rc->peer_count < rc->num_peers) | ||
718 | return; | ||
719 | DEBUG ("%u peers created in %s\n", rc->num_peers, prof_time (rc)); | ||
720 | rc->state = RC_PEERS_CREATED; | ||
721 | GNUNET_SCHEDULER_add_now (&start_peers_task, rc); | ||
722 | } | ||
723 | |||
724 | |||
725 | /** | ||
726 | * call test master callback | ||
727 | * | ||
728 | * @param rc the RunContext | ||
729 | */ | ||
730 | static void | ||
731 | call_master (struct GNUNET_TESTBED_RunHandle *rc) | ||
732 | { | ||
733 | GNUNET_SCHEDULER_cancel (rc->timeout_task); | ||
734 | rc->timeout_task = NULL; | ||
735 | if (NULL != rc->test_master) | ||
736 | rc->test_master (rc->test_master_cls, rc, rc->num_peers, rc->peers, | ||
737 | rc->links_succeeded, rc->links_failed); | ||
738 | } | ||
739 | |||
740 | |||
741 | /** | ||
742 | * Callbacks of this type are called when topology configuration is completed | ||
743 | * | ||
744 | * @param cls the operation closure given to | ||
745 | * GNUNET_TESTBED_overlay_configure_topology_va() and | ||
746 | * GNUNET_TESTBED_overlay_configure() calls | ||
747 | * @param nsuccess the number of successful overlay connects | ||
748 | * @param nfailures the number of overlay connects which failed | ||
749 | */ | ||
750 | static void | ||
751 | topology_completion_callback (void *cls, unsigned int nsuccess, | ||
752 | unsigned int nfailures) | ||
753 | { | ||
754 | struct GNUNET_TESTBED_RunHandle *rc = cls; | ||
755 | |||
756 | DEBUG ("Overlay topology generated in %s\n", prof_time (rc)); | ||
757 | GNUNET_TESTBED_operation_done (rc->topology_operation); | ||
758 | rc->topology_operation = NULL; | ||
759 | rc->links_succeeded = nsuccess; | ||
760 | rc->links_failed = nfailures; | ||
761 | rc->state = RC_READY; | ||
762 | call_master (rc); | ||
763 | } | ||
764 | |||
765 | |||
766 | /** | ||
767 | * Function to create peers | ||
768 | * | ||
769 | * @param rc the RunContext | ||
770 | */ | ||
771 | static void | ||
772 | create_peers (struct GNUNET_TESTBED_RunHandle *rc) | ||
773 | { | ||
774 | struct RunContextOperation *rcop; | ||
775 | unsigned int peer; | ||
776 | |||
777 | DEBUG ("Creating peers\n"); | ||
778 | rc->pstart_time = GNUNET_TIME_absolute_get (); | ||
779 | rc->peers = | ||
780 | GNUNET_malloc (sizeof(struct GNUNET_TESTBED_Peer *) * rc->num_peers); | ||
781 | GNUNET_assert (NULL != rc->c); | ||
782 | rc->peer_count = 0; | ||
783 | for (peer = 0; peer < rc->num_peers; peer++) | ||
784 | { | ||
785 | rcop = GNUNET_new (struct RunContextOperation); | ||
786 | rcop->rc = rc; | ||
787 | rcop->op = | ||
788 | GNUNET_TESTBED_peer_create (rc->c, | ||
789 | (0 == | ||
790 | rc->num_hosts) ? rc->h : rc->hosts[peer | ||
791 | % rc-> | ||
792 | num_hosts], | ||
793 | rc->cfg, &peer_create_cb, rcop); | ||
794 | GNUNET_assert (NULL != rcop->op); | ||
795 | insert_rcop (rc, rcop); | ||
796 | } | ||
797 | } | ||
798 | |||
799 | |||
800 | /** | ||
801 | * Signature of the event handler function called by the | ||
802 | * respective event controller. | ||
803 | * | ||
804 | * @param cls closure | ||
805 | * @param event information about the event | ||
806 | */ | ||
807 | static void | ||
808 | event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) | ||
809 | { | ||
810 | struct GNUNET_TESTBED_RunHandle *rc = cls; | ||
811 | struct RunContextOperation *rcop; | ||
812 | |||
813 | if (RC_INIT == rc->state) | ||
814 | { | ||
815 | switch (event->type) | ||
816 | { | ||
817 | case GNUNET_TESTBED_ET_OPERATION_FINISHED: | ||
818 | rcop = event->op_cls; | ||
819 | if (NULL != event->details.operation_finished.emsg) | ||
820 | { | ||
821 | LOG (GNUNET_ERROR_TYPE_ERROR, _ ( | ||
822 | "Linking controllers failed. Exiting")); | ||
823 | GNUNET_SCHEDULER_shutdown (); | ||
824 | } | ||
825 | else | ||
826 | rc->reg_hosts++; | ||
827 | GNUNET_assert (event->op == rcop->op); | ||
828 | remove_rcop (rc, rcop); | ||
829 | GNUNET_TESTBED_operation_done (rcop->op); | ||
830 | GNUNET_free (rcop); | ||
831 | if (rc->reg_hosts == rc->num_hosts) | ||
832 | { | ||
833 | rc->state = RC_LINKED; | ||
834 | create_peers (rc); | ||
835 | } | ||
836 | return; | ||
837 | |||
838 | default: | ||
839 | GNUNET_break (0); | ||
840 | GNUNET_SCHEDULER_shutdown (); | ||
841 | return; | ||
842 | } | ||
843 | } | ||
844 | if (GNUNET_TESTBED_ET_OPERATION_FINISHED != event->type) | ||
845 | goto call_cc; | ||
846 | if (NULL == (rcop = search_rcop (rc, event->op))) | ||
847 | goto call_cc; | ||
848 | remove_rcop (rc, rcop); | ||
849 | GNUNET_TESTBED_operation_done (rcop->op); | ||
850 | GNUNET_free (rcop); | ||
851 | if ((GNUNET_NO == rc->shutdown) | ||
852 | && (NULL != event->details.operation_finished.emsg)) | ||
853 | { | ||
854 | LOG (GNUNET_ERROR_TYPE_ERROR, "A operation has failed with error: %s\n", | ||
855 | event->details.operation_finished.emsg); | ||
856 | GNUNET_SCHEDULER_shutdown (); | ||
857 | return; | ||
858 | } | ||
859 | GNUNET_assert (GNUNET_YES == rc->shutdown); | ||
860 | switch (rc->state) | ||
861 | { | ||
862 | case RC_LINKED: | ||
863 | case RC_PEERS_CREATED: | ||
864 | case RC_READY: | ||
865 | rc->state = RC_PEERS_SHUTDOWN; | ||
866 | GNUNET_free (rc->peers); | ||
867 | rc->peers = NULL; | ||
868 | DEBUG ("Peers shut down in %s\n", prof_time (rc)); | ||
869 | GNUNET_SCHEDULER_shutdown (); | ||
870 | break; | ||
871 | |||
872 | default: | ||
873 | GNUNET_assert (0); | ||
874 | } | ||
875 | return; | ||
876 | |||
877 | call_cc: | ||
878 | if ((0 != (rc->event_mask & (1LL << event->type))) && (NULL != rc->cc)) | ||
879 | rc->cc (rc->cc_cls, event); | ||
880 | if (GNUNET_TESTBED_ET_PEER_START != event->type) | ||
881 | return; | ||
882 | if (NULL == (rcop = search_rcop (rc, event->op))) /* Not our operation */ | ||
883 | return; | ||
884 | remove_rcop (rc, rcop); | ||
885 | GNUNET_TESTBED_operation_done (rcop->op); | ||
886 | GNUNET_free (rcop); | ||
887 | rc->peer_count++; | ||
888 | if (rc->peer_count < rc->num_peers) | ||
889 | return; | ||
890 | DEBUG ("%u peers started in %s\n", rc->num_peers, prof_time (rc)); | ||
891 | if (GNUNET_TESTBED_TOPOLOGY_NONE != rc->topology) | ||
892 | { | ||
893 | switch (rc->topology) | ||
894 | { | ||
895 | case GNUNET_TESTBED_TOPOLOGY_NONE: | ||
896 | GNUNET_assert (0); | ||
897 | |||
898 | case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: | ||
899 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: | ||
900 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: | ||
901 | rc->topology_operation = | ||
902 | GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, | ||
903 | rc->peers, &rc->num_oc, | ||
904 | &topology_completion_callback, | ||
905 | rc, | ||
906 | rc->topology, | ||
907 | rc->random_links, | ||
908 | GNUNET_TESTBED_TOPOLOGY_OPTION_END); | ||
909 | break; | ||
910 | |||
911 | case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: | ||
912 | GNUNET_assert (NULL != rc->topo_file); | ||
913 | rc->topology_operation = | ||
914 | GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, | ||
915 | rc->peers, &rc->num_oc, | ||
916 | &topology_completion_callback, | ||
917 | rc, | ||
918 | rc->topology, | ||
919 | rc->topo_file, | ||
920 | GNUNET_TESTBED_TOPOLOGY_OPTION_END); | ||
921 | break; | ||
922 | |||
923 | case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: | ||
924 | { | ||
925 | unsigned long long number; | ||
926 | unsigned int cap; | ||
927 | GNUNET_assert (GNUNET_OK == | ||
928 | GNUNET_CONFIGURATION_get_value_number (rc->cfg, | ||
929 | TESTBED_CONFIG_SECTION, | ||
930 | SCALE_FREE_CAP, | ||
931 | &number)); | ||
932 | cap = (unsigned int) number; | ||
933 | GNUNET_assert (GNUNET_OK == | ||
934 | GNUNET_CONFIGURATION_get_value_number (rc->cfg, | ||
935 | TESTBED_CONFIG_SECTION, | ||
936 | SCALE_FREE_M, | ||
937 | &number)); | ||
938 | rc->topology_operation = | ||
939 | GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, | ||
940 | rc->peers, &rc->num_oc, | ||
941 | & | ||
942 | topology_completion_callback, | ||
943 | rc, | ||
944 | rc->topology, | ||
945 | cap, /* uint16_t */ | ||
946 | (unsigned int) number, /* uint8_t */ | ||
947 | GNUNET_TESTBED_TOPOLOGY_OPTION_END); | ||
948 | } | ||
949 | break; | ||
950 | |||
951 | default: | ||
952 | rc->topology_operation = | ||
953 | GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, | ||
954 | rc->peers, &rc->num_oc, | ||
955 | &topology_completion_callback, | ||
956 | rc, | ||
957 | rc->topology, | ||
958 | GNUNET_TESTBED_TOPOLOGY_OPTION_END); | ||
959 | } | ||
960 | if (NULL == rc->topology_operation) | ||
961 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
962 | "Not generating a topology. Check number of peers\n"); | ||
963 | else | ||
964 | { | ||
965 | DEBUG ("Creating overlay topology\n"); | ||
966 | rc->pstart_time = GNUNET_TIME_absolute_get (); | ||
967 | return; | ||
968 | } | ||
969 | } | ||
970 | rc->state = RC_READY; | ||
971 | call_master (rc); | ||
972 | } | ||
973 | |||
974 | |||
975 | /** | ||
976 | * Task to register all hosts available in the global host list | ||
977 | * | ||
978 | * @param cls the RunContext | ||
979 | */ | ||
980 | static void | ||
981 | register_hosts (void *cls); | ||
982 | |||
983 | |||
984 | /** | ||
985 | * Callback which will be called to after a host registration succeeded or failed | ||
986 | * | ||
987 | * @param cls the closure | ||
988 | * @param emsg the error message; NULL if host registration is successful | ||
989 | */ | ||
990 | static void | ||
991 | host_registration_completion (void *cls, const char *emsg) | ||
992 | { | ||
993 | struct GNUNET_TESTBED_RunHandle *rc = cls; | ||
994 | |||
995 | rc->reg_handle = NULL; | ||
996 | if (NULL != emsg) | ||
997 | { | ||
998 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
999 | _ ("Host registration failed for a host. Error: %s\n"), emsg); | ||
1000 | GNUNET_SCHEDULER_shutdown (); | ||
1001 | return; | ||
1002 | } | ||
1003 | rc->register_hosts_task = GNUNET_SCHEDULER_add_now (®ister_hosts, | ||
1004 | rc); | ||
1005 | } | ||
1006 | |||
1007 | |||
1008 | /** | ||
1009 | * Task to register all hosts available in the global host list | ||
1010 | * | ||
1011 | * @param cls RunContext | ||
1012 | */ | ||
1013 | static void | ||
1014 | register_hosts (void *cls) | ||
1015 | { | ||
1016 | struct GNUNET_TESTBED_RunHandle *rc = cls; | ||
1017 | struct RunContextOperation *rcop; | ||
1018 | unsigned int slave; | ||
1019 | |||
1020 | rc->register_hosts_task = NULL; | ||
1021 | if (rc->reg_hosts == rc->num_hosts) | ||
1022 | { | ||
1023 | DEBUG ("All hosts successfully registered\n"); | ||
1024 | /* Start slaves */ | ||
1025 | for (slave = 0; slave < rc->num_hosts; slave++) | ||
1026 | { | ||
1027 | rcop = GNUNET_new (struct RunContextOperation); | ||
1028 | rcop->rc = rc; | ||
1029 | rcop->op = | ||
1030 | GNUNET_TESTBED_controller_link (rcop, rc->c, rc->hosts[slave], | ||
1031 | rc->h, GNUNET_YES); | ||
1032 | GNUNET_assert (NULL != rcop->op); | ||
1033 | insert_rcop (rc, rcop); | ||
1034 | } | ||
1035 | rc->reg_hosts = 0; | ||
1036 | return; | ||
1037 | } | ||
1038 | rc->reg_handle = | ||
1039 | GNUNET_TESTBED_register_host (rc->c, rc->hosts[rc->reg_hosts], | ||
1040 | host_registration_completion, rc); | ||
1041 | rc->reg_hosts++; | ||
1042 | } | ||
1043 | |||
1044 | |||
1045 | /** | ||
1046 | * Callback to signal successful startup of the controller process | ||
1047 | * | ||
1048 | * @param cls the closure from GNUNET_TESTBED_controller_start() | ||
1049 | * @param cfg the configuration with which the controller has been started; | ||
1050 | * NULL if status is not GNUNET_OK | ||
1051 | * @param status GNUNET_OK if the startup is successful; GNUNET_SYSERR if not, | ||
1052 | * GNUNET_TESTBED_controller_stop() shouldn't be called in this case | ||
1053 | */ | ||
1054 | static void | ||
1055 | controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
1056 | int status) | ||
1057 | { | ||
1058 | struct GNUNET_TESTBED_RunHandle *rc = cls; | ||
1059 | uint64_t event_mask; | ||
1060 | |||
1061 | if (status != GNUNET_OK) | ||
1062 | { | ||
1063 | rc->cproc = NULL; | ||
1064 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1065 | _ ("Controller crash detected. Shutting down.\n")); | ||
1066 | GNUNET_SCHEDULER_shutdown (); | ||
1067 | return; | ||
1068 | } | ||
1069 | GNUNET_CONFIGURATION_destroy (rc->cfg); | ||
1070 | rc->cfg = GNUNET_CONFIGURATION_dup (cfg); | ||
1071 | event_mask = rc->event_mask; | ||
1072 | event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
1073 | event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START); | ||
1074 | if (rc->topology < GNUNET_TESTBED_TOPOLOGY_NONE) | ||
1075 | event_mask |= GNUNET_TESTBED_ET_CONNECT; | ||
1076 | rc->c = | ||
1077 | GNUNET_TESTBED_controller_connect (rc->h, event_mask, &event_cb, rc); | ||
1078 | if (0 < rc->num_hosts) | ||
1079 | { | ||
1080 | rc->reg_hosts = 0; | ||
1081 | rc->register_hosts_task = GNUNET_SCHEDULER_add_now (®ister_hosts, rc); | ||
1082 | return; | ||
1083 | } | ||
1084 | rc->state = RC_LINKED; | ||
1085 | create_peers (rc); | ||
1086 | } | ||
1087 | |||
1088 | |||
1089 | /** | ||
1090 | * Callback function invoked for each interface found. | ||
1091 | * | ||
1092 | * @param cls closure | ||
1093 | * @param name name of the interface (can be NULL for unknown) | ||
1094 | * @param isDefault is this presumably the default interface | ||
1095 | * @param addr address of this interface (can be NULL for unknown or unassigned) | ||
1096 | * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned) | ||
1097 | * @param netmask the network mask (can be NULL for unknown or unassigned)) | ||
1098 | * @param addrlen length of the address | ||
1099 | * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort | ||
1100 | */ | ||
1101 | static int | ||
1102 | netint_proc (void *cls, const char *name, int isDefault, | ||
1103 | const struct sockaddr *addr, const struct sockaddr *broadcast_addr, | ||
1104 | const struct sockaddr *netmask, socklen_t addrlen) | ||
1105 | { | ||
1106 | struct GNUNET_TESTBED_RunHandle *rc = cls; | ||
1107 | char hostip[NI_MAXHOST]; | ||
1108 | char *buf; | ||
1109 | |||
1110 | if (sizeof(struct sockaddr_in) != addrlen) | ||
1111 | return GNUNET_OK; /* Only consider IPv4 for now */ | ||
1112 | if (0 != | ||
1113 | getnameinfo (addr, addrlen, hostip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST)) | ||
1114 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "getnameinfo"); | ||
1115 | if (NULL == rc->trusted_ip) | ||
1116 | { | ||
1117 | rc->trusted_ip = GNUNET_strdup (hostip); | ||
1118 | return GNUNET_YES; | ||
1119 | } | ||
1120 | (void) GNUNET_asprintf (&buf, "%s; %s", rc->trusted_ip, hostip); | ||
1121 | GNUNET_free (rc->trusted_ip); | ||
1122 | rc->trusted_ip = buf; | ||
1123 | return GNUNET_YES; | ||
1124 | } | ||
1125 | |||
1126 | |||
1127 | /** | ||
1128 | * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to | ||
1129 | * inform whether the given host is habitable or not. The Handle returned by | ||
1130 | * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called | ||
1131 | * | ||
1132 | * @param cls NULL | ||
1133 | * @param host the host whose status is being reported; will be NULL if the host | ||
1134 | * given to GNUNET_TESTBED_is_host_habitable() is NULL | ||
1135 | * @param status GNUNET_YES if it is habitable; GNUNET_NO if not | ||
1136 | */ | ||
1137 | static void | ||
1138 | host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host, | ||
1139 | int status) | ||
1140 | { | ||
1141 | struct CompatibilityCheckContext *hc = cls; | ||
1142 | struct GNUNET_TESTBED_RunHandle *rc; | ||
1143 | struct GNUNET_TESTBED_Host **old_hosts; | ||
1144 | unsigned int nhost; | ||
1145 | |||
1146 | GNUNET_assert (NULL != (rc = hc->rc)); | ||
1147 | nhost = hc->index; | ||
1148 | GNUNET_assert (nhost <= rc->num_hosts); | ||
1149 | GNUNET_assert (host == rc->hosts[nhost]); | ||
1150 | hc->h = NULL; | ||
1151 | if (GNUNET_NO == status) | ||
1152 | { | ||
1153 | if ((NULL != host) && (NULL != GNUNET_TESTBED_host_get_hostname (host))) | ||
1154 | LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Host %s cannot start testbed\n"), | ||
1155 | GNUNET_TESTBED_host_get_hostname (host)); | ||
1156 | else | ||
1157 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1158 | _ ("Testbed cannot be started on localhost\n")); | ||
1159 | GNUNET_SCHEDULER_shutdown (); | ||
1160 | return; | ||
1161 | } | ||
1162 | rc->reg_hosts++; | ||
1163 | if (rc->reg_hosts < rc->num_hosts) | ||
1164 | return; | ||
1165 | GNUNET_free (rc->hclist); | ||
1166 | rc->hclist = NULL; | ||
1167 | rc->h = rc->hosts[0]; | ||
1168 | rc->num_hosts--; | ||
1169 | if (0 < rc->num_hosts) | ||
1170 | { | ||
1171 | old_hosts = rc->hosts; | ||
1172 | rc->hosts = | ||
1173 | GNUNET_malloc (sizeof(struct GNUNET_TESTBED_Host *) * rc->num_hosts); | ||
1174 | GNUNET_memcpy (rc->hosts, &old_hosts[1], | ||
1175 | (sizeof(struct GNUNET_TESTBED_Host *) * rc->num_hosts)); | ||
1176 | GNUNET_free (old_hosts); | ||
1177 | } | ||
1178 | else | ||
1179 | { | ||
1180 | GNUNET_free (rc->hosts); | ||
1181 | rc->hosts = NULL; | ||
1182 | } | ||
1183 | GNUNET_TESTBED_host_resolve_ (rc->h); | ||
1184 | for (nhost = 0; nhost < rc->num_hosts; nhost++) | ||
1185 | GNUNET_TESTBED_host_resolve_ (rc->hosts[nhost]); | ||
1186 | GNUNET_OS_network_interfaces_list (netint_proc, rc); | ||
1187 | if (NULL == rc->trusted_ip) | ||
1188 | rc->trusted_ip = GNUNET_strdup ("127.0.0.1"); | ||
1189 | rc->cproc = | ||
1190 | GNUNET_TESTBED_controller_start (rc->trusted_ip, rc->h, | ||
1191 | &controller_status_cb, rc); | ||
1192 | GNUNET_free (rc->trusted_ip); | ||
1193 | rc->trusted_ip = NULL; | ||
1194 | if (NULL == rc->cproc) | ||
1195 | { | ||
1196 | LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Cannot start the master controller")); | ||
1197 | GNUNET_SCHEDULER_shutdown (); | ||
1198 | } | ||
1199 | } | ||
1200 | |||
1201 | |||
1202 | /** | ||
1203 | * Task run upon timeout while setting up the testbed | ||
1204 | * | ||
1205 | * @param cls the RunContext | ||
1206 | */ | ||
1207 | static void | ||
1208 | timeout_task (void *cls) | ||
1209 | { | ||
1210 | struct GNUNET_TESTBED_RunHandle *rc = cls; | ||
1211 | |||
1212 | rc->timeout_task = NULL; | ||
1213 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1214 | _ ("Shutting down testbed due to timeout while setup.\n")); | ||
1215 | GNUNET_SCHEDULER_shutdown (); | ||
1216 | if (NULL != rc->test_master) | ||
1217 | rc->test_master (rc->test_master_cls, rc, 0, NULL, 0, 0); | ||
1218 | rc->test_master = NULL; | ||
1219 | } | ||
1220 | |||
1221 | |||
1222 | /** | ||
1223 | * Convenience method for running a testbed with | ||
1224 | * a single call. Underlay and overlay topology | ||
1225 | * are configured using the "UNDERLAY" and "OVERLAY" | ||
1226 | * options in the "[testbed]" section of the configuration\ | ||
1227 | * (with possible options given in "UNDERLAY_XXX" and/or | ||
1228 | * "OVERLAY_XXX"). | ||
1229 | * | ||
1230 | * The testbed is to be terminated using a call to | ||
1231 | * "GNUNET_SCHEDULER_shutdown". | ||
1232 | * | ||
1233 | * @param host_filename name of the file with the 'hosts', NULL | ||
1234 | * to run everything on 'localhost' | ||
1235 | * @param cfg configuration to use (for testbed, controller and peers) | ||
1236 | * @param num_peers number of peers to start; FIXME: maybe put that ALSO into cfg? | ||
1237 | * @param event_mask bit mask with set of events to call 'cc' for; | ||
1238 | * or-ed values of "1LL" shifted by the | ||
1239 | * respective 'enum GNUNET_TESTBED_EventType' | ||
1240 | * (e.g. "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...") | ||
1241 | * @param cc controller callback to invoke on events; This callback is called | ||
1242 | * for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't | ||
1243 | * set in the event_mask as this is the only way get access to the | ||
1244 | * handle of each peer | ||
1245 | * @param cc_cls closure for cc | ||
1246 | * @param test_master this callback will be called once the test is ready | ||
1247 | * @param test_master_cls closure for 'test_master'. | ||
1248 | */ | ||
1249 | void | ||
1250 | GNUNET_TESTBED_run (const char *host_filename, | ||
1251 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
1252 | unsigned int num_peers, uint64_t event_mask, | ||
1253 | GNUNET_TESTBED_ControllerCallback cc, void *cc_cls, | ||
1254 | GNUNET_TESTBED_TestMaster test_master, | ||
1255 | void *test_master_cls) | ||
1256 | { | ||
1257 | struct GNUNET_TESTBED_RunHandle *rc; | ||
1258 | char *topology; | ||
1259 | struct CompatibilityCheckContext *hc; | ||
1260 | struct GNUNET_TIME_Relative timeout; | ||
1261 | unsigned long long number; | ||
1262 | unsigned int hid; | ||
1263 | unsigned int nhost; | ||
1264 | |||
1265 | GNUNET_assert (num_peers > 0); | ||
1266 | rc = GNUNET_new (struct GNUNET_TESTBED_RunHandle); | ||
1267 | rc->cfg = GNUNET_CONFIGURATION_dup (cfg); | ||
1268 | if (NULL != host_filename) | ||
1269 | { | ||
1270 | rc->num_hosts = | ||
1271 | GNUNET_TESTBED_hosts_load_from_file (host_filename, rc->cfg, | ||
1272 | &rc->hosts); | ||
1273 | if (0 == rc->num_hosts) | ||
1274 | { | ||
1275 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1276 | _ ("No hosts loaded. Need at least one host\n")); | ||
1277 | goto error_cleanup; | ||
1278 | } | ||
1279 | } | ||
1280 | else | ||
1281 | rc->h = GNUNET_TESTBED_host_create (NULL, NULL, rc->cfg, 0); | ||
1282 | rc->num_peers = num_peers; | ||
1283 | rc->event_mask = event_mask; | ||
1284 | rc->cc = cc; | ||
1285 | rc->cc_cls = cc_cls; | ||
1286 | rc->test_master = test_master; | ||
1287 | rc->test_master_cls = test_master_cls; | ||
1288 | rc->state = RC_INIT; | ||
1289 | rc->topology = GNUNET_TESTBED_TOPOLOGY_NONE; | ||
1290 | if (GNUNET_OK == | ||
1291 | GNUNET_CONFIGURATION_get_value_string (rc->cfg, TESTBED_CONFIG_SECTION, | ||
1292 | "OVERLAY_TOPOLOGY", &topology)) | ||
1293 | { | ||
1294 | if (GNUNET_NO == GNUNET_TESTBED_topology_get_ (&rc->topology, topology)) | ||
1295 | { | ||
1296 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
1297 | TESTBED_CONFIG_SECTION, | ||
1298 | "OVERLAY_TOPLOGY", | ||
1299 | _ | ||
1300 | ( | ||
1301 | "Specified topology must be supported by testbed")); | ||
1302 | } | ||
1303 | GNUNET_free (topology); | ||
1304 | } | ||
1305 | switch (rc->topology) | ||
1306 | { | ||
1307 | case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: | ||
1308 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: | ||
1309 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: | ||
1310 | if (GNUNET_OK != | ||
1311 | GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, | ||
1312 | "OVERLAY_RANDOM_LINKS", | ||
1313 | &number)) | ||
1314 | { | ||
1315 | /* OVERLAY option RANDOM & SMALL_WORLD_RING requires OVERLAY_RANDOM_LINKS | ||
1316 | * option to be set to the number of random links to be established */ | ||
1317 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
1318 | TESTBED_CONFIG_SECTION, | ||
1319 | "OVERLAY_RANDOM_LINKS"); | ||
1320 | goto error_cleanup; | ||
1321 | } | ||
1322 | if (number > UINT32_MAX) | ||
1323 | { | ||
1324 | GNUNET_break (0); /* Too big number */ | ||
1325 | goto error_cleanup; | ||
1326 | } | ||
1327 | rc->random_links = (unsigned int) number; | ||
1328 | break; | ||
1329 | |||
1330 | case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: | ||
1331 | if (GNUNET_OK != | ||
1332 | GNUNET_CONFIGURATION_get_value_filename (rc->cfg, | ||
1333 | TESTBED_CONFIG_SECTION, | ||
1334 | "OVERLAY_TOPOLOGY_FILE", | ||
1335 | &rc->topo_file)) | ||
1336 | { | ||
1337 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
1338 | TESTBED_CONFIG_SECTION, | ||
1339 | "OVERLAY_TOPOLOGY_FILE"); | ||
1340 | goto error_cleanup; | ||
1341 | } | ||
1342 | goto warn_ignore; | ||
1343 | |||
1344 | case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: | ||
1345 | if (GNUNET_OK != | ||
1346 | GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, | ||
1347 | SCALE_FREE_CAP, &number)) | ||
1348 | { | ||
1349 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
1350 | TESTBED_CONFIG_SECTION, | ||
1351 | SCALE_FREE_CAP); | ||
1352 | goto error_cleanup; | ||
1353 | } | ||
1354 | if (UINT16_MAX < number) | ||
1355 | { | ||
1356 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1357 | _ ("Maximum number of edges a peer can have in a scale free topology" | ||
1358 | " cannot be more than %u. Given `%s = %llu'"), UINT16_MAX, | ||
1359 | SCALE_FREE_CAP, number); | ||
1360 | goto error_cleanup; | ||
1361 | } | ||
1362 | if (GNUNET_OK != | ||
1363 | GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, | ||
1364 | SCALE_FREE_M, &number)) | ||
1365 | { | ||
1366 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
1367 | TESTBED_CONFIG_SECTION, | ||
1368 | SCALE_FREE_M); | ||
1369 | goto error_cleanup; | ||
1370 | } | ||
1371 | if (UINT8_MAX < number) | ||
1372 | { | ||
1373 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1374 | _ ("The number of edges that can established when adding a new node" | ||
1375 | " to scale free topology cannot be more than %u. Given `%s = %llu'"), | ||
1376 | UINT8_MAX, SCALE_FREE_M, number); | ||
1377 | goto error_cleanup; | ||
1378 | } | ||
1379 | goto warn_ignore; | ||
1380 | |||
1381 | case GNUNET_TESTBED_TOPOLOGY_OPTION_END: | ||
1382 | /* not allowed! */ | ||
1383 | GNUNET_assert (0); | ||
1384 | |||
1385 | default: | ||
1386 | warn_ignore: | ||
1387 | /* Warn if OVERLAY_RANDOM_LINKS is present that it will be ignored */ | ||
1388 | if (GNUNET_YES == | ||
1389 | GNUNET_CONFIGURATION_have_value (rc->cfg, TESTBED_CONFIG_SECTION, | ||
1390 | "OVERLAY_RANDOM_LINKS")) | ||
1391 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1392 | "Ignoring value of `OVERLAY_RANDOM_LINKS' in given configuration\n"); | ||
1393 | break; | ||
1394 | } | ||
1395 | if (0 != rc->num_hosts) | ||
1396 | { | ||
1397 | rc->hclist = GNUNET_malloc (sizeof(struct CompatibilityCheckContext) | ||
1398 | * rc->num_hosts); | ||
1399 | for (nhost = 0; nhost < rc->num_hosts; nhost++) | ||
1400 | { | ||
1401 | hc = &rc->hclist[nhost]; | ||
1402 | hc->index = nhost; | ||
1403 | hc->rc = rc; | ||
1404 | hc->h = GNUNET_TESTBED_is_host_habitable (rc->hosts[nhost], rc->cfg, | ||
1405 | &host_habitable_cb, hc); | ||
1406 | if (NULL == hc->h) | ||
1407 | { | ||
1408 | GNUNET_break (0); | ||
1409 | for (nhost = 0; nhost < rc->num_hosts; nhost++) | ||
1410 | { | ||
1411 | hc = &rc->hclist[nhost]; | ||
1412 | if (NULL != hc->h) | ||
1413 | GNUNET_TESTBED_is_host_habitable_cancel (hc->h); | ||
1414 | } | ||
1415 | GNUNET_free (rc->hclist); | ||
1416 | rc->hclist = NULL; | ||
1417 | goto error_cleanup; | ||
1418 | } | ||
1419 | } | ||
1420 | } | ||
1421 | else | ||
1422 | rc->cproc = | ||
1423 | GNUNET_TESTBED_controller_start ("127.0.0.1", rc->h, | ||
1424 | &controller_status_cb, rc); | ||
1425 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, | ||
1426 | TESTBED_CONFIG_SECTION, | ||
1427 | "SETUP_TIMEOUT", | ||
1428 | &timeout)) | ||
1429 | { | ||
1430 | timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, | ||
1431 | DEFAULT_SETUP_TIMEOUT); | ||
1432 | } | ||
1433 | rc->rcop_map = GNUNET_CONTAINER_multihashmap32_create (256); | ||
1434 | rc->timeout_task = | ||
1435 | GNUNET_SCHEDULER_add_delayed (timeout, &timeout_task, rc); | ||
1436 | GNUNET_assert (NULL == rc->interrupt_task); | ||
1437 | rc->interrupt_task = | ||
1438 | GNUNET_SCHEDULER_add_shutdown (&interrupt, | ||
1439 | rc); | ||
1440 | return; | ||
1441 | |||
1442 | error_cleanup: | ||
1443 | if (NULL != rc->h) | ||
1444 | GNUNET_TESTBED_host_destroy (rc->h); | ||
1445 | if (NULL != rc->hosts) | ||
1446 | { | ||
1447 | for (hid = 0; hid < rc->num_hosts; hid++) | ||
1448 | if (NULL != rc->hosts[hid]) | ||
1449 | GNUNET_TESTBED_host_destroy (rc->hosts[hid]); | ||
1450 | GNUNET_free (rc->hosts); | ||
1451 | } | ||
1452 | if (NULL != rc->cfg) | ||
1453 | GNUNET_CONFIGURATION_destroy (rc->cfg); | ||
1454 | GNUNET_free (rc); | ||
1455 | } | ||
1456 | |||
1457 | |||
1458 | /** | ||
1459 | * Obtain handle to the master controller from a testbed run. The handle | ||
1460 | * returned should not be disconnected. | ||
1461 | * | ||
1462 | * @param h the testbed run handle | ||
1463 | * @return handle to the master controller | ||
1464 | */ | ||
1465 | struct GNUNET_TESTBED_Controller * | ||
1466 | GNUNET_TESTBED_run_get_controller_handle (struct GNUNET_TESTBED_RunHandle *h) | ||
1467 | { | ||
1468 | return h->c; | ||
1469 | } | ||
1470 | |||
1471 | |||
1472 | /* end of testbed_api_testbed.c */ | ||
diff --git a/src/testbed/testbed_api_topology.c b/src/testbed/testbed_api_topology.c deleted file mode 100644 index 0f7c0b15c..000000000 --- a/src/testbed/testbed_api_topology.c +++ /dev/null | |||
@@ -1,1661 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_topology.c | ||
23 | * @brief topology-generation functions | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_testbed_service.h" | ||
28 | #include "testbed_api.h" | ||
29 | #include "testbed_api_peers.h" | ||
30 | #include "testbed_api_operations.h" | ||
31 | #include "testbed_api_topology.h" | ||
32 | |||
33 | /** | ||
34 | * Generic loggins shorthand | ||
35 | */ | ||
36 | #define LOG(kind, ...) \ | ||
37 | GNUNET_log_from (kind, "testbed-api-topology", __VA_ARGS__) | ||
38 | |||
39 | |||
40 | /** | ||
41 | * Default number of retires | ||
42 | */ | ||
43 | #define DEFAULT_RETRY_CNT 3 | ||
44 | |||
45 | |||
46 | /** | ||
47 | * Context information for topology operations | ||
48 | */ | ||
49 | struct TopologyContext; | ||
50 | |||
51 | |||
52 | /** | ||
53 | * Representation of an overlay link | ||
54 | */ | ||
55 | struct OverlayLink | ||
56 | { | ||
57 | /** | ||
58 | * An operation corresponding to this link | ||
59 | */ | ||
60 | struct GNUNET_TESTBED_Operation *op; | ||
61 | |||
62 | /** | ||
63 | * The topology context this link is a part of | ||
64 | */ | ||
65 | struct TopologyContext *tc; | ||
66 | |||
67 | /** | ||
68 | * position of peer A's handle in peers array | ||
69 | */ | ||
70 | uint32_t A; | ||
71 | |||
72 | /** | ||
73 | * position of peer B's handle in peers array | ||
74 | */ | ||
75 | uint32_t B; | ||
76 | }; | ||
77 | |||
78 | |||
79 | /** | ||
80 | * Representation of an underlay link | ||
81 | */ | ||
82 | struct UnderlayLink | ||
83 | { | ||
84 | /** | ||
85 | * position of peer A's handle in peers array | ||
86 | */ | ||
87 | uint32_t A; | ||
88 | |||
89 | /** | ||
90 | * position of peer B's handle in peers array | ||
91 | */ | ||
92 | uint32_t B; | ||
93 | |||
94 | /** | ||
95 | * Bandwidth of the link in bytes per second | ||
96 | */ | ||
97 | uint32_t bandwidth; | ||
98 | |||
99 | /** | ||
100 | * Latency of the link in milliseconds | ||
101 | */ | ||
102 | uint32_t latency; | ||
103 | |||
104 | /** | ||
105 | * Loss in the link in percentage of message dropped | ||
106 | */ | ||
107 | uint32_t loss; | ||
108 | }; | ||
109 | |||
110 | |||
111 | struct RetryListEntry | ||
112 | { | ||
113 | /** | ||
114 | * the next pointer for the DLL | ||
115 | */ | ||
116 | struct RetryListEntry *next; | ||
117 | |||
118 | /** | ||
119 | * the prev pointer for the DLL | ||
120 | */ | ||
121 | struct RetryListEntry *prev; | ||
122 | |||
123 | /** | ||
124 | * The link to be retired | ||
125 | */ | ||
126 | struct OverlayLink *link; | ||
127 | }; | ||
128 | |||
129 | |||
130 | /** | ||
131 | * Context information for overlay topologies | ||
132 | */ | ||
133 | struct TopologyContextOverlay | ||
134 | { | ||
135 | /** | ||
136 | * The array of peers | ||
137 | */ | ||
138 | struct GNUNET_TESTBED_Peer **peers; | ||
139 | |||
140 | /** | ||
141 | * An array of links; this array is of size link_array_size | ||
142 | */ | ||
143 | struct OverlayLink *link_array; | ||
144 | |||
145 | /** | ||
146 | * The operation closure | ||
147 | */ | ||
148 | void *op_cls; | ||
149 | |||
150 | /** | ||
151 | * topology generation completion callback | ||
152 | */ | ||
153 | GNUNET_TESTBED_TopologyCompletionCallback comp_cb; | ||
154 | |||
155 | /** | ||
156 | * The closure for the above callback | ||
157 | */ | ||
158 | void *comp_cb_cls; | ||
159 | |||
160 | /** | ||
161 | * DLL head for retry list | ||
162 | */ | ||
163 | struct RetryListEntry *rl_head; | ||
164 | |||
165 | /** | ||
166 | * DLL tail for retry list | ||
167 | */ | ||
168 | struct RetryListEntry *rl_tail; | ||
169 | |||
170 | /** | ||
171 | * How many retries to do before we give up | ||
172 | */ | ||
173 | unsigned int retry_cnt; | ||
174 | |||
175 | /** | ||
176 | * Number of links to try | ||
177 | */ | ||
178 | unsigned int nlinks; | ||
179 | |||
180 | /** | ||
181 | * How many links have been completed | ||
182 | */ | ||
183 | unsigned int ncompleted; | ||
184 | |||
185 | /** | ||
186 | * Total successfully established overlay connections | ||
187 | */ | ||
188 | unsigned int nsuccess; | ||
189 | |||
190 | /** | ||
191 | * Total failed overlay connections | ||
192 | */ | ||
193 | unsigned int nfailures; | ||
194 | }; | ||
195 | |||
196 | |||
197 | /** | ||
198 | * Topology context information for underlay topologies | ||
199 | */ | ||
200 | struct TopologyContextUnderlay | ||
201 | { | ||
202 | /** | ||
203 | * The link array | ||
204 | */ | ||
205 | struct UnderlayLink *link_array; | ||
206 | }; | ||
207 | |||
208 | |||
209 | /** | ||
210 | * Context information for topology operations | ||
211 | */ | ||
212 | struct TopologyContext | ||
213 | { | ||
214 | /** | ||
215 | * The type of this context | ||
216 | */ | ||
217 | enum | ||
218 | { | ||
219 | /** | ||
220 | * Type for underlay topology | ||
221 | */ | ||
222 | TOPOLOGYCONTEXT_TYPE_UNDERLAY = 0, | ||
223 | |||
224 | /** | ||
225 | * Type for overlay topology | ||
226 | */ | ||
227 | TOPOLOGYCONTEXT_TYPE_OVERLAY | ||
228 | } type; | ||
229 | |||
230 | union | ||
231 | { | ||
232 | /** | ||
233 | * Topology context information for overlay topology | ||
234 | */ | ||
235 | struct TopologyContextOverlay overlay; | ||
236 | |||
237 | /** | ||
238 | * Topology context information for underlay topology | ||
239 | */ | ||
240 | struct TopologyContextUnderlay underlay; | ||
241 | } u; | ||
242 | |||
243 | /** | ||
244 | * The number of peers | ||
245 | */ | ||
246 | unsigned int num_peers; | ||
247 | |||
248 | /** | ||
249 | * The size of the link array | ||
250 | */ | ||
251 | unsigned int link_array_size; | ||
252 | }; | ||
253 | |||
254 | |||
255 | /** | ||
256 | * A array of names representing topologies. Should be in sync with enum | ||
257 | * GNUNET_TESTBED_TopologyOption | ||
258 | */ | ||
259 | static const char *topology_strings[] = { | ||
260 | /** | ||
261 | * A clique (everyone connected to everyone else). No options. If there are N | ||
262 | * peers this topology results in (N * (N -1)) connections. | ||
263 | */ | ||
264 | "CLIQUE", | ||
265 | |||
266 | /* | ||
267 | * Small-world network (2d torus plus random links). Followed | ||
268 | * by the number of random links to add (unsigned int). | ||
269 | */ | ||
270 | "SMALL_WORLD", | ||
271 | |||
272 | /** | ||
273 | * Small-world network (ring plus random links). Followed | ||
274 | * by the number of random links to add (unsigned int). | ||
275 | */ | ||
276 | "SMALL_WORLD_RING", | ||
277 | |||
278 | /** | ||
279 | * Ring topology. No options. | ||
280 | */ | ||
281 | "RING", | ||
282 | |||
283 | /** | ||
284 | * Star topology. No options. | ||
285 | */ | ||
286 | "STAR", | ||
287 | |||
288 | /** | ||
289 | * 2-d torus. No options. | ||
290 | */ | ||
291 | "2D_TORUS", | ||
292 | |||
293 | /** | ||
294 | * Random graph. Followed by the number of random links to be established | ||
295 | * (unsigned int) | ||
296 | */ | ||
297 | "RANDOM", // GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI | ||
298 | |||
299 | /** | ||
300 | * Certain percentage of peers are unable to communicate directly | ||
301 | * replicating NAT conditions. Followed by the fraction of | ||
302 | * NAT'ed peers (float). | ||
303 | */ | ||
304 | "INTERNAT", | ||
305 | |||
306 | /** | ||
307 | * Scale free topology. Followed by the maximum number of links a node can | ||
308 | * have (unsigned int); and the number of links a new node should have when | ||
309 | * it is added to the network (unsigned int) | ||
310 | */ | ||
311 | "SCALE_FREE", | ||
312 | |||
313 | /** | ||
314 | * Straight line topology. No options. | ||
315 | */ | ||
316 | "LINE", | ||
317 | |||
318 | /** | ||
319 | * Read a topology from a given file. Followed by the name of the file (const char *). | ||
320 | */ | ||
321 | "FROM_FILE", | ||
322 | |||
323 | /** | ||
324 | * All peers are disconnected. No options. | ||
325 | */ | ||
326 | "NONE", | ||
327 | |||
328 | /** | ||
329 | * End of strings | ||
330 | */ | ||
331 | NULL | ||
332 | }; | ||
333 | |||
334 | |||
335 | /** | ||
336 | * Callback to be called when an overlay_link operation complete | ||
337 | * | ||
338 | * @param cls element of the link_op array which points to the corresponding operation | ||
339 | * @param op the operation that has been finished | ||
340 | * @param emsg error message in case the operation has failed; will be NULL if | ||
341 | * operation has executed successfully. | ||
342 | */ | ||
343 | static void | ||
344 | overlay_link_completed (void *cls, | ||
345 | struct GNUNET_TESTBED_Operation *op, | ||
346 | const char *emsg) | ||
347 | { | ||
348 | struct OverlayLink *link = cls; | ||
349 | struct TopologyContext *tc; | ||
350 | struct TopologyContextOverlay *overlay; | ||
351 | struct RetryListEntry *retry_entry; | ||
352 | |||
353 | GNUNET_assert (op == link->op); | ||
354 | GNUNET_TESTBED_operation_done (op); | ||
355 | link->op = NULL; | ||
356 | tc = link->tc; | ||
357 | GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type); | ||
358 | overlay = &tc->u.overlay; | ||
359 | if (NULL != emsg) | ||
360 | { | ||
361 | overlay->nfailures++; | ||
362 | if (0 != overlay->retry_cnt) | ||
363 | { | ||
364 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
365 | "Error while establishing a link: %s -- Retrying\n", | ||
366 | emsg); | ||
367 | retry_entry = GNUNET_new (struct RetryListEntry); | ||
368 | retry_entry->link = link; | ||
369 | GNUNET_CONTAINER_DLL_insert_tail (overlay->rl_head, | ||
370 | overlay->rl_tail, | ||
371 | retry_entry); | ||
372 | } | ||
373 | } | ||
374 | else | ||
375 | overlay->nsuccess++; | ||
376 | overlay->ncompleted++; | ||
377 | if (overlay->ncompleted < overlay->nlinks) | ||
378 | return; | ||
379 | if ((0 != overlay->retry_cnt) && (NULL != overlay->rl_head)) | ||
380 | { | ||
381 | overlay->retry_cnt--; | ||
382 | overlay->ncompleted = 0; | ||
383 | overlay->nlinks = 0; | ||
384 | while (NULL != (retry_entry = overlay->rl_head)) | ||
385 | { | ||
386 | link = retry_entry->link; | ||
387 | link->op = | ||
388 | GNUNET_TESTBED_overlay_connect (overlay->op_cls, | ||
389 | &overlay_link_completed, | ||
390 | link, | ||
391 | overlay->peers[link->A], | ||
392 | overlay->peers[link->B]); | ||
393 | overlay->nlinks++; | ||
394 | GNUNET_CONTAINER_DLL_remove (overlay->rl_head, | ||
395 | overlay->rl_tail, | ||
396 | retry_entry); | ||
397 | GNUNET_free (retry_entry); | ||
398 | } | ||
399 | return; | ||
400 | } | ||
401 | if (NULL != overlay->comp_cb) | ||
402 | { | ||
403 | overlay->comp_cb (overlay->comp_cb_cls, | ||
404 | overlay->nsuccess, | ||
405 | overlay->nfailures); | ||
406 | } | ||
407 | } | ||
408 | |||
409 | |||
410 | /** | ||
411 | * Function called when a overlay connect operation is ready | ||
412 | * | ||
413 | * @param cls the Topology context | ||
414 | */ | ||
415 | static void | ||
416 | opstart_overlay_configure_topology (void *cls) | ||
417 | { | ||
418 | struct TopologyContext *tc = cls; | ||
419 | struct TopologyContextOverlay *overlay; | ||
420 | unsigned int p; | ||
421 | |||
422 | GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type); | ||
423 | overlay = &tc->u.overlay; | ||
424 | overlay->nlinks = tc->link_array_size; | ||
425 | for (p = 0; p < tc->link_array_size; p++) | ||
426 | { | ||
427 | overlay->link_array[p].op = | ||
428 | GNUNET_TESTBED_overlay_connect (overlay->op_cls, | ||
429 | &overlay_link_completed, | ||
430 | &overlay->link_array[p], | ||
431 | overlay->peers[overlay->link_array[p].A], | ||
432 | overlay->peers[overlay->link_array[p].B]); | ||
433 | } | ||
434 | } | ||
435 | |||
436 | |||
437 | /** | ||
438 | * Callback which will be called when overlay connect operation is released | ||
439 | * | ||
440 | * @param cls the Topology context | ||
441 | */ | ||
442 | static void | ||
443 | oprelease_overlay_configure_topology (void *cls) | ||
444 | { | ||
445 | struct TopologyContext *tc = cls; | ||
446 | struct TopologyContextOverlay *overlay; | ||
447 | struct RetryListEntry *retry_entry; | ||
448 | unsigned int p; | ||
449 | |||
450 | GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type); | ||
451 | overlay = &tc->u.overlay; | ||
452 | while (NULL != (retry_entry = overlay->rl_head)) | ||
453 | { | ||
454 | GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail, | ||
455 | retry_entry); | ||
456 | GNUNET_free (retry_entry); | ||
457 | } | ||
458 | if (NULL != overlay->link_array) | ||
459 | { | ||
460 | for (p = 0; p < tc->link_array_size; p++) | ||
461 | if (NULL != overlay->link_array[p].op) | ||
462 | GNUNET_TESTBED_operation_done (overlay->link_array[p].op); | ||
463 | GNUNET_free (overlay->link_array); | ||
464 | } | ||
465 | GNUNET_free (tc); | ||
466 | } | ||
467 | |||
468 | |||
469 | /** | ||
470 | * Populates the OverlayLink structure. | ||
471 | * | ||
472 | * @param offset the offset of the link array to use | ||
473 | * @param A the peer A. Should be different from B | ||
474 | * @param B the peer B. Should be different from A | ||
475 | * @param tc the TopologyContext | ||
476 | * @return | ||
477 | */ | ||
478 | static void | ||
479 | make_link (unsigned int offset, | ||
480 | uint32_t A, | ||
481 | uint32_t B, | ||
482 | struct TopologyContext *tc) | ||
483 | { | ||
484 | GNUNET_assert (A != B); | ||
485 | switch (tc->type) | ||
486 | { | ||
487 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
488 | { | ||
489 | struct TopologyContextOverlay *overlay; | ||
490 | struct OverlayLink *olink; | ||
491 | |||
492 | overlay = &tc->u.overlay; | ||
493 | GNUNET_assert (offset < tc->link_array_size); | ||
494 | olink = &overlay->link_array[offset]; | ||
495 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A); | ||
496 | olink->A = A; | ||
497 | olink->B = B; | ||
498 | olink->op = NULL; | ||
499 | olink->tc = tc; | ||
500 | } | ||
501 | break; | ||
502 | |||
503 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
504 | { | ||
505 | struct TopologyContextUnderlay *underlay; | ||
506 | struct UnderlayLink *ulink; | ||
507 | |||
508 | underlay = &tc->u.underlay; | ||
509 | GNUNET_assert (offset < tc->link_array_size); | ||
510 | ulink = &underlay->link_array[offset]; | ||
511 | ulink->A = A; | ||
512 | ulink->B = B; | ||
513 | } | ||
514 | break; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | |||
519 | /** | ||
520 | * Generates line topology | ||
521 | * | ||
522 | * @param tc the topology context | ||
523 | */ | ||
524 | static void | ||
525 | gen_topo_line (struct TopologyContext *tc) | ||
526 | { | ||
527 | unsigned int cnt; | ||
528 | |||
529 | tc->link_array_size = tc->num_peers - 1; | ||
530 | switch (tc->type) | ||
531 | { | ||
532 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
533 | { | ||
534 | struct TopologyContextOverlay *overlay; | ||
535 | |||
536 | overlay = &tc->u.overlay; | ||
537 | overlay->link_array = | ||
538 | GNUNET_new_array (tc->link_array_size, | ||
539 | struct OverlayLink); | ||
540 | } | ||
541 | break; | ||
542 | |||
543 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
544 | { | ||
545 | struct TopologyContextUnderlay *underlay; | ||
546 | |||
547 | underlay = &tc->u.underlay; | ||
548 | underlay->link_array = | ||
549 | GNUNET_new_array (tc->link_array_size, | ||
550 | struct UnderlayLink); | ||
551 | } | ||
552 | break; | ||
553 | } | ||
554 | for (cnt = 0; cnt < (tc->link_array_size); cnt++) | ||
555 | make_link (cnt, cnt, cnt + 1, tc); | ||
556 | } | ||
557 | |||
558 | |||
559 | /** | ||
560 | * Generates star topology | ||
561 | * | ||
562 | * @param tc the topology context | ||
563 | */ | ||
564 | static void | ||
565 | gen_topo_star (struct TopologyContext *tc) | ||
566 | { | ||
567 | unsigned int cnt; | ||
568 | |||
569 | tc->link_array_size = tc->num_peers - 1; | ||
570 | switch (tc->type) | ||
571 | { | ||
572 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
573 | { | ||
574 | struct TopologyContextOverlay *overlay; | ||
575 | |||
576 | overlay = &tc->u.overlay; | ||
577 | overlay->link_array = | ||
578 | GNUNET_new_array (tc->link_array_size, | ||
579 | struct OverlayLink); | ||
580 | } | ||
581 | break; | ||
582 | |||
583 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
584 | { | ||
585 | struct TopologyContextUnderlay *underlay; | ||
586 | |||
587 | underlay = &tc->u.underlay; | ||
588 | underlay->link_array = | ||
589 | GNUNET_new_array (tc->link_array_size, | ||
590 | struct UnderlayLink); | ||
591 | } | ||
592 | break; | ||
593 | } | ||
594 | for (cnt = tc->link_array_size; cnt; cnt--) | ||
595 | make_link (cnt - 1, | ||
596 | 0, | ||
597 | cnt, | ||
598 | tc); | ||
599 | } | ||
600 | |||
601 | |||
602 | /** | ||
603 | * Generates ring topology | ||
604 | * | ||
605 | * @param tc the topology context | ||
606 | */ | ||
607 | static void | ||
608 | gen_topo_ring (struct TopologyContext *tc) | ||
609 | { | ||
610 | gen_topo_line (tc); | ||
611 | tc->link_array_size++; | ||
612 | switch (tc->type) | ||
613 | { | ||
614 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
615 | { | ||
616 | struct TopologyContextOverlay *overlay; | ||
617 | |||
618 | overlay = &tc->u.overlay; | ||
619 | overlay->link_array = | ||
620 | GNUNET_realloc (overlay->link_array, sizeof(struct OverlayLink) | ||
621 | * tc->link_array_size); | ||
622 | } | ||
623 | break; | ||
624 | |||
625 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
626 | { | ||
627 | struct TopologyContextUnderlay *underlay; | ||
628 | |||
629 | underlay = &tc->u.underlay; | ||
630 | underlay->link_array = | ||
631 | GNUNET_realloc (underlay->link_array, sizeof(struct UnderlayLink) | ||
632 | * tc->link_array_size); | ||
633 | } | ||
634 | break; | ||
635 | } | ||
636 | make_link (tc->link_array_size - 1, tc->num_peers - 1, 0, tc); | ||
637 | } | ||
638 | |||
639 | |||
640 | /** | ||
641 | * Returns the number of links that are required to generate a 2d torus for the | ||
642 | * given number of peers. Also returns the arrangement (number of rows and the | ||
643 | * length of each row) | ||
644 | * | ||
645 | * @param num_peers number of peers | ||
646 | * @param rows number of rows in the 2d torus. Can be NULL | ||
647 | * @param rows_len the length of each row. This array will be allocated | ||
648 | * fresh. The caller should free it. Can be NULL | ||
649 | * @return the number of links that are required to generate a 2d torus for the | ||
650 | * given number of peers | ||
651 | */ | ||
652 | unsigned int | ||
653 | GNUNET_TESTBED_2dtorus_calc_links (unsigned int num_peers, unsigned int *rows, | ||
654 | unsigned int **rows_len) | ||
655 | { | ||
656 | double sq; | ||
657 | unsigned int sq_floor; | ||
658 | unsigned int _rows; | ||
659 | unsigned int *_rows_len; | ||
660 | unsigned int x; | ||
661 | unsigned int y; | ||
662 | unsigned int _num_peers; | ||
663 | unsigned int cnt; | ||
664 | |||
665 | sq = sqrt (num_peers); | ||
666 | sq = floor (sq); | ||
667 | sq_floor = (unsigned int) sq; | ||
668 | _rows = (sq_floor + 1); | ||
669 | _rows_len = GNUNET_malloc (sizeof(unsigned int) * _rows); | ||
670 | for (y = 0; y < _rows - 1; y++) | ||
671 | _rows_len[y] = sq_floor; | ||
672 | _num_peers = sq_floor * sq_floor; | ||
673 | cnt = (_num_peers < 2) ? _num_peers : 2 * _num_peers; | ||
674 | x = 0; | ||
675 | y = 0; | ||
676 | while (_num_peers < num_peers) | ||
677 | { | ||
678 | if (x < y) | ||
679 | _rows_len[_rows - 1] = ++x; | ||
680 | else | ||
681 | _rows_len[y++]++; | ||
682 | _num_peers++; | ||
683 | } | ||
684 | cnt += (x < 2) ? x : 2 * x; | ||
685 | cnt += (y < 2) ? y : 2 * y; | ||
686 | if (0 == _rows_len[_rows - 1]) | ||
687 | _rows--; | ||
688 | if (NULL != rows) | ||
689 | *rows = _rows; | ||
690 | if (NULL != rows_len) | ||
691 | *rows_len = _rows_len; | ||
692 | else | ||
693 | GNUNET_free (_rows_len); | ||
694 | return cnt; | ||
695 | } | ||
696 | |||
697 | |||
698 | /** | ||
699 | * Generates ring topology | ||
700 | * | ||
701 | * @param tc the topology context | ||
702 | */ | ||
703 | static void | ||
704 | gen_topo_2dtorus (struct TopologyContext *tc) | ||
705 | { | ||
706 | unsigned int rows; | ||
707 | unsigned int *rows_len; | ||
708 | unsigned int x; | ||
709 | unsigned int y; | ||
710 | unsigned int cnt; | ||
711 | unsigned int offset; | ||
712 | |||
713 | tc->link_array_size = | ||
714 | GNUNET_TESTBED_2dtorus_calc_links (tc->num_peers, &rows, &rows_len); | ||
715 | switch (tc->type) | ||
716 | { | ||
717 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
718 | { | ||
719 | struct TopologyContextOverlay *overlay; | ||
720 | |||
721 | overlay = &tc->u.overlay; | ||
722 | overlay->link_array = | ||
723 | GNUNET_malloc (sizeof(struct OverlayLink) * tc->link_array_size); | ||
724 | } | ||
725 | break; | ||
726 | |||
727 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
728 | { | ||
729 | struct TopologyContextUnderlay *underlay; | ||
730 | |||
731 | underlay = &tc->u.underlay; | ||
732 | underlay->link_array = | ||
733 | GNUNET_malloc (sizeof(struct UnderlayLink) * tc->link_array_size); | ||
734 | break; | ||
735 | } | ||
736 | } | ||
737 | cnt = 0; | ||
738 | offset = 0; | ||
739 | for (y = 0; y < rows; y++) | ||
740 | { | ||
741 | for (x = 0; x < rows_len[y] - 1; x++) | ||
742 | { | ||
743 | make_link (cnt, offset + x, offset + x + 1, tc); | ||
744 | cnt++; | ||
745 | } | ||
746 | if (0 == x) | ||
747 | break; | ||
748 | make_link (cnt, offset + x, offset, tc); | ||
749 | cnt++; | ||
750 | offset += rows_len[y]; | ||
751 | } | ||
752 | for (x = 0; x < rows_len[0]; x++) | ||
753 | { | ||
754 | offset = 0; | ||
755 | for (y = 0; y < rows - 1; y++) | ||
756 | { | ||
757 | if (x >= rows_len[y + 1]) | ||
758 | break; | ||
759 | GNUNET_assert (x < rows_len[y + 1]); | ||
760 | make_link (cnt, offset + x, offset + rows_len[y] + x, tc); | ||
761 | offset += rows_len[y]; | ||
762 | cnt++; | ||
763 | } | ||
764 | if (0 == offset) | ||
765 | break; | ||
766 | make_link (cnt, offset + x, x, tc); | ||
767 | cnt++; | ||
768 | } | ||
769 | GNUNET_assert (cnt == tc->link_array_size); | ||
770 | GNUNET_free (rows_len); | ||
771 | } | ||
772 | |||
773 | |||
774 | /** | ||
775 | * Generates ring topology | ||
776 | * | ||
777 | * @param tc the topology context | ||
778 | * @param links the number of random links to establish | ||
779 | * @param append #GNUNET_YES to add links to existing link array; #GNUNET_NO to | ||
780 | * create a new link array | ||
781 | */ | ||
782 | static void | ||
783 | gen_topo_random (struct TopologyContext *tc, | ||
784 | unsigned int links, | ||
785 | int append) | ||
786 | { | ||
787 | unsigned int cnt; | ||
788 | unsigned int index; | ||
789 | uint32_t A_rand; | ||
790 | uint32_t B_rand; | ||
791 | |||
792 | if (1 == tc->num_peers) | ||
793 | return; | ||
794 | if (GNUNET_YES == append) | ||
795 | { | ||
796 | index = tc->link_array_size; | ||
797 | tc->link_array_size += links; | ||
798 | } | ||
799 | else | ||
800 | { | ||
801 | index = 0; | ||
802 | tc->link_array_size = links; | ||
803 | } | ||
804 | switch (tc->type) | ||
805 | { | ||
806 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
807 | { | ||
808 | struct TopologyContextOverlay *overlay; | ||
809 | |||
810 | overlay = &tc->u.overlay; | ||
811 | if (GNUNET_YES != append) | ||
812 | { | ||
813 | GNUNET_assert (NULL == overlay->link_array); | ||
814 | overlay->link_array = | ||
815 | GNUNET_malloc (sizeof(struct OverlayLink) * tc->link_array_size); | ||
816 | break; | ||
817 | } | ||
818 | GNUNET_assert ((0 < tc->link_array_size) && (NULL != | ||
819 | overlay->link_array)); | ||
820 | overlay->link_array = | ||
821 | GNUNET_realloc (overlay->link_array, | ||
822 | sizeof(struct OverlayLink) * tc->link_array_size); | ||
823 | break; | ||
824 | } | ||
825 | |||
826 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
827 | { | ||
828 | struct TopologyContextUnderlay *underlay; | ||
829 | |||
830 | underlay = &tc->u.underlay; | ||
831 | if (GNUNET_YES != append) | ||
832 | { | ||
833 | GNUNET_assert (NULL == underlay->link_array); | ||
834 | underlay->link_array = | ||
835 | GNUNET_malloc (sizeof(struct UnderlayLink) * tc->link_array_size); | ||
836 | break; | ||
837 | } | ||
838 | GNUNET_assert ((0 < tc->link_array_size) && (NULL != | ||
839 | underlay->link_array)); | ||
840 | underlay->link_array = | ||
841 | GNUNET_realloc (underlay->link_array, | ||
842 | sizeof(struct UnderlayLink) * tc->link_array_size); | ||
843 | break; | ||
844 | } | ||
845 | } | ||
846 | for (cnt = 0; cnt < links; cnt++) | ||
847 | { | ||
848 | do | ||
849 | { | ||
850 | A_rand = | ||
851 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers); | ||
852 | B_rand = | ||
853 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers); | ||
854 | } | ||
855 | while (A_rand == B_rand); | ||
856 | make_link (index + cnt, A_rand, B_rand, tc); | ||
857 | } | ||
858 | } | ||
859 | |||
860 | |||
861 | /** | ||
862 | * Generates scale free network. Its construction is described in: | ||
863 | * | ||
864 | * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999. | ||
865 | * | ||
866 | * @param tc the topology context | ||
867 | * @param cap maximum allowed node degree | ||
868 | * @param m number of edges to establish for a new node when it is added to the | ||
869 | * network | ||
870 | */ | ||
871 | static void | ||
872 | gen_topo_scale_free (struct TopologyContext *tc, | ||
873 | uint16_t cap, | ||
874 | uint8_t m) | ||
875 | { | ||
876 | unsigned int *deg; | ||
877 | unsigned int *etab; | ||
878 | unsigned int *used; | ||
879 | unsigned int etaboff; | ||
880 | unsigned int cnt; | ||
881 | unsigned int cnt2; | ||
882 | unsigned int peer; | ||
883 | unsigned int random_peer; | ||
884 | unsigned int links; | ||
885 | unsigned int off; | ||
886 | unsigned int redo_threshold; | ||
887 | |||
888 | etaboff = 0; | ||
889 | tc->link_array_size = tc->num_peers * m; | ||
890 | switch (tc->type) | ||
891 | { | ||
892 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
893 | { | ||
894 | struct TopologyContextOverlay *overlay; | ||
895 | |||
896 | overlay = &tc->u.overlay; | ||
897 | overlay->link_array = GNUNET_malloc_large (sizeof(struct OverlayLink) | ||
898 | * tc->link_array_size); | ||
899 | } | ||
900 | break; | ||
901 | |||
902 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
903 | { | ||
904 | struct TopologyContextUnderlay *underlay; | ||
905 | |||
906 | underlay = &tc->u.underlay; | ||
907 | underlay->link_array = GNUNET_malloc_large (sizeof(struct UnderlayLink) | ||
908 | * tc->link_array_size); | ||
909 | } | ||
910 | break; | ||
911 | } | ||
912 | etab = GNUNET_malloc_large (sizeof(unsigned int) * 2 * tc->link_array_size); | ||
913 | deg = GNUNET_malloc (sizeof(unsigned int) * tc->num_peers); | ||
914 | used = GNUNET_malloc (sizeof(unsigned int) * m); | ||
915 | /* start by connecting peer 1 to peer 0 */ | ||
916 | make_link (0, 0, 1, tc); | ||
917 | deg[0]++; | ||
918 | deg[1]++; | ||
919 | etab[etaboff++] = 0; | ||
920 | etab[etaboff++] = 1; | ||
921 | links = 1; | ||
922 | for (peer = 2; peer < tc->num_peers; peer++) | ||
923 | { | ||
924 | if (cap < deg[peer]) | ||
925 | continue; | ||
926 | for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++) | ||
927 | { | ||
928 | redo_threshold = 0; | ||
929 | redo: | ||
930 | off = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, etaboff); | ||
931 | random_peer = etab[off]; | ||
932 | if (cap < deg[random_peer]) | ||
933 | { | ||
934 | if (++redo_threshold > GNUNET_MAX (1, cap / 2)) | ||
935 | { | ||
936 | redo_threshold = 0; | ||
937 | off = 0; | ||
938 | for (cnt2 = 0; cnt2 < etaboff; cnt2++) | ||
939 | { | ||
940 | if (random_peer == etab[cnt2]) | ||
941 | { | ||
942 | off++; | ||
943 | continue; | ||
944 | } | ||
945 | etab[cnt2 - off] = etab[cnt2]; | ||
946 | } | ||
947 | etaboff -= off; | ||
948 | } | ||
949 | goto redo; | ||
950 | } | ||
951 | for (cnt2 = 0; cnt2 < cnt; cnt2++) | ||
952 | if (random_peer == used[cnt2]) | ||
953 | goto redo; | ||
954 | make_link (links + cnt, random_peer, peer, tc); | ||
955 | deg[random_peer]++; | ||
956 | deg[peer]++; | ||
957 | used[cnt] = random_peer; | ||
958 | } | ||
959 | for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++) | ||
960 | { | ||
961 | etab[etaboff++] = used[cnt]; | ||
962 | etab[etaboff++] = peer; | ||
963 | } | ||
964 | links += GNUNET_MIN (peer, m); | ||
965 | } | ||
966 | GNUNET_free (etab); | ||
967 | GNUNET_free (used); | ||
968 | GNUNET_free (deg); | ||
969 | GNUNET_assert (links <= tc->link_array_size); | ||
970 | tc->link_array_size = links; | ||
971 | switch (tc->type) | ||
972 | { | ||
973 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
974 | { | ||
975 | struct TopologyContextOverlay *overlay; | ||
976 | |||
977 | overlay = &tc->u.overlay; | ||
978 | overlay->link_array = | ||
979 | GNUNET_realloc (overlay->link_array, sizeof(struct OverlayLink) | ||
980 | * tc->link_array_size); | ||
981 | } | ||
982 | break; | ||
983 | |||
984 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
985 | { | ||
986 | struct TopologyContextUnderlay *underlay; | ||
987 | |||
988 | underlay = &tc->u.underlay; | ||
989 | underlay->link_array = | ||
990 | GNUNET_realloc (underlay->link_array, sizeof(struct UnderlayLink) | ||
991 | * tc->link_array_size); | ||
992 | } | ||
993 | break; | ||
994 | } | ||
995 | } | ||
996 | |||
997 | |||
998 | /** | ||
999 | * Generates topology from the given file | ||
1000 | * | ||
1001 | * @param tc the topology context | ||
1002 | * @param filename the filename of the file containing topology data | ||
1003 | */ | ||
1004 | static void | ||
1005 | gen_topo_from_file (struct TopologyContext *tc, | ||
1006 | const char *filename) | ||
1007 | { | ||
1008 | char *data; | ||
1009 | char *end; | ||
1010 | char *buf; | ||
1011 | uint64_t fs; | ||
1012 | uint64_t offset; | ||
1013 | unsigned long int peer_id; | ||
1014 | unsigned long int other_peer_id; | ||
1015 | enum ParseState | ||
1016 | { | ||
1017 | /** | ||
1018 | * We read the peer index | ||
1019 | */ | ||
1020 | PEER_INDEX, | ||
1021 | |||
1022 | /** | ||
1023 | * We read the other peer indices | ||
1024 | */ | ||
1025 | OTHER_PEER_INDEX, | ||
1026 | } state; | ||
1027 | int status; | ||
1028 | |||
1029 | status = GNUNET_SYSERR; | ||
1030 | if (GNUNET_YES != GNUNET_DISK_file_test (filename)) | ||
1031 | { | ||
1032 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1033 | _ ("Topology file %s not found\n"), | ||
1034 | filename); | ||
1035 | return; | ||
1036 | } | ||
1037 | if (GNUNET_OK != | ||
1038 | GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES)) | ||
1039 | { | ||
1040 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1041 | _ ("Topology file %s has no data\n"), | ||
1042 | filename); | ||
1043 | return; | ||
1044 | } | ||
1045 | data = GNUNET_malloc (fs); | ||
1046 | if (fs != GNUNET_DISK_fn_read (filename, data, fs)) | ||
1047 | { | ||
1048 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1049 | _ ("Topology file %s cannot be read\n"), | ||
1050 | filename); | ||
1051 | goto _exit; | ||
1052 | } | ||
1053 | |||
1054 | offset = 0; | ||
1055 | peer_id = 0; | ||
1056 | state = PEER_INDEX; | ||
1057 | while (offset < fs) | ||
1058 | { | ||
1059 | if (0 != isspace ((unsigned char) data[offset])) | ||
1060 | { | ||
1061 | offset++; | ||
1062 | continue; | ||
1063 | } | ||
1064 | switch (state) | ||
1065 | { | ||
1066 | case PEER_INDEX: | ||
1067 | buf = strchr (&data[offset], ':'); | ||
1068 | if (NULL == buf) | ||
1069 | { | ||
1070 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1071 | _ ("Failed to read peer index from toology file: %s"), filename); | ||
1072 | goto _exit; | ||
1073 | } | ||
1074 | *buf = '\0'; | ||
1075 | errno = 0; | ||
1076 | peer_id = (unsigned int) strtoul (&data[offset], &end, 10); | ||
1077 | if (0 != errno) | ||
1078 | { | ||
1079 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1080 | _ ("Value in given topology file: %s out of range\n"), filename); | ||
1081 | goto _exit; | ||
1082 | } | ||
1083 | if (&data[offset] == end) | ||
1084 | { | ||
1085 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1086 | _ ("Failed to read peer index from topology file: %s"), filename); | ||
1087 | goto _exit; | ||
1088 | } | ||
1089 | if (tc->num_peers <= peer_id) | ||
1090 | { | ||
1091 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1092 | _ ("Topology file needs more peers than given ones\n")); | ||
1093 | goto _exit; | ||
1094 | } | ||
1095 | state = OTHER_PEER_INDEX; | ||
1096 | offset += ((unsigned int) (buf - &data[offset])) + 1; | ||
1097 | break; | ||
1098 | |||
1099 | case OTHER_PEER_INDEX: | ||
1100 | errno = 0; | ||
1101 | other_peer_id = (unsigned int) strtoul (&data[offset], &end, 10); | ||
1102 | if (0 != errno) | ||
1103 | { | ||
1104 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1105 | _ ("Value in given topology file: %s out of range\n"), filename); | ||
1106 | goto _exit; | ||
1107 | } | ||
1108 | if (&data[offset] == end) | ||
1109 | { | ||
1110 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1111 | _ ("Failed to read peer index from topology file: %s"), filename); | ||
1112 | goto _exit; | ||
1113 | } | ||
1114 | if (tc->num_peers <= other_peer_id) | ||
1115 | { | ||
1116 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1117 | _ ("Topology file needs more peers than given ones\n")); | ||
1118 | goto _exit; | ||
1119 | } | ||
1120 | if (peer_id != other_peer_id) | ||
1121 | { | ||
1122 | tc->link_array_size++; | ||
1123 | switch (tc->type) | ||
1124 | { | ||
1125 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
1126 | { | ||
1127 | struct TopologyContextOverlay *overlay; | ||
1128 | |||
1129 | overlay = &tc->u.overlay; | ||
1130 | overlay->link_array = | ||
1131 | GNUNET_realloc (overlay->link_array, | ||
1132 | sizeof(struct OverlayLink) * tc->link_array_size); | ||
1133 | } | ||
1134 | break; | ||
1135 | |||
1136 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
1137 | { | ||
1138 | struct TopologyContextUnderlay *underlay; | ||
1139 | |||
1140 | underlay = &tc->u.underlay; | ||
1141 | underlay->link_array = | ||
1142 | GNUNET_realloc (underlay->link_array, | ||
1143 | sizeof(struct UnderlayLink) | ||
1144 | * tc->link_array_size); | ||
1145 | } | ||
1146 | break; | ||
1147 | } | ||
1148 | offset += end - &data[offset]; | ||
1149 | make_link (tc->link_array_size - 1, peer_id, other_peer_id, tc); | ||
1150 | } | ||
1151 | else | ||
1152 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1153 | _ ("Ignoring to connect peer %lu to peer %lu\n"), | ||
1154 | peer_id, | ||
1155 | other_peer_id); | ||
1156 | while (('\n' != data[offset]) && ('|' != data[offset]) && (offset < fs)) | ||
1157 | offset++; | ||
1158 | if ((offset < fs) && | ||
1159 | ('\n' == data[offset])) | ||
1160 | state = PEER_INDEX; | ||
1161 | else if ((offset < fs) && | ||
1162 | ('|' == data[offset])) | ||
1163 | { | ||
1164 | state = OTHER_PEER_INDEX; | ||
1165 | offset++; | ||
1166 | } | ||
1167 | break; | ||
1168 | } | ||
1169 | } | ||
1170 | status = GNUNET_OK; | ||
1171 | |||
1172 | _exit: | ||
1173 | GNUNET_free (data); | ||
1174 | if (GNUNET_OK != status) | ||
1175 | { | ||
1176 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1177 | "Removing link data read from the file\n"); | ||
1178 | tc->link_array_size = 0; | ||
1179 | switch (tc->type) | ||
1180 | { | ||
1181 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
1182 | { | ||
1183 | struct TopologyContextOverlay *overlay; | ||
1184 | |||
1185 | overlay = &tc->u.overlay; | ||
1186 | GNUNET_free (overlay->link_array); | ||
1187 | overlay->link_array = NULL; | ||
1188 | } | ||
1189 | break; | ||
1190 | |||
1191 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
1192 | { | ||
1193 | struct TopologyContextUnderlay *underlay; | ||
1194 | |||
1195 | underlay = &tc->u.underlay; | ||
1196 | GNUNET_free (underlay->link_array); | ||
1197 | underlay->link_array = NULL; | ||
1198 | } | ||
1199 | break; | ||
1200 | } | ||
1201 | } | ||
1202 | } | ||
1203 | |||
1204 | |||
1205 | /** | ||
1206 | * Generates clique topology | ||
1207 | * | ||
1208 | * @param tc the topology context | ||
1209 | */ | ||
1210 | static void | ||
1211 | gen_topo_clique (struct TopologyContext *tc) | ||
1212 | { | ||
1213 | unsigned int cnt; | ||
1214 | unsigned int offset; | ||
1215 | unsigned int neighbour; | ||
1216 | |||
1217 | tc->link_array_size = tc->num_peers * (tc->num_peers - 1); | ||
1218 | switch (tc->type) | ||
1219 | { | ||
1220 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
1221 | { | ||
1222 | struct TopologyContextOverlay *overlay; | ||
1223 | |||
1224 | overlay = &tc->u.overlay; | ||
1225 | overlay->link_array = GNUNET_new_array (tc->link_array_size, | ||
1226 | struct OverlayLink); | ||
1227 | } | ||
1228 | break; | ||
1229 | |||
1230 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
1231 | { | ||
1232 | struct TopologyContextUnderlay *underlay; | ||
1233 | |||
1234 | underlay = &tc->u.underlay; | ||
1235 | underlay->link_array = GNUNET_new_array (tc->link_array_size, | ||
1236 | struct UnderlayLink); | ||
1237 | } | ||
1238 | } | ||
1239 | offset = 0; | ||
1240 | for (cnt = 0; cnt < tc->num_peers; cnt++) | ||
1241 | { | ||
1242 | for (neighbour = 0; neighbour < tc->num_peers; neighbour++) | ||
1243 | { | ||
1244 | if (neighbour == cnt) | ||
1245 | continue; | ||
1246 | make_link (offset, cnt, neighbour, tc); | ||
1247 | offset++; | ||
1248 | } | ||
1249 | } | ||
1250 | } | ||
1251 | |||
1252 | |||
1253 | /** | ||
1254 | * Configure overall network topology to have a particular shape. | ||
1255 | * | ||
1256 | * @param op_cls closure argument to give with the operation event | ||
1257 | * @param num_peers number of peers in @a peers | ||
1258 | * @param peers array of @a num_peers with the peers to configure | ||
1259 | * @param topo desired underlay topology to use | ||
1260 | * @param ap topology-specific options | ||
1261 | * @return handle to the operation, NULL if configuring the topology | ||
1262 | * is not allowed at this time | ||
1263 | */ | ||
1264 | struct GNUNET_TESTBED_Operation * | ||
1265 | GNUNET_TESTBED_underlay_configure_topology_va (void *op_cls, | ||
1266 | unsigned int num_peers, | ||
1267 | struct GNUNET_TESTBED_Peer | ||
1268 | **peers, | ||
1269 | enum | ||
1270 | GNUNET_TESTBED_TopologyOption | ||
1271 | topo, va_list ap) | ||
1272 | { | ||
1273 | GNUNET_break (0); | ||
1274 | return NULL; | ||
1275 | } | ||
1276 | |||
1277 | |||
1278 | /** | ||
1279 | * Configure overall network topology to have a particular shape. | ||
1280 | * | ||
1281 | * @param op_cls closure argument to give with the operation event | ||
1282 | * @param num_peers number of peers in @a peers | ||
1283 | * @param peers array of @a num_peers with the peers to configure | ||
1284 | * @param topo desired underlay topology to use | ||
1285 | * @param ... topology-specific options | ||
1286 | * @return handle to the operation, NULL if configuring the topology | ||
1287 | * is not allowed at this time | ||
1288 | */ | ||
1289 | struct GNUNET_TESTBED_Operation * | ||
1290 | GNUNET_TESTBED_underlay_configure_topology (void *op_cls, | ||
1291 | unsigned int num_peers, | ||
1292 | struct GNUNET_TESTBED_Peer **peers, | ||
1293 | enum GNUNET_TESTBED_TopologyOption | ||
1294 | topo, ...) | ||
1295 | { | ||
1296 | GNUNET_break (0); | ||
1297 | return NULL; | ||
1298 | } | ||
1299 | |||
1300 | |||
1301 | /** | ||
1302 | * All peers must have been started before calling this function. | ||
1303 | * This function then connects the given peers in the P2P overlay | ||
1304 | * using the given topology. | ||
1305 | * | ||
1306 | * @param op_cls closure argument to give with the peer connect operation events | ||
1307 | * generated through this function | ||
1308 | * @param num_peers number of peers in @a peers | ||
1309 | * @param peers array of @a num_peers with the peers to configure | ||
1310 | * @param max_connections the maximums number of overlay connections that will | ||
1311 | * be made to achieve the given topology | ||
1312 | * @param comp_cb the completion callback to call when the topology generation | ||
1313 | * is completed | ||
1314 | * @param comp_cb_cls closure for the above completion callback | ||
1315 | * @param topo desired underlay topology to use | ||
1316 | * @param va topology-specific options | ||
1317 | * @return handle to the operation, NULL if connecting these | ||
1318 | * peers is fundamentally not possible at this time (peers | ||
1319 | * not running or underlay disallows) or if num_peers is less than 2 | ||
1320 | */ | ||
1321 | struct GNUNET_TESTBED_Operation * | ||
1322 | GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls, | ||
1323 | unsigned int num_peers, | ||
1324 | struct GNUNET_TESTBED_Peer **peers, | ||
1325 | unsigned int *max_connections, | ||
1326 | GNUNET_TESTBED_TopologyCompletionCallback | ||
1327 | comp_cb, | ||
1328 | void *comp_cb_cls, | ||
1329 | enum GNUNET_TESTBED_TopologyOption | ||
1330 | topo, | ||
1331 | va_list va) | ||
1332 | { | ||
1333 | struct TopologyContext *tc; | ||
1334 | struct TopologyContextOverlay *overlay; | ||
1335 | struct GNUNET_TESTBED_Operation *op; | ||
1336 | struct GNUNET_TESTBED_Controller *c; | ||
1337 | enum GNUNET_TESTBED_TopologyOption secondary_option; | ||
1338 | |||
1339 | if (num_peers < 2) | ||
1340 | return NULL; | ||
1341 | c = peers[0]->controller; | ||
1342 | tc = GNUNET_new (struct TopologyContext); | ||
1343 | tc->type = TOPOLOGYCONTEXT_TYPE_OVERLAY; | ||
1344 | overlay = &tc->u.overlay; | ||
1345 | overlay->peers = peers; | ||
1346 | tc->num_peers = num_peers; | ||
1347 | overlay->op_cls = op_cls; | ||
1348 | overlay->retry_cnt = DEFAULT_RETRY_CNT; | ||
1349 | overlay->comp_cb = comp_cb; | ||
1350 | overlay->comp_cb_cls = comp_cb_cls; | ||
1351 | switch (topo) | ||
1352 | { | ||
1353 | case GNUNET_TESTBED_TOPOLOGY_LINE: | ||
1354 | gen_topo_line (tc); | ||
1355 | break; | ||
1356 | |||
1357 | case GNUNET_TESTBED_TOPOLOGY_STAR: | ||
1358 | gen_topo_star (tc); | ||
1359 | break; | ||
1360 | |||
1361 | case GNUNET_TESTBED_TOPOLOGY_RING: | ||
1362 | gen_topo_ring (tc); | ||
1363 | break; | ||
1364 | |||
1365 | case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: | ||
1366 | gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_NO); | ||
1367 | break; | ||
1368 | |||
1369 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: | ||
1370 | gen_topo_ring (tc); | ||
1371 | gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES); | ||
1372 | break; | ||
1373 | |||
1374 | case GNUNET_TESTBED_TOPOLOGY_CLIQUE: | ||
1375 | gen_topo_clique (tc); | ||
1376 | break; | ||
1377 | |||
1378 | case GNUNET_TESTBED_TOPOLOGY_2D_TORUS: | ||
1379 | gen_topo_2dtorus (tc); | ||
1380 | break; | ||
1381 | |||
1382 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: | ||
1383 | gen_topo_2dtorus (tc); | ||
1384 | gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES); | ||
1385 | |||
1386 | break; | ||
1387 | |||
1388 | case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: | ||
1389 | { | ||
1390 | uint16_t cap; | ||
1391 | uint8_t m; | ||
1392 | |||
1393 | cap = (uint16_t) va_arg (va, unsigned int); | ||
1394 | m = (uint8_t) va_arg (va, unsigned int); | ||
1395 | gen_topo_scale_free (tc, cap, m); | ||
1396 | } | ||
1397 | break; | ||
1398 | |||
1399 | case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: | ||
1400 | { | ||
1401 | const char *filename; | ||
1402 | |||
1403 | filename = va_arg (va, const char *); | ||
1404 | |||
1405 | GNUNET_assert (NULL != filename); | ||
1406 | gen_topo_from_file (tc, filename); | ||
1407 | } | ||
1408 | break; | ||
1409 | |||
1410 | default: | ||
1411 | GNUNET_break (0); | ||
1412 | GNUNET_free (tc); | ||
1413 | return NULL; | ||
1414 | } | ||
1415 | do | ||
1416 | { | ||
1417 | secondary_option = GNUNET_VA_ARG_ENUM (va, GNUNET_TESTBED_TopologyOption); | ||
1418 | |||
1419 | switch (secondary_option) | ||
1420 | { | ||
1421 | case GNUNET_TESTBED_TOPOLOGY_RETRY_CNT: | ||
1422 | overlay->retry_cnt = va_arg (va, unsigned int); | ||
1423 | break; | ||
1424 | |||
1425 | case GNUNET_TESTBED_TOPOLOGY_OPTION_END: | ||
1426 | break; | ||
1427 | |||
1428 | default: | ||
1429 | GNUNET_break (0); /* Should not use any other option apart from | ||
1430 | * the ones handled here */ | ||
1431 | GNUNET_free (overlay->link_array); | ||
1432 | GNUNET_free (tc); | ||
1433 | return NULL; | ||
1434 | } | ||
1435 | } | ||
1436 | while (GNUNET_TESTBED_TOPOLOGY_OPTION_END != secondary_option); | ||
1437 | op = GNUNET_TESTBED_operation_create_ (tc, | ||
1438 | &opstart_overlay_configure_topology, | ||
1439 | &oprelease_overlay_configure_topology); | ||
1440 | GNUNET_TESTBED_operation_queue_insert_ | ||
1441 | (c->opq_parallel_topology_config_operations, op); | ||
1442 | GNUNET_TESTBED_operation_begin_wait_ (op); | ||
1443 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1444 | "Generated %u connections\n", | ||
1445 | tc->link_array_size); | ||
1446 | if (NULL != max_connections) | ||
1447 | *max_connections = tc->link_array_size; | ||
1448 | return op; | ||
1449 | } | ||
1450 | |||
1451 | |||
1452 | /** | ||
1453 | * All peers must have been started before calling this function. | ||
1454 | * This function then connects the given peers in the P2P overlay | ||
1455 | * using the given topology. | ||
1456 | * | ||
1457 | * @param op_cls closure argument to give with the peer connect operation events | ||
1458 | * generated through this function | ||
1459 | * @param num_peers number of peers in 'peers' | ||
1460 | * @param peers array of 'num_peers' with the peers to configure | ||
1461 | * @param max_connections the maximums number of overlay connections that will | ||
1462 | * be made to achieve the given topology | ||
1463 | * @param comp_cb the completion callback to call when the topology generation | ||
1464 | * is completed | ||
1465 | * @param comp_cb_cls closure for the above completion callback | ||
1466 | * @param topo desired underlay topology to use | ||
1467 | * @param ... topology-specific options | ||
1468 | * @return handle to the operation, NULL if connecting these | ||
1469 | * peers is fundamentally not possible at this time (peers | ||
1470 | * not running or underlay disallows) or if num_peers is less than 2 | ||
1471 | */ | ||
1472 | struct GNUNET_TESTBED_Operation * | ||
1473 | GNUNET_TESTBED_overlay_configure_topology (void *op_cls, | ||
1474 | unsigned int num_peers, | ||
1475 | struct GNUNET_TESTBED_Peer **peers, | ||
1476 | unsigned int *max_connections, | ||
1477 | GNUNET_TESTBED_TopologyCompletionCallback | ||
1478 | comp_cb, | ||
1479 | void *comp_cb_cls, | ||
1480 | enum GNUNET_TESTBED_TopologyOption | ||
1481 | topo, | ||
1482 | ...) | ||
1483 | { | ||
1484 | struct GNUNET_TESTBED_Operation *op; | ||
1485 | va_list vargs; | ||
1486 | |||
1487 | GNUNET_assert (topo < GNUNET_TESTBED_TOPOLOGY_OPTION_END); | ||
1488 | va_start (vargs, topo); | ||
1489 | op = GNUNET_TESTBED_overlay_configure_topology_va (op_cls, num_peers, peers, | ||
1490 | max_connections, | ||
1491 | comp_cb, comp_cb_cls, | ||
1492 | topo, | ||
1493 | vargs); | ||
1494 | va_end (vargs); | ||
1495 | return op; | ||
1496 | } | ||
1497 | |||
1498 | |||
1499 | /** | ||
1500 | * Get a topology from a string input. | ||
1501 | * | ||
1502 | * @param topology where to write the retrieved topology | ||
1503 | * @param topology_string The string to attempt to | ||
1504 | * get a configuration value from | ||
1505 | * @return #GNUNET_YES if topology string matched a | ||
1506 | * known topology, #GNUNET_NO if not | ||
1507 | */ | ||
1508 | int | ||
1509 | GNUNET_TESTBED_topology_get_ (enum GNUNET_TESTBED_TopologyOption *topology, | ||
1510 | const char *topology_string) | ||
1511 | { | ||
1512 | unsigned int cnt; | ||
1513 | |||
1514 | for (cnt = 0; NULL != topology_strings[cnt]; cnt++) | ||
1515 | { | ||
1516 | if (0 == strcasecmp (topology_string, topology_strings[cnt])) | ||
1517 | { | ||
1518 | if (NULL != topology) | ||
1519 | *topology = (enum GNUNET_TESTBED_TopologyOption) cnt; | ||
1520 | GNUNET_assert (GNUNET_TESTBED_TOPOLOGY_OPTION_END != | ||
1521 | (enum GNUNET_TESTBED_TopologyOption) cnt); | ||
1522 | return GNUNET_YES; | ||
1523 | } | ||
1524 | } | ||
1525 | return GNUNET_NO; | ||
1526 | } | ||
1527 | |||
1528 | |||
1529 | /** | ||
1530 | * Returns the string corresponding to the given topology | ||
1531 | * | ||
1532 | * @param topology the topology | ||
1533 | * @return the string (freshly allocated) of given topology; NULL if topology cannot be | ||
1534 | * expressed as a string | ||
1535 | */ | ||
1536 | char * | ||
1537 | GNUNET_TESTBED_topology_to_str_ (enum GNUNET_TESTBED_TopologyOption topology) | ||
1538 | { | ||
1539 | if (GNUNET_TESTBED_TOPOLOGY_OPTION_END <= topology) | ||
1540 | return NULL; | ||
1541 | return GNUNET_strdup (topology_strings[topology]); | ||
1542 | } | ||
1543 | |||
1544 | |||
1545 | /** | ||
1546 | * Function to construct an underlay topology | ||
1547 | * | ||
1548 | * @param num_peers the number of peers for which the topology should be | ||
1549 | * generated | ||
1550 | * @param proc the underlay link processor callback. Will be called for each | ||
1551 | * underlay link generated unless a previous call to this callback | ||
1552 | * returned #GNUNET_SYSERR. Cannot be NULL. | ||
1553 | * @param cls closure for @a proc | ||
1554 | * @param ... variable arguments denoting the topology and its parameters. They | ||
1555 | * should start with the type of topology to generate followed by their | ||
1556 | * options. | ||
1557 | * @return #GNUNET_OK if underlay link generation is successful; #GNUNET_SYSERR | ||
1558 | * upon error in generating the underlay or if any calls to the | ||
1559 | * underlay link processor returned #GNUNET_SYSERR | ||
1560 | */ | ||
1561 | int | ||
1562 | GNUNET_TESTBED_underlay_construct_ (int num_peers, | ||
1563 | underlay_link_processor proc, | ||
1564 | void *cls, | ||
1565 | ...) | ||
1566 | { | ||
1567 | struct TopologyContext tc; | ||
1568 | struct TopologyContextUnderlay *underlay; | ||
1569 | struct UnderlayLink *ulink; | ||
1570 | va_list vargs; | ||
1571 | enum GNUNET_TESTBED_TopologyOption topology; | ||
1572 | unsigned int cnt; | ||
1573 | int ret; | ||
1574 | |||
1575 | GNUNET_assert (NULL != proc); | ||
1576 | ret = GNUNET_OK; | ||
1577 | memset (&tc, 0, sizeof(tc)); | ||
1578 | tc.num_peers = num_peers; | ||
1579 | tc.type = TOPOLOGYCONTEXT_TYPE_UNDERLAY; | ||
1580 | underlay = &tc.u.underlay; | ||
1581 | va_start (vargs, cls); | ||
1582 | topology = GNUNET_VA_ARG_ENUM (vargs, GNUNET_TESTBED_TopologyOption); | ||
1583 | switch (topology) | ||
1584 | { | ||
1585 | case GNUNET_TESTBED_TOPOLOGY_LINE: | ||
1586 | gen_topo_line (&tc); | ||
1587 | break; | ||
1588 | |||
1589 | case GNUNET_TESTBED_TOPOLOGY_STAR: | ||
1590 | gen_topo_star (&tc); | ||
1591 | break; | ||
1592 | |||
1593 | case GNUNET_TESTBED_TOPOLOGY_RING: | ||
1594 | gen_topo_ring (&tc); | ||
1595 | break; | ||
1596 | |||
1597 | case GNUNET_TESTBED_TOPOLOGY_CLIQUE: | ||
1598 | gen_topo_clique (&tc); | ||
1599 | break; | ||
1600 | |||
1601 | case GNUNET_TESTBED_TOPOLOGY_2D_TORUS: | ||
1602 | gen_topo_2dtorus (&tc); | ||
1603 | break; | ||
1604 | |||
1605 | case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: | ||
1606 | gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_NO); | ||
1607 | break; | ||
1608 | |||
1609 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: | ||
1610 | gen_topo_ring (&tc); | ||
1611 | gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES); | ||
1612 | break; | ||
1613 | |||
1614 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: | ||
1615 | gen_topo_2dtorus (&tc); | ||
1616 | gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES); | ||
1617 | break; | ||
1618 | |||
1619 | case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: | ||
1620 | { | ||
1621 | const char *filename; | ||
1622 | filename = va_arg (vargs, char *); | ||
1623 | GNUNET_assert (NULL != filename); | ||
1624 | gen_topo_from_file (&tc, filename); | ||
1625 | } | ||
1626 | break; | ||
1627 | |||
1628 | case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: | ||
1629 | { | ||
1630 | uint16_t cap; | ||
1631 | uint8_t m; | ||
1632 | cap = (uint16_t) va_arg (vargs, unsigned int); | ||
1633 | m = (uint8_t) va_arg (vargs, unsigned int); | ||
1634 | gen_topo_scale_free (&tc, cap, m); | ||
1635 | } | ||
1636 | break; | ||
1637 | |||
1638 | default: | ||
1639 | GNUNET_assert (0); | ||
1640 | } | ||
1641 | va_end (vargs); | ||
1642 | for (cnt = 0; cnt < tc.link_array_size; cnt++) | ||
1643 | { | ||
1644 | ulink = &underlay->link_array[cnt]; | ||
1645 | if (GNUNET_SYSERR == proc (cls, | ||
1646 | ulink->A, | ||
1647 | ulink->B, | ||
1648 | ulink->bandwidth, | ||
1649 | ulink->latency, | ||
1650 | ulink->loss)) | ||
1651 | { | ||
1652 | ret = GNUNET_SYSERR; | ||
1653 | break; | ||
1654 | } | ||
1655 | } | ||
1656 | GNUNET_free (underlay->link_array); | ||
1657 | return ret; | ||
1658 | } | ||
1659 | |||
1660 | |||
1661 | /* end of testbed_api_topology.c */ | ||
diff --git a/src/testbed/testbed_api_topology.h b/src/testbed/testbed_api_topology.h deleted file mode 100644 index 564fa421f..000000000 --- a/src/testbed/testbed_api_topology.h +++ /dev/null | |||
@@ -1,113 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_topology.h | ||
23 | * @brief header for intra library exported functions | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #ifndef TESTBED_API_TOPOLOGY_H | ||
28 | #define TESTBED_API_TOPOLOGY_H | ||
29 | |||
30 | /** | ||
31 | * Returns the number of links that are required to generate a 2d torus for the | ||
32 | * given number of peers. Also returns the arrangement (number of rows and the | ||
33 | * length of each row) | ||
34 | * | ||
35 | * @param num_peers number of peers | ||
36 | * @param rows number of rows in the 2d torus. Can be NULL. | ||
37 | * @param rows_len the length of each row. This array will be allocated | ||
38 | * fresh. The caller should free it. Can be NULL. | ||
39 | */ | ||
40 | unsigned int | ||
41 | GNUNET_TESTBED_2dtorus_calc_links (unsigned int num_peers, unsigned int *rows, | ||
42 | unsigned int **rows_len); | ||
43 | |||
44 | |||
45 | /** | ||
46 | * Get a topology from a string input. | ||
47 | * | ||
48 | * @param topology where to write the retrieved topology | ||
49 | * @param topology_string The string to attempt to | ||
50 | * get a configuration value from | ||
51 | * @return GNUNET_YES if topology string matched a | ||
52 | * known topology, GNUNET_NO if not | ||
53 | */ | ||
54 | int | ||
55 | GNUNET_TESTBED_topology_get_ (enum GNUNET_TESTBED_TopologyOption *topology, | ||
56 | const char *topology_string); | ||
57 | |||
58 | |||
59 | /** | ||
60 | * Returns the string corresponding to the given topology | ||
61 | * | ||
62 | * @param topology the topology | ||
63 | * @return the string (freshly allocated) of given topology; NULL if topology cannot be | ||
64 | * expressed as a string | ||
65 | */ | ||
66 | char * | ||
67 | GNUNET_TESTBED_topology_to_str_ (enum GNUNET_TESTBED_TopologyOption topology); | ||
68 | |||
69 | |||
70 | /** | ||
71 | * Functions of this type are called to process underlay link | ||
72 | * | ||
73 | * @param cls closure | ||
74 | * @param A offset of first peer | ||
75 | * @param B offset of second peer | ||
76 | * @param bandwidth the bandwidth of the link in bytes per second | ||
77 | * @param latency the latency of link in milliseconds | ||
78 | * @param loss the percentage of messages dropped on the link | ||
79 | * @return GNUNET_OK to continue processing; GNUNET_SYSERR to abort | ||
80 | */ | ||
81 | typedef int (*underlay_link_processor) (void *cls, | ||
82 | unsigned int A, | ||
83 | unsigned int B, | ||
84 | unsigned int bandwidth, | ||
85 | unsigned int latency, | ||
86 | unsigned int loss); | ||
87 | |||
88 | |||
89 | /** | ||
90 | * Function to construct an underlay topology | ||
91 | * | ||
92 | * @param num_peers the number of peers for which the topology should be | ||
93 | * generated | ||
94 | * @param proc the underlay link processor callback. Will be called for each | ||
95 | * underlay link generated unless a previous call to this callback | ||
96 | * returned GNUNET_SYSERR. Cannot be NULL. | ||
97 | * @param cls closure for proc | ||
98 | * @param ... variable arguments denoting the topology and its parameters. They | ||
99 | * should start with the type of topology to generate followed by their | ||
100 | * options. These arguments should *always* end with | ||
101 | * GNUNET_TESTBED_TOPOLOGY_OPTION_END option | ||
102 | * @return GNUNET_OK if underlay link generation is successful; GNUNET_SYSERR | ||
103 | * upon error in generating the underlay or if any calls to the | ||
104 | * underlay link processor returned GNUNET_SYSERR | ||
105 | */ | ||
106 | int | ||
107 | GNUNET_TESTBED_underlay_construct_ (int num_peers, | ||
108 | underlay_link_processor proc, | ||
109 | void *cls, | ||
110 | ...); | ||
111 | |||
112 | #endif | ||
113 | /* end of testbed_api_topology.h */ | ||
diff --git a/src/testbed/testbed_api_underlay.c b/src/testbed/testbed_api_underlay.c deleted file mode 100644 index 7e509fdfe..000000000 --- a/src/testbed/testbed_api_underlay.c +++ /dev/null | |||
@@ -1,259 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_api_underlay.c | ||
23 | * @brief testbed underlay API implementation | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "testbed_api_peers.h" | ||
28 | |||
29 | |||
30 | /** | ||
31 | * An underlay link | ||
32 | */ | ||
33 | struct LinkProperty | ||
34 | { | ||
35 | /** | ||
36 | * next pointer for list | ||
37 | */ | ||
38 | struct LinkProperty *next; | ||
39 | |||
40 | /** | ||
41 | * the peer whose link is defined by these properties | ||
42 | */ | ||
43 | struct GNUNET_TESTBED_Peer *peer; | ||
44 | |||
45 | /** | ||
46 | * latency of the link in microseconds | ||
47 | */ | ||
48 | uint32_t latency; | ||
49 | |||
50 | /** | ||
51 | * data loss on the link expressed as percentage | ||
52 | */ | ||
53 | uint32_t loss; | ||
54 | |||
55 | /** | ||
56 | * bandwidth of the link in kilobytes per second | ||
57 | */ | ||
58 | uint32_t bandwidth; | ||
59 | }; | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Container for holding a peer in whitelist/blacklist | ||
64 | */ | ||
65 | struct ListEntry | ||
66 | { | ||
67 | /** | ||
68 | * the next pointer | ||
69 | */ | ||
70 | struct ListEntry *next; | ||
71 | |||
72 | /** | ||
73 | * the peer | ||
74 | */ | ||
75 | struct GNUNET_TESTBED_Peer *peer; | ||
76 | }; | ||
77 | |||
78 | |||
79 | /** | ||
80 | * Model for configuring underlay links of a peer | ||
81 | * @ingroup underlay | ||
82 | */ | ||
83 | struct GNUNET_TESTBED_UnderlayLinkModel | ||
84 | { | ||
85 | /** | ||
86 | * The peer associated with this model | ||
87 | */ | ||
88 | struct GNUNET_TESTBED_Peer *peer; | ||
89 | |||
90 | /** | ||
91 | * List of peers in the list | ||
92 | */ | ||
93 | struct ListEntry *entries; | ||
94 | |||
95 | /** | ||
96 | * list of link properties | ||
97 | */ | ||
98 | struct LinkProperty *props; | ||
99 | |||
100 | /** | ||
101 | * the type of this model | ||
102 | */ | ||
103 | enum GNUNET_TESTBED_UnderlayLinkModelType type; | ||
104 | } | ||
105 | |||
106 | |||
107 | /** | ||
108 | * Function to free resources of list entries | ||
109 | * | ||
110 | * @param model the model | ||
111 | */ | ||
112 | static void | ||
113 | free_entries (struct GNUNET_TESTBED_UnderlayLinkModel *model) | ||
114 | { | ||
115 | struct ListEntry *e; | ||
116 | |||
117 | while (NULL != (e = model->entries)) | ||
118 | { | ||
119 | model->entries = e->next; | ||
120 | GNUNET_free (e); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | |||
125 | /** | ||
126 | * Function to free resources of link properties added to the given model | ||
127 | * | ||
128 | * @param model the model | ||
129 | */ | ||
130 | static void | ||
131 | free_link_properties (struct GNUNET_TESTBED_UnderlayLinkModel *model) | ||
132 | { | ||
133 | struct LinkProperty *p; | ||
134 | |||
135 | while (NULL != (p = model->props)) | ||
136 | { | ||
137 | model->props = p->next; | ||
138 | GNUNET_free (p); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | |||
143 | /** | ||
144 | * Create a GNUNET_TESTBED_UnderlayLinkModel for the given peer. A peer can | ||
145 | * have ONLY ONE model and it can be either a blacklist or whitelist based one. | ||
146 | * | ||
147 | * @ingroup underlay | ||
148 | * @param peer the peer for which the model has to be created | ||
149 | * @param type the type of the model | ||
150 | * @return the model | ||
151 | */ | ||
152 | struct GNUNET_TESTBED_UnderlayLinkModel * | ||
153 | GNUNET_TESTBED_underlaylinkmodel_create (struct GNUNET_TESTBED_Peer *peer, | ||
154 | enum | ||
155 | GNUNET_TESTBED_UnderlayLinkModelType | ||
156 | type) | ||
157 | { | ||
158 | struct GNUNET_TESTBED_UnderlayLinkModel *m; | ||
159 | |||
160 | GNUNET_assert (0 == peer->underlay_model_exists); | ||
161 | m = GNUNET_new (struct GNUNET_TESTBED_UnderlayLinkModel); | ||
162 | peer->underlay_model_exists = 1; | ||
163 | m->type = type; | ||
164 | return m; | ||
165 | } | ||
166 | |||
167 | |||
168 | /** | ||
169 | * Add a peer to the given model. Underlay connections to the given peer will | ||
170 | * be permitted if the model is whitelist based; otherwise they will not be | ||
171 | * permitted. | ||
172 | * | ||
173 | * @ingroup underlay | ||
174 | * @param model the model | ||
175 | * @param peer the peer to add | ||
176 | */ | ||
177 | void | ||
178 | GNUNET_TESTBED_underlaylinkmodel_add_peer (struct | ||
179 | GNUNET_TESTBED_UnderlayLinkModel * | ||
180 | model, | ||
181 | struct GNUNET_TESTBED_Peer *peer) | ||
182 | { | ||
183 | struct ListEntry *entry; | ||
184 | |||
185 | entry = GNUNET_new (struct ListEntry); | ||
186 | entry->peer = peer; | ||
187 | entry->next = model->entries; | ||
188 | model->entries = entry; | ||
189 | } | ||
190 | |||
191 | |||
192 | /** | ||
193 | * Set the metrics for a link to the given peer in the underlay model. The link | ||
194 | * SHOULD be permittable according to the given model. | ||
195 | * | ||
196 | * @ingroup underlay | ||
197 | * @param model the model | ||
198 | * @param peer the other end peer of the link | ||
199 | * @param latency latency of the link in microseconds | ||
200 | * @param loss data loss of the link expressed as a percentage | ||
201 | * @param bandwidth bandwidth of the link in kilobytes per second [kB/s] | ||
202 | */ | ||
203 | void | ||
204 | GNUNET_TESTBED_underlaylinkmodel_set_link (struct | ||
205 | GNUNET_TESTBED_UnderlayLinkModel * | ||
206 | model, | ||
207 | struct GNUNET_TESTBED_Peer *peer, | ||
208 | uint32_t latency, | ||
209 | uint32_t loss, | ||
210 | uint32_t bandwidth) | ||
211 | { | ||
212 | struct LinkProperty *prop; | ||
213 | |||
214 | prop = GNUNET_new (struct LinkProperty); | ||
215 | prop->peer = peer; | ||
216 | prop->latency = latency; | ||
217 | prop->loss = loss; | ||
218 | prop->bandwidth = bandwidth; | ||
219 | prop->next = model->props; | ||
220 | model->props = prop; | ||
221 | } | ||
222 | |||
223 | |||
224 | /** | ||
225 | * Free the resources of the model. Use this function only if the model has not | ||
226 | * be committed and has to be unallocated. The peer can then have another model | ||
227 | * created. | ||
228 | * | ||
229 | * @ingroup underlay | ||
230 | * @param model the model to unallocate | ||
231 | */ | ||
232 | void | ||
233 | GNUNET_TESTBED_underlaylinkmodel_free (struct | ||
234 | GNUNET_TESTBED_UnderlayLinkModel *model) | ||
235 | { | ||
236 | model->peer->underlay_model_exists = 0; | ||
237 | free_entries (model); | ||
238 | free_link_properties (model); | ||
239 | gnunet_free (model); | ||
240 | } | ||
241 | |||
242 | |||
243 | /** | ||
244 | * Commit the model. The model is freed in this function(!). | ||
245 | * | ||
246 | * @ingroup underlay | ||
247 | * @param model the model to commit | ||
248 | */ | ||
249 | void | ||
250 | GNUNET_TESTBED_underlaylinkmodel_commit (struct | ||
251 | GNUNET_TESTBED_UnderlayLinkModel *model) | ||
252 | { | ||
253 | /* FIXME: Marshal the model into a message */ | ||
254 | GNUNET_break (0); | ||
255 | /* do not reset the value of model->peer->underlay_model_exists */ | ||
256 | free_entries (model); | ||
257 | free_link_properties (model); | ||
258 | GNUNET_free (model); | ||
259 | } | ||
diff --git a/src/testbed/testbed_helper.h b/src/testbed/testbed_helper.h deleted file mode 100644 index 817ad559d..000000000 --- a/src/testbed/testbed_helper.h +++ /dev/null | |||
@@ -1,89 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/testbed_helper.h | ||
23 | * @brief Message formats for communication between testbed api and | ||
24 | * gnunet-helper-testbed process | ||
25 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
26 | */ | ||
27 | |||
28 | #ifndef TESTBED_HELPER_H | ||
29 | #define TESTBED_HELPER_H | ||
30 | |||
31 | GNUNET_NETWORK_STRUCT_BEGIN | ||
32 | /** | ||
33 | * Initialization message for gnunet-helper-testbed to start testbed service | ||
34 | */ | ||
35 | struct GNUNET_TESTBED_HelperInit | ||
36 | { | ||
37 | /** | ||
38 | * Type is GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT | ||
39 | */ | ||
40 | struct GNUNET_MessageHeader header; | ||
41 | |||
42 | /** | ||
43 | * The controller hostname size excluding the NULL termination character - | ||
44 | * strlen (hostname); cannot be zero | ||
45 | */ | ||
46 | uint16_t trusted_ip_size GNUNET_PACKED; | ||
47 | |||
48 | /** | ||
49 | * The hostname size excluding the NULL termination character - strlen | ||
50 | * (hostname); cannot be zero | ||
51 | */ | ||
52 | uint16_t hostname_size GNUNET_PACKED; | ||
53 | |||
54 | /** | ||
55 | * The size of the uncompressed configuration | ||
56 | */ | ||
57 | uint16_t config_size GNUNET_PACKED; | ||
58 | |||
59 | /* Followed by NULL terminated trusted ip */ | ||
60 | |||
61 | /* Followed by hostname of the machine on which helper runs. This is not NULL | ||
62 | * terminated */ | ||
63 | |||
64 | /* Followed by serialized and compressed configuration which should be | ||
65 | * config_size long when un-compressed */ | ||
66 | }; | ||
67 | |||
68 | /** | ||
69 | * Reply message from helper process | ||
70 | */ | ||
71 | struct GNUNET_TESTBED_HelperReply | ||
72 | { | ||
73 | /** | ||
74 | * Type is GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY | ||
75 | */ | ||
76 | struct GNUNET_MessageHeader header; | ||
77 | |||
78 | /** | ||
79 | * Size of the uncompressed configuration | ||
80 | */ | ||
81 | uint16_t config_size GNUNET_PACKED; | ||
82 | |||
83 | /* Followed by compressed configuration which should be config_size long when | ||
84 | * un-compressed */ | ||
85 | }; | ||
86 | |||
87 | GNUNET_NETWORK_STRUCT_END | ||
88 | #endif | ||
89 | /* end of testbed_helper.h */ | ||
diff --git a/src/testbed/valgrind-zlib.supp b/src/testbed/valgrind-zlib.supp deleted file mode 100644 index ca6ce115f..000000000 --- a/src/testbed/valgrind-zlib.supp +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | { | ||
2 | <ZlibInflateReset2UninitJump> | ||
3 | Memcheck:Cond | ||
4 | fun:inflateReset2 | ||
5 | ... | ||
6 | } | ||
diff --git a/src/testbed/x64_misc.supp b/src/testbed/x64_misc.supp deleted file mode 100644 index e6a19c33e..000000000 --- a/src/testbed/x64_misc.supp +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | { | ||
2 | <unknown invalid free> | ||
3 | Memcheck:Free | ||
4 | fun:free | ||
5 | fun:free_mem | ||
6 | fun:__libc_freeres | ||
7 | fun:_vgnU_freeres | ||
8 | fun:__run_exit_handlers | ||
9 | fun:exit | ||
10 | fun:(below main) | ||
11 | } | ||
12 | { | ||
13 | <gnunet_crypto_init> | ||
14 | Memcheck:Leak | ||
15 | fun:malloc | ||
16 | obj:/usr/lib/libgcrypt.so.11.5.3 | ||
17 | ... | ||
18 | obj:/usr/lib/libgcrypt.so.11.5.3 | ||
19 | fun:gcry_control | ||
20 | fun:GNUNET_CRYPTO_random_init | ||
21 | obj:/home/harsha/repos/gnunet/src/util/.libs/libgnunetutil.so.8.0.0 | ||
22 | obj:/home/harsha/repos/gnunet/src/util/.libs/libgnunetutil.so.8.0.0 | ||
23 | } | ||
24 | |||
25 | { | ||
26 | <insert_a_suppression_name_here> | ||
27 | Memcheck:Leak | ||
28 | fun:malloc | ||
29 | ... | ||
30 | fun:gcry_control | ||
31 | fun:GNUNET_CRYPTO_random_init | ||
32 | obj:/home/totakura/gnunet/src/util/.libs/libgnunetutil.so.8.0.0 | ||
33 | obj:/home/totakura/gnunet/src/util/.libs/libgnunetutil.so.8.0.0 | ||
34 | } | ||