aboutsummaryrefslogtreecommitdiff
path: root/src/testbed
diff options
context:
space:
mode:
Diffstat (limited to 'src/testbed')
-rw-r--r--src/testbed/.gitignore37
-rw-r--r--src/testbed/Makefile.am401
-rw-r--r--src/testbed/barriers.README.org95
-rw-r--r--src/testbed/buildvars.py.in34
-rw-r--r--src/testbed/generate-underlay-topology.c407
-rw-r--r--src/testbed/gnunet-daemon-latency-logger.c322
-rw-r--r--src/testbed/gnunet-daemon-testbed-blacklist.c254
-rw-r--r--src/testbed/gnunet-daemon-testbed-underlay.c481
-rw-r--r--src/testbed/gnunet-helper-testbed-valgrind.patch21
-rw-r--r--src/testbed/gnunet-helper-testbed.c613
-rw-r--r--src/testbed/gnunet-service-test-barriers.c152
-rw-r--r--src/testbed/gnunet-service-testbed.c985
-rw-r--r--src/testbed/gnunet-service-testbed.h900
-rw-r--r--src/testbed/gnunet-service-testbed_barriers.c926
-rw-r--r--src/testbed/gnunet-service-testbed_barriers.h128
-rw-r--r--src/testbed/gnunet-service-testbed_cache.c269
-rw-r--r--src/testbed/gnunet-service-testbed_connectionpool.c1044
-rw-r--r--src/testbed/gnunet-service-testbed_connectionpool.h172
-rw-r--r--src/testbed/gnunet-service-testbed_cpustatus.c664
-rw-r--r--src/testbed/gnunet-service-testbed_links.c1467
-rw-r--r--src/testbed/gnunet-service-testbed_links.h209
-rw-r--r--src/testbed/gnunet-service-testbed_meminfo.c279
-rw-r--r--src/testbed/gnunet-service-testbed_meminfo.h55
-rw-r--r--src/testbed/gnunet-service-testbed_oc.c1996
-rw-r--r--src/testbed/gnunet-service-testbed_peers.c1569
-rw-r--r--src/testbed/gnunet-testbed-profiler.c323
-rw-r--r--src/testbed/gnunet_mpi_test.c108
-rw-r--r--src/testbed/misc.supp49
-rw-r--r--src/testbed/overlay_topology.txt5
-rw-r--r--src/testbed/profile-testbed.patch43
-rwxr-xr-xsrc/testbed/sample.job16
-rw-r--r--src/testbed/sample_hosts.txt7
-rw-r--r--src/testbed/test-underlay.sqlitebin3072 -> 0 bytes
-rw-r--r--src/testbed/test_gnunet_helper_testbed.c255
-rw-r--r--src/testbed/test_testbed_api.c515
-rw-r--r--src/testbed/test_testbed_api.conf1
-rw-r--r--src/testbed/test_testbed_api_2peers_1controller.c540
-rw-r--r--src/testbed/test_testbed_api_3peers_3controllers.c964
-rw-r--r--src/testbed/test_testbed_api_barriers.c234
-rw-r--r--src/testbed/test_testbed_api_barriers.conf.in103
-rw-r--r--src/testbed/test_testbed_api_barriers.h4
-rw-r--r--src/testbed/test_testbed_api_controllerlink.c881
-rw-r--r--src/testbed/test_testbed_api_hosts.c183
-rw-r--r--src/testbed/test_testbed_api_operations.c568
-rw-r--r--src/testbed/test_testbed_api_peer_reconfiguration.c194
-rw-r--r--src/testbed/test_testbed_api_peers_manage_services.c216
-rw-r--r--src/testbed/test_testbed_api_sd.c111
-rw-r--r--src/testbed/test_testbed_api_statistics.c205
-rw-r--r--src/testbed/test_testbed_api_statistics.conf9
-rw-r--r--src/testbed/test_testbed_api_template.conf49
-rw-r--r--src/testbed/test_testbed_api_test.c251
-rw-r--r--src/testbed/test_testbed_api_test_timeout.c126
-rw-r--r--src/testbed/test_testbed_api_test_timeout.conf5
-rw-r--r--src/testbed/test_testbed_api_testbed_run.c242
-rw-r--r--src/testbed/test_testbed_api_testbed_run_topology2dtorus.conf5
-rw-r--r--src/testbed/test_testbed_api_testbed_run_topologyclique.conf4
-rw-r--r--src/testbed/test_testbed_api_testbed_run_topologyfromfile.conf5
-rw-r--r--src/testbed/test_testbed_api_testbed_run_topologyline.conf4
-rw-r--r--src/testbed/test_testbed_api_testbed_run_topologyrandom.conf5
-rw-r--r--src/testbed/test_testbed_api_testbed_run_topologyring.conf4
-rw-r--r--src/testbed/test_testbed_api_testbed_run_topologyscalefree.conf6
-rw-r--r--src/testbed/test_testbed_api_testbed_run_topologysmallworld.conf5
-rw-r--r--src/testbed/test_testbed_api_testbed_run_topologysmallworldring.conf5
-rw-r--r--src/testbed/test_testbed_api_testbed_run_topologystar.conf4
-rw-r--r--src/testbed/test_testbed_api_topology.c189
-rw-r--r--src/testbed/test_testbed_api_topology_clique.c185
-rw-r--r--src/testbed/test_testbed_underlay.c174
-rw-r--r--src/testbed/test_testbed_underlay.conf.in13
-rw-r--r--src/testbed/testbed.conf.in116
-rw-r--r--src/testbed/testbed.h866
-rw-r--r--src/testbed/testbed_api.c2474
-rw-r--r--src/testbed/testbed_api.h521
-rw-r--r--src/testbed/testbed_api_barriers.c264
-rw-r--r--src/testbed/testbed_api_hosts.c1539
-rw-r--r--src/testbed/testbed_api_hosts.h227
-rw-r--r--src/testbed/testbed_api_operations.c1387
-rw-r--r--src/testbed/testbed_api_operations.h233
-rw-r--r--src/testbed/testbed_api_peers.c1016
-rw-r--r--src/testbed/testbed_api_peers.h311
-rw-r--r--src/testbed/testbed_api_sd.c213
-rw-r--r--src/testbed/testbed_api_sd.h81
-rw-r--r--src/testbed/testbed_api_services.c291
-rw-r--r--src/testbed/testbed_api_statistics.c435
-rw-r--r--src/testbed/testbed_api_test.c175
-rw-r--r--src/testbed/testbed_api_testbed.c1472
-rw-r--r--src/testbed/testbed_api_topology.c1661
-rw-r--r--src/testbed/testbed_api_topology.h113
-rw-r--r--src/testbed/testbed_api_underlay.c259
-rw-r--r--src/testbed/testbed_helper.h89
-rw-r--r--src/testbed/valgrind-zlib.supp6
-rw-r--r--src/testbed/x64_misc.supp34
91 files changed, 0 insertions, 34078 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 @@
1gnunet-testbed-profiler
2generate-underlay-topology
3gnunet-daemon-latency-logger
4gnunet-daemon-testbed-blacklist
5gnunet-daemon-testbed-underlay
6gnunet-helper-testbed
7gnunet-service-testbed
8gnunet-service-test-barriers
9test_gnunet_helper_testbed
10test_testbed_api
11test_testbed_api_2peers_1controller
12test_testbed_api_3peers_3controllers
13test_testbed_api_barriers
14test_testbed_api_controllerlink
15test_testbed_api_hosts
16test_testbed_api_operations
17test_testbed_api_peer_reconfiguration
18test_testbed_api_peers_manage_services
19test_testbed_api_sd
20test_testbed_api_statistics
21test_testbed_api_test
22test_testbed_api_test_timeout
23test_testbed_api_testbed_run
24test_testbed_api_testbed_run_topology2dtorus
25test_testbed_api_testbed_run_topologyclique
26test_testbed_api_testbed_run_topologyfromfile
27test_testbed_api_testbed_run_topologyline
28test_testbed_api_testbed_run_topologyrandom
29test_testbed_api_testbed_run_topologyring
30test_testbed_api_testbed_run_topologyscalefree
31test_testbed_api_testbed_run_topologysmallworld
32test_testbed_api_testbed_run_topologysmallworldring
33test_testbed_api_testbed_run_topologystar
34test_testbed_api_testbed_run_waitforever
35test_testbed_api_topology
36test_testbed_api_topology_clique
37test_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
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4if USE_COVERAGE
5 AM_CFLAGS = --coverage -O0
6 XLIB = -lgcov
7endif
8
9plugindir = $(libdir)/gnunet
10
11libexecdir= $(pkglibdir)/libexec/
12
13pkgcfgdir= $(pkgdatadir)/config.d/
14
15pkgcfg_DATA = \
16 testbed.conf
17
18if 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
23endif
24
25libexec_PROGRAMS = \
26 gnunet-service-testbed \
27 gnunet-helper-testbed \
28 gnunet-daemon-testbed-blacklist \
29 $(underlay_daemon) \
30 $(latency_logger)
31
32bin_PROGRAMS = \
33 gnunet-testbed-profiler
34
35noinst_PROGRAMS = \
36 $(generate_underlay)
37
38gnunet_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
48gnunet_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
59gnunet_testbed_profiler_SOURCES = \
60 gnunet-testbed-profiler.c
61gnunet_testbed_profiler_LDADD = $(XLIB) \
62 $(top_builddir)/src/testing/libgnunettesting.la \
63 $(top_builddir)/src/util/libgnunetutil.la \
64 libgnunettestbed.la
65gnunet_testbed_profiler_LDFLAGS = \
66 $(GN_LIBINTL)
67
68gnunet_helper_testbed_SOURCES = \
69 gnunet-helper-testbed.c
70gnunet_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
76gnunet_daemon_testbed_blacklist_SOURCES = gnunet-daemon-testbed-blacklist.c
77gnunet_daemon_testbed_blacklist_LDADD = $(XLIB) \
78 $(top_builddir)/src/transport/libgnunettransport.la \
79 $(top_builddir)/src/util/libgnunetutil.la \
80 $(LTLIBINTL)
81
82gnunet_daemon_testbed_underlay_SOURCES = gnunet-daemon-testbed-underlay.c
83gnunet_daemon_testbed_underlay_LDADD = $(XLIB) \
84 $(top_builddir)/src/transport/libgnunettransport.la \
85 $(top_builddir)/src/util/libgnunetutil.la \
86 $(LTLIBINTL) -lsqlite3
87
88gnunet_daemon_latency_logger_SOURCES = gnunet-daemon-latency-logger.c
89gnunet_daemon_latency_logger_LDADD = $(XLIB) \
90 $(top_builddir)/src/ats/libgnunetats.la \
91 $(top_builddir)/src/util/libgnunetutil.la \
92 $(LTLIBINTL) -lsqlite3
93
94lib_LTLIBRARIES = \
95 libgnunettestbed.la
96
97libgnunettestbed_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
109libgnunettestbed_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)
118libgnunettestbed_la_LDFLAGS = \
119 $(GN_LIB_LDFLAGS) \
120 -version-info 0:0:0
121
122generate_underlay_topology_SOURCES = generate-underlay-topology.c
123generate_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
129check_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
161if 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)
192endif
193
194test_testbed_api_SOURCES = \
195 test_testbed_api.c
196test_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
202test_testbed_api_sd_SOURCES = \
203 test_testbed_api_sd.c
204test_testbed_api_sd_LDADD = \
205 $(top_builddir)/src/util/libgnunetutil.la \
206 libgnunettestbed.la
207
208test_testbed_api_2peers_1controller_SOURCES = \
209 test_testbed_api_2peers_1controller.c
210test_testbed_api_2peers_1controller_LDADD = \
211 $(top_builddir)/src/util/libgnunetutil.la \
212 $(top_builddir)/src/testing/libgnunettesting.la \
213 libgnunettestbed.la
214
215test_testbed_api_3peers_3controllers_SOURCES = \
216 test_testbed_api_3peers_3controllers.c
217test_testbed_api_3peers_3controllers_LDADD = \
218 $(top_builddir)/src/util/libgnunetutil.la \
219 $(top_builddir)/src/testing/libgnunettesting.la \
220 libgnunettestbed.la
221
222test_testbed_api_operations_SOURCES = \
223 test_testbed_api_operations.c
224test_testbed_api_operations_LDADD = \
225 $(top_builddir)/src/util/libgnunetutil.la \
226 libgnunettestbed.la
227
228test_testbed_api_hosts_SOURCES = \
229 test_testbed_api_hosts.c
230test_testbed_api_hosts_LDADD = \
231 $(top_builddir)/src/util/libgnunetutil.la \
232 libgnunettestbed.la
233
234test_testbed_api_controllerlink_SOURCES = \
235 test_testbed_api_controllerlink.c
236test_testbed_api_controllerlink_LDADD = \
237 $(top_builddir)/src/util/libgnunetutil.la \
238 libgnunettestbed.la
239
240test_testbed_api_testbed_run_SOURCES = \
241 test_testbed_api_testbed_run.c
242test_testbed_api_testbed_run_LDADD = \
243 $(top_builddir)/src/util/libgnunetutil.la \
244 libgnunettestbed.la
245
246test_testbed_api_test_SOURCES = \
247 test_testbed_api_test.c
248test_testbed_api_test_LDADD = \
249 $(top_builddir)/src/util/libgnunetutil.la \
250 libgnunettestbed.la
251
252test_testbed_api_test_timeout_SOURCES = \
253 test_testbed_api_test_timeout.c
254test_testbed_api_test_timeout_LDADD = \
255 $(top_builddir)/src/util/libgnunetutil.la \
256 libgnunettestbed.la
257
258test_testbed_api_topology_SOURCES = \
259 test_testbed_api_topology.c
260test_testbed_api_topology_LDADD = \
261 $(top_builddir)/src/util/libgnunetutil.la \
262 libgnunettestbed.la
263
264test_testbed_api_topology_clique_SOURCES = \
265 test_testbed_api_topology_clique.c
266test_testbed_api_topology_clique_LDADD = \
267 $(top_builddir)/src/util/libgnunetutil.la \
268 libgnunettestbed.la
269
270test_gnunet_helper_testbed_SOURCES = \
271 test_gnunet_helper_testbed.c
272test_gnunet_helper_testbed_LDADD = \
273 $(top_builddir)/src/util/libgnunetutil.la \
274 libgnunettestbed.la \
275 $(Z_LIBS)
276
277test_testbed_api_testbed_run_topologyrandom_SOURCES = \
278 test_testbed_api_testbed_run.c
279test_testbed_api_testbed_run_topologyrandom_LDADD = \
280 $(top_builddir)/src/util/libgnunetutil.la \
281 libgnunettestbed.la
282
283test_testbed_api_testbed_run_topologyline_SOURCES = \
284 test_testbed_api_testbed_run.c
285test_testbed_api_testbed_run_topologyline_LDADD = \
286 $(top_builddir)/src/util/libgnunetutil.la \
287 libgnunettestbed.la
288
289test_testbed_api_testbed_run_topologystar_SOURCES = \
290 test_testbed_api_testbed_run.c
291test_testbed_api_testbed_run_topologystar_LDADD = \
292 $(top_builddir)/src/util/libgnunetutil.la \
293 libgnunettestbed.la
294
295test_testbed_api_testbed_run_topologyclique_SOURCES = \
296 test_testbed_api_testbed_run.c
297test_testbed_api_testbed_run_topologyclique_LDADD = \
298 $(top_builddir)/src/util/libgnunetutil.la \
299 libgnunettestbed.la
300
301test_testbed_api_testbed_run_topologyring_SOURCES = \
302 test_testbed_api_testbed_run.c
303test_testbed_api_testbed_run_topologyring_LDADD = \
304 $(top_builddir)/src/util/libgnunetutil.la \
305 libgnunettestbed.la
306
307test_testbed_api_testbed_run_topologysmallworldring_SOURCES = \
308 test_testbed_api_testbed_run.c
309test_testbed_api_testbed_run_topologysmallworldring_LDADD = \
310 $(top_builddir)/src/util/libgnunetutil.la \
311 libgnunettestbed.la
312
313test_testbed_api_testbed_run_topology2dtorus_SOURCES = \
314 test_testbed_api_testbed_run.c
315test_testbed_api_testbed_run_topology2dtorus_LDADD = \
316 $(top_builddir)/src/util/libgnunetutil.la \
317 libgnunettestbed.la
318
319test_testbed_api_testbed_run_topologysmallworld_SOURCES = \
320 test_testbed_api_testbed_run.c
321test_testbed_api_testbed_run_topologysmallworld_LDADD = \
322 $(top_builddir)/src/util/libgnunetutil.la \
323 libgnunettestbed.la
324
325test_testbed_api_testbed_run_topologyfromfile_SOURCES = \
326 test_testbed_api_testbed_run.c
327test_testbed_api_testbed_run_topologyfromfile_LDADD = \
328 $(top_builddir)/src/util/libgnunetutil.la \
329 libgnunettestbed.la
330
331test_testbed_api_testbed_run_topologyscalefree_SOURCES = \
332 test_testbed_api_testbed_run.c
333test_testbed_api_testbed_run_topologyscalefree_LDADD = \
334 $(top_builddir)/src/util/libgnunetutil.la \
335 libgnunettestbed.la
336
337test_testbed_api_testbed_run_waitforever_SOURCES = \
338 test_testbed_api_testbed_run.c
339test_testbed_api_testbed_run_waitforever_LDADD = \
340 $(top_builddir)/src/util/libgnunetutil.la \
341 libgnunettestbed.la
342
343test_testbed_api_statistics_SOURCES = \
344 test_testbed_api_statistics.c
345test_testbed_api_statistics_LDADD = \
346 $(top_builddir)/src/util/libgnunetutil.la \
347 libgnunettestbed.la
348
349test_testbed_api_peers_manage_services_SOURCES = \
350 test_testbed_api_peers_manage_services.c
351test_testbed_api_peers_manage_services_LDADD = \
352 $(top_builddir)/src/util/libgnunetutil.la \
353 libgnunettestbed.la
354
355test_testbed_api_peer_reconfiguration_SOURCES = \
356 test_testbed_api_peer_reconfiguration.c
357test_testbed_api_peer_reconfiguration_LDADD = \
358 $(top_builddir)/src/util/libgnunetutil.la \
359 libgnunettestbed.la
360
361test_testbed_api_barriers_SOURCES = \
362 test_testbed_api_barriers.c \
363 test_testbed_api_barriers.h
364test_testbed_api_barriers_LDADD = \
365 $(top_builddir)/src/util/libgnunetutil.la \
366 libgnunettestbed.la
367
368gnunet_service_test_barriers_SOURCES = \
369 gnunet-service-test-barriers.c \
370 test_testbed_api_barriers.h
371gnunet_service_test_barriers_LDADD = \
372 $(top_builddir)/src/util/libgnunetutil.la \
373 libgnunettestbed.la
374
375test_testbed_underlay_SOURCES = \
376 test_testbed_underlay.c
377test_testbed_underlay_LDADD = \
378 $(top_builddir)/src/util/libgnunetutil.la \
379 libgnunettestbed.la
380
381EXTRA_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
2The testbed subsystem's barriers API facilitates coordination among the peers
3run by the testbed and the experiment driver. The concept is similar to the
4barrier synchronisation mechanism found in parallel programming or
5multi-threading paradigms - a peer waits at a barrier upon reaching it until the
6barrier is reached by a predefined number of peers. This predefined number of
7peers required to cross a barrier is also called quorum. We say a peer has
8reached a barrier if the peer is waiting for the barrier to be crossed.
9Similarly a barrier is said to be reached if the required quorum of peers reach
10the barrier. A barrier which is reached is deemed as crossed after all the
11peers waiting on it are notified.
12
13The barriers API provides the following functions:
141) GNUNET_TESTBED_barrier_init(): function to initialise a barrier in the
15 experiment
162) GNUNET_TESTBED_barrier_cancel(): function to cancel a barrier which has been
17 initialised before
183) 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
204) GNUNET_TESTBED_barrier_wait_cancel(): function to stop waiting for a barrier
21 to be crossed
22
23Among the above functions, the first two, namely GNUNET_TESTBED_barrier_init()
24and GNUNET_TESTBED_barrier_cacel() are used by experiment drivers. All barriers
25should be initialised by the experiment driver by calling
26GNUNET_TESTBED_barrier_init(). This function takes a name to identify the
27barrier, the quorum required for the barrier to be crossed and a notification
28callback for notifying the experiment driver when the barrier is crossed. The
29GNUNET_TESTBED_function barrier_cancel() cancels an initialised barrier and
30frees the resources allocated for it. This function can be called upon a
31initialised barrier before it is crossed.
32
33The remaining two functions GNUNET_TESTBED_barrier_wait() and
34GNUNET_TESTBED_barrier_wait_cancel() are used in the peer's processes.
35GNUNET_TESTBED_barrier_wait() connects to the local barrier service running on
36the same host the peer is running on and registers that the caller has reached
37the barrier and is waiting for the barrier to be crossed. Note that this
38function can only be used by peers which are started by testbed as this function
39tries to access the local barrier service which is part of the testbed
40controller service. Calling GNUNET_TESTBED_barrier_wait() on an uninitialised
41barrier results in failure. GNUNET_TESTBED_barrier_wait_cancel() cancels the
42notification registered by GNUNET_TESTBED_barrier_wait().
43
44
45* Implementation
46Since barriers involve coordination between experiment driver and peers, the
47barrier service in the testbed controller is split into two components. The
48first component responds to the message generated by the barrier API used by the
49experiment driver (functions GNUNET_TESTBED_barrier_init() and
50GNUNET_TESTBED_barrier_cancel()) and the second component to the messages
51generated by barrier API used by peers (functions GNUNET_TESTBED_barrier_wait()
52and GNUNET_TESTBED_barrier_wait_cancel()).
53
54Calling GNUNET_TESTBED_barrier_init() sends a BARRIER_INIT message to the master
55controller. The master controller then registers a barrier and calls
56GNUNET_TESTBED_barrier_init() for each its subcontrollers. In this way barrier
57initialisation is propagated to the controller hierarchy. While propagating
58initialisation, any errors at a subcontroller such as timeout during further
59propagation are reported up the hierarchy back to the experiment driver.
60
61Similar to GNUNET_TESTBED_barrier_init(), GNUNET_TESTBED_barrier_cancel()
62propagates BARRIER_CANCEL message which causes controllers to remove an
63initialised barrier.
64
65The second component is implemented as a separate service in the binary
66`gnunet-service-testbed' which already has the testbed controller service.
67Although this deviates from the gnunet process architecture of having one
68service per binary, it is needed in this case as this component needs access to
69barrier data created by the first component. This component responds to
70BARRIER_WAIT messages from local peers when they call
71GNUNET_TESTBED_barrier_wait(). Upon receiving BARRIER_WAIT message, the service
72checks if the requested barrier has been initialised before and if it was not
73initialised, an error status is sent through BARRIER_STATUS message to the local
74peer and the connection from the peer is terminated. If the barrier is
75initialised before, the barrier's counter for reached peers is incremented and a
76notification is registered to notify the peer when the barrier is reached. The
77connection from the peer is left open.
78
79When enough peers required to attain the quorum send BARRIER_WAIT messages, the
80controller sends a BARRIER_STATUS message to its parent informing that the
81barrier is crossed. If the controller has started further subcontrollers, it
82delays this message until it receives a similar notification from each of those
83subcontrollers. Finally, the barriers API at the experiment driver receives the
84BARRIER_STATUS when the barrier is reached at all the controllers.
85
86The barriers API at the experiment driver responds to the BARRIER_STATUS message
87by echoing it back to the master controller and notifying the experiment
88controller through the notification callback that a barrier has been crossed.
89The echoed BARRIER_STATUS message is propagated by the master controller to the
90controller hierarchy. This propagation triggers the notifications registered by
91peers at each of the controllers in the hierarchy. Note the difference between
92this downward propagation of the BARRIER_STATUS message from its upward
93propagation -- the upward propagation is needed for ensuring that the barrier is
94reached by all the controllers and the downward propagation is for triggering
95that 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
23import os
24
25exec_prefix = '@exec_prefix@'
26libexecdir = '@libexecdir@'
27
28if libexecdir.startswith(exec_prefix):
29 libexecdir = libexecdir[len(exec_prefix):]
30
31gnunet_prefix = os.environ.get('GNUNET_PREFIX', None)
32
33if 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 */
66static struct sqlite3 *db;
67
68/**
69 * Prepared statement for inserting link values into db
70 */
71struct sqlite3_stmt *stmt_insert;
72
73/**
74 * The topology to generate
75 */
76enum GNUNET_TESTBED_TopologyOption topology;
77
78/**
79 * The number of peers to include in the topology
80 */
81static unsigned int num_peers;
82
83/**
84 * program result
85 */
86static 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 */
100static int
101link_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 */
150static int
151setup_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
203err_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 */
216static void
217run (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 */
359int
360main (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 */
64struct 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 */
82static struct GNUNET_CONTAINER_MultiPeerMap *map;
83
84/**
85 * The SQLite database handle
86 */
87static struct sqlite3 *db;
88
89/**
90 * Handle to the ATS performance subsystem
91 */
92static struct GNUNET_ATS_PerformanceHandle *ats;
93
94/**
95 * Prepared statement for inserting values into the database table
96 */
97static 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 */
111static int
112free_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 */
131static void
132do_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 */
167static void
168addr_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
245err_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 */
258static void
259run (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 */
304int
305main (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 */
59static struct GNUNET_CONTAINER_MultiPeerMap *map;
60
61/**
62 * The array of peer identities we read from whitelist/blacklist
63 */
64static struct GNUNET_PeerIdentity *ilist;
65
66/**
67 * The blacklist handle we obtain from transport when we register ourselves for
68 * access control
69 */
70static struct GNUNET_TRANSPORT_Blacklist *bh;
71
72/**
73 * Are we allowing or denying access from peers
74 */
75static int mode;
76
77
78/**
79 * Cleaup and destroy the map
80 */
81static void
82cleanup_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 */
97static void
98do_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 */
113static int
114check_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 */
135static void
136setup_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 */
183static void
184run (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 */
233int
234main (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 */
68static struct GNUNET_CONTAINER_MultiPeerMap *map;
69
70/**
71 * The database connection
72 */
73static struct sqlite3 *db;
74
75/**
76 * The blacklist handle we obtain from transport when we register ourselves for
77 * access control
78 */
79static struct GNUNET_TRANSPORT_Blacklist *bh;
80
81/**
82 * The hostkeys file
83 */
84struct GNUNET_DISK_FileHandle *hostkeys_fd;
85
86/**
87 * The hostkeys map
88 */
89static struct GNUNET_DISK_MapHandle *hostkeys_map;
90
91/**
92 * The hostkeys data
93 */
94static void *hostkeys_data;
95
96/**
97 * Handle to the transport service. This is used for setting link metrics
98 */
99static struct GNUNET_TRANSPORT_ManipulationHandle *transport;
100
101/**
102 * The number of hostkeys in the hostkeys array
103 */
104static 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 */
118static int
119iterator (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 */
130static void
131cleanup_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 */
152static int
153check_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
169static int
170get_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 */
189struct 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 */
211static int
212load_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 */
265static void
266unload_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 */
288static void
289do_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 */
311static int
312db_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 */
360static void
361run (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
447close_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 */
459int
460main (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 @@
1Index: 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 */
63struct 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 */
85static struct GNUNET_TESTING_System *test_system;
86
87/**
88 * Our message stream tokenizer
89 */
90struct GNUNET_MessageStreamTokenizer *tokenizer;
91
92/**
93 * Disk handle from stdin
94 */
95static struct GNUNET_DISK_FileHandle *stdin_fd;
96
97/**
98 * Disk handle for stdout
99 */
100static struct GNUNET_DISK_FileHandle *stdout_fd;
101
102/**
103 * The process handle to the testbed service
104 */
105static struct GNUNET_OS_Process *testbed;
106
107/**
108 * Pipe used to communicate shutdown via signal.
109 */
110static struct GNUNET_DISK_PipeHandle *sigpipe;
111
112/**
113 * Task identifier for the read task
114 */
115static struct GNUNET_SCHEDULER_Task *read_task_id;
116
117/**
118 * Task identifier for the write task
119 */
120static struct GNUNET_SCHEDULER_Task *write_task_id;
121
122/**
123 * Task to kill the child
124 */
125static struct GNUNET_SCHEDULER_Task *child_death_task_id;
126
127/**
128 * Are we done reading messages from stdin?
129 */
130static int done_reading;
131
132/**
133 * Result to return in case we fail
134 */
135static int status;
136
137
138/**
139 * Task to shut down cleanly
140 *
141 * @param cls NULL
142 */
143static void
144shutdown_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 */
196static void
197write_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 */
234static void
235child_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 */
288static int
289tokenizer_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
476error:
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 */
488static void
489read_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 */
535static void
536run (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 */
556static void
557sighandler_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 */
580int
581main (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 */
42static struct GNUNET_TESTBED_BarrierWaitHandle *wh;
43
44static struct GNUNET_SCHEDULER_Task *tt;
45
46
47/**
48 * Dummy task callback to keep us running forever
49 *
50 * @param cls NULL
51 */
52static void
53do_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 */
78static void
79barrier_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 */
95static void
96do_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 */
114static void
115run (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 */
136int
137main (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 */
38struct GNUNET_CONFIGURATION_Handle *GST_config;
39
40/**
41 * The master context; generated with the first INIT message
42 */
43struct Context *GST_context;
44
45/**
46 * Array of hosts
47 */
48struct GNUNET_TESTBED_Host **GST_host_list;
49
50/**
51 * DLL head for forwarded operation contexts
52 */
53struct ForwardedOperationContext *fopcq_head;
54
55/**
56 * DLL tail for forwarded operation contexts
57 */
58struct ForwardedOperationContext *fopcq_tail;
59
60/**
61 * Operation queue for open file descriptors
62 */
63struct OperationQueue *GST_opq_openfds;
64
65/**
66 * Timeout for operations which may take some time
67 */
68struct GNUNET_TIME_Relative GST_timeout;
69
70/**
71 * The size of the host list
72 */
73unsigned int GST_host_list_size;
74
75/**
76 * The size of the peer list
77 */
78unsigned 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 */
88static 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 */
98static int
99host_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 */
123void
124GST_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 */
152void
153GST_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 */
174static void
175hr_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 */
185static void
186register_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 */
210static void
211hr_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 */
245void
246GST_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 */
277void
278GST_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 */
303void
304GST_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 */
331static struct GNUNET_TESTING_SharedService *
332parse_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 */
390static int
391check_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 */
414static void
415handle_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 */
486static int
487check_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 */
521static void
522handle_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 */
618static void
619handle_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 */
680void
681GST_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 */
735static void
736shutdown_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 */
790static void *
791client_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 */
806static void
807client_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 */
851static void
852testbed_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 */
907GNUNET_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 */
62struct 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 */
79struct 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 */
126struct 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 */
158struct 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 */
175struct 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 */
245struct 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 */
272struct 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
291struct RegisteredHostContext;
292
293
294/**
295 * Context information to used during operations which forward the overlay
296 * connect message
297 */
298struct 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 */
351struct 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 */
394struct 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 */
413extern struct GNUNET_CONFIGURATION_Handle *GST_config;
414
415/**
416 * The master context; generated with the first INIT message
417 */
418extern struct Context *GST_context;
419
420/**
421 * DLL head for forwarded operation contexts
422 */
423extern struct ForwardedOperationContext *fopcq_head;
424
425/**
426 * DLL tail for forwarded operation contexts
427 */
428extern struct ForwardedOperationContext *fopcq_tail;
429
430/**
431 * A list of peers we know about
432 */
433extern struct Peer **GST_peer_list;
434
435/**
436 * Array of hosts
437 */
438extern struct GNUNET_TESTBED_Host **GST_host_list;
439
440/**
441 * Operation queue for open file descriptors
442 */
443extern struct OperationQueue *GST_opq_openfds;
444
445/**
446 * Timeout for operations which may take some time
447 */
448extern struct GNUNET_TIME_Relative GST_timeout;
449
450/**
451 * The size of the peer list
452 */
453extern unsigned int GST_peer_list_size;
454
455/**
456 * The current number of peers running locally under this controller
457 */
458extern unsigned int GST_num_local_peers;
459
460/**
461 * The size of the host list
462 */
463extern unsigned int GST_host_list_size;
464
465/**
466 * The directory where to store load statistics data
467 */
468extern 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 */
512void
513GST_destroy_peer (struct Peer *peer);
514
515
516/**
517 * Stops and destroys all peers
518 */
519void
520GST_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 */
531struct Route *
532GST_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 */
541void
542handle_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 */
555void
556GST_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 */
567void
568GST_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 */
578void
579GST_forwarded_operation_timeout (void *cls);
580
581
582/**
583 * Clears the forwarded operations queue
584 */
585void
586GST_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 */
596void
597GST_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 */
607void
608GST_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 */
616void
617GST_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 */
626void
627GST_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 */
638int
639check_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 */
650void
651handle_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 */
663int
664check_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 */
674void
675handle_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 */
685void
686handle_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 */
696void
697handle_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 */
707void
708handle_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 */
718void
719handle_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 */
730void
731handle_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 */
742int
743check_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 */
754void
755handle_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 */
767int
768check_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 */
781void
782handle_peer_reconfigure (void *cls,
783 const struct
784 GNUNET_TESTBED_PeerReconfigureMessage *msg);
785
786
787/**
788 * Frees the ManageServiceContext queue
789 */
790void
791GST_free_mctxq (void);
792
793
794/**
795 * Cleans up the queue used for forwarding link controllers requests
796 */
797void
798GST_free_lcf (void);
799
800
801/**
802 * Cleans up the route list
803 */
804void
805GST_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 */
813void
814GST_process_next_focc (struct RegisteredHostContext *rhc);
815
816
817/**
818 * Cleans up ForwardedOverlayConnectContext
819 *
820 * @param focc the ForwardedOverlayConnectContext to cleanup
821 */
822void
823GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc);
824
825
826/**
827 * Clears all pending overlay connect contexts in queue
828 */
829void
830GST_free_occq (void);
831
832
833/**
834 * Clears all pending remote overlay connect contexts in queue
835 */
836void
837GST_free_roccq (void);
838
839
840/**
841 * Cleans up the Peer reconfigure context list
842 */
843void
844GST_free_prcq (void);
845
846
847/**
848 * Initializes the cache
849 *
850 * @param size the size of the cache
851 */
852void
853GST_cache_init (unsigned int size);
854
855
856/**
857 * Clear cache
858 */
859void
860GST_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 */
869const struct GNUNET_MessageHeader *
870GST_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 */
880void
881GST_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 */
890void
891GST_stats_init (const struct GNUNET_CONFIGURATION_Handle *cfg);
892
893
894/**
895 * Shutdown the status calls module.
896 */
897void
898GST_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 */
60struct Barrier;
61
62
63/**
64 * Context to be associated with each client
65 */
66struct 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 */
93struct 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 */
130struct 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 */
212static struct GNUNET_CONTAINER_MultiHashMap *barrier_map;
213
214/**
215 * Service context
216 */
217static 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 */
226static void
227remove_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 */
252static void
253cancel_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 */
277static void
278send_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 */
315static void
316send_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 */
333static int
334check_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 */
352static void
353handle_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 */
418static void *
419connect_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 */
440static void
441disconnect_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 */
465void
466GST_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 */
498static int
499barrier_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 */
515void
516GST_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 */
543static void
544wbarrier_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 */
606static void
607fwd_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 */
626int
627check_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 */
645void
646handle_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 */
748int
749check_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 */
767void
768handle_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 */
825int
826check_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 */
866void
867handle_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 */
35void
36GST_barriers_init (struct GNUNET_CONFIGURATION_Handle *cfg);
37
38
39/**
40 * Function to stop the barrier service
41 */
42void
43GST_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 */
53int
54check_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 */
69void
70handle_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 */
81int
82check_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 */
97void
98handle_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 */
109int
110check_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 */
122void
123handle_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 */
41struct 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 */
68static 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 */
76static 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 */
84static struct CacheEntry *cache_tail;
85
86/**
87 * Maximum number of elements to cache
88 */
89static 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 */
99static struct CacheEntry *
100cache_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 */
119static void
120free_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 */
134static struct CacheEntry *
135add_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 */
172static int
173cache_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 */
188void
189GST_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 */
210void
211GST_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 */
226const struct GNUNET_MessageHeader *
227GST_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 */
253void
254GST_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 59780e6c1..000000000
--- a/src/testbed/gnunet-service-testbed_connectionpool.c
+++ /dev/null
@@ -1,1044 +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 */
52struct GST_ConnectionPool_GetHandle;
53
54
55/**
56 * A pooled connection
57 */
58struct 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 */
172struct 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 */
239static 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 */
245static struct PooledConnection *head_lru;
246
247/**
248 * DLL tail for maitaining the least recently used #PooledConnection objects
249 */
250static 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 */
257static 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 */
263static struct PooledConnection *tail_not_pooled;
264
265/**
266 * The maximum number of entries that can be present in the connection pool
267 */
268static 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 */
276static void
277expire_task_cancel (struct PooledConnection *entry);
278
279
280/**
281 * Destroy a #PooledConnection object
282 *
283 * @param entry the #PooledConnection object
284 */
285static void
286destroy_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 */
337static void
338expire (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 */
352static void
353expire_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 */
368static void
369add_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 */
392static struct GST_ConnectionPool_GetHandle *
393search_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 */
434static void
435connection_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,
449 entry->tail_waiting,
450 gh);
451 gh->connection_ready_called = 1;
452 if (NULL != gh_next)
453 entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready,
454 entry);
455 if ((NULL != gh->target) && (NULL != gh->connect_notify_cb))
456 {
457 GNUNET_CONTAINER_DLL_insert_tail (entry->head_notify,
458 entry->tail_notify,
459 gh);
460 gh->notify_waiting = 1;
461 }
462 LOG_DEBUG ("Connection ready to %u for handle type %u\n",
463 (unsigned int) entry->index,
464 gh->service);
465 gh->cb (gh->cb_cls,
466 entry->handle_core,
467 entry->handle_transport,
468 entry->handle_ats_connectivity,
469 entry->peer_identity,
470 entry->cfg);
471}
472
473
474/**
475 * Function called from peer connect notify callbacks from CORE and TRANSPORT
476 * connections. This function calls the pending peer connect notify callbacks
477 * which are queued in an entry.
478 *
479 * @param cls the #PooledConnection object
480 * @param peer the peer that connected
481 * @param service the service where this notification has originated
482 */
483static void
484peer_connect_notify_cb (void *cls,
485 const struct GNUNET_PeerIdentity *peer,
486 const enum GST_ConnectionPool_Service service)
487{
488 struct PooledConnection *entry = cls;
489 struct GST_ConnectionPool_GetHandle *gh;
490 struct GST_ConnectionPool_GetHandle *gh_next;
491 GST_connection_pool_peer_connect_notify cb;
492 void *cb_cls;
493
494 for (gh = entry->head_notify; NULL != gh;)
495 {
496 GNUNET_assert (NULL != gh->target);
497 GNUNET_assert (NULL != gh->connect_notify_cb);
498 GNUNET_assert (gh->connection_ready_called);
499 if (service != gh->service)
500 {
501 gh = gh->next;
502 continue;
503 }
504 if (0 != memcmp (gh->target, peer, sizeof(struct GNUNET_PeerIdentity)))
505 {
506 gh = gh->next;
507 continue;
508 }
509 cb = gh->connect_notify_cb;
510 cb_cls = gh->connect_notify_cb_cls;
511 gh_next = gh->next;
512 GNUNET_CONTAINER_DLL_remove (entry->head_notify, entry->tail_notify, gh);
513 gh->notify_waiting = 0;
514 LOG_DEBUG ("Peer connected to peer %u at service %u\n",
515 entry->index,
516 gh->service);
517 gh = gh_next;
518 cb (cb_cls, peer);
519 }
520}
521
522
523/**
524 * Function called to notify transport users that another
525 * peer connected to us.
526 *
527 * @param cls the #PooledConnection object
528 * @param peer the peer that connected
529 * @param mq queue for sending data to @a peer
530 * @return NULL
531 */
532static void *
533transport_peer_connect_notify_cb (void *cls,
534 const struct GNUNET_PeerIdentity *peer,
535 struct GNUNET_MQ_Handle *mq)
536{
537 struct PooledConnection *entry = cls;
538
539 peer_connect_notify_cb (entry, peer, GST_CONNECTIONPOOL_SERVICE_TRANSPORT);
540 return NULL;
541}
542
543
544/**
545 * Function called when resources for opening a connection to TRANSPORT are
546 * available.
547 *
548 * @param cls the #PooledConnection object
549 */
550static void
551opstart_get_handle_transport (void *cls)
552{
553 struct PooledConnection *entry = cls;
554
555 GNUNET_assert (NULL != entry);
556 LOG_DEBUG ("Opening a transport connection to peer %u\n", entry->index);
557 entry->handle_transport =
558 GNUNET_TRANSPORT_core_connect (entry->cfg,
559 NULL,
560 NULL,
561 entry,
562 &transport_peer_connect_notify_cb,
563 NULL,
564 NULL);
565 if (NULL == entry->handle_transport)
566 {
567 GNUNET_break (0);
568 return;
569 }
570 if (0 == entry->demand)
571 return;
572 if (NULL != entry->notify_task)
573 return;
574 if (NULL != search_waiting (entry, entry->head_waiting))
575 {
576 entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready, entry);
577 return;
578 }
579}
580
581
582/**
583 * Function called when the operation responsible for opening a TRANSPORT
584 * connection is marked as done.
585 *
586 * @param cls the cache entry
587 */
588static void
589oprelease_get_handle_transport (void *cls)
590{
591 struct PooledConnection *entry = cls;
592
593 if (NULL == entry->handle_transport)
594 return;
595 GNUNET_TRANSPORT_core_disconnect (entry->handle_transport);
596 entry->handle_transport = NULL;
597}
598
599
600/**
601 * Method called whenever a given peer connects at CORE level
602 *
603 * @param cls the #PooledConnection object
604 * @param peer peer identity this notification is about
605 * @param mq message queue for talking to @a peer
606 * @return peer
607 */
608static void *
609core_peer_connect_cb (void *cls,
610 const struct GNUNET_PeerIdentity *peer,
611 struct GNUNET_MQ_Handle *mq)
612{
613 struct PooledConnection *entry = cls;
614
615 peer_connect_notify_cb (entry, peer, GST_CONNECTIONPOOL_SERVICE_CORE);
616 return (void *) peer;
617}
618
619
620/**
621 * Function called after #GNUNET_CORE_connect() has succeeded (or failed
622 * for good). Note that the private key of the peer is intentionally
623 * not exposed here; if you need it, your process should try to read
624 * the private key file directly (which should work if you are
625 * authorized...). Implementations of this function must not call
626 * #GNUNET_CORE_disconnect() (other than by scheduling a new task to
627 * do this later).
628 *
629 * @param cls the #PooledConnection object
630 * @param my_identity ID of this peer, NULL if we failed
631 */
632static void
633core_startup_cb (void *cls,
634 const struct GNUNET_PeerIdentity *my_identity)
635{
636 struct PooledConnection *entry = cls;
637
638 if (NULL == my_identity)
639 {
640 GNUNET_break (0);
641 return;
642 }
643 GNUNET_assert (NULL == entry->peer_identity);
644 entry->peer_identity = GNUNET_new (struct GNUNET_PeerIdentity);
645 *entry->peer_identity = *my_identity;
646 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
647 "Established CORE connection for peer %s (%u)\n",
648 GNUNET_i2s (my_identity),
649 (unsigned int) entry->index);
650 if (0 == entry->demand)
651 return;
652 if (NULL != entry->notify_task)
653 return;
654 if (NULL != search_waiting (entry, entry->head_waiting))
655 {
656 entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready, entry);
657 return;
658 }
659}
660
661
662/**
663 * Function called when resources for opening a connection to CORE are
664 * available.
665 *
666 * @param cls the #PooledConnection object
667 */
668static void
669opstart_get_handle_core (void *cls)
670{
671 struct PooledConnection *entry = cls;
672
673 GNUNET_assert (NULL != entry);
674 LOG_DEBUG ("Opening a CORE connection to peer %u\n", entry->index);
675 entry->handle_core =
676 GNUNET_CORE_connect (entry->cfg,
677 entry, /* closure */
678 &core_startup_cb, /* core startup notify */
679 &core_peer_connect_cb, /* peer connect notify */
680 NULL, /* peer disconnect notify */
681 NULL);
682}
683
684
685/**
686 * Function called when the operation responsible for opening a CORE
687 * connection is marked as done.
688 *
689 * @param cls the #PooledConnection object
690 */
691static void
692oprelease_get_handle_core (void *cls)
693{
694 struct PooledConnection *entry = cls;
695
696 if (NULL == entry->handle_core)
697 return;
698 GNUNET_CORE_disconnect (entry->handle_core);
699 entry->handle_core = NULL;
700 GNUNET_free (entry->peer_identity);
701 entry->peer_identity = NULL;
702}
703
704
705/**
706 * Function called when resources for opening a connection to ATS are
707 * available.
708 *
709 * @param cls the #PooledConnection object
710 */
711static void
712opstart_get_handle_ats_connectivity (void *cls)
713{
714 struct PooledConnection *entry = cls;
715
716 entry->handle_ats_connectivity = GNUNET_ATS_connectivity_init (entry->cfg);
717}
718
719
720/**
721 * Function called when the operation responsible for opening a ATS
722 * connection is marked as done.
723 *
724 * @param cls the #PooledConnection object
725 */
726static void
727oprelease_get_handle_ats_connectivity (void *cls)
728{
729 struct PooledConnection *entry = cls;
730
731 if (NULL == entry->handle_ats_connectivity)
732 return;
733 GNUNET_ATS_connectivity_done (entry->handle_ats_connectivity);
734 entry->handle_ats_connectivity = NULL;
735}
736
737
738/**
739 * This function will be called for every #PooledConnection object in @p map
740 *
741 * @param cls NULL
742 * @param key current key code
743 * @param value the #PooledConnection object
744 * @return #GNUNET_YES if we should continue to
745 * iterate,
746 * #GNUNET_NO if not.
747 */
748static int
749cleanup_iterator (void *cls, uint32_t key, void *value)
750{
751 struct PooledConnection *entry = value;
752
753 GNUNET_assert (NULL != entry);
754 destroy_pooled_connection (entry);
755 return GNUNET_YES;
756}
757
758
759/**
760 * Initialise the connection pool.
761 *
762 * @param size the size of the connection pool. Each entry in the connection
763 * pool can handle a connection to each of the services enumerated in
764 * #GST_ConnectionPool_Service
765 */
766void
767GST_connection_pool_init (unsigned int size)
768{
769 max_size = size;
770 if (0 == max_size)
771 return;
772 GNUNET_assert (NULL == map);
773 map = GNUNET_CONTAINER_multihashmap32_create (((size * 3) / 4) + 1);
774}
775
776
777/**
778 * Cleanup the connection pool
779 */
780void
781GST_connection_pool_destroy ()
782{
783 struct PooledConnection *entry;
784
785 if (NULL != map)
786 {
787 GNUNET_assert (
788 GNUNET_SYSERR !=
789 GNUNET_CONTAINER_multihashmap32_iterate (map, &cleanup_iterator, NULL));
790 GNUNET_CONTAINER_multihashmap32_destroy (map);
791 map = NULL;
792 }
793 while (NULL != (entry = head_lru))
794 {
795 GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry);
796 destroy_pooled_connection (entry);
797 }
798 GNUNET_assert (NULL == head_not_pooled);
799}
800
801
802/**
803 * Get a connection handle to @a service. If the connection is opened before
804 * and the connection handle is present in the connection pool, it is returned
805 * through @a cb. @a peer_id is used for the lookup in the connection pool. If
806 * the connection handle is not present in the connection pool, a new connection
807 * handle is opened for the @a service using @a cfg. Additionally, @a target,
808 * @a connect_notify_cb can be specified to get notified when @a target is
809 * connected at @a service.
810 *
811 * @note @a connect_notify_cb will not be called if @a target is
812 * already connected @a service level. Use
813 * GNUNET_TRANSPORT_check_peer_connected() or a similar function from the
814 * respective @a service's API to check if the target peer is already connected
815 * or not. @a connect_notify_cb will be called only once or never (in case @a
816 * target cannot be connected or is already connected).
817 *
818 * @param peer_id the index of the peer
819 * @param cfg the configuration with which the transport handle has to be
820 * created if it was not present in the cache
821 * @param service the service of interest
822 * @param cb the callback to notify when the transport handle is available
823 * @param cb_cls the closure for @a cb
824 * @param target the peer identify of the peer whose connection to our TRANSPORT
825 * subsystem will be notified through the @a connect_notify_cb. Can be
826 * NULL
827 * @param connect_notify_cb the callback to call when the @a target peer is
828 * connected. This callback will only be called once or never again (in
829 * case the target peer cannot be connected). Can be NULL
830 * @param connect_notify_cb_cls the closure for @a connect_notify_cb
831 * @return the handle which can be used cancel or mark that the handle is no
832 * longer being used
833 */
834struct GST_ConnectionPool_GetHandle *
835GST_connection_pool_get_handle (
836 unsigned int peer_id,
837 const struct GNUNET_CONFIGURATION_Handle *cfg,
838 enum GST_ConnectionPool_Service service,
839 GST_connection_pool_connection_ready_cb cb,
840 void *cb_cls,
841 const struct GNUNET_PeerIdentity *target,
842 GST_connection_pool_peer_connect_notify connect_notify_cb,
843 void *connect_notify_cb_cls)
844{
845 struct GST_ConnectionPool_GetHandle *gh;
846 struct PooledConnection *entry;
847 struct GNUNET_TESTBED_Operation *op;
848 void *handle;
849 uint32_t peer_id32;
850
851 peer_id32 = (uint32_t) peer_id;
852 handle = NULL;
853 entry = NULL;
854 if (NULL != map)
855 entry = GNUNET_CONTAINER_multihashmap32_get (map, peer_id32);
856 if (NULL != entry)
857 {
858 if (entry->in_lru)
859 {
860 GNUNET_assert (0 == entry->demand);
861 expire_task_cancel (entry);
862 GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry);
863 entry->in_lru = GNUNET_NO;
864 }
865 switch (service)
866 {
867 case GST_CONNECTIONPOOL_SERVICE_TRANSPORT:
868 handle = entry->handle_transport;
869 if (NULL != handle)
870 LOG_DEBUG ("Found TRANSPORT handle for peer %u\n",
871 entry->index);
872 break;
873 case GST_CONNECTIONPOOL_SERVICE_CORE:
874 handle = entry->handle_core;
875 if (NULL != handle)
876 LOG_DEBUG ("Found CORE handle for peer %u\n",
877 entry->index);
878 break;
879 case GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY:
880 handle = entry->handle_ats_connectivity;
881 if (NULL != handle)
882 LOG_DEBUG ("Found ATS CONNECTIVITY handle for peer %u\n",
883 entry->index);
884 break;
885 }
886 }
887 else
888 {
889 entry = GNUNET_new (struct PooledConnection);
890 entry->index = peer_id32;
891 if ((NULL != map) &&
892 (GNUNET_CONTAINER_multihashmap32_size (map) < max_size))
893 {
894 GNUNET_assert (GNUNET_OK ==
895 GNUNET_CONTAINER_multihashmap32_put (
896 map,
897 entry->index,
898 entry,
899 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
900 entry->in_pool = GNUNET_YES;
901 }
902 else
903 {
904 GNUNET_CONTAINER_DLL_insert_tail (head_not_pooled,
905 tail_not_pooled,
906 entry);
907 }
908 entry->cfg = GNUNET_CONFIGURATION_dup (cfg);
909 }
910 entry->demand++;
911 gh = GNUNET_new (struct GST_ConnectionPool_GetHandle);
912 gh->entry = entry;
913 gh->cb = cb;
914 gh->cb_cls = cb_cls;
915 gh->target = target;
916 gh->connect_notify_cb = connect_notify_cb;
917 gh->connect_notify_cb_cls = connect_notify_cb_cls;
918 gh->service = service;
919 GNUNET_CONTAINER_DLL_insert (entry->head_waiting,
920 entry->tail_waiting,
921 gh);
922 if (NULL != handle)
923 {
924 if (NULL == entry->notify_task)
925 {
926 if (NULL != search_waiting (entry, entry->head_waiting))
927 entry->notify_task =
928 GNUNET_SCHEDULER_add_now (&connection_ready, entry);
929 }
930 return gh;
931 }
932 op = NULL;
933 switch (gh->service)
934 {
935 case GST_CONNECTIONPOOL_SERVICE_TRANSPORT:
936 if (NULL != entry->op_transport)
937 return gh; /* Operation pending */
938 op = GNUNET_TESTBED_operation_create_ (entry,
939 &opstart_get_handle_transport,
940 &oprelease_get_handle_transport);
941 entry->op_transport = op;
942 break;
943
944 case GST_CONNECTIONPOOL_SERVICE_CORE:
945 if (NULL != entry->op_core)
946 return gh; /* Operation pending */
947 op = GNUNET_TESTBED_operation_create_ (entry,
948 &opstart_get_handle_core,
949 &oprelease_get_handle_core);
950 entry->op_core = op;
951 break;
952
953 case GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY:
954 if (NULL != entry->op_ats_connectivity)
955 return gh; /* Operation pending */
956 op =
957 GNUNET_TESTBED_operation_create_ (entry,
958 &opstart_get_handle_ats_connectivity,
959 &oprelease_get_handle_ats_connectivity);
960 entry->op_ats_connectivity = op;
961 break;
962 }
963 GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, op);
964 GNUNET_TESTBED_operation_begin_wait_ (op);
965 return gh;
966}
967
968
969/**
970 * Relinquish a #GST_ConnectionPool_GetHandle object. If the connection
971 * associated with the object is currently being used by other
972 * #GST_ConnectionPool_GetHandle objects, it is left in the connection pool. If
973 * no other objects are using the connection and the connection pool is not full
974 * then it is placed in a LRU queue. If the connection pool is full, then
975 * connections from the LRU queue are evicted and closed to create place for
976 * this connection. If the connection pool if full and the LRU queue is empty,
977 * then the connection is closed.
978 *
979 * @param gh the handle
980 */
981void
982GST_connection_pool_get_handle_done (struct GST_ConnectionPool_GetHandle *gh)
983{
984 struct PooledConnection *entry;
985
986 if (NULL == gh)
987 return;
988 entry = gh->entry;
989 LOG_DEBUG ("Cleaning up get handle %p for service %u, peer %u\n",
990 gh,
991 gh->service,
992 entry->index);
993 if (! gh->connection_ready_called)
994 {
995 GNUNET_CONTAINER_DLL_remove (entry->head_waiting, entry->tail_waiting, gh);
996 if ((NULL == search_waiting (entry, entry->head_waiting)) &&
997 (NULL != entry->notify_task))
998 {
999 GNUNET_SCHEDULER_cancel (entry->notify_task);
1000 entry->notify_task = NULL;
1001 }
1002 }
1003 if (gh->notify_waiting)
1004 {
1005 GNUNET_CONTAINER_DLL_remove (entry->head_notify, entry->tail_notify, gh);
1006 gh->notify_waiting = 0;
1007 }
1008 GNUNET_free (gh);
1009 gh = NULL;
1010 GNUNET_assert (! entry->in_lru);
1011 if (! entry->in_pool)
1012 GNUNET_CONTAINER_DLL_remove (head_not_pooled, tail_not_pooled, entry);
1013 if (NULL != map)
1014 {
1015 if (GNUNET_YES ==
1016 GNUNET_CONTAINER_multihashmap32_contains (map, entry->index))
1017 goto unallocate;
1018 if (GNUNET_CONTAINER_multihashmap32_size (map) == max_size)
1019 {
1020 if (NULL == head_lru)
1021 goto unallocate;
1022 destroy_pooled_connection (head_lru);
1023 }
1024 GNUNET_assert (GNUNET_OK ==
1025 GNUNET_CONTAINER_multihashmap32_put (
1026 map,
1027 entry->index,
1028 entry,
1029 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1030 entry->in_pool = GNUNET_YES;
1031 }
1032
1033unallocate:
1034 GNUNET_assert (0 < entry->demand);
1035 entry->demand--;
1036 if (0 != entry->demand)
1037 return;
1038 if (entry->in_pool)
1039 {
1040 add_to_lru (entry);
1041 return;
1042 }
1043 destroy_pooled_connection (entry);
1044}
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 */
33struct GST_ConnectionPool_GetHandle;
34
35
36/**
37 * The type of service
38 */
39enum 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 */
65void
66GST_connection_pool_init (unsigned int size);
67
68
69/**
70 * Cleanup the connection pool
71 */
72void
73GST_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 */
90typedef 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 */
107typedef 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 */
144struct GST_ConnectionPool_GetHandle *
145GST_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 */
168void
169GST_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
55static processor_cpu_load_info_t prev_cpu_load;
56#endif
57
58#define DEBUG_STATUSCALLS GNUNET_NO
59
60#ifdef __linux__
61static FILE *proc_stat;
62#endif
63
64/**
65 * Current CPU load, as percentage of CPU cycles not idle or
66 * blocked on IO.
67 */
68static int currentCPULoad;
69
70static double agedCPULoad = -1;
71
72/**
73 * Current IO load, as percentage of CPU cycles blocked on IO.
74 */
75static int currentIOLoad;
76
77static double agedIOLoad = -1;
78
79
80/**
81 * handle to the file to write the load statistics to
82 */
83struct GNUNET_BIO_WriteHandle *bw;
84
85struct GNUNET_SCHEDULER_Task *sample_load_task_id;
86
87
88#ifdef OSX
89static int
90initMachCpuStats ()
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 */
131static int
132updateUsage ()
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;
368ABORT_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 */
416static void
417updateAgedLoad ()
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 */
475static int
476cpu_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 */
488static int
489disk_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 */
501static unsigned int
502mem_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 */
519static unsigned int
520get_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
543static void
544sample_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
577reschedule:
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 */
589void
590GST_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 */
640void
641GST_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 */
48enum 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 */
75struct 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 */
138struct 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 */
170struct 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 */
218static struct Neighbour **neighbour_list;
219
220/**
221 * The size of the neighbour list
222 */
223static 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 */
230struct 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 */
272struct NeighbourConnectCtxt *ncc_head;
273
274/**
275 * DLL tail for the list of neighbour connect contexts
276 */
277struct NeighbourConnectCtxt *ncc_tail;
278
279/**
280 * A list of directly linked neighbours
281 */
282struct Slave **GST_slave_list;
283
284/**
285 * The size of directly linked neighbours list
286 */
287unsigned int GST_slave_list_size;
288
289/**
290 * A list of routes
291 */
292static struct Route **route_list;
293
294/**
295 * The LCF queue
296 */
297static struct LCFContext *lcf_head;
298
299/**
300 * The tail for the LCF queue
301 */
302static struct LCFContext *lcf_tail;
303
304/**
305 * The lcf_task handle
306 */
307static struct GNUNET_SCHEDULER_Task *lcf_proc_task_id;
308
309/**
310 * The size of the route list
311 */
312static 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 */
320static void
321slave_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 */
341static int
342drop_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 */
366static void
367route_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 */
382static void
383neighbour_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 */
396void
397GST_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 */
418static int
419reghost_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 */
442static void
443kill_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 */
475static void
476destroy_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 */
491void
492GST_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 */
524struct Route *
525GST_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 */
553static void
554send_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 */
608static void
609lcf_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 */
618static void
619lcf_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
646registration_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 */
661static void
662lcf_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 */
670static void
671lcf_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 */
694static void
695lcf_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 */
767static void
768slave_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 */
805static void
806slave_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
846clean_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 */
869static void
870trigger_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 */
879static void
880neighbour_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 */
904static void
905trigger_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 */
933static void
934opstart_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 */
954static void
955oprelease_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 */
984struct NeighbourConnectNotification *
985GST_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 */
1018void
1019GST_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 */
1056void
1057GST_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 */
1075static void
1076cleanup_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 */
1092void
1093GST_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 */
1118struct Neighbour *
1119GST_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 */
1130void
1131GST_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 */
1143static void
1144timeout_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 */
1163static void
1164neighbour_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 */
1186struct Neighbour *
1187GST_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 */
1204void
1205handle_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 */
1389void
1390GST_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 */
1442void
1443GST_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 */
32struct Neighbour;
33
34
35/**
36 * Structure representing a connected(directly-linked) controller
37 */
38struct 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 */
85extern struct Slave **GST_slave_list;
86
87/**
88 * The size of directly linked neighbours list
89 */
90extern unsigned int GST_slave_list_size;
91
92
93/**
94 * Cleans up the neighbour list
95 */
96void
97GST_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 */
107struct Neighbour *
108GST_get_neighbour (uint32_t id);
109
110
111/**
112 * Function to cleanup the neighbour connect contexts
113 */
114void
115GST_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 */
122struct 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 */
131typedef 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 */
148struct NeighbourConnectNotification *
149GST_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 */
159void
160GST_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 */
170void
171GST_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 */
179struct Neighbour *
180GST_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 */
189void
190handle_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 */
201void
202GST_link_notify_disconnect (struct GNUNET_SERVICE_Client *client);
203
204
205/**
206 * Cleans up the slave list
207 */
208void
209GST_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"
58static 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.
64static 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
99typedef 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
105static int
106compare_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 */
148unsigned long kb_main_shared;
149/* old but still kicking -- the important stuff */
150unsigned long kb_main_buffers;
151unsigned long kb_main_cached;
152unsigned long kb_main_free;
153unsigned long kb_main_total;
154unsigned long kb_swap_free;
155unsigned long kb_swap_total;
156/* recently introduced */
157unsigned long kb_high_free;
158unsigned long kb_high_total;
159unsigned long kb_low_free;
160unsigned long kb_low_total;
161/* 2.4.xx era */
162unsigned long kb_active;
163unsigned long kb_inact_laundry;
164unsigned long kb_inact_dirty;
165unsigned long kb_inact_clean;
166unsigned long kb_inact_target;
167unsigned long kb_swap_cached; /* late 2.4 and 2.6+ only */
168/* derived values */
169unsigned long kb_swap_used;
170unsigned long kb_main_used;
171/* 2.5.41+ */
172unsigned long kb_writeback;
173unsigned long kb_slab;
174unsigned long nr_reversemaps;
175unsigned long kb_committed_as;
176unsigned long kb_dirty;
177unsigned long kb_inactive;
178unsigned long kb_mapped;
179unsigned long kb_pagetables;
180// seen on a 2.6.x kernel:
181static unsigned long kb_vmalloc_chunk;
182static unsigned long kb_vmalloc_total;
183static unsigned long kb_vmalloc_used;
184// seen on 2.6.24-rc6-git12
185static unsigned long kb_anon_pages;
186static unsigned long kb_bounce;
187static unsigned long kb_commit_limit;
188static unsigned long kb_nfs_unstable;
189static unsigned long kb_swap_reclaimable;
190static unsigned long kb_swap_unreclaimable;
191
192void
193meminfo (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);
262nextline:
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 */
22extern unsigned long kb_main_shared;
23/* old but still kicking -- the important stuff */
24extern unsigned long kb_main_buffers;
25extern unsigned long kb_main_cached;
26extern unsigned long kb_main_free;
27extern unsigned long kb_main_total;
28extern unsigned long kb_swap_free;
29extern unsigned long kb_swap_total;
30/* recently introduced */
31extern unsigned long kb_high_free;
32extern unsigned long kb_high_total;
33extern unsigned long kb_low_free;
34extern unsigned long kb_low_total;
35/* 2.4.xx era */
36extern unsigned long kb_active;
37extern unsigned long kb_inact_laundry; // grrr...
38extern unsigned long kb_inact_dirty;
39extern unsigned long kb_inact_clean;
40extern unsigned long kb_inact_target;
41extern unsigned long kb_swap_cached; /* late 2.4+ */
42/* derived values */
43extern unsigned long kb_swap_used;
44extern unsigned long kb_main_used;
45/* 2.5.41+ */
46extern unsigned long kb_writeback;
47extern unsigned long kb_slab;
48extern unsigned long nr_reversemaps;
49extern unsigned long kb_committed_as;
50extern unsigned long kb_dirty;
51extern unsigned long kb_inactive;
52extern unsigned long kb_mapped;
53extern unsigned long kb_pagetables;
54
55extern 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 b13a3b7e0..000000000
--- a/src/testbed/gnunet-service-testbed_oc.c
+++ /dev/null
@@ -1,1996 +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 */
44struct 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 */
77enum 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 */
103struct 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 */
122struct 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 */
153struct 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 */
274struct 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 */
331static struct OverlayConnectContext *occq_head;
332
333/**
334 * DLL tail for OverlayConnectContext DLL
335 */
336static struct OverlayConnectContext *occq_tail;
337
338/**
339 * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
340 * shutdown
341 */
342static struct RemoteOverlayConnectCtx *roccq_head;
343
344/**
345 * DLL tail for RequectOverlayConnectContext DLL
346 */
347static struct RemoteOverlayConnectCtx *roccq_tail;
348
349
350/**
351 * Cleans up ForwardedOverlayConnectContext
352 *
353 * @param focc the ForwardedOverlayConnectContext to cleanup
354 */
355void
356GST_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 */
373static void
374forwarded_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 */
401static void
402forwarded_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 */
423void
424GST_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 */
466static void
467cleanup_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 */
498static void
499cleanup_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 */
532static void
533cleanup_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 */
585static void
586do_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 */
600static void
601timeout_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 */
622void
623GST_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 */
652static void
653send_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 */
678static void
679overlay_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 GNUNET_memcmp (new_peer,
689 &occ->peer_identity))
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 GNUNET_memcmp (new_peer,
695 &occ->other_peer_identity))
696 {
697 LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n",
698 new_peer_str,
699 other_peer_str);
700 GNUNET_free (new_peer_str);
701 GNUNET_free (other_peer_str);
702 return;
703 }
704 GNUNET_free (new_peer_str);
705 LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n",
706 (unsigned long long) occ->op_id,
707 other_peer_str,
708 GNUNET_i2s (&occ->peer_identity));
709 GNUNET_free (other_peer_str);
710 if (NULL != occ->send_hello_task)
711 {
712 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
713 occ->send_hello_task = NULL;
714 }
715 GNUNET_assert (NULL != occ->timeout_task);
716 GNUNET_SCHEDULER_cancel (occ->timeout_task);
717 occ->timeout_task = NULL;
718 switch (occ->type)
719 {
720 case OCC_TYPE_LOCAL:
721 cleanup_occ_lp2c (&occ->p2ctx.local);
722 break;
723
724 case OCC_TYPE_REMOTE_SLAVE:
725 case OCC_TYPE_REMOTE_LATERAL:
726 cleanup_occ_rp2c (&occ->p2ctx.remote);
727 break;
728 }
729 GNUNET_free (occ->emsg);
730 occ->emsg = NULL;
731 send_overlay_connect_success_msg (occ);
732 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ,
733 occ);
734}
735
736
737/**
738 * Callback from cache with needed ATS handle set
739 *
740 * @param cls a `struct OverlayConnectCtx *`
741 * @param ch the handle to CORE. Can be NULL if it is not requested
742 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
743 * @param ac the handle to ATS. Can be NULL if it is not requested
744 * @param my_identity the identity of our peer
745 * @param cfg configuration of the peer
746 */
747static void
748occ_cache_get_handle_ats_occ_cb (void *cls,
749 struct GNUNET_CORE_Handle *ch,
750 struct GNUNET_TRANSPORT_CoreHandle *th,
751 struct GNUNET_ATS_ConnectivityHandle *ac,
752 const struct GNUNET_PeerIdentity *my_identity,
753 const struct GNUNET_CONFIGURATION_Handle *cfg)
754{
755 struct OverlayConnectContext *occ = cls;
756 struct LocalPeer2Context *lp2c;
757
758 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
759 GNUNET_assert (NULL != occ->timeout_task);
760 GNUNET_free (occ->emsg);
761 if (NULL == ac)
762 {
763 GNUNET_asprintf (&occ->emsg,
764 "0x%llx: Failed to connect to ATS of peer with id: %u",
765 (unsigned long long) occ->op_id,
766 occ->peer->id);
767 GNUNET_SCHEDULER_cancel (occ->timeout_task);
768 occ->timeout_task =
769 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect,
770 occ);
771 return;
772 }
773 occ->emsg = NULL;
774
775 GNUNET_asprintf (&occ->emsg,
776 "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s",
777 (unsigned long long) occ->op_id,
778 GNUNET_i2s (&occ->other_peer_identity));
779
780 lp2c = &occ->p2ctx.local;
781 lp2c->tcc.csh =
782 GNUNET_ATS_connectivity_suggest (ac,
783 &occ->peer_identity,
784 1);
785}
786
787
788/**
789 * Callback from cache with needed ATS handle set
790 *
791 * @param cls a `struct RemoteOverlayConnectCtx *`
792 * @param ch the handle to CORE. Can be NULL if it is not requested
793 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
794 * @param ac the handle to ATS. Can be NULL if it is not requested
795 * @param my_identity the identity of our peer
796 */
797static void
798occ_cache_get_handle_ats_rocc_cb (void *cls,
799 struct GNUNET_CORE_Handle *ch,
800 struct GNUNET_TRANSPORT_CoreHandle *th,
801 struct GNUNET_ATS_ConnectivityHandle *ac,
802 const struct GNUNET_PeerIdentity *my_identity,
803 const struct GNUNET_CONFIGURATION_Handle *cfg)
804{
805 struct RemoteOverlayConnectCtx *rocc = cls;
806
807 rocc->tcc.csh =
808 GNUNET_ATS_connectivity_suggest (ac,
809 &rocc->a_id,
810 1);
811}
812
813
814/**
815 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
816 * peer 1.
817 *
818 * @param cls the OverlayConnectContext
819 */
820static void
821send_hello (void *cls);
822
823
824/**
825 * Task that is run when hello has been sent If tc->reason =
826 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
827 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
828 *
829 * @param cls the overlay connect context
830 */
831static void
832occ_hello_sent_cb (void *cls)
833{
834 struct OverlayConnectContext *occ = cls;
835 struct LocalPeer2Context *lp2c;
836 struct Peer *peer2;
837
838 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
839 GNUNET_assert (NULL != occ->timeout_task);
840 lp2c = &occ->p2ctx.local;
841 lp2c->ohh = NULL;
842
843 GNUNET_assert (NULL == occ->send_hello_task);
844 GNUNET_free (occ->emsg);
845
846 GNUNET_asprintf (&occ->emsg,
847 "0x%llx: Timeout while acquiring ATS of %s from cache",
848 (unsigned long long) occ->op_id,
849 GNUNET_i2s (&occ->other_peer_identity));
850 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
851 lp2c->tcc.cgh_p2_ats =
852 GST_connection_pool_get_handle (occ->other_peer_id,
853 peer2->details.local.cfg,
854 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
855 &occ_cache_get_handle_ats_occ_cb,
856 occ, NULL, NULL, NULL);
857}
858
859
860/**
861 * Sends the HELLO of peer1 to peer2's controller through remote overlay connect
862 * request.
863 *
864 * @param occ the overlay connect context. Its type must be either
865 * #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL
866 */
867static void
868send_hello_thru_rocc (struct OverlayConnectContext *occ)
869{
870 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
871 char *other_peer_str;
872 uint16_t msize;
873 uint16_t hello_size;
874
875 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
876 GNUNET_assert (NULL != occ->hello);
877 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
878 LOG_DEBUG (
879 "0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n",
880 (unsigned long long) occ->op_id,
881 GNUNET_i2s (&occ->peer_identity),
882 ntohs (occ->hello->size),
883 other_peer_str);
884 GNUNET_free (other_peer_str);
885 hello_size = ntohs (occ->hello->size);
886 msize = sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage)
887 + hello_size;
888 msg = GNUNET_malloc (msize);
889 msg->header.type =
890 htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
891 msg->header.size = htons (msize);
892 msg->peer = htonl (occ->other_peer_id);
893 msg->operation_id = GNUNET_htonll (occ->op_id);
894 msg->peer_identity = occ->peer_identity;
895 GNUNET_memcpy (msg->hello,
896 occ->hello,
897 hello_size);
898 GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c,
899 &msg->header);
900}
901
902
903/**
904 * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered
905 * using its TRANSPORT connection; if remote the HELLO is sent remotely by using
906 * send_hello_thru_rocc()
907 *
908 * @param cls the OverlayConnectContext
909 */
910static void
911send_hello (void *cls)
912{
913 struct OverlayConnectContext *occ = cls;
914 struct LocalPeer2Context *lp2c;
915 char *other_peer_str;
916
917 occ->send_hello_task = NULL;
918 GNUNET_assert (NULL != occ->timeout_task);
919 GNUNET_assert (NULL != occ->hello);
920 if (OCC_TYPE_LOCAL != occ->type)
921 {
922 send_hello_thru_rocc (occ);
923 return;
924 }
925 lp2c = &occ->p2ctx.local;
926 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
927 LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n",
928 (unsigned long long) occ->op_id,
929 GNUNET_i2s (&occ->peer_identity),
930 other_peer_str);
931 GNUNET_free (other_peer_str);
932 lp2c->ohh =
933 GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg,
934 occ->hello,
935 &occ_hello_sent_cb,
936 occ);
937 if (NULL == lp2c->ohh)
938 {
939 GNUNET_break (0);
940 occ->send_hello_task =
941 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
942 (GNUNET_TIME_UNIT_MILLISECONDS,
943 100
944 + GNUNET_CRYPTO_random_u32
945 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
946 &send_hello, occ);
947 }
948}
949
950
951/**
952 * Callback from cache with needed handles set
953 *
954 * @param cls the closure passed to GST_cache_get_handle_transport()
955 * @param ch the handle to CORE. Can be NULL if it is not requested
956 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
957 * @param ac the handle to ATS. Can be NULL if it is not requested
958 * @param ignore_ peer identity which is ignored in this callback
959 * @param cfg configuration of the peer
960 */
961static void
962p2_transport_connect_cache_callback (void *cls,
963 struct GNUNET_CORE_Handle *ch,
964 struct GNUNET_TRANSPORT_CoreHandle *th,
965 struct GNUNET_ATS_ConnectivityHandle *ac,
966 const struct GNUNET_PeerIdentity *ignore_,
967 const struct
968 GNUNET_CONFIGURATION_Handle *cfg)
969{
970 struct OverlayConnectContext *occ = cls;
971
972 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
973 if (NULL == th)
974 {
975 GNUNET_asprintf (&occ->emsg,
976 "0x%llx: Cannot connect to TRANSPORT of %s",
977 (unsigned long long) occ->op_id,
978 GNUNET_i2s (&occ->other_peer_identity));
979 GNUNET_SCHEDULER_cancel (occ->timeout_task);
980 occ->timeout_task =
981 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
982 return;
983 }
984 occ->p2ctx.local.tcc.th_ = th;
985 occ->p2ctx.local.tcc.cfg = cfg;
986 GNUNET_asprintf (&occ->emsg,
987 "0x%llx: Timeout while offering HELLO to %s",
988 (unsigned long long) occ->op_id,
989 GNUNET_i2s (&occ->other_peer_identity));
990 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
991}
992
993
994/**
995 * Connects to the transport of the other peer if it is a local peer and
996 * schedules the send hello task
997 *
998 * @param occ the overlay connect context
999 */
1000static void
1001p2_transport_connect (struct OverlayConnectContext *occ)
1002{
1003 struct Peer *peer2;
1004
1005 /* HUH? Why to *obtain* HELLO? Seems we use this to *SEND* the
1006 HELLO! */
1007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1008 "Connecting to transport of peer %s to obtain HELLO\n",
1009 GNUNET_i2s (&occ->other_peer_identity));
1010 GNUNET_assert (NULL == occ->emsg);
1011 GNUNET_assert (NULL != occ->hello);
1012 GNUNET_assert (NULL == occ->ghh);
1013 GNUNET_assert (NULL == occ->p1th_);
1014 GNUNET_assert (NULL == occ->cgh_p1th);
1015 if (OCC_TYPE_LOCAL == occ->type)
1016 {
1017 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
1018 occ->p2ctx.local.tcc.cgh_p2_th =
1019 GST_connection_pool_get_handle (occ->other_peer_id,
1020 peer2->details.local.cfg,
1021 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1022 &p2_transport_connect_cache_callback,
1023 occ, NULL, NULL, NULL);
1024 return;
1025 }
1026 GNUNET_asprintf (&occ->emsg,
1027 "0x%llx: Timeout while offering HELLO to %s",
1028 (unsigned long long) occ->op_id,
1029 GNUNET_i2s (&occ->other_peer_identity));
1030 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
1031}
1032
1033
1034/**
1035 * Test for checking whether HELLO message is empty
1036 *
1037 * @param cls empty flag to set
1038 * @param address the HELLO
1039 * @param expiration expiration of the HELLO
1040 * @return #GNUNET_OK
1041 */
1042static int
1043test_address (void *cls,
1044 const struct GNUNET_HELLO_Address *address,
1045 struct GNUNET_TIME_Absolute expiration)
1046{
1047 int *empty = cls;
1048
1049 *empty = GNUNET_NO;
1050 return GNUNET_OK;
1051}
1052
1053
1054/**
1055 * Function called whenever there is an update to the HELLO of peers in the
1056 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
1057 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
1058 *
1059 * @param cls closure
1060 * @param hello our updated HELLO
1061 */
1062static void
1063hello_update_cb (void *cls,
1064 const struct GNUNET_MessageHeader *hello)
1065{
1066 struct OverlayConnectContext *occ = cls;
1067 int empty;
1068 uint16_t msize;
1069
1070 msize = ntohs (hello->size);
1071 empty = GNUNET_YES;
1072 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
1073 hello, GNUNET_NO,
1074 &test_address,
1075 &empty);
1076 if (GNUNET_YES == empty)
1077 {
1078 LOG_DEBUG ("0x%llx: HELLO of %s is empty\n",
1079 (unsigned long long) occ->op_id,
1080 GNUNET_i2s (&occ->peer_identity));
1081 return;
1082 }
1083 LOG_DEBUG ("0x%llx: Received HELLO of %s\n",
1084 (unsigned long long) occ->op_id,
1085 GNUNET_i2s (&occ->peer_identity));
1086 occ->hello = GNUNET_malloc (msize);
1087 GST_cache_add_hello (occ->peer->id, hello);
1088 GNUNET_memcpy (occ->hello, hello, msize);
1089 GNUNET_TRANSPORT_hello_get_cancel (occ->ghh);
1090 occ->ghh = NULL;
1091 GST_connection_pool_get_handle_done (occ->cgh_p1th);
1092 occ->cgh_p1th = NULL;
1093 occ->p1th_ = NULL;
1094 GNUNET_free (occ->emsg);
1095 occ->emsg = NULL;
1096 p2_transport_connect (occ);
1097}
1098
1099
1100/**
1101 * Callback from cache with needed handles set
1102 *
1103 * @param cls the closure passed to GST_cache_get_handle_transport()
1104 * @param ch the handle to CORE. Can be NULL if it is not requested
1105 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1106 * @param ac the handle to ATS. Can be NULL if it is not requested
1107 * @param ignore_ peer identity which is ignored in this callback
1108 */
1109static void
1110p1_transport_connect_cache_callback (void *cls,
1111 struct GNUNET_CORE_Handle *ch,
1112 struct GNUNET_TRANSPORT_CoreHandle *th,
1113 struct GNUNET_ATS_ConnectivityHandle *ac,
1114 const struct GNUNET_PeerIdentity *ignore_,
1115 const struct
1116 GNUNET_CONFIGURATION_Handle *cfg)
1117{
1118 struct OverlayConnectContext *occ = cls;
1119
1120 GNUNET_free (occ->emsg);
1121 occ->emsg = NULL;
1122 if (NULL == th)
1123 {
1124 GNUNET_asprintf (&occ->emsg,
1125 "0x%llx: Cannot connect to TRANSPORT of %s",
1126 (unsigned long long) occ->op_id,
1127 GNUNET_i2s (&occ->peer_identity));
1128 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1129 occ->timeout_task =
1130 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1131 return;
1132 }
1133 GNUNET_assert (NULL == occ->p1th_);
1134 GNUNET_assert (NULL != occ->cgh_p1th);
1135 occ->p1th_ = th;
1136 GNUNET_asprintf (&occ->emsg,
1137 "0x%llx: Timeout while acquiring HELLO of peer %s",
1138 (unsigned long long) occ->op_id,
1139 GNUNET_i2s (&occ->peer_identity));
1140 occ->ghh = GNUNET_TRANSPORT_hello_get (cfg,
1141 GNUNET_TRANSPORT_AC_ANY,
1142 &hello_update_cb,
1143 occ);
1144}
1145
1146
1147/**
1148 * Callback from cache with needed CORE handle set
1149 *
1150 * @param cls the closure passed to GST_cache_get_handle_transport()
1151 * @param ch the handle to CORE. Can be NULL if it is not requested
1152 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1153 * @param ac the handle to ATS. Can be NULL if it is not requested
1154 * @param my_identity the identity of our peer
1155 */
1156static void
1157occ_cache_get_handle_core_cb (void *cls,
1158 struct GNUNET_CORE_Handle *ch,
1159 struct GNUNET_TRANSPORT_CoreHandle *th,
1160 struct GNUNET_ATS_ConnectivityHandle *ac,
1161 const struct GNUNET_PeerIdentity *my_identity,
1162 const struct GNUNET_CONFIGURATION_Handle *cfg)
1163{
1164 struct OverlayConnectContext *occ = cls;
1165 const struct GNUNET_MessageHeader *hello;
1166
1167 GNUNET_assert (NULL != occ->timeout_task);
1168 GNUNET_free (occ->emsg);
1169 if ((NULL == ch) || (NULL == my_identity))
1170 {
1171 GNUNET_asprintf (&occ->emsg,
1172 "0x%llx: Failed to connect to CORE of peer with "
1173 "id: %u",
1174 (unsigned long long) occ->op_id,
1175 occ->peer->id);
1176 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1177 occ->timeout_task =
1178 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1179 return;
1180 }
1181 occ->emsg = NULL;
1182 occ->peer_identity = *my_identity;
1183 if (NULL !=
1184 GNUNET_CORE_get_mq (ch,
1185 &occ->other_peer_identity))
1186 {
1187 LOG_DEBUG ("0x%llx: Target peer %s already connected\n",
1188 (unsigned long long) occ->op_id,
1189 GNUNET_i2s (&occ->other_peer_identity));
1190 LOG_DEBUG ("0x%llx: Target peer %s connected\n",
1191 (unsigned long long) occ->op_id,
1192 GNUNET_i2s (&occ->peer_identity));
1193 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1194 occ->timeout_task = NULL;
1195 send_overlay_connect_success_msg (occ);
1196 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
1197 return;
1198 }
1199 LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n",
1200 (unsigned long long) occ->op_id,
1201 GNUNET_i2s (&occ->peer_identity));
1202 /* Lookup for HELLO in hello cache */
1203 if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
1204 {
1205 LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n",
1206 (unsigned long long) occ->op_id,
1207 GNUNET_i2s (&occ->peer_identity));
1208 occ->hello = GNUNET_copy_message (hello);
1209 p2_transport_connect (occ);
1210 return;
1211 }
1212 GNUNET_asprintf (&occ->emsg,
1213 "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
1214 (unsigned long long) occ->op_id,
1215 GNUNET_i2s (&occ->peer_identity));
1216 occ->cgh_p1th =
1217 GST_connection_pool_get_handle (occ->peer->id,
1218 occ->peer->details.local.cfg,
1219 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1220 p1_transport_connect_cache_callback,
1221 occ,
1222 NULL, NULL, NULL);
1223}
1224
1225
1226/**
1227 * Callback to be called when forwarded get peer config operation as part of
1228 * overlay connect is successful. Connection to Peer 1's core is made and is
1229 * checked for new connection from peer 2
1230 *
1231 * @param cls ForwardedOperationContext
1232 * @param msg the peer create success message
1233 */
1234static void
1235overlay_connect_get_config (void *cls,
1236 const struct GNUNET_MessageHeader *msg)
1237{
1238 struct OverlayConnectContext *occ = cls;
1239 struct RemotePeer2Context *rp2c;
1240 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
1241
1242 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1243 rp2c = &occ->p2ctx.remote;
1244 rp2c->opc = NULL;
1245 GNUNET_assert (NULL != occ->timeout_task);
1246 if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type))
1247 {
1248 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1249 occ->timeout_task =
1250 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1251 }
1252 cmsg =
1253 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1254 occ->other_peer_identity = cmsg->peer_identity;
1255 GNUNET_free (occ->emsg);
1256 GNUNET_asprintf (&occ->emsg,
1257 "0x%llx: Timeout while connecting to CORE of peer with "
1258 "id: %u",
1259 (unsigned long long) occ->op_id,
1260 occ->peer->id);
1261 occ->cgh_ch =
1262 GST_connection_pool_get_handle (occ->peer->id,
1263 occ->peer->details.local.cfg,
1264 GST_CONNECTIONPOOL_SERVICE_CORE,
1265 &occ_cache_get_handle_core_cb,
1266 occ,
1267 &occ->other_peer_identity,
1268 &overlay_connect_notify,
1269 occ);
1270}
1271
1272
1273/**
1274 * Callback which will be called after a host registration succeeded or failed
1275 *
1276 * @param cls the RegisteredHostContext
1277 * @param emsg the error message; NULL if host registration is successful
1278 */
1279static void
1280host_registration_comp (void *cls, const char *emsg)
1281{
1282 struct RegisteredHostContext *rhc = cls;
1283
1284 rhc->state = RHC_DONE;
1285 GST_process_next_focc (rhc);
1286}
1287
1288
1289/**
1290 * Iterator to match a registered host context
1291 *
1292 * @param cls pointer 2 pointer of RegisteredHostContext
1293 * @param key current key code
1294 * @param value value in the hash map
1295 * @return #GNUNET_YES if we should continue to
1296 * iterate,
1297 * #GNUNET_NO if not.
1298 */
1299static int
1300reghost_match_iterator (void *cls,
1301 const struct GNUNET_HashCode *key,
1302 void *value)
1303{
1304 struct RegisteredHostContext **rh = cls;
1305 struct RegisteredHostContext *rh_val = value;
1306
1307 if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1308 {
1309 GNUNET_free (*rh);
1310 *rh = rh_val;
1311 return GNUNET_NO;
1312 }
1313 return GNUNET_YES;
1314}
1315
1316
1317/**
1318 * Function to generate the hashcode corresponding to a RegisteredHostContext
1319 *
1320 * @param reg_host the host which is being registered in RegisteredHostContext
1321 * @param host the host of the controller which has to connect to the above rhost
1322 * @return the hashcode
1323 */
1324static struct GNUNET_HashCode
1325hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1326 struct GNUNET_TESTBED_Host *host)
1327{
1328 struct GNUNET_HashCode hash;
1329 uint32_t host_ids[2];
1330
1331 host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1332 host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1333 GNUNET_CRYPTO_hash (host_ids, sizeof(host_ids), &hash);
1334 return hash;
1335}
1336
1337
1338/**
1339 * Checks if the given host is registered at the given slave.
1340 *
1341 * @param slave the slave where registration has to be checked. The check is
1342 * actually done through a locally maintained hashmap. No
1343 * communication with the slave is involved.
1344 * @param host the host to register
1345 * @return If the given host is not registered already or the registration is
1346 * pending, it returns the registration context. Any overlay connects
1347 * to be forwarded should be queued in the context so that they can be
1348 * executed when the registration is completed. If the given host is
1349 * already registered, NULL is returned.
1350 */
1351static struct RegisteredHostContext *
1352register_host (struct Slave *slave,
1353 struct GNUNET_TESTBED_Host *host)
1354{
1355 struct GNUNET_HashCode hash;
1356 struct RegisteredHostContext *rhc;
1357
1358 rhc = GNUNET_new (struct RegisteredHostContext);
1359 rhc->reg_host = host;
1360 rhc->host = GST_host_list[slave->host_id];
1361 GNUNET_assert (NULL != rhc->reg_host);
1362 GNUNET_assert (NULL != rhc->host);
1363 rhc->state = RHC_INIT;
1364 hash = hash_hosts (rhc->reg_host, rhc->host);
1365 if ((GNUNET_NO ==
1366 GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map,
1367 &hash)) ||
1368 (GNUNET_SYSERR !=
1369 GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map,
1370 &hash,
1371 reghost_match_iterator,
1372 &rhc)))
1373 {
1374 /* create and add a new registered host context */
1375 /* add the focc to its queue */
1376 GNUNET_CONTAINER_multihashmap_put (slave->reghost_map,
1377 &hash,
1378 rhc,
1379 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1380 GST_queue_host_registration (slave,
1381 host_registration_comp,
1382 rhc,
1383 rhc->reg_host);
1384 }
1385 else
1386 {
1387 /* rhc is now set to the existing one from the hash map by
1388 * reghost_match_iterator() */
1389 /* if queue is empty then ignore creating focc and proceed with normal
1390 * forwarding */
1391 if (RHC_DONE == rhc->state)
1392 return NULL;
1393 }
1394 return rhc;
1395}
1396
1397
1398/**
1399 * Forwards the overlay connect request to a slave controller. Before
1400 * forwarding, any hosts which are needed to be known by the slave controller to
1401 * execute the overlay connect request are registered at slave.
1402 *
1403 * @param msg the overlay connect request message to be forwarded
1404 * @param client the client to which the status of the forwarded request has to
1405 * be notified
1406 */
1407static void
1408forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg,
1409 struct GNUNET_SERVICE_Client *client)
1410{
1411 struct ForwardedOperationContext *fopc;
1412 struct Route *route_to_peer2_host;
1413 struct Route *route_to_peer1_host;
1414 struct Peer *peer;
1415 struct RegisteredHostContext *rhc;
1416 struct ForwardedOverlayConnectContext *focc;
1417 uint64_t op_id;
1418 uint32_t peer2_host_id;
1419 uint32_t p1;
1420 uint32_t p2;
1421
1422 p1 = ntohl (msg->peer1);
1423 p2 = ntohl (msg->peer2);
1424 op_id = GNUNET_ntohll (msg->operation_id);
1425 peer2_host_id = ntohl (msg->peer2_host_id);
1426 GNUNET_assert (VALID_PEER_ID (p1));
1427 GNUNET_assert (VALID_HOST_ID (peer2_host_id));
1428 peer = GST_peer_list[p1];
1429 GNUNET_assert (GNUNET_YES == peer->is_remote);
1430 LOG_DEBUG ("0x%llx: Forwarding overlay connect\n",
1431 (unsigned long long) op_id);
1432 route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1433 route_to_peer1_host = GST_find_dest_route
1434 (peer->details.remote.remote_host_id);
1435 GNUNET_assert (NULL != route_to_peer1_host);
1436 if ((NULL != route_to_peer2_host) &&
1437 (route_to_peer1_host->dest == route_to_peer2_host->dest))
1438 goto forward;
1439 /* Peer2 is either with us OR peer1 and peer2 can be reached through
1440 different subtrees OR peer2 is on a subtree unknown to us */
1441 if (NULL != (rhc = register_host (peer->details.remote.slave,
1442 GST_host_list[peer2_host_id])))
1443 {
1444 LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1,
1445 p2);
1446 focc = GNUNET_new (struct ForwardedOverlayConnectContext);
1447 focc->rhc = rhc;
1448 focc->peer1 = p1;
1449 focc->peer2 = p2;
1450 focc->peer2_host_id = peer2_host_id;
1451 focc->orig_msg = GNUNET_copy_message (&msg->header);
1452 focc->operation_id = op_id;
1453 focc->client = client;
1454 GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head,
1455 rhc->focc_dll_tail,
1456 focc);
1457 return;
1458 }
1459
1460forward:
1461 LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1,
1462 p2);
1463 fopc = GNUNET_new (struct ForwardedOperationContext);
1464 fopc->client = client;
1465 fopc->operation_id = op_id;
1466 fopc->type = OP_OVERLAY_CONNECT;
1467 fopc->opc =
1468 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1469 slave->controller, op_id,
1470 &msg->header,
1471 &GST_forwarded_operation_reply_relay,
1472 fopc);
1473 fopc->timeout_task =
1474 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1475 &GST_forwarded_operation_timeout,
1476 fopc);
1477 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
1478 fopcq_tail,
1479 fopc);
1480}
1481
1482
1483/**
1484 * Callback called when a connection to the controller of peer2 has been
1485 * established
1486 *
1487 * @param cls the overlay connect contexts
1488 * @param c handle to the controller connection
1489 */
1490static void
1491p2_controller_connect_cb (void *cls,
1492 struct GNUNET_TESTBED_Controller *c)
1493{
1494 struct OverlayConnectContext *occ = cls;
1495 struct RemotePeer2Context *rp2c;
1496 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1497
1498 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1499 rp2c = &occ->p2ctx.remote;
1500 rp2c->ncn = NULL;
1501 rp2c->p2c = c;
1502 cmsg.header.size =
1503 htons (sizeof(struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1504 cmsg.header.type =
1505 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
1506 cmsg.peer_id = htonl (occ->other_peer_id);
1507 cmsg.operation_id = GNUNET_htonll (occ->op_id);
1508 rp2c->opc =
1509 GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c,
1510 occ->op_id,
1511 &cmsg.header,
1512 &overlay_connect_get_config,
1513 occ);
1514 GNUNET_free (occ->emsg);
1515 GNUNET_asprintf (&occ->emsg,
1516 "0x%llx: Timeout while getting peer identity of peer "
1517 "with id: %u",
1518 (unsigned long long) occ->op_id,
1519 occ->other_peer_id);
1520}
1521
1522
1523/**
1524 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages
1525 *
1526 * @param cls identification of the client
1527 * @param msg the actual message
1528 */
1529void
1530handle_overlay_connect (void *cls,
1531 const struct GNUNET_TESTBED_OverlayConnectMessage *msg)
1532{
1533 struct GNUNET_SERVICE_Client *client = cls;
1534 struct Peer *peer;
1535 struct Peer *peer2;
1536 struct OverlayConnectContext *occ;
1537 struct Neighbour *p2n;
1538 uint64_t operation_id;
1539 uint32_t p1;
1540 uint32_t p2;
1541 uint32_t peer2_host_id;
1542
1543 p1 = ntohl (msg->peer1);
1544 p2 = ntohl (msg->peer2);
1545 if (p1 == p2)
1546 {
1547 GNUNET_break (0);
1548 GNUNET_SERVICE_client_drop (client);
1549 return;
1550 }
1551 if (! VALID_PEER_ID (p1))
1552 {
1553 GNUNET_break (0);
1554 GNUNET_SERVICE_client_drop (client);
1555 return;
1556 }
1557 peer = GST_peer_list[p1];
1558 operation_id = GNUNET_ntohll (msg->operation_id);
1559 LOG_DEBUG
1560 ("Received overlay connect for peers %u and %u with op id: 0x%llx\n",
1561 p1,
1562 p2,
1563 (unsigned long long) operation_id);
1564 peer2_host_id = ntohl (msg->peer2_host_id);
1565 if (GNUNET_YES == peer->is_remote)
1566 {
1567 if (! VALID_HOST_ID (peer2_host_id))
1568 {
1569 GNUNET_break (0);
1570 GNUNET_SERVICE_client_drop (client);
1571 return;
1572 }
1573 forward_overlay_connect (msg, client);
1574 GNUNET_SERVICE_client_continue (client);
1575 return;
1576 }
1577 p2n = NULL;
1578 occ = GNUNET_new (struct OverlayConnectContext);
1579 occ->type = OCC_TYPE_LOCAL;
1580 if (! VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */
1581 {
1582 if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
1583 {
1584 if (! VALID_HOST_ID (peer2_host_id))
1585 {
1586 GNUNET_break (0);
1587 LOG (GNUNET_ERROR_TYPE_WARNING,
1588 "0x%llx: Peer %u's host not in our neighbours list\n",
1589 (unsigned long long) operation_id, p2);
1590 GNUNET_SERVICE_client_drop (client);
1591 GNUNET_free (occ);
1592 return;
1593 }
1594 p2n = GST_create_neighbour (GST_host_list[peer2_host_id]);
1595 }
1596 occ->type = OCC_TYPE_REMOTE_LATERAL;
1597 occ->p2ctx.remote.p2n = p2n;
1598 }
1599 else if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1600 {
1601 occ->type = OCC_TYPE_REMOTE_SLAVE;
1602 occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller;
1603 }
1604 GNUNET_CONTAINER_DLL_insert_tail (occq_head,
1605 occq_tail,
1606 occ);
1607 occ->client = client;
1608 occ->other_peer_id = p2;
1609 GST_peer_list[p1]->reference_cnt++;
1610 occ->peer = GST_peer_list[p1];
1611 occ->op_id = operation_id;
1612 GNUNET_assert (NULL == occ->timeout_task);
1613 occ->timeout_task =
1614 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1615 &timeout_overlay_connect,
1616 occ);
1617 switch (occ->type)
1618 {
1619 case OCC_TYPE_REMOTE_LATERAL:
1620 GNUNET_asprintf (&occ->emsg,
1621 "0x%llx: Timeout while acquiring connection to peer %u's "
1622 "host: %u\n",
1623 (unsigned long long) occ->op_id,
1624 occ->other_peer_id,
1625 peer2_host_id);
1626 occ->p2ctx.remote.ncn
1627 = GST_neighbour_get_connection (p2n,
1628 &p2_controller_connect_cb,
1629 occ);
1630 break;
1631 case OCC_TYPE_REMOTE_SLAVE:
1632 p2_controller_connect_cb (occ,
1633 occ->p2ctx.remote.p2c);
1634 break;
1635 case OCC_TYPE_LOCAL:
1636 peer2 = GST_peer_list[occ->other_peer_id];
1637 peer2->reference_cnt++;
1638 GNUNET_TESTING_peer_get_identity (peer2->details.local.peer,
1639 &occ->other_peer_identity);
1640 GNUNET_asprintf (&occ->emsg,
1641 "0x%llx: Timeout while connecting to CORE of peer with "
1642 "id: %u",
1643 (unsigned long long) occ->op_id,
1644 occ->peer->id);
1645 LOG_DEBUG ("Peer %u has PID %s\n",
1646 occ->other_peer_id,
1647 GNUNET_i2s (&occ->other_peer_identity));
1648 {
1649 struct GNUNET_PeerIdentity lpid;
1650
1651 GNUNET_TESTING_peer_get_identity (peer->details.local.peer,
1652 &lpid);
1653 LOG_DEBUG ("Peer %u has PID %s\n",
1654 p1,
1655 GNUNET_i2s (&lpid));
1656 }
1657 occ->cgh_ch =
1658 GST_connection_pool_get_handle (occ->peer->id,
1659 occ->peer->details.local.cfg,
1660 GST_CONNECTIONPOOL_SERVICE_CORE,
1661 &occ_cache_get_handle_core_cb, occ,
1662 &occ->other_peer_identity,
1663 &overlay_connect_notify, occ);
1664 break;
1665 }
1666 GNUNET_SERVICE_client_continue (client);
1667}
1668
1669
1670/**
1671 * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1672 * with it
1673 *
1674 * @param rocc the RemoteOverlayConnectCtx
1675 */
1676static void
1677cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1678{
1679 LOG_DEBUG ("0x%llx: Cleaning up rocc\n",
1680 (unsigned long long) rocc->op_id);
1681 if (NULL != rocc->attempt_connect_task_id)
1682 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1683 if (NULL != rocc->timeout_rocc_task_id)
1684 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1685 if (NULL != rocc->ohh)
1686 GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1687 if (NULL != rocc->tcc.csh)
1688 GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh);
1689 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th);
1690 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats);
1691 GNUNET_assert (rocc->peer->reference_cnt > 0);
1692 rocc->peer->reference_cnt--;
1693 if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1694 (0 == rocc->peer->reference_cnt))
1695 GST_destroy_peer (rocc->peer);
1696 GNUNET_free (rocc->hello);
1697 GNUNET_CONTAINER_DLL_remove (roccq_head,
1698 roccq_tail,
1699 rocc);
1700 GNUNET_free (rocc);
1701}
1702
1703
1704/**
1705 * Task to timeout rocc and cleanit up
1706 *
1707 * @param cls the RemoteOverlayConnectCtx
1708 */
1709static void
1710timeout_rocc_task (void *cls)
1711{
1712 struct RemoteOverlayConnectCtx *rocc = cls;
1713
1714 GNUNET_assert (rocc->timeout_rocc_task_id != NULL);
1715 rocc->timeout_rocc_task_id = NULL;
1716 LOG_DEBUG ("0x%llx: rocc timed out\n",
1717 (unsigned long long) rocc->op_id);
1718 cleanup_rocc (rocc);
1719}
1720
1721
1722/**
1723 * Function called to notify transport users that another
1724 * peer connected to us.
1725 *
1726 * @param cls the RemoteOverlayConnectContext
1727 * @param new_peer the peer that connected
1728 */
1729static void
1730cache_transport_peer_connect_notify (void *cls,
1731 const struct GNUNET_PeerIdentity *new_peer)
1732{
1733 struct RemoteOverlayConnectCtx *rocc = cls;
1734
1735 LOG_DEBUG ("0x%llx: Request Overlay connect notify\n",
1736 (unsigned long long) rocc->op_id);
1737 GNUNET_assert (0 ==
1738 memcmp (new_peer, &rocc->a_id,
1739 sizeof(struct GNUNET_PeerIdentity)));
1740 LOG_DEBUG ("0x%llx: Peer %s connected\n",
1741 (unsigned long long) rocc->op_id,
1742 GNUNET_i2s (&rocc->a_id));
1743 cleanup_rocc (rocc);
1744}
1745
1746
1747/**
1748 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1749 * whose identity is in RemoteOverlayConnectCtx
1750 *
1751 * @param cls the RemoteOverlayConnectCtx
1752 */
1753static void
1754attempt_connect_task (void *cls);
1755
1756
1757/**
1758 * Task that is run when hello has been sent If tc->reason =
1759 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1760 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1761 *
1762 * @param cls the overlay connect context
1763 */
1764static void
1765rocc_hello_sent_cb (void *cls)
1766{
1767 struct RemoteOverlayConnectCtx *rocc = cls;
1768
1769 rocc->ohh = NULL;
1770 GNUNET_assert (NULL == rocc->attempt_connect_task_id);
1771 LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n",
1772 (unsigned long long) rocc->op_id,
1773 GNUNET_i2s (&rocc->a_id),
1774 rocc->peer->id);
1775 rocc->tcc.cgh_p2_ats =
1776 GST_connection_pool_get_handle (rocc->peer->id,
1777 rocc->peer->details.local.cfg,
1778 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
1779 &occ_cache_get_handle_ats_rocc_cb,
1780 rocc, NULL, NULL, NULL);
1781}
1782
1783
1784/**
1785 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1786 * whose identity is in RemoteOverlayConnectCtx
1787 *
1788 * @param cls the RemoteOverlayConnectCtx
1789 */
1790static void
1791attempt_connect_task (void *cls)
1792{
1793 struct RemoteOverlayConnectCtx *rocc = cls;
1794
1795 GNUNET_assert (NULL != rocc->attempt_connect_task_id);
1796 rocc->attempt_connect_task_id = NULL;
1797 LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n",
1798 (unsigned long long) rocc->op_id,
1799 GNUNET_i2s (&rocc->a_id),
1800 rocc->peer->id);
1801 rocc->ohh =
1802 GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg,
1803 rocc->hello,
1804 &rocc_hello_sent_cb,
1805 rocc);
1806 if (NULL == rocc->ohh)
1807 rocc->attempt_connect_task_id =
1808 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1809 (GNUNET_TIME_UNIT_MILLISECONDS,
1810 100
1811 + GNUNET_CRYPTO_random_u32
1812 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1813 &attempt_connect_task, rocc);
1814}
1815
1816
1817/**
1818 * Callback from cache with needed handles set
1819 *
1820 * @param cls the closure passed to GST_cache_get_handle_transport()
1821 * @param ch the handle to CORE. Can be NULL if it is not requested
1822 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1823 * @param ac the handle to ATS. Can be NULL if it is not requested
1824 * @param ignore_ peer identity which is ignored in this callback
1825 */
1826static void
1827rocc_cache_get_handle_transport_cb (void *cls,
1828 struct GNUNET_CORE_Handle *ch,
1829 struct GNUNET_TRANSPORT_CoreHandle *th,
1830 struct GNUNET_ATS_ConnectivityHandle *ac,
1831 const struct GNUNET_PeerIdentity *ignore_,
1832 const struct
1833 GNUNET_CONFIGURATION_Handle *cfg)
1834{
1835 struct RemoteOverlayConnectCtx *rocc = cls;
1836
1837 if (NULL == th)
1838 {
1839 rocc->timeout_rocc_task_id =
1840 GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
1841 return;
1842 }
1843 rocc->tcc.th_ = th;
1844 rocc->tcc.cfg = cfg;
1845 if (NULL !=
1846 GNUNET_TRANSPORT_core_get_mq (rocc->tcc.th_,
1847 &rocc->a_id))
1848 {
1849 LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n",
1850 (unsigned long long) rocc->op_id,
1851 GNUNET_i2s (&rocc->a_id),
1852 rocc->peer->id);
1853 cleanup_rocc (rocc);
1854 return;
1855 }
1856 rocc->attempt_connect_task_id =
1857 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1858}
1859
1860
1861/**
1862 * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
1863 *
1864 * @param cls identification of the client
1865 * @param msg the actual message
1866 * @return #GNUNET_OK if @a msg is well-formed
1867 */
1868int
1869check_remote_overlay_connect (void *cls,
1870 const struct
1871 GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
1872{
1873 uint32_t peer_id;
1874 uint16_t msize;
1875 uint16_t hsize;
1876
1877 msize = ntohs (msg->header.size);
1878 if (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))
1879 {
1880 GNUNET_break (0);
1881 return GNUNET_SYSERR;
1882 }
1883 hsize = ntohs (msg->hello->size);
1884 if ((sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) !=
1885 msize)
1886 {
1887 GNUNET_break (0);
1888 return GNUNET_SYSERR;
1889 }
1890 peer_id = ntohl (msg->peer);
1891 if ((peer_id >= GST_peer_list_size) ||
1892 (NULL == GST_peer_list[peer_id]))
1893 {
1894 GNUNET_break_op (0);
1895 return GNUNET_SYSERR;
1896 }
1897 return GNUNET_OK;
1898}
1899
1900
1901/**
1902 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
1903 *
1904 * @param cls identification of the client
1905 * @param msg the actual message
1906 */
1907void
1908handle_remote_overlay_connect (void *cls,
1909 const struct
1910 GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
1911{
1912 struct GNUNET_SERVICE_Client *client = cls;
1913 struct RemoteOverlayConnectCtx *rocc;
1914 struct Peer *peer;
1915 struct GNUNET_PeerIdentity pid;
1916 static char pid_str[16];
1917 uint32_t peer_id;
1918 uint16_t hsize;
1919
1920 hsize = ntohs (msg->hello->size);
1921 peer_id = ntohl (msg->peer);
1922 peer = GST_peer_list[peer_id];
1923 if (GNUNET_YES == peer->is_remote)
1924 {
1925 struct GNUNET_MessageHeader *msg2;
1926
1927 msg2 = GNUNET_copy_message (&msg->header);
1928 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1929 msg2);
1930 GNUNET_SERVICE_client_continue (client);
1931 return;
1932 }
1933 rocc = GNUNET_new (struct RemoteOverlayConnectCtx);
1934 rocc->op_id = GNUNET_ntohll (msg->operation_id);
1935 GNUNET_CONTAINER_DLL_insert_tail (roccq_head,
1936 roccq_tail,
1937 rocc);
1938 rocc->a_id = msg->peer_identity;
1939 GNUNET_TESTING_peer_get_identity (peer->details.local.peer,
1940 &pid);
1941 (void) GNUNET_strlcpy (pid_str,
1942 GNUNET_i2s (&pid),
1943 sizeof(pid_str));
1944 LOG_DEBUG (
1945 "0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n",
1946 (unsigned long long) rocc->op_id,
1947 pid_str,
1948 GNUNET_i2s (&rocc->a_id),
1949 hsize);
1950 rocc->peer = peer;
1951 rocc->peer->reference_cnt++;
1952 rocc->hello = GNUNET_malloc (hsize);
1953 GNUNET_memcpy (rocc->hello,
1954 msg->hello,
1955 hsize);
1956 rocc->tcc.cgh_p2_th =
1957 GST_connection_pool_get_handle (peer_id,
1958 rocc->peer->details.local.cfg,
1959 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1960 &rocc_cache_get_handle_transport_cb,
1961 rocc,
1962 &rocc->a_id,
1963 &cache_transport_peer_connect_notify,
1964 rocc);
1965 rocc->timeout_rocc_task_id =
1966 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1967 &timeout_rocc_task,
1968 rocc);
1969 GNUNET_SERVICE_client_continue (client);
1970}
1971
1972
1973/**
1974 * Clears all pending overlay connect contexts in queue
1975 */
1976void
1977GST_free_occq ()
1978{
1979 struct OverlayConnectContext *occ;
1980
1981 while (NULL != (occ = occq_head))
1982 cleanup_occ (occ);
1983}
1984
1985
1986/**
1987 * Clears all pending remote overlay connect contexts in queue
1988 */
1989void
1990GST_free_roccq ()
1991{
1992 struct RemoteOverlayConnectCtx *rocc;
1993
1994 while (NULL != (rocc = roccq_head))
1995 cleanup_rocc (rocc);
1996}
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 */
36struct Peer **GST_peer_list;
37
38/**
39 * The current number of peers running locally under this controller
40 */
41unsigned int GST_num_local_peers;
42
43
44/**
45 * Context information to manage peers' services
46 */
47struct 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 */
100struct 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 */
143static struct PeerReconfigureContext *prc_head;
144
145/**
146 * The DLL tail for the peer reconfigure list
147 */
148static struct PeerReconfigureContext *prc_tail;
149
150
151/**
152 * DLL head for queue of manage service requests
153 */
154static struct ManageServiceContext *mctx_head;
155
156/**
157 * DLL tail for queue of manage service requests
158 */
159static struct ManageServiceContext *mctx_tail;
160
161
162/**
163 * Adds a peer to the peer array
164 *
165 * @param peer the peer to add
166 */
167static void
168peer_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 */
184static void
185peer_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 */
219static void
220peer_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 */
236static void
237peer_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 */
258void
259GST_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 */
285static void
286cleanup_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 */
309static int
310stop_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 */
325static void
326cleanup_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 */
353void
354GST_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 */
396static void
397peer_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 */
423int
424check_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 */
437void
438handle_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 */
569void
570handle_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 */
636static int
637start_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 */
653void
654handle_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 */
723void
724handle_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 */
807void
808handle_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 */
891void
892GST_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 */
906static char *
907update_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 */
934static void
935prc_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
966cleanup:
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 */
979int
980check_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 */
995void
996handle_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 */
1124void
1125GST_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 */
1138static const char *
1139arm_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 */
1159static const char *
1160arm_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 */
1208static void
1209service_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
1243service_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
1256ret:
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 */
1279int
1280check_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 */
1310void
1311handle_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
1415err_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 */
1426void
1427GST_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 */
1476static void
1477shutdown_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 */
1514void
1515handle_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 */
42struct GNUNET_CONFIGURATION_Handle *cfg;
43
44/**
45 * Peer linking - topology operation
46 */
47struct 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 */
53static char *hosts_file;
54
55/**
56 * Abort task identifier
57 */
58static struct GNUNET_SCHEDULER_Task *abort_task;
59
60/**
61 * Global event mask for all testbed events
62 */
63uint64_t event_mask;
64
65/**
66 * Number of peers to be started by the profiler
67 */
68static unsigned int num_peers;
69
70/**
71 * Number of timeout failures to tolerate
72 */
73static unsigned int num_cont_fails;
74
75/**
76 * Continuous failures during overlay connect operations
77 */
78static unsigned int cont_fails;
79
80/**
81 * Links which are successfully established
82 */
83static unsigned int established_links;
84
85/**
86 * Links which are not successfully established
87 */
88static unsigned int failed_links;
89
90/**
91 * Global testing status
92 */
93static int result;
94
95/**
96 * Are we running non interactively
97 */
98static int noninteractive;
99
100
101/**
102 * Shutdown nicely
103 *
104 * @param cls NULL
105 */
106static void
107do_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 */
127static void
128do_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 */
142static void
143print_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 */
161static void
162controller_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 */
213static void
214test_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 */
247static void
248run (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 */
275int
276main (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
11int
12main (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
102finalize:
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
21:2|3
33:4| 0| 1
42: 3|1|0
50: 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 @@
1Index: 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
14Index: 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 @@
1totakura@192.168.0.1:22
2totakura@192.168.0.2:22
3totakura@opt01:22
4totakura@i19-n015:2022
5totakura@asgard.realm
6rivendal
7rohan: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 */
46static struct GNUNET_HELPER_Handle *helper;
47
48/**
49 * Message to helper
50 */
51static struct GNUNET_TESTBED_HelperInit *msg;
52
53/**
54 * Message send handle
55 */
56static struct GNUNET_HELPER_SendHandle *shandle;
57
58/**
59 * Abort task identifier
60 */
61static struct GNUNET_SCHEDULER_Task *abort_task;
62
63/**
64 * Shutdown task identifier
65 */
66static struct GNUNET_SCHEDULER_Task *shutdown_task;
67
68/**
69 * Configuration handle.
70 */
71static struct GNUNET_CONFIGURATION_Handle *cfg;
72
73/**
74 * Global testing status
75 */
76static int result;
77
78
79/**
80 * Shutdown nicely
81 *
82 * @param cls NULL
83 */
84static void
85do_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 */
102static void
103do_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 */
123static void
124cont_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 */
145static int
146mst_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 */
185static void
186exp_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 */
201static void
202run (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 */
238int
239main (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 */
48static struct GNUNET_TESTBED_Host *host;
49
50/**
51 * The controller process
52 */
53static struct GNUNET_TESTBED_ControllerProc *cp;
54
55/**
56 * The controller handle
57 */
58static struct GNUNET_TESTBED_Controller *controller;
59
60/**
61 * A neighbouring host
62 */
63static struct GNUNET_TESTBED_Host *neighbour;
64
65/**
66 * Handle for neighbour registration
67 */
68static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
69
70/**
71 * Handle for a peer
72 */
73static struct GNUNET_TESTBED_Peer *peer;
74
75/**
76 * Handle to configuration
77 */
78static struct GNUNET_CONFIGURATION_Handle *cfg;
79
80/**
81 * Handle to operation
82 */
83static struct GNUNET_TESTBED_Operation *operation;
84
85/**
86 * Handle to peer's ARM service
87 */
88static struct GNUNET_ARM_Handle *arm_handle;
89
90/**
91 * Abort task identifier
92 */
93static struct GNUNET_SCHEDULER_Task *abort_task;
94
95/**
96 * The testing result
97 */
98static int result;
99
100
101/**
102 * Enumeration of sub testcases
103 */
104enum 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 */
130static enum Test sub_test;
131
132/**
133 * Shutdown nicely
134 *
135 * @param cls NULL
136 * @param tc the task context
137 */
138static void
139do_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 */
180static void
181do_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 */
199static void *
200arm_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 */
218static void
219arm_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 */
242static void
243service_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 */
274static void
275peerinfo_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 */
307static void
308controller_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 */
380static void
381peer_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 */
406static void
407registration_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 */
431static void
432status_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, &registration_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 */
470static void
471run (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 */
493int
494main (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 */
49struct 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 */
70static struct GNUNET_TESTBED_Host *host;
71
72/**
73 * The controller process
74 */
75static struct GNUNET_TESTBED_ControllerProc *cp;
76
77/**
78 * The controller handle
79 */
80static struct GNUNET_TESTBED_Controller *controller;
81
82/**
83 * A neighbouring host
84 */
85static struct GNUNET_TESTBED_Host *neighbour;
86
87/**
88 * Handle for neighbour registration
89 */
90static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
91
92/**
93 * peer 1
94 */
95static struct PeerContext peer1;
96
97/**
98 * peer2
99 */
100static struct PeerContext peer2;
101
102/**
103 * Handle to configuration
104 */
105static struct GNUNET_CONFIGURATION_Handle *cfg;
106
107/**
108 * Handle to operations involving both peers
109 */
110static struct GNUNET_TESTBED_Operation *common_operation;
111
112/**
113 * Abort task identifier
114 */
115static struct GNUNET_SCHEDULER_Task *abort_task;
116
117/**
118 * Delayed connect job identifier
119 */
120static struct GNUNET_SCHEDULER_Task *delayed_connect_task;
121
122/**
123 * Different stages in testing
124 */
125enum 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 */
166static 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 */
189static void
190do_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 */
212static void
213do_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 */
229static void
230op_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 */
238static void
239do_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 */
257static void
258op_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 */
288static void
289controller_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 */
416static void
417peer_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 */
436static void
437registration_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 */
461static void
462status_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, &registration_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 */
498static void
499run (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 */
517int
518main (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 */
67struct 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 */
88static struct GNUNET_TESTBED_Host *host;
89
90/**
91 * The controller process of one controller
92 */
93static struct GNUNET_TESTBED_ControllerProc *cp1;
94
95/**
96 * A neighbouring host
97 */
98static struct GNUNET_TESTBED_Host *neighbour1;
99
100/**
101 * Another neighbouring host
102 */
103static struct GNUNET_TESTBED_Host *neighbour2;
104
105/**
106 * Handle for neighbour registration
107 */
108static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
109
110/**
111 * The controller handle of one controller
112 */
113static struct GNUNET_TESTBED_Controller *controller1;
114
115/**
116 * peer 1
117 */
118static struct PeerContext peer1;
119
120/**
121 * peer2
122 */
123static struct PeerContext peer2;
124
125/**
126 * peer3
127 */
128static struct PeerContext peer3;
129
130/**
131 * Handle to starting configuration
132 */
133static 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 */
139static struct GNUNET_CONFIGURATION_Handle *cfg2;
140
141/**
142 * Handle to operations involving both peers
143 */
144static struct GNUNET_TESTBED_Operation *common_operation;
145
146/**
147 * The handle for whether a host is habitable or not
148 */
149struct GNUNET_TESTBED_HostHabitableCheckHandle *hc_handle;
150
151/**
152 * Abort task identifier
153 */
154static struct GNUNET_SCHEDULER_Task *abort_task;
155
156/**
157 * Delayed connect job identifier
158 */
159static struct GNUNET_SCHEDULER_Task *delayed_connect_task;
160
161/**
162 * Different stages in testing
163 */
164enum 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 */
250static enum Stage result;
251
252/**
253 * Shutdown nicely
254 *
255 * @param cls NULL
256 */
257static void
258do_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 */
290static void
291do_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
304static void
305abort_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 */
321static void
322op_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 */
330static void
331do_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 */
354static void
355op_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 */
395static void
396peer_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 */
454static void
455controller_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 */
747static void
748registration_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 &registration_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 */
798static void
799status_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 &registration_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 */
865static void
866host_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 */
896static void
897run (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 */
932int
933main (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 */
48struct GNUNET_TESTBED_Barrier *barrier;
49
50/**
51 * Identifier for the shutdown task
52 */
53static struct GNUNET_SCHEDULER_Task *timeout_task;
54
55/**
56 * Result of this test case
57 */
58static int result;
59
60
61/**
62 * Handle SIGINT and SIGTERM
63 */
64static void
65shutdown_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 */
80static void
81do_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 */
103static void
104barrier_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 */
156static void
157test_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 */
200int
201main (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]
2START_ON_DEMAND = NO
3PORT = 12113
4ACCEPT_FROM = 127.0.0.1;
5HOSTNAME = localhost
6TOPOLOGY = RANDOM
7#PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args
8
9[arm]
10PORT = 12366
11
12[test-barriers]
13START_ON_DEMAND = NO
14PORT = 12114
15BINARY = /will/be/overwritten/in/test_testbed_api_barriers/
16IMMEDIATE_START = YES
17
18[fs]
19START_ON_DEMAND = NO
20IMMEDIATE_START = NO
21
22[resolver]
23HOSTNAME = localhost
24START_ON_DEMAND = NO
25
26[cadet]
27START_ON_DEMAND = NO
28IMMEDIATE_START = NO
29
30[dht]
31START_ON_DEMAND = NO
32IMMEDIATE_START = NO
33
34[dhtcache]
35QUOTA = 1 MB
36DATABASE = heap
37
38[transport]
39PLUGINS = udp
40ACCEPT_FROM6 = ::1;
41ACCEPT_FROM = 127.0.0.1;
42NEIGHBOUR_LIMIT = 50
43PORT = 12365
44IMMEDIATE_START = YES
45
46[ats]
47WAN_QUOTA_OUT = 3932160
48WAN_QUOTA_IN = 3932160
49
50[core]
51PORT = 12092
52START_ON_DEMAND = YES
53IMMEDIATE_START = YES
54USE_EPHEMERAL_KEYS = NO
55
56[transport-udp]
57TIMEOUT = 300 s
58PORT = 12368
59
60[PATHS]
61GNUNET_TEST_HOME = $GNUNET_TMP/test-testbed/
62
63[dns]
64START_ON_DEMAND = NO
65IMMEDIATE_START = NO
66
67[nse]
68START_ON_DEMAND = NO
69IMMEDIATE_START = NO
70
71[vpn]
72START_ON_DEMAND = NO
73IMMEDIATE_START = NO
74
75[nat]
76RETURN_LOCAL_ADDRESSES = YES
77IMMEDIATE_START = NO
78
79[gns-helper-service-w32]
80START_ON_DEMAND = NO
81
82[consensus]
83START_ON_DEMAND = NO
84IMMEDIATE_START = NO
85
86[gns]
87START_ON_DEMAND = NO
88IMMEDIATE_START = NO
89
90[statistics]
91START_ON_DEMAND = NO
92IMMEDIATE_START = NO
93
94[peerinfo]
95NO_IO = YES
96
97[set]
98START_ON_DEMAND = NO
99IMMEDIATE_START = NO
100
101[revocation]
102START_ON_DEMAND = NO
103IMMEDIATE_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 */
58enum 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 */
199static struct GNUNET_TESTBED_Host *host;
200
201/**
202 * The master controller process
203 */
204static struct GNUNET_TESTBED_ControllerProc *cp;
205
206/**
207 * Handle to master controller
208 */
209static struct GNUNET_TESTBED_Controller *mc;
210
211/**
212 * Slave host for running slave controller
213 */
214static struct GNUNET_TESTBED_Host *slave;
215
216/**
217 * Another slave host for running another slave controller
218 */
219static struct GNUNET_TESTBED_Host *slave2;
220
221/**
222 * Host for slave 3
223 */
224static struct GNUNET_TESTBED_Host *slave3;
225
226/**
227 * Slave host registration handle
228 */
229static struct GNUNET_TESTBED_HostRegistrationHandle *rh;
230
231/**
232 * Handle to global configuration
233 */
234static struct GNUNET_CONFIGURATION_Handle *cfg;
235
236/**
237 * Configuration of slave 3 controller
238 */
239static struct GNUNET_CONFIGURATION_Handle *cfg3;
240
241/**
242 * Abort task
243 */
244static struct GNUNET_SCHEDULER_Task *abort_task;
245
246/**
247 * Operation handle for linking controllers
248 */
249static struct GNUNET_TESTBED_Operation *op;
250
251/**
252 * Handle to peer started at slave 1
253 */
254static struct GNUNET_TESTBED_Peer *slave1_peer;
255
256/**
257 * Handle to peer started at slave 2
258 */
259static struct GNUNET_TESTBED_Peer *slave2_peer;
260
261/**
262 * Handle to peer started at slave 2
263 */
264static struct GNUNET_TESTBED_Peer *slave3_peer;
265
266/**
267 * Handle to a peer started at master controller
268 */
269static struct GNUNET_TESTBED_Peer *master_peer;
270
271/**
272 * The handle for whether a host is habitable or not
273 */
274static struct GNUNET_TESTBED_HostHabitableCheckHandle *hc_handle;
275
276/**
277 * The task handle for the delay task
278 */
279static struct GNUNET_SCHEDULER_Task *delay_task_id;
280
281/**
282 * Event mask
283 */
284static uint64_t event_mask;
285
286/**
287 * Global testing status
288 */
289static 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 */
314static void
315do_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 */
357static void
358do_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 */
372static void
373do_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 */
387static void
388registration_cont (void *cls, const char *emsg);
389
390
391/**
392 * Task for inserting delay between tests
393 *
394 * @param
395 * @return
396 */
397static void
398delay_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, &registration_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 */
433static void
434peer_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 */
485static void
486check_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 */
504static void
505controller_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, &registration_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 */
688static void
689registration_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, &registration_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 */
738static void
739status_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 */
780static void
781host_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 */
810static void
811run (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 */
846int
847main (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 */
39static struct GNUNET_CONFIGURATION_Handle *cfg;
40
41/**
42 * Host we are creating and using
43 */
44static struct GNUNET_TESTBED_Host *host;
45
46/**
47 * An array of hosts which are loaded from a file
48 */
49static struct GNUNET_TESTBED_Host **hosts;
50
51/**
52 * Number of hosts in the above list
53 */
54static unsigned int num_hosts;
55
56/**
57 * Global test status
58 */
59static int status;
60
61
62/**
63 * The shutdown task
64 *
65 * @param cls NULL
66 */
67static void
68do_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 */
93static void
94run (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
163int
164main (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 */
48struct OperationQueue *q1;
49
50/**
51 * Queue B. Max active set to 2 is not changed throughout the test
52 */
53struct OperationQueue *q2;
54
55/**
56 * This operation should go into both queues and block op2 until it is done
57 */
58struct GNUNET_TESTBED_Operation *op1;
59
60/**
61 * This operation should go into q1 and q2
62 */
63struct 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 */
71struct 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 */
78struct 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 */
84struct 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 */
90struct 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 */
98struct 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 */
105struct 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 */
113struct GNUNET_TESTBED_Operation *op9;
114
115/**
116 * The delay task identifier
117 */
118struct GNUNET_SCHEDULER_Task *step_task;
119
120
121/**
122 * Enumeration of test stages
123 */
124enum 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 */
236enum 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 */
244static void
245start_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 */
257static void
258release_cb (void *cls);
259
260
261/**
262 * Task to simulate artificial delay and change the test stage
263 *
264 * @param cls NULL
265 */
266static void
267step (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 */
348static void
349start_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 */
426static void
427release_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 */
514static void
515run (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 */
538int
539main (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 */
40static struct GNUNET_TESTBED_Peer **peers;
41
42/**
43 * Operation handle
44 */
45static struct GNUNET_TESTBED_Operation *op;
46
47/**
48 * Abort task identifier
49 */
50static struct GNUNET_SCHEDULER_Task *abort_task;
51
52/**
53 * States in this test
54 */
55enum
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 */
92static void
93do_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 */
113static void
114controller_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 */
152static void
153test_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 */
181int
182main (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 */
40static struct GNUNET_TESTBED_Peer **peers;
41
42/**
43 * Operation handle
44 */
45static struct GNUNET_TESTBED_Operation *op;
46
47/**
48 * dummy pointer
49 */
50static void *dummy_cls = (void *) 0xDEAD0001;
51
52/**
53 * Abort task identifier
54 */
55static struct GNUNET_SCHEDULER_Task *abort_task;
56
57/**
58 * States in this test
59 */
60enum
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 */
107static void
108do_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 */
129static void
130op_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 */
177static void
178test_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 */
204int
205main (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 */
35static 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 */
45static void
46run (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
85err:
86 GNUNET_TESTBED_SD_destroy_ (h);
87}
88
89
90/**
91 * Main function
92 */
93int
94main (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 */
39static struct GNUNET_TESTBED_Peer **peers;
40
41/**
42 * Operation handle
43 */
44static struct GNUNET_TESTBED_Operation *op;
45
46/**
47 * dummy pointer
48 */
49static void *dummy_cls = (void *) 0xDEAD0001;
50
51/**
52 * Abort task identifier
53 */
54static struct GNUNET_SCHEDULER_Task *abort_task;
55
56/**
57 * Global testing result
58 */
59static int result;
60
61/**
62 * The peers we have seen in the statistics iterator
63 */
64static struct GNUNET_TESTBED_Peer **seen_peers;
65
66/**
67 * Number of peers in the above array
68 */
69static 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 */
91static void
92do_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 */
116static int
117stats_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 */
143static void
144op_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 */
169static void
170test_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 */
193int
194main (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]
4OVERLAY_TOPOLOGY = 2D_TORUS
5MAX_PARALLEL_SERVICE_CONNECTIONS = 2
6
7[statistics]
8START_ON_DEMAND = YES
9PORT = 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]
5START_ON_DEMAND = NO
6PORT = 12113
7ACCEPT_FROM = 127.0.0.1;
8HOSTNAME = localhost
9OVERLAY_TOPOLOGY = NONE
10#PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args
11
12[dhtcache]
13QUOTA = 1 MB
14DATABASE = heap
15
16[transport]
17PLUGINS = tcp
18ACCEPT_FROM6 = ::1;
19ACCEPT_FROM = 127.0.0.1;
20NEIGHBOUR_LIMIT = 50
21IMMEDIATE_START = YES
22
23# Transport requires resolver when connecting to a peer, so enable it
24[resolver]
25START_ON_DEMAND = YES
26
27[ats]
28WAN_QUOTA_OUT = 3932160
29WAN_QUOTA_IN = 3932160
30
31[core]
32USE_EPHEMERAL_KEYS = NO
33IMMEDIATE_START = YES
34
35[transport-tcp]
36TIMEOUT = 300 s
37
38[PATHS]
39GNUNET_TEST_HOME = $GNUNET_TMP/test-testbed/
40
41[nat]
42RETURN_LOCAL_ADDRESSES = YES
43
44[peerinfo]
45NO_IO = YES
46
47[rps]
48START_ON_DEMAND = NO
49IMMEDIATE_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 */
46static struct GNUNET_TESTBED_Peer **peers;
47
48/**
49 * Operation handle
50 */
51static struct GNUNET_TESTBED_Operation *op;
52
53/**
54 * Abort task identifier
55 */
56static struct GNUNET_SCHEDULER_Task *abort_task;
57
58/**
59 * shutdown task identifier
60 */
61static struct GNUNET_SCHEDULER_Task *shutdown_task;
62
63/**
64 * Testing result
65 */
66static int result;
67
68
69/**
70 * Shutdown nicely
71 *
72 * @param cls NULL
73 */
74static void
75do_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 */
107static void
108do_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 */
127static void
128peerinfo_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 */
152static void
153op_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 */
175static void
176controller_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 */
204static void
205test_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 */
232int
233main (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 */
48static 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 */
69static void
70controller_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 */
89static void
90test_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 */
108int
109main (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]
4OVERLAY_TOPOLOGY = CLIQUE
5SETUP_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 */
39static struct GNUNET_TESTBED_Peer *peers[NUM_PEERS];
40
41/**
42 * Operation handle
43 */
44static struct GNUNET_TESTBED_Operation *op;
45
46/**
47 * Abort task identifier
48 */
49static struct GNUNET_SCHEDULER_Task *abort_task;
50
51/**
52 * Current peer id
53 */
54static unsigned int peer_id;
55
56/**
57 * Testing result
58 */
59static int result;
60
61/**
62 * Should we wait forever after testbed is initialized?
63 */
64static int wait_forever;
65
66
67/**
68 * Shutdown nicely
69 *
70 * @param cls NULL
71 */
72static void
73do_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 */
86static void
87do_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 */
108static void
109test_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 */
138static void
139controller_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 */
171static void
172run (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 */
196int
197main (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]
4OVERLAY_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]
4OVERLAY_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]
4OVERLAY_TOPOLOGY = FROM_FILE
5OVERLAY_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]
4OVERLAY_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]
4OVERLAY_TOPOLOGY = RANDOM
5OVERLAY_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]
4OVERLAY_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]
4OVERLAY_TOPOLOGY = SCALE_FREE
5SCALE_FREE_TOPOLOGY_CAP = 70
6SCALE_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]
4OVERLAY_TOPOLOGY = SMALL_WORLD
5OVERLAY_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]
4OVERLAY_TOPOLOGY = SMALL_WORLD_RING
5OVERLAY_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]
4OVERLAY_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 */
39static struct GNUNET_TESTBED_Peer **peers;
40
41/**
42 * Operation handle
43 */
44static struct GNUNET_TESTBED_Operation *op;
45
46/**
47 * Shutdown task
48 */
49static struct GNUNET_SCHEDULER_Task *shutdown_task;
50
51/**
52 * Testing result
53 */
54static int result;
55
56/**
57 * Counter for counting overlay connections
58 */
59static unsigned int overlay_connects;
60
61
62/**
63 * Shutdown nicely
64 *
65 * @param cls NULL
66 */
67static void
68do_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 */
86static void
87controller_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 */
132static void
133test_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 */
170int
171main (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 */
39static struct GNUNET_TESTBED_Peer **peers;
40
41/**
42 * Operation handle
43 */
44static struct GNUNET_TESTBED_Operation *op;
45
46/**
47 * Shutdown task
48 */
49static struct GNUNET_SCHEDULER_Task *shutdown_task;
50
51/**
52 * Testing result
53 */
54static int result;
55
56/**
57 * Counter for counting overlay connections
58 */
59static unsigned int overlay_connects;
60
61
62/**
63 * Shutdown nicely
64 *
65 * @param cls NULL
66 */
67static void
68do_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 */
86static void
87controller_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 */
127static void
128test_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 */
166int
167main (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 */
40static int result;
41
42static struct GNUNET_TESTBED_Operation *op;
43
44
45/**
46 * Shutdown testcase
47 *
48 * @param cls NULL
49 * @param tc scheduler task context
50 */
51static void
52do_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 */
68static void
69overlay_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 */
101static void
102test_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 */
140int
141main (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]
4OVERLAY_TOPOLOGY = LINE
5OPERATION_TIMEOUT = 5 s
6
7[testbed-underlay]
8START_ON_DEMAND = NO
9DBFILE = /will/be/overwritten/by/testcase
10IMMEDIATE_START = YES
11
12[dv]
13START_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]
2START_ON_DEMAND = NO
3@JAVAPORT@ PORT = 2101
4HOSTNAME = localhost
5BINARY = gnunet-service-testbed
6
7# How long should operations wait?
8OPERATION_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 `;'
18ACCEPT_FROM = 127.0.0.1;
19ACCEPT_FROM6 = ::1;
20
21UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-testbed.sock
22UNIX_MATCH_UID = YES
23UNIX_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.
28MAX_PARALLEL_OPERATIONS = 1000
29MAX_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
35OVERLAY_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
51SCALE_FREE_TOPOLOGY_CAP = 70
52# The minimum number of peers which a peer has to connect
53SCALE_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.
58MAX_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.
62CACHE_SIZE = 30
63
64# Maximum number of file descriptors a testbed controller is permitted to keep
65# open.
66MAX_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()
70SETUP_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
89SHARED_SERVICES =
90
91
92[testbed-barrier]
93START_ON_DEMAND = NO
94@UNIXONLY@ PORT = 2103
95HOSTNAME = localhost
96UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-testbed-barrier.sock
97UNIX_MATCH_UID = YES
98UNIX_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]
104START_ON_DEMAND = NO
105NOARMBIND = YES
106BINARY = gnunet-daemon-testbed-underlay
107# The sqlite3 database file containing information about what underlay
108# restrictions to apply
109# DBFILE =
110
111[latency-logger]
112START_ON_DEMAND = NO
113NOARMBIND = YES
114BINARY = 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
32GNUNET_NETWORK_STRUCT_BEGIN
33/**
34 * Initial message from a client to a testing control service.
35 */
36struct 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 */
64struct 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 */
114struct 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 */
136struct 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 */
169struct 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 */
204struct 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 */
240struct 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 */
271struct 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 */
294struct 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 */
317struct 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 */
340struct 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 */
375struct 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 */
408struct 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 */
442struct 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 */
475struct 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 */
508struct 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 */
533struct 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 */
557struct 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 */
581struct 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 */
603struct 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 */
637struct 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 */
659struct 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 */
688struct 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 */
705struct 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 */
737struct 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 */
782struct 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 */
804struct 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 */
821struct 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 */
850struct 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
864GNUNET_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 */
70struct 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 */
87struct 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 */
99struct 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 */
116struct 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 */
133struct 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 */
155static struct ExpireOperationEntry *exop_head;
156
157/**
158 * DLL tail for list of operation marked for expiry
159 */
160static 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 */
168static void
169exop_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 */
190static int
191exop_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 */
225struct 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 */
248static int
249opc_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 */
271static struct OperationContext *
272find_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 */
297void
298GNUNET_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 */
318void
319GNUNET_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 */
340static int
341check_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 */
368static void
369handle_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 */
414static void
415handle_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 */
438static void
439handle_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 */
542static void
543handle_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 */
600static void
601handle_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 */
681static void
682handle_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 */
757static int
758check_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 */
774static void
775handle_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 */
847static int
848check_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 */
864static void
865handle_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 */
1003static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
1004GNUNET_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 */
1027static int
1028check_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 */
1043static void
1044handle_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 */
1088static int
1089check_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 */
1105static void
1106handle_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 */
1195static int
1196check_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 */
1241static void
1242handle_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
1317cleanup:
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 */
1335void
1336GNUNET_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 */
1369struct OperationContext *
1370GNUNET_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 */
1406void
1407GNUNET_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 */
1421static void
1422opstart_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 */
1443static void
1444oprelease_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 */
1473static void
1474opstart_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 */
1496static void
1497oprelease_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 */
1528static void
1529mq_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 */
1554struct GNUNET_TESTBED_Controller *
1555GNUNET_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 */
1698static int
1699opc_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 */
1720void
1721GNUNET_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 */
1757size_t
1758GNUNET_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 */
1784char *
1785GNUNET_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 */
1831struct GNUNET_TESTBED_Operation *
1832GNUNET_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 */
1893struct GNUNET_TESTBED_Operation *
1894GNUNET_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 */
1935struct GNUNET_TESTBED_Operation *
1936GNUNET_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 */
1958void
1959GNUNET_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 */
1980struct GNUNET_TESTBED_HelperInit *
1981GNUNET_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 */
2044void
2045GNUNET_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 */
2066struct GNUNET_CONFIGURATION_Handle *
2067GNUNET_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 */
2180const char *
2181GNUNET_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 */
2208uint64_t
2209GNUNET_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 */
2225static void
2226opstart_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 */
2245static void
2246oprelease_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 */
2282struct GNUNET_TESTBED_Operation *
2283GNUNET_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 */
2321uint32_t
2322GNUNET_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 */
2334void
2335GNUNET_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 */
2370struct GNUNET_TESTBED_Barrier *
2371GNUNET_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 */
2437struct GNUNET_TESTBED_Barrier *
2438GNUNET_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 */
2458void
2459GNUNET_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 */
44enum 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 */
111enum 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 */
136struct 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 */
180typedef 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 */
193struct 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 */
277struct 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 */
318void
319GNUNET_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 */
331void
332GNUNET_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 */
343void
344GNUNET_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 */
357size_t
358GNUNET_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 */
372char *
373GNUNET_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 */
391struct GNUNET_TESTBED_HelperInit *
392GNUNET_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 */
412struct OperationContext *
413GNUNET_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 */
426void
427GNUNET_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 */
439struct GNUNET_CONFIGURATION_Handle *
440GNUNET_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 */
450const char *
451GNUNET_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 */
463uint64_t
464GNUNET_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 */
479struct GNUNET_TESTBED_Operation *
480GNUNET_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 */
501struct GNUNET_TESTBED_Barrier *
502GNUNET_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 */
516void
517GNUNET_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 */
46struct 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 */
82static int
83check_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 */
101static void
102handle_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 */
150static void
151mq_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 */
174struct GNUNET_TESTBED_BarrierWaitHandle *
175GNUNET_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 */
250void
251GNUNET_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 */
88struct 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 */
112struct 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 */
173static struct GNUNET_TESTBED_Host **host_list;
174
175/**
176 * The size of the available hosts list
177 */
178static 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 */
188struct GNUNET_TESTBED_Host *
189GNUNET_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 */
209struct GNUNET_TESTBED_Host *
210GNUNET_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 */
225uint32_t
226GNUNET_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 */
238const char *
239GNUNET_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 */
251const char *
252GNUNET_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 */
264uint16_t
265GNUNET_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 */
277int
278GNUNET_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 */
290const struct GNUNET_CONFIGURATION_Handle *
291GNUNET_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 */
303void
304GNUNET_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 */
326struct GNUNET_TESTBED_Host *
327GNUNET_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 */
374struct GNUNET_TESTBED_Host *
375GNUNET_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 */
407unsigned int
408GNUNET_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 */
534const char *
535simple_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 */
576void
577GNUNET_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 */
622void
623GNUNET_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 */
649void
650GNUNET_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 */
676int
677GNUNET_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 */
697struct 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 */
742static char **
743copy_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 */
765static char **
766join_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 */
795static void
796free_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 */
820static char **
821gen_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 */
900static char **
901gen_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 */
944static int
945helper_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 */
998static void
999clear_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 */
1016static void
1017helper_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 */
1055struct GNUNET_TESTBED_ControllerProc *
1056GNUNET_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 */
1165void
1166GNUNET_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 */
1180void
1181GNUNET_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 */
1205void
1206GNUNET_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 */
1216struct 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 */
1261static void
1262habitability_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 */
1315struct GNUNET_TESTBED_HostHabitableCheckHandle *
1316GNUNET_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 */
1376void
1377GNUNET_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 */
1401struct GNUNET_TESTBED_HostRegistrationHandle *
1402GNUNET_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 */
1484void
1485GNUNET_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 */
1506void
1507GNUNET_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 */
1521void
1522GNUNET_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 */
38struct 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 */
69struct GNUNET_TESTBED_Host *
70GNUNET_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 */
85struct GNUNET_TESTBED_Host *
86GNUNET_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 */
98uint32_t
99GNUNET_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 */
108const char *
109GNUNET_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 */
118uint16_t
119GNUNET_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 */
128const struct GNUNET_CONFIGURATION_Handle *
129GNUNET_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 */
138void
139GNUNET_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 */
150void
151GNUNET_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 */
162void
163GNUNET_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 */
175int
176GNUNET_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 */
189void
190GNUNET_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 */
199void
200GNUNET_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 */
208void
209GNUNET_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 */
218void
219GNUNET_TESTBED_host_resolve_ (struct GNUNET_TESTBED_Host *host);
220
221void
222GNUNET_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 */
47struct 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 */
75struct OperationQueue;
76
77
78/**
79 * A slot to record time taken by an operation
80 */
81struct 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 */
118struct 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 */
162struct 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 */
250enum 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 */
285struct 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 */
307struct 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 */
382static struct ReadyQueueEntry *rq_head;
383
384/**
385 * DLL tail for the ready queue
386 */
387static struct ReadyQueueEntry *rq_tail;
388
389/**
390 * Array of operation queues which are to be destroyed
391 */
392static struct OperationQueue **expired_opqs;
393
394/**
395 * Number of expired operation queues in the above array
396 */
397static unsigned int n_expired_opqs;
398
399/**
400 * The id of the task to process the ready queue
401 */
402struct 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 */
412static void
413assign_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 */
435static void
436remove_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 */
475static void
476change_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 */
537static void
538rq_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 */
560static void
561process_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 */
591static void
592rq_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 */
613static int
614is_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 */
641static int
642decide_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
698ret:
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 */
719static void
720merge_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 */
754static int
755check_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 */
805static void
806defer (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 */
828static void
829cleanup_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 */
862static void
863adaptive_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 */
890static void
891adapt_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 */
982static void
983update_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 */
1027struct GNUNET_TESTBED_Operation *
1028GNUNET_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 */
1050struct OperationQueue *
1051GNUNET_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 */
1080static void
1081queue_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 */
1103void
1104GNUNET_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 */
1124int
1125GNUNET_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 */
1140static void
1141recheck_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 */
1165void
1166GNUNET_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 */
1191void
1192GNUNET_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 */
1217void
1218GNUNET_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 */
1234void
1235GNUNET_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 */
1252void
1253GNUNET_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 */
1281void
1282GNUNET_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 */
1295void
1296GNUNET_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 */
1354void
1355GNUNET_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 */
1365void __attribute__ ((destructor))
1366GNUNET_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 */
37struct OperationQueue;
38
39
40/**
41 * The type of operation queue
42 */
43enum 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 */
67struct OperationQueue *
68GNUNET_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 */
78void
79GNUNET_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 */
89int
90GNUNET_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 */
101void
102GNUNET_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 */
117void
118GNUNET_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 */
132void
133GNUNET_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 */
146void
147GNUNET_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 */
157typedef 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 */
173typedef 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 */
184struct GNUNET_TESTBED_Operation *
185GNUNET_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 */
195void
196GNUNET_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 */
208void
209GNUNET_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 */
219void
220GNUNET_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 */
228void
229GNUNET_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 */
40static struct GNUNET_TESTBED_Peer *peer_list_head;
41
42/**
43 * Peer list DLL tail
44 */
45static 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 */
53void
54GNUNET_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 */
65void
66GNUNET_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 */
75void
76GNUNET_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 */
95static void
96opstart_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 */
139static void
140oprelease_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 */
167static void
168opstart_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 */
193static void
194oprelease_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 */
219static void
220opstart_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 */
249static void
250oprelease_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 */
276static void
277opstart_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 */
304static void
305oprelease_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 */
334struct GNUNET_TESTBED_PeerGetConfigurationMessage *
335GNUNET_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 */
357static void
358opstart_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 */
379static void
380oprelease_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 */
424static void
425opstart_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 */
453static void
454oprelease_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 */
482static void
483opstart_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 */
523static void
524oprelease_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 */
553struct GNUNET_TESTBED_Peer *
554GNUNET_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 */
590struct GNUNET_TESTBED_Operation *
591GNUNET_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 */
637struct GNUNET_TESTBED_Operation *
638GNUNET_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 */
676struct GNUNET_TESTBED_Operation *
677GNUNET_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 */
718struct GNUNET_TESTBED_Operation *
719GNUNET_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 */
759struct GNUNET_TESTBED_Operation *
760GNUNET_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 */
806struct GNUNET_TESTBED_Operation *
807GNUNET_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 */
838struct GNUNET_TESTBED_Operation *
839GNUNET_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 */
864struct GNUNET_TESTBED_Operation *
865GNUNET_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 */
900static void
901opstart_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 */
934static void
935oprelease_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 */
975struct GNUNET_TESTBED_Operation *
976GNUNET_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 */
38enum 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 */
66struct 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 */
109struct 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 */
141struct 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 */
163struct 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 */
177struct 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 */
204struct 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 */
226struct 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
257struct 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 */
281struct GNUNET_TESTBED_PeerGetConfigurationMessage *
282GNUNET_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 */
291void
292GNUNET_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 */
300void
301GNUNET_TESTBED_peer_deregister_ (struct GNUNET_TESTBED_Peer *peer);
302
303
304/**
305 * Frees all peers
306 */
307void
308GNUNET_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 */
34struct 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 */
56struct 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 */
106struct SDHandle *
107GNUNET_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 */
123void
124GNUNET_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 */
143void
144GNUNET_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 */
184int
185GNUNET_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 */
34struct 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 */
43struct SDHandle *
44GNUNET_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 */
52void
53GNUNET_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 */
62void
63GNUNET_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 */
76int
77GNUNET_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 */
35enum 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 */
57struct 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 */
133static void
134configuration_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
167call_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 */
181static void
182opstart_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 */
209static void
210oprelease_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 */
256struct GNUNET_TESTBED_Operation *
257GNUNET_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 */
50struct 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 */
115struct 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 */
142static 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 */
153static void
154call_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 */
171static void
172op_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 */
194static void
195iteration_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 */
224static int
225iterator_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 */
255static void
256service_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 */
284static void *
285statistics_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 */
301static void
302statistics_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 */
324static void
325opstart_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 */
360static void
361oprelease_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 */
403struct GNUNET_TESTBED_Operation *
404GNUNET_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 */
36struct 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 */
78static void
79run (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 */
122int
123GNUNET_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 */
74struct 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 */
96enum 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 */
140struct 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 */
162struct 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 */
337static uint32_t
338rcop_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 */
347struct 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 */
369static int
370search_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 */
394static struct RunContextOperation *
395search_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 */
421static void
422insert_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 */
439static void
440remove_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 */
455static void
456cleanup (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 */
492static int
493rcop_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 */
511static void
512rc_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 */
562static void
563cancel_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 */
576static void
577wait_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
605cleanup_:
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 */
617static void
618interrupt (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 */
650static const char *
651prof_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 */
665static void
666start_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 */
696static void
697peer_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 */
730static void
731call_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 */
750static void
751topology_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 */
771static void
772create_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 */
807static void
808event_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
877call_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 */
980static void
981register_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 */
990static void
991host_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 (&register_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 */
1013static void
1014register_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 */
1054static void
1055controller_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 (&register_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 */
1101static int
1102netint_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 */
1137static void
1138host_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 */
1207static void
1208timeout_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 */
1249void
1250GNUNET_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:
1386warn_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
1442error_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 */
1465struct GNUNET_TESTBED_Controller *
1466GNUNET_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 e68e449ad..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 */
49struct TopologyContext;
50
51
52/**
53 * Representation of an overlay link
54 */
55struct 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 */
82struct 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
111struct 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 */
133struct 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 */
200struct TopologyContextUnderlay
201{
202 /**
203 * The link array
204 */
205 struct UnderlayLink *link_array;
206};
207
208
209/**
210 * Context information for topology operations
211 */
212struct 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 */
259static 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 */
343static void
344overlay_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 */
415static void
416opstart_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 */
442static void
443oprelease_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 */
478static void
479make_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 */
524static void
525gen_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 */
564static void
565gen_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 */
607static void
608gen_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 */
652unsigned int
653GNUNET_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 */
703static void
704gen_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 */
782static void
783gen_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 */
871static void
872gen_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;
929redo:
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 */
1004static void
1005gen_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 */
1210static void
1211gen_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 */
1264struct GNUNET_TESTBED_Operation *
1265GNUNET_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 */
1289struct GNUNET_TESTBED_Operation *
1290GNUNET_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 */
1321struct GNUNET_TESTBED_Operation *
1322GNUNET_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 topology with %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 */
1472struct GNUNET_TESTBED_Operation *
1473GNUNET_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 */
1508int
1509GNUNET_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 */
1536char *
1537GNUNET_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 */
1561int
1562GNUNET_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 */
40unsigned int
41GNUNET_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 */
54int
55GNUNET_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 */
66char *
67GNUNET_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 */
81typedef 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 */
106int
107GNUNET_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 */
33struct 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 */
65struct 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 */
83struct 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 */
112static void
113free_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 */
130static void
131free_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 */
152struct GNUNET_TESTBED_UnderlayLinkModel *
153GNUNET_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 */
177void
178GNUNET_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 */
203void
204GNUNET_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 */
232void
233GNUNET_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 */
249void
250GNUNET_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
31GNUNET_NETWORK_STRUCT_BEGIN
32/**
33 * Initialization message for gnunet-helper-testbed to start testbed service
34 */
35struct 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 */
71struct 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
87GNUNET_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}