diff options
Diffstat (limited to 'src/nse')
-rw-r--r-- | src/nse/.gitignore | 5 | ||||
-rw-r--r-- | src/nse/Makefile.am | 106 | ||||
-rw-r--r-- | src/nse/gnunet-nse-profiler.c | 921 | ||||
-rw-r--r-- | src/nse/gnunet-nse.c | 130 | ||||
-rw-r--r-- | src/nse/gnunet-service-nse.c | 1596 | ||||
-rw-r--r-- | src/nse/hostkeys.dat | bin | 10389438 -> 0 bytes | |||
-rw-r--r-- | src/nse/nse.conf.in | 38 | ||||
-rw-r--r-- | src/nse/nse.h | 73 | ||||
-rw-r--r-- | src/nse/nse_api.c | 209 | ||||
-rw-r--r-- | src/nse/nse_infiniband.conf | 77 | ||||
-rw-r--r-- | src/nse/nse_profiler_test.conf | 72 | ||||
-rw-r--r-- | src/nse/perf_kdf.c | 67 | ||||
-rw-r--r-- | src/nse/test_nse.conf | 26 | ||||
-rw-r--r-- | src/nse/test_nse_api.c | 107 | ||||
-rw-r--r-- | src/nse/test_nse_multipeer.c | 235 |
15 files changed, 0 insertions, 3662 deletions
diff --git a/src/nse/.gitignore b/src/nse/.gitignore deleted file mode 100644 index a2575673c..000000000 --- a/src/nse/.gitignore +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | gnunet-service-nse | ||
2 | gnunet-nse | ||
3 | gnunet-nse-profiler | ||
4 | test_nse_api | ||
5 | perf_kdf | ||
diff --git a/src/nse/Makefile.am b/src/nse/Makefile.am deleted file mode 100644 index 0c6182e61..000000000 --- a/src/nse/Makefile.am +++ /dev/null | |||
@@ -1,106 +0,0 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | if USE_COVERAGE | ||
5 | AM_CFLAGS = --coverage -O0 | ||
6 | XLIB = -lgcov | ||
7 | endif | ||
8 | |||
9 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
10 | |||
11 | libexecdir= $(pkglibdir)/libexec/ | ||
12 | |||
13 | pkgcfg_DATA = \ | ||
14 | nse.conf | ||
15 | |||
16 | bin_PROGRAMS = gnunet-nse | ||
17 | |||
18 | gnunet_nse_SOURCES = gnunet-nse.c | ||
19 | gnunet_nse_LDADD = \ | ||
20 | libgnunetnse.la \ | ||
21 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
22 | $(XLIB) $(GN_LIBINTL) | ||
23 | |||
24 | lib_LTLIBRARIES = libgnunetnse.la | ||
25 | |||
26 | libgnunetnse_la_SOURCES = \ | ||
27 | nse_api.c nse.h | ||
28 | libgnunetnse_la_LIBADD = \ | ||
29 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
30 | $(GN_LIBINTL) $(XLIB) | ||
31 | libgnunetnse_la_LDFLAGS = \ | ||
32 | $(GN_LIB_LDFLAGS) \ | ||
33 | -version-info 0:0:0 | ||
34 | |||
35 | |||
36 | libexec_PROGRAMS = \ | ||
37 | gnunet-service-nse | ||
38 | |||
39 | noinst_PROGRAMS = \ | ||
40 | gnunet-nse-profiler | ||
41 | |||
42 | gnunet_nse_profiler_SOURCES = \ | ||
43 | gnunet-nse-profiler.c | ||
44 | gnunet_nse_profiler_LDADD = -lm \ | ||
45 | libgnunetnse.la \ | ||
46 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
47 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
48 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
49 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
50 | $(GN_LIBINTL) | ||
51 | |||
52 | gnunet_service_nse_SOURCES = \ | ||
53 | gnunet-service-nse.c | ||
54 | gnunet_service_nse_LDADD = \ | ||
55 | libgnunetnse.la \ | ||
56 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
57 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
58 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
59 | $(LIBGCRYPT_LIBS) \ | ||
60 | -lm -lgcrypt \ | ||
61 | $(GN_LIBINTL) | ||
62 | if ENABLE_NSE_HISTOGRAM | ||
63 | gnunet_service_nse_LDADD += \ | ||
64 | $(top_builddir)/src/testbed-logger/libgnunettestbedlogger.la | ||
65 | endif | ||
66 | |||
67 | |||
68 | if HAVE_BENCHMARKS | ||
69 | MULTIPEER_TEST = test_nse_multipeer | ||
70 | endif | ||
71 | |||
72 | check_PROGRAMS = \ | ||
73 | test_nse_api \ | ||
74 | perf_kdf \ | ||
75 | $(MULTIPEER_TEST) | ||
76 | |||
77 | if ENABLE_TEST_RUN | ||
78 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
79 | TESTS = $(check_PROGRAMS) | ||
80 | endif | ||
81 | |||
82 | test_nse_api_SOURCES = \ | ||
83 | test_nse_api.c | ||
84 | test_nse_api_LDADD = \ | ||
85 | libgnunetnse.la \ | ||
86 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
87 | $(top_builddir)/src/util/libgnunetutil.la | ||
88 | |||
89 | test_nse_multipeer_SOURCES = \ | ||
90 | test_nse_multipeer.c | ||
91 | test_nse_multipeer_LDADD = \ | ||
92 | libgnunetnse.la \ | ||
93 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
94 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
95 | -lm | ||
96 | |||
97 | perf_kdf_SOURCES = \ | ||
98 | perf_kdf.c | ||
99 | perf_kdf_LDADD = \ | ||
100 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
101 | $(LIBGCRYPT_LIBS) \ | ||
102 | -lgcrypt | ||
103 | |||
104 | EXTRA_DIST = \ | ||
105 | test_nse.conf \ | ||
106 | nse_profiler_test.conf | ||
diff --git a/src/nse/gnunet-nse-profiler.c b/src/nse/gnunet-nse-profiler.c deleted file mode 100644 index 4b256bc52..000000000 --- a/src/nse/gnunet-nse-profiler.c +++ /dev/null | |||
@@ -1,921 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2012 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 | * @file nse/gnunet-nse-profiler.c | ||
22 | * | ||
23 | * @brief Profiling driver for the network size estimation service. | ||
24 | * Generally, the profiler starts a given number of peers, | ||
25 | * then churns some off, waits a certain amount of time, then | ||
26 | * churns again, and repeats. | ||
27 | * @author Christian Grothoff | ||
28 | * @author Nathan Evans | ||
29 | * @author Sree Harsha Totakura | ||
30 | */ | ||
31 | |||
32 | #include "platform.h" | ||
33 | #include "gnunet_testbed_service.h" | ||
34 | #include "gnunet_nse_service.h" | ||
35 | |||
36 | /** | ||
37 | * Generic loggins shorthand | ||
38 | */ | ||
39 | #define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__) | ||
40 | |||
41 | /** | ||
42 | * Debug logging shorthand | ||
43 | */ | ||
44 | #define LOG_DEBUG(...) LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Information we track for a peer in the testbed. | ||
49 | */ | ||
50 | struct NSEPeer | ||
51 | { | ||
52 | /** | ||
53 | * Prev reference in DLL. | ||
54 | */ | ||
55 | struct NSEPeer *prev; | ||
56 | |||
57 | /** | ||
58 | * Next reference in DLL. | ||
59 | */ | ||
60 | struct NSEPeer *next; | ||
61 | |||
62 | /** | ||
63 | * Handle with testbed. | ||
64 | */ | ||
65 | struct GNUNET_TESTBED_Peer *daemon; | ||
66 | |||
67 | /** | ||
68 | * Testbed operation to connect to NSE service. | ||
69 | */ | ||
70 | struct GNUNET_TESTBED_Operation *nse_op; | ||
71 | |||
72 | /** | ||
73 | * Testbed operation to connect to statistics service | ||
74 | */ | ||
75 | struct GNUNET_TESTBED_Operation *stat_op; | ||
76 | |||
77 | /** | ||
78 | * Handle to the statistics service | ||
79 | */ | ||
80 | struct GNUNET_STATISTICS_Handle *sh; | ||
81 | }; | ||
82 | |||
83 | |||
84 | /** | ||
85 | * Operation map entry | ||
86 | */ | ||
87 | struct OpListEntry | ||
88 | { | ||
89 | /** | ||
90 | * DLL next ptr | ||
91 | */ | ||
92 | struct OpListEntry *next; | ||
93 | |||
94 | /** | ||
95 | * DLL prev ptr | ||
96 | */ | ||
97 | struct OpListEntry *prev; | ||
98 | |||
99 | /** | ||
100 | * The testbed operation | ||
101 | */ | ||
102 | struct GNUNET_TESTBED_Operation *op; | ||
103 | |||
104 | /** | ||
105 | * Depending on whether we start or stop NSE service at the peer set this to 1 | ||
106 | * or -1 | ||
107 | */ | ||
108 | int delta; | ||
109 | }; | ||
110 | |||
111 | |||
112 | /** | ||
113 | * Head of DLL of peers we monitor closely. | ||
114 | */ | ||
115 | static struct NSEPeer *peer_head; | ||
116 | |||
117 | /** | ||
118 | * Tail of DLL of peers we monitor closely. | ||
119 | */ | ||
120 | static struct NSEPeer *peer_tail; | ||
121 | |||
122 | /** | ||
123 | * Return value from 'main' (0 == success) | ||
124 | */ | ||
125 | static int ok; | ||
126 | |||
127 | /** | ||
128 | * Be verbose (configuration option) | ||
129 | */ | ||
130 | static unsigned int verbose; | ||
131 | |||
132 | /** | ||
133 | * Name of the file with the hosts to run the test over (configuration option) | ||
134 | */ | ||
135 | static char *hosts_file; | ||
136 | |||
137 | /** | ||
138 | * Maximum number of peers in the test. | ||
139 | */ | ||
140 | static unsigned int num_peers; | ||
141 | |||
142 | /** | ||
143 | * Total number of rounds to execute. | ||
144 | */ | ||
145 | static unsigned int num_rounds; | ||
146 | |||
147 | /** | ||
148 | * Current round we are in. | ||
149 | */ | ||
150 | static unsigned int current_round; | ||
151 | |||
152 | /** | ||
153 | * Array of size 'num_rounds' with the requested number of peers in the given round. | ||
154 | */ | ||
155 | static unsigned int *num_peers_in_round; | ||
156 | |||
157 | /** | ||
158 | * How many peers are running right now? | ||
159 | */ | ||
160 | static unsigned int peers_running; | ||
161 | |||
162 | /** | ||
163 | * Specification for the numbers of peers to have in each round. | ||
164 | */ | ||
165 | static char *num_peer_spec; | ||
166 | |||
167 | /** | ||
168 | * Handles to all of the running peers. | ||
169 | */ | ||
170 | static struct GNUNET_TESTBED_Peer **daemons; | ||
171 | |||
172 | /** | ||
173 | * Global configuration file | ||
174 | */ | ||
175 | static struct GNUNET_CONFIGURATION_Handle *testing_cfg; | ||
176 | |||
177 | /** | ||
178 | * Maximum number of connections to NSE services. | ||
179 | */ | ||
180 | static unsigned int connection_limit; | ||
181 | |||
182 | /** | ||
183 | * Total number of connections in the whole network. | ||
184 | */ | ||
185 | static unsigned int total_connections; | ||
186 | |||
187 | /** | ||
188 | * File to report results to. | ||
189 | */ | ||
190 | static struct GNUNET_DISK_FileHandle *output_file; | ||
191 | |||
192 | /** | ||
193 | * Filename to log results to. | ||
194 | */ | ||
195 | static char *output_filename; | ||
196 | |||
197 | /** | ||
198 | * File to log connection info, statistics to. | ||
199 | */ | ||
200 | static struct GNUNET_DISK_FileHandle *data_file; | ||
201 | |||
202 | /** | ||
203 | * Filename to log connection info, statistics to. | ||
204 | */ | ||
205 | static char *data_filename; | ||
206 | |||
207 | /** | ||
208 | * How long to wait before triggering next round? | ||
209 | * Default: 60 s. | ||
210 | */ | ||
211 | static struct GNUNET_TIME_Relative wait_time = { 60 * 1000 }; | ||
212 | |||
213 | /** | ||
214 | * DLL head for operation list | ||
215 | */ | ||
216 | static struct OpListEntry *oplist_head; | ||
217 | |||
218 | /** | ||
219 | * DLL tail for operation list | ||
220 | */ | ||
221 | static struct OpListEntry *oplist_tail; | ||
222 | |||
223 | /** | ||
224 | * Task running each round of the experiment. | ||
225 | */ | ||
226 | static struct GNUNET_SCHEDULER_Task *round_task; | ||
227 | |||
228 | |||
229 | /** | ||
230 | * Clean up all of the monitoring connections to NSE and | ||
231 | * STATISTICS that we keep to selected peers. | ||
232 | */ | ||
233 | static void | ||
234 | close_monitor_connections () | ||
235 | { | ||
236 | struct NSEPeer *pos; | ||
237 | struct OpListEntry *oplist_entry; | ||
238 | |||
239 | while (NULL != (pos = peer_head)) | ||
240 | { | ||
241 | if (NULL != pos->nse_op) | ||
242 | GNUNET_TESTBED_operation_done (pos->nse_op); | ||
243 | if (NULL != pos->stat_op) | ||
244 | GNUNET_TESTBED_operation_done (pos->stat_op); | ||
245 | GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, pos); | ||
246 | GNUNET_free (pos); | ||
247 | } | ||
248 | while (NULL != (oplist_entry = oplist_head)) | ||
249 | { | ||
250 | GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, oplist_entry); | ||
251 | GNUNET_TESTBED_operation_done (oplist_entry->op); | ||
252 | GNUNET_free (oplist_entry); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | |||
257 | /** | ||
258 | * Task run on shutdown; cleans up everything. | ||
259 | * | ||
260 | * @param cls unused | ||
261 | */ | ||
262 | static void | ||
263 | shutdown_task (void *cls) | ||
264 | { | ||
265 | LOG_DEBUG ("Ending test.\n"); | ||
266 | close_monitor_connections (); | ||
267 | if (NULL != round_task) | ||
268 | { | ||
269 | GNUNET_SCHEDULER_cancel (round_task); | ||
270 | round_task = NULL; | ||
271 | } | ||
272 | if (NULL != data_file) | ||
273 | { | ||
274 | GNUNET_DISK_file_close (data_file); | ||
275 | data_file = NULL; | ||
276 | } | ||
277 | if (NULL != output_file) | ||
278 | { | ||
279 | GNUNET_DISK_file_close (output_file); | ||
280 | output_file = NULL; | ||
281 | } | ||
282 | if (NULL != testing_cfg) | ||
283 | { | ||
284 | GNUNET_CONFIGURATION_destroy (testing_cfg); | ||
285 | testing_cfg = NULL; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | |||
290 | /** | ||
291 | * Callback to call when network size estimate is updated. | ||
292 | * | ||
293 | * @param cls closure with the 'struct NSEPeer' providing the update | ||
294 | * @param timestamp server timestamp | ||
295 | * @param estimate the value of the current network size estimate | ||
296 | * @param std_dev standard deviation (rounded down to nearest integer) | ||
297 | * of the size estimation values seen | ||
298 | */ | ||
299 | static void | ||
300 | handle_estimate (void *cls, | ||
301 | struct GNUNET_TIME_Absolute timestamp, | ||
302 | double estimate, | ||
303 | double std_dev) | ||
304 | { | ||
305 | struct NSEPeer *peer = cls; | ||
306 | char output_buffer[512]; | ||
307 | size_t size; | ||
308 | |||
309 | if (NULL == output_file) | ||
310 | { | ||
311 | fprintf (stderr, | ||
312 | "Received network size estimate from peer %p. Size: %f std.dev. %f\n", | ||
313 | peer, | ||
314 | estimate, | ||
315 | std_dev); | ||
316 | return; | ||
317 | } | ||
318 | size = GNUNET_snprintf (output_buffer, | ||
319 | sizeof(output_buffer), | ||
320 | "%p %u %llu %f %f %f\n", | ||
321 | peer, | ||
322 | peers_running, | ||
323 | (unsigned long long) timestamp.abs_value_us, | ||
324 | GNUNET_NSE_log_estimate_to_n (estimate), | ||
325 | estimate, | ||
326 | std_dev); | ||
327 | if (size != GNUNET_DISK_file_write (output_file, output_buffer, size)) | ||
328 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n"); | ||
329 | } | ||
330 | |||
331 | |||
332 | /** | ||
333 | * Adapter function called to establish a connection to | ||
334 | * NSE service. | ||
335 | * | ||
336 | * @param cls closure (the 'struct NSEPeer') | ||
337 | * @param cfg configuration of the peer to connect to; will be available until | ||
338 | * GNUNET_TESTBED_operation_done() is called on the operation returned | ||
339 | * from GNUNET_TESTBED_service_connect() | ||
340 | * @return service handle to return in 'op_result', NULL on error | ||
341 | */ | ||
342 | static void * | ||
343 | nse_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
344 | { | ||
345 | struct NSEPeer *current_peer = cls; | ||
346 | |||
347 | return GNUNET_NSE_connect (cfg, &handle_estimate, current_peer); | ||
348 | } | ||
349 | |||
350 | |||
351 | /** | ||
352 | * Adapter function called to destroy a connection to | ||
353 | * NSE service. | ||
354 | * | ||
355 | * @param cls closure | ||
356 | * @param op_result service handle returned from the connect adapter | ||
357 | */ | ||
358 | static void | ||
359 | nse_disconnect_adapter (void *cls, void *op_result) | ||
360 | { | ||
361 | GNUNET_NSE_disconnect (op_result); | ||
362 | } | ||
363 | |||
364 | |||
365 | /** | ||
366 | * Callback function to process statistic values. | ||
367 | * | ||
368 | * @param cls `struct NSEPeer` | ||
369 | * @param subsystem name of subsystem that created the statistic | ||
370 | * @param name the name of the datum | ||
371 | * @param value the current value | ||
372 | * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not | ||
373 | * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration | ||
374 | */ | ||
375 | static int | ||
376 | stat_iterator (void *cls, | ||
377 | const char *subsystem, | ||
378 | const char *name, | ||
379 | uint64_t value, | ||
380 | int is_persistent) | ||
381 | { | ||
382 | char *output_buffer; | ||
383 | struct GNUNET_TIME_Absolute now; | ||
384 | int size; | ||
385 | unsigned int flag; | ||
386 | |||
387 | GNUNET_assert (NULL != data_file); | ||
388 | now = GNUNET_TIME_absolute_get (); | ||
389 | flag = strcasecmp (subsystem, "core"); | ||
390 | if (0 != flag) | ||
391 | flag = 1; | ||
392 | size = GNUNET_asprintf (&output_buffer, | ||
393 | "%llu %llu %u\n", | ||
394 | (unsigned long long) now.abs_value_us / 1000LL / 1000LL, | ||
395 | (unsigned long long) value, | ||
396 | flag); | ||
397 | if (0 > size) | ||
398 | { | ||
399 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Error formatting output buffer.\n"); | ||
400 | GNUNET_free (output_buffer); | ||
401 | return GNUNET_SYSERR; | ||
402 | } | ||
403 | if (size != GNUNET_DISK_file_write (data_file, output_buffer, (size_t) size)) | ||
404 | { | ||
405 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n"); | ||
406 | GNUNET_free (output_buffer); | ||
407 | return GNUNET_SYSERR; | ||
408 | } | ||
409 | GNUNET_free (output_buffer); | ||
410 | return GNUNET_OK; | ||
411 | } | ||
412 | |||
413 | |||
414 | /** | ||
415 | * Called to open a connection to the peer's statistics | ||
416 | * | ||
417 | * @param cls peer context | ||
418 | * @param cfg configuration of the peer to connect to; will be available until | ||
419 | * GNUNET_TESTBED_operation_done() is called on the operation returned | ||
420 | * from GNUNET_TESTBED_service_connect() | ||
421 | * @return service handle to return in 'op_result', NULL on error | ||
422 | */ | ||
423 | static void * | ||
424 | stat_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
425 | { | ||
426 | struct NSEPeer *peer = cls; | ||
427 | |||
428 | peer->sh = GNUNET_STATISTICS_create ("nse-profiler", cfg); | ||
429 | return peer->sh; | ||
430 | } | ||
431 | |||
432 | |||
433 | /** | ||
434 | * Called to disconnect from peer's statistics service | ||
435 | * | ||
436 | * @param cls peer context | ||
437 | * @param op_result service handle returned from the connect adapter | ||
438 | */ | ||
439 | static void | ||
440 | stat_disconnect_adapter (void *cls, void *op_result) | ||
441 | { | ||
442 | struct NSEPeer *peer = cls; | ||
443 | |||
444 | GNUNET_break (GNUNET_OK == | ||
445 | GNUNET_STATISTICS_watch_cancel (peer->sh, | ||
446 | "core", | ||
447 | "# peers connected", | ||
448 | stat_iterator, | ||
449 | peer)); | ||
450 | GNUNET_break (GNUNET_OK == | ||
451 | GNUNET_STATISTICS_watch_cancel (peer->sh, | ||
452 | "nse", | ||
453 | "# peers connected", | ||
454 | stat_iterator, | ||
455 | peer)); | ||
456 | GNUNET_STATISTICS_destroy (op_result, GNUNET_NO); | ||
457 | peer->sh = NULL; | ||
458 | } | ||
459 | |||
460 | |||
461 | /** | ||
462 | * Called after successfully opening a connection to a peer's statistics | ||
463 | * service; we register statistics monitoring for CORE and NSE here. | ||
464 | * | ||
465 | * @param cls the callback closure from functions generating an operation | ||
466 | * @param op the operation that has been finished | ||
467 | * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() | ||
468 | * @param emsg error message in case the operation has failed; will be NULL if | ||
469 | * operation has executed successfully. | ||
470 | */ | ||
471 | static void | ||
472 | stat_comp_cb (void *cls, | ||
473 | struct GNUNET_TESTBED_Operation *op, | ||
474 | void *ca_result, | ||
475 | const char *emsg) | ||
476 | { | ||
477 | struct GNUNET_STATISTICS_Handle *sh = ca_result; | ||
478 | struct NSEPeer *peer = cls; | ||
479 | |||
480 | if (NULL != emsg) | ||
481 | { | ||
482 | GNUNET_break (0); | ||
483 | return; | ||
484 | } | ||
485 | GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch (sh, | ||
486 | "core", | ||
487 | "# peers connected", | ||
488 | stat_iterator, | ||
489 | peer)); | ||
490 | GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch (sh, | ||
491 | "nse", | ||
492 | "# peers connected", | ||
493 | stat_iterator, | ||
494 | peer)); | ||
495 | } | ||
496 | |||
497 | |||
498 | /** | ||
499 | * Task run to connect to the NSE and statistics services to a subset of | ||
500 | * all of the running peers. | ||
501 | */ | ||
502 | static void | ||
503 | connect_nse_service () | ||
504 | { | ||
505 | struct NSEPeer *current_peer; | ||
506 | unsigned int i; | ||
507 | unsigned int connections; | ||
508 | |||
509 | if (0 == connection_limit) | ||
510 | return; | ||
511 | LOG_DEBUG ("Connecting to nse service of peers\n"); | ||
512 | connections = 0; | ||
513 | for (i = 0; i < num_peers_in_round[current_round]; i++) | ||
514 | { | ||
515 | if ((num_peers_in_round[current_round] > connection_limit) && | ||
516 | (0 != (i % (num_peers_in_round[current_round] / connection_limit)))) | ||
517 | continue; | ||
518 | LOG_DEBUG ("Connecting to nse service of peer %d\n", i); | ||
519 | current_peer = GNUNET_new (struct NSEPeer); | ||
520 | current_peer->daemon = daemons[i]; | ||
521 | current_peer->nse_op = | ||
522 | GNUNET_TESTBED_service_connect (NULL, | ||
523 | current_peer->daemon, | ||
524 | "nse", | ||
525 | NULL, | ||
526 | NULL, | ||
527 | &nse_connect_adapter, | ||
528 | &nse_disconnect_adapter, | ||
529 | current_peer); | ||
530 | if (NULL != data_file) | ||
531 | current_peer->stat_op = | ||
532 | GNUNET_TESTBED_service_connect (NULL, | ||
533 | current_peer->daemon, | ||
534 | "statistics", | ||
535 | stat_comp_cb, | ||
536 | current_peer, | ||
537 | &stat_connect_adapter, | ||
538 | &stat_disconnect_adapter, | ||
539 | current_peer); | ||
540 | GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, current_peer); | ||
541 | if (++connections == connection_limit) | ||
542 | break; | ||
543 | } | ||
544 | } | ||
545 | |||
546 | |||
547 | /** | ||
548 | * Task that starts/stops peers to move to the next round. | ||
549 | * | ||
550 | * @param cls NULL, unused | ||
551 | */ | ||
552 | static void | ||
553 | next_round (void *cls); | ||
554 | |||
555 | |||
556 | /** | ||
557 | * We're at the end of a round. Stop monitoring, write total | ||
558 | * number of connections to log and get full stats. Then trigger | ||
559 | * the next round. | ||
560 | * | ||
561 | * @param cls unused, NULL | ||
562 | */ | ||
563 | static void | ||
564 | finish_round (void *cls) | ||
565 | { | ||
566 | LOG (GNUNET_ERROR_TYPE_INFO, "Have %u connections\n", total_connections); | ||
567 | close_monitor_connections (); | ||
568 | round_task = GNUNET_SCHEDULER_add_now (&next_round, NULL); | ||
569 | } | ||
570 | |||
571 | |||
572 | /** | ||
573 | * We have reached the desired number of peers for the current round. | ||
574 | * Run it (by connecting and monitoring a few peers and waiting the | ||
575 | * specified delay before finishing the round). | ||
576 | */ | ||
577 | static void | ||
578 | run_round () | ||
579 | { | ||
580 | LOG_DEBUG ("Running round %u\n", current_round); | ||
581 | connect_nse_service (); | ||
582 | GNUNET_SCHEDULER_add_delayed (wait_time, &finish_round, NULL); | ||
583 | } | ||
584 | |||
585 | |||
586 | /** | ||
587 | * Creates an oplist entry and adds it to the oplist DLL | ||
588 | */ | ||
589 | static struct OpListEntry * | ||
590 | make_oplist_entry () | ||
591 | { | ||
592 | struct OpListEntry *entry; | ||
593 | |||
594 | entry = GNUNET_new (struct OpListEntry); | ||
595 | GNUNET_CONTAINER_DLL_insert_tail (oplist_head, oplist_tail, entry); | ||
596 | return entry; | ||
597 | } | ||
598 | |||
599 | |||
600 | /** | ||
601 | * Callback to be called when NSE service is started or stopped at peers | ||
602 | * | ||
603 | * @param cls NULL | ||
604 | * @param op the operation handle | ||
605 | * @param emsg NULL on success; otherwise an error description | ||
606 | */ | ||
607 | static void | ||
608 | manage_service_cb (void *cls, | ||
609 | struct GNUNET_TESTBED_Operation *op, | ||
610 | const char *emsg) | ||
611 | { | ||
612 | struct OpListEntry *entry = cls; | ||
613 | |||
614 | GNUNET_TESTBED_operation_done (entry->op); | ||
615 | if (NULL != emsg) | ||
616 | { | ||
617 | LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to start/stop NSE at a peer\n"); | ||
618 | GNUNET_SCHEDULER_shutdown (); | ||
619 | return; | ||
620 | } | ||
621 | GNUNET_assert (0 != entry->delta); | ||
622 | peers_running += entry->delta; | ||
623 | GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry); | ||
624 | GNUNET_free (entry); | ||
625 | if (num_peers_in_round[current_round] == peers_running) | ||
626 | run_round (); | ||
627 | } | ||
628 | |||
629 | |||
630 | /** | ||
631 | * Adjust the number of running peers to match the required number of running | ||
632 | * peers for the round | ||
633 | */ | ||
634 | static void | ||
635 | adjust_running_peers () | ||
636 | { | ||
637 | struct OpListEntry *entry; | ||
638 | unsigned int i; | ||
639 | |||
640 | /* start peers if we have too few */ | ||
641 | for (i = peers_running; i < num_peers_in_round[current_round]; i++) | ||
642 | { | ||
643 | entry = make_oplist_entry (); | ||
644 | entry->delta = 1; | ||
645 | entry->op = GNUNET_TESTBED_peer_manage_service (NULL, | ||
646 | daemons[i], | ||
647 | "nse", | ||
648 | &manage_service_cb, | ||
649 | entry, | ||
650 | 1); | ||
651 | } | ||
652 | /* stop peers if we have too many */ | ||
653 | for (i = num_peers_in_round[current_round]; i < peers_running; i++) | ||
654 | { | ||
655 | entry = make_oplist_entry (); | ||
656 | entry->delta = -1; | ||
657 | entry->op = GNUNET_TESTBED_peer_manage_service (NULL, | ||
658 | daemons[i], | ||
659 | "nse", | ||
660 | &manage_service_cb, | ||
661 | entry, | ||
662 | 0); | ||
663 | } | ||
664 | } | ||
665 | |||
666 | |||
667 | /** | ||
668 | * Task run at the end of a round. Disconnect from all monitored | ||
669 | * peers; then get statistics from *all* peers. | ||
670 | * | ||
671 | * @param cls NULL, unused | ||
672 | */ | ||
673 | static void | ||
674 | next_round (void *cls) | ||
675 | { | ||
676 | round_task = NULL; | ||
677 | LOG_DEBUG ("Disconnecting nse service of peers\n"); | ||
678 | current_round++; | ||
679 | if (current_round == num_rounds) | ||
680 | { | ||
681 | /* this was the last round, terminate */ | ||
682 | ok = 0; | ||
683 | GNUNET_SCHEDULER_shutdown (); | ||
684 | return; | ||
685 | } | ||
686 | if (num_peers_in_round[current_round] == peers_running) | ||
687 | { | ||
688 | /* no need to churn, just run next round */ | ||
689 | run_round (); | ||
690 | return; | ||
691 | } | ||
692 | adjust_running_peers (); | ||
693 | } | ||
694 | |||
695 | |||
696 | /** | ||
697 | * Function that will be called whenever something in the | ||
698 | * testbed changes. | ||
699 | * | ||
700 | * @param cls closure, NULL | ||
701 | * @param event information on what is happening | ||
702 | */ | ||
703 | static void | ||
704 | master_controller_cb (void *cls, | ||
705 | const struct GNUNET_TESTBED_EventInformation *event) | ||
706 | { | ||
707 | switch (event->type) | ||
708 | { | ||
709 | case GNUNET_TESTBED_ET_CONNECT: | ||
710 | total_connections++; | ||
711 | break; | ||
712 | |||
713 | case GNUNET_TESTBED_ET_DISCONNECT: | ||
714 | total_connections--; | ||
715 | break; | ||
716 | |||
717 | default: | ||
718 | break; | ||
719 | } | ||
720 | } | ||
721 | |||
722 | |||
723 | /** | ||
724 | * Signature of a main function for a testcase. | ||
725 | * | ||
726 | * @param cls NULL | ||
727 | * @param h the run handle | ||
728 | * @param num_peers_ number of peers in 'peers' | ||
729 | * @param peers handle to peers run in the testbed. NULL upon timeout (see | ||
730 | * GNUNET_TESTBED_test_run()). | ||
731 | * @param links_succeeded the number of overlay link connection attempts that | ||
732 | * succeeded | ||
733 | * @param links_failed the number of overlay link connection attempts that | ||
734 | * failed | ||
735 | */ | ||
736 | static void | ||
737 | test_master (void *cls, | ||
738 | struct GNUNET_TESTBED_RunHandle *h, | ||
739 | unsigned int num_peers_, | ||
740 | struct GNUNET_TESTBED_Peer **peers, | ||
741 | unsigned int links_succeeded, | ||
742 | unsigned int links_failed) | ||
743 | { | ||
744 | if (NULL == peers) | ||
745 | { | ||
746 | GNUNET_SCHEDULER_shutdown (); | ||
747 | return; | ||
748 | } | ||
749 | daemons = peers; | ||
750 | GNUNET_break (num_peers_ == num_peers); | ||
751 | peers_running = num_peers; | ||
752 | if (num_peers_in_round[current_round] == peers_running) | ||
753 | { | ||
754 | /* no need to churn, just run the starting round */ | ||
755 | run_round (); | ||
756 | return; | ||
757 | } | ||
758 | adjust_running_peers (); | ||
759 | } | ||
760 | |||
761 | |||
762 | /** | ||
763 | * Actual main function that runs the emulation. | ||
764 | * | ||
765 | * @param cls unused | ||
766 | * @param args remaining args, unused | ||
767 | * @param cfgfile name of the configuration | ||
768 | * @param cfg configuration handle | ||
769 | */ | ||
770 | static void | ||
771 | run (void *cls, | ||
772 | char *const *args, | ||
773 | const char *cfgfile, | ||
774 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
775 | { | ||
776 | char *tok; | ||
777 | uint64_t event_mask; | ||
778 | unsigned int num; | ||
779 | |||
780 | ok = 1; | ||
781 | testing_cfg = GNUNET_CONFIGURATION_dup (cfg); | ||
782 | LOG_DEBUG ("Starting daemons.\n"); | ||
783 | if (NULL == num_peer_spec) | ||
784 | { | ||
785 | fprintf (stderr, "You need to specify the number of peers to run\n"); | ||
786 | return; | ||
787 | } | ||
788 | for (tok = strtok (num_peer_spec, ","); NULL != tok; tok = strtok (NULL, ",")) | ||
789 | { | ||
790 | if (1 != sscanf (tok, "%u", &num)) | ||
791 | { | ||
792 | fprintf (stderr, "You need to specify numbers, not `%s'\n", tok); | ||
793 | return; | ||
794 | } | ||
795 | if (0 == num) | ||
796 | { | ||
797 | fprintf (stderr, "Refusing to run a round with 0 peers\n"); | ||
798 | return; | ||
799 | } | ||
800 | GNUNET_array_append (num_peers_in_round, num_rounds, num); | ||
801 | num_peers = GNUNET_MAX (num_peers, num); | ||
802 | } | ||
803 | if (0 == num_peers) | ||
804 | { | ||
805 | fprintf (stderr, "Refusing to run a testbed with no rounds\n"); | ||
806 | return; | ||
807 | } | ||
808 | if ((NULL != data_filename) && | ||
809 | (NULL == | ||
810 | (data_file = GNUNET_DISK_file_open (data_filename, | ||
811 | GNUNET_DISK_OPEN_READWRITE | ||
812 | | GNUNET_DISK_OPEN_TRUNCATE | ||
813 | | GNUNET_DISK_OPEN_CREATE, | ||
814 | GNUNET_DISK_PERM_USER_READ | ||
815 | | GNUNET_DISK_PERM_USER_WRITE)))) | ||
816 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", data_filename); | ||
817 | |||
818 | if ((NULL != output_filename) && | ||
819 | (NULL == | ||
820 | (output_file = GNUNET_DISK_file_open (output_filename, | ||
821 | GNUNET_DISK_OPEN_READWRITE | ||
822 | | GNUNET_DISK_OPEN_CREATE, | ||
823 | GNUNET_DISK_PERM_USER_READ | ||
824 | | GNUNET_DISK_PERM_USER_WRITE)))) | ||
825 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", output_filename); | ||
826 | event_mask = 0LL; | ||
827 | event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START); | ||
828 | event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP); | ||
829 | event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); | ||
830 | event_mask |= (1LL << GNUNET_TESTBED_ET_DISCONNECT); | ||
831 | GNUNET_TESTBED_run (hosts_file, | ||
832 | cfg, | ||
833 | num_peers, | ||
834 | event_mask, | ||
835 | master_controller_cb, | ||
836 | NULL, /* master_controller_cb cls */ | ||
837 | &test_master, | ||
838 | NULL); /* test_master cls */ | ||
839 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | ||
840 | } | ||
841 | |||
842 | |||
843 | /** | ||
844 | * Main function. | ||
845 | * | ||
846 | * @return 0 on success | ||
847 | */ | ||
848 | int | ||
849 | main (int argc, char *const *argv) | ||
850 | { | ||
851 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
852 | { GNUNET_GETOPT_option_uint ( | ||
853 | 'C', | ||
854 | "connections", | ||
855 | "COUNT", | ||
856 | gettext_noop ( | ||
857 | "limit to the number of connections to NSE services, 0 for none"), | ||
858 | &connection_limit), | ||
859 | GNUNET_GETOPT_option_string ( | ||
860 | 'd', | ||
861 | "details", | ||
862 | "FILENAME", | ||
863 | gettext_noop ( | ||
864 | "name of the file for writing connection information and statistics"), | ||
865 | &data_filename), | ||
866 | |||
867 | GNUNET_GETOPT_option_string ( | ||
868 | 'H', | ||
869 | "hosts", | ||
870 | "FILENAME", | ||
871 | gettext_noop ( | ||
872 | "name of the file with the login information for the testbed"), | ||
873 | &hosts_file), | ||
874 | |||
875 | GNUNET_GETOPT_option_string ( | ||
876 | 'o', | ||
877 | "output", | ||
878 | "FILENAME", | ||
879 | gettext_noop ("name of the file for writing the main results"), | ||
880 | &output_filename), | ||
881 | |||
882 | |||
883 | GNUNET_GETOPT_option_string ( | ||
884 | 'p', | ||
885 | "peers", | ||
886 | "NETWORKSIZESPEC", | ||
887 | gettext_noop ( | ||
888 | "Number of peers to run in each round, separated by commas"), | ||
889 | &num_peer_spec), | ||
890 | |||
891 | GNUNET_GETOPT_option_increment_uint ( | ||
892 | 'V', | ||
893 | "verbose", | ||
894 | gettext_noop ("be verbose (print progress information)"), | ||
895 | &verbose), | ||
896 | |||
897 | GNUNET_GETOPT_option_relative_time ('w', | ||
898 | "wait", | ||
899 | "DELAY", | ||
900 | gettext_noop ("delay between rounds"), | ||
901 | &wait_time), | ||
902 | GNUNET_GETOPT_OPTION_END }; | ||
903 | |||
904 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
905 | return 2; | ||
906 | if ( | ||
907 | GNUNET_OK != | ||
908 | GNUNET_PROGRAM_run (argc, | ||
909 | argv, | ||
910 | "nse-profiler", | ||
911 | gettext_noop ( | ||
912 | "Measure quality and performance of the NSE service."), | ||
913 | options, | ||
914 | &run, | ||
915 | NULL)) | ||
916 | ok = 1; | ||
917 | return ok; | ||
918 | } | ||
919 | |||
920 | |||
921 | /* end of nse-profiler.c */ | ||
diff --git a/src/nse/gnunet-nse.c b/src/nse/gnunet-nse.c deleted file mode 100644 index edb73c0fc..000000000 --- a/src/nse/gnunet-nse.c +++ /dev/null | |||
@@ -1,130 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2014, 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 nse/gnunet-nse.c | ||
23 | * @brief Program to display network size estimates from the NSE service | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_nse_service.h" | ||
29 | |||
30 | /** | ||
31 | * The handle to the NSE service | ||
32 | */ | ||
33 | static struct GNUNET_NSE_Handle *nse; | ||
34 | |||
35 | /** | ||
36 | * The program status; 0 for success. | ||
37 | */ | ||
38 | static int status; | ||
39 | |||
40 | |||
41 | /** | ||
42 | * Task to shutdown and clean up all state | ||
43 | * | ||
44 | * @param cls NULL | ||
45 | */ | ||
46 | static void | ||
47 | do_shutdown (void *cls) | ||
48 | { | ||
49 | (void) cls; | ||
50 | if (NULL != nse) | ||
51 | { | ||
52 | GNUNET_NSE_disconnect (nse); | ||
53 | nse = NULL; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Callback to call when network size estimate is updated. | ||
60 | * | ||
61 | * @param cls NULL | ||
62 | * @param timestamp server timestamp | ||
63 | * @param estimate the value of the current network size estimate | ||
64 | * @param std_dev standard deviation (rounded down to nearest integer) | ||
65 | * of the size estimation values seen | ||
66 | */ | ||
67 | static void | ||
68 | handle_estimate (void *cls, | ||
69 | struct GNUNET_TIME_Absolute timestamp, | ||
70 | double estimate, | ||
71 | double std_dev) | ||
72 | { | ||
73 | (void) cls; | ||
74 | status = 0; | ||
75 | fprintf (stdout, | ||
76 | "%llu %f %f %f\n", | ||
77 | (unsigned long long) timestamp.abs_value_us, | ||
78 | GNUNET_NSE_log_estimate_to_n (estimate), | ||
79 | estimate, | ||
80 | std_dev); | ||
81 | } | ||
82 | |||
83 | |||
84 | /** | ||
85 | * Actual main function that runs the emulation. | ||
86 | * | ||
87 | * @param cls unused | ||
88 | * @param args remaining args, unused | ||
89 | * @param cfgfile name of the configuration | ||
90 | * @param cfg configuration handle | ||
91 | */ | ||
92 | static void | ||
93 | run (void *cls, | ||
94 | char *const *args, | ||
95 | const char *cfgfile, | ||
96 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
97 | { | ||
98 | (void) cls; | ||
99 | (void) args; | ||
100 | (void) cfgfile; | ||
101 | nse = GNUNET_NSE_connect (cfg, &handle_estimate, NULL); | ||
102 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
103 | } | ||
104 | |||
105 | |||
106 | /** | ||
107 | * Main function. | ||
108 | * | ||
109 | * @return 0 on success | ||
110 | */ | ||
111 | int | ||
112 | main (int argc, char *const *argv) | ||
113 | { | ||
114 | static struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
115 | GNUNET_GETOPT_OPTION_END | ||
116 | }; | ||
117 | |||
118 | status = 1; | ||
119 | if (GNUNET_OK != | ||
120 | GNUNET_PROGRAM_run (argc, | ||
121 | argv, | ||
122 | "gnunet-nse", | ||
123 | gettext_noop ( | ||
124 | "Show network size estimates from NSE service."), | ||
125 | options, | ||
126 | &run, | ||
127 | NULL)) | ||
128 | return 2; | ||
129 | return status; | ||
130 | } | ||
diff --git a/src/nse/gnunet-service-nse.c b/src/nse/gnunet-service-nse.c deleted file mode 100644 index 972b3a79d..000000000 --- a/src/nse/gnunet-service-nse.c +++ /dev/null | |||
@@ -1,1596 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009, 2010, 2011, 2012, 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 nse/gnunet-service-nse.c | ||
23 | * @brief network size estimation service | ||
24 | * @author Nathan Evans | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * The purpose of this service is to estimate the size of the network. | ||
28 | * Given a specified interval, each peer hashes the most recent | ||
29 | * timestamp which is evenly divisible by that interval. This hash is | ||
30 | * compared in distance to the peer identity to choose an offset. The | ||
31 | * closer the peer identity to the hashed timestamp, the earlier the | ||
32 | * peer sends out a "nearest peer" message. The closest peer's | ||
33 | * message should thus be received before any others, which stops | ||
34 | * those peer from sending their messages at a later duration. So | ||
35 | * every peer should receive the same nearest peer message, and from | ||
36 | * this can calculate the expected number of peers in the network. | ||
37 | */ | ||
38 | #include "platform.h" | ||
39 | #include <math.h> | ||
40 | #include "gnunet_util_lib.h" | ||
41 | #include "gnunet_constants.h" | ||
42 | #include "gnunet_protocols.h" | ||
43 | #include "gnunet_signatures.h" | ||
44 | #include "gnunet_statistics_service.h" | ||
45 | #include "gnunet_core_service.h" | ||
46 | #include "gnunet_nse_service.h" | ||
47 | #if ENABLE_NSE_HISTOGRAM | ||
48 | #include "gnunet_testbed_logger_service.h" | ||
49 | #endif | ||
50 | #include "nse.h" | ||
51 | #include <gcrypt.h> | ||
52 | |||
53 | |||
54 | /** | ||
55 | * Should messages be delayed randomly? This option should be set to | ||
56 | * #GNUNET_NO only for experiments, not in production. | ||
57 | */ | ||
58 | #define USE_RANDOM_DELAYS GNUNET_YES | ||
59 | |||
60 | /** | ||
61 | * Generate extensive debug-level log messages? | ||
62 | */ | ||
63 | #define DEBUG_NSE GNUNET_NO | ||
64 | |||
65 | /** | ||
66 | * Over how many values do we calculate the weighted average? | ||
67 | */ | ||
68 | #define HISTORY_SIZE 64 | ||
69 | |||
70 | /** | ||
71 | * Message priority to use. No real rush, reliability not | ||
72 | * required. Corking OK. | ||
73 | */ | ||
74 | #define NSE_PRIORITY \ | ||
75 | (GNUNET_MQ_PRIO_BACKGROUND | GNUNET_MQ_PREF_UNRELIABLE \ | ||
76 | | GNUNET_MQ_PREF_CORK_ALLOWED) | ||
77 | |||
78 | #ifdef BSD | ||
79 | #define log2(a) (log (a) / log (2)) | ||
80 | #endif | ||
81 | |||
82 | /** | ||
83 | * Amount of work required (W-bit collisions) for NSE proofs, in collision-bits. | ||
84 | */ | ||
85 | static unsigned long long nse_work_required; | ||
86 | |||
87 | /** | ||
88 | * Interval for sending network size estimation flood requests. | ||
89 | */ | ||
90 | static struct GNUNET_TIME_Relative gnunet_nse_interval; | ||
91 | |||
92 | /** | ||
93 | * Interval between proof find runs. | ||
94 | */ | ||
95 | static struct GNUNET_TIME_Relative proof_find_delay; | ||
96 | |||
97 | #if ENABLE_NSE_HISTOGRAM | ||
98 | |||
99 | /** | ||
100 | * Handle to test if testbed logger service is running or not | ||
101 | */ | ||
102 | struct GNUNET_CLIENT_TestHandle *logger_test; | ||
103 | |||
104 | /** | ||
105 | * Handle for writing when we received messages to disk. | ||
106 | */ | ||
107 | static struct GNUNET_TESTBED_LOGGER_Handle *lh; | ||
108 | |||
109 | /** | ||
110 | * Handle for writing message received timestamp information to disk. | ||
111 | */ | ||
112 | static struct GNUNET_BIO_WriteHandle *histogram; | ||
113 | |||
114 | #endif | ||
115 | |||
116 | /** | ||
117 | * Salt for PoW calcualations. | ||
118 | */ | ||
119 | static struct GNUNET_CRYPTO_PowSalt salt = { "gnunet-nse-proof" }; | ||
120 | |||
121 | |||
122 | /** | ||
123 | * Per-peer information. | ||
124 | */ | ||
125 | struct NSEPeerEntry | ||
126 | { | ||
127 | /** | ||
128 | * Core handle for sending messages to this peer. | ||
129 | */ | ||
130 | struct GNUNET_MQ_Handle *mq; | ||
131 | |||
132 | /** | ||
133 | * What is the identity of the peer? | ||
134 | */ | ||
135 | const struct GNUNET_PeerIdentity *id; | ||
136 | |||
137 | /** | ||
138 | * Task scheduled to send message to this peer. | ||
139 | */ | ||
140 | struct GNUNET_SCHEDULER_Task *transmit_task; | ||
141 | |||
142 | /** | ||
143 | * Did we receive or send a message about the previous round | ||
144 | * to this peer yet? #GNUNET_YES if the previous round has | ||
145 | * been taken care of. | ||
146 | */ | ||
147 | int previous_round; | ||
148 | |||
149 | #if ENABLE_NSE_HISTOGRAM | ||
150 | /** | ||
151 | * Amount of messages received from this peer on this round. | ||
152 | */ | ||
153 | unsigned int received_messages; | ||
154 | |||
155 | /** | ||
156 | * Amount of messages transmitted to this peer on this round. | ||
157 | */ | ||
158 | unsigned int transmitted_messages; | ||
159 | |||
160 | /** | ||
161 | * Which size did we tell the peer the network is? | ||
162 | */ | ||
163 | unsigned int last_transmitted_size; | ||
164 | #endif | ||
165 | }; | ||
166 | |||
167 | |||
168 | GNUNET_NETWORK_STRUCT_BEGIN | ||
169 | |||
170 | /** | ||
171 | * Network size estimate reply; sent when "this" | ||
172 | * peer's timer has run out before receiving a | ||
173 | * valid reply from another peer. | ||
174 | */ | ||
175 | struct GNUNET_NSE_FloodMessage | ||
176 | { | ||
177 | /** | ||
178 | * Type: #GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD | ||
179 | */ | ||
180 | struct GNUNET_MessageHeader header; | ||
181 | |||
182 | /** | ||
183 | * Number of hops this message has taken so far. | ||
184 | */ | ||
185 | uint32_t hop_count GNUNET_PACKED; | ||
186 | |||
187 | /** | ||
188 | * Purpose. | ||
189 | */ | ||
190 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | ||
191 | |||
192 | /** | ||
193 | * The current timestamp value (which all | ||
194 | * peers should agree on). | ||
195 | */ | ||
196 | struct GNUNET_TIME_AbsoluteNBO timestamp; | ||
197 | |||
198 | /** | ||
199 | * Number of matching bits between the hash | ||
200 | * of timestamp and the initiator's public | ||
201 | * key. | ||
202 | */ | ||
203 | uint32_t matching_bits GNUNET_PACKED; | ||
204 | |||
205 | /** | ||
206 | * Public key of the originator. | ||
207 | */ | ||
208 | struct GNUNET_PeerIdentity origin; | ||
209 | |||
210 | /** | ||
211 | * Proof of work, causing leading zeros when hashed with pkey. | ||
212 | */ | ||
213 | uint64_t proof_of_work GNUNET_PACKED; | ||
214 | |||
215 | /** | ||
216 | * Signature (over range specified in purpose). | ||
217 | */ | ||
218 | struct GNUNET_CRYPTO_EddsaSignature signature; | ||
219 | }; | ||
220 | GNUNET_NETWORK_STRUCT_END | ||
221 | |||
222 | /** | ||
223 | * Handle to our current configuration. | ||
224 | */ | ||
225 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
226 | |||
227 | /** | ||
228 | * Handle to the statistics service. | ||
229 | */ | ||
230 | static struct GNUNET_STATISTICS_Handle *stats; | ||
231 | |||
232 | /** | ||
233 | * Handle to the core service. | ||
234 | */ | ||
235 | static struct GNUNET_CORE_Handle *core_api; | ||
236 | |||
237 | /** | ||
238 | * Map of all connected peers. | ||
239 | */ | ||
240 | static struct GNUNET_CONTAINER_MultiPeerMap *peers; | ||
241 | |||
242 | /** | ||
243 | * The current network size estimate. Number of bits matching on | ||
244 | * average thus far. | ||
245 | */ | ||
246 | static double current_size_estimate; | ||
247 | |||
248 | /** | ||
249 | * The standard deviation of the last #HISTORY_SIZE network | ||
250 | * size estimates. | ||
251 | */ | ||
252 | static double current_std_dev = NAN; | ||
253 | |||
254 | /** | ||
255 | * Current hop counter estimate (estimate for network diameter). | ||
256 | */ | ||
257 | static uint32_t hop_count_max; | ||
258 | |||
259 | /** | ||
260 | * Message for the next round, if we got any. | ||
261 | */ | ||
262 | static struct GNUNET_NSE_FloodMessage next_message; | ||
263 | |||
264 | /** | ||
265 | * Array of recent size estimate messages. | ||
266 | */ | ||
267 | static struct GNUNET_NSE_FloodMessage size_estimate_messages[HISTORY_SIZE]; | ||
268 | |||
269 | /** | ||
270 | * Index of most recent estimate. | ||
271 | */ | ||
272 | static unsigned int estimate_index; | ||
273 | |||
274 | /** | ||
275 | * Number of valid entries in the history. | ||
276 | */ | ||
277 | static unsigned int estimate_count; | ||
278 | |||
279 | /** | ||
280 | * Task scheduled to update our flood message for the next round. | ||
281 | */ | ||
282 | static struct GNUNET_SCHEDULER_Task *flood_task; | ||
283 | |||
284 | /** | ||
285 | * Task scheduled to compute our proof. | ||
286 | */ | ||
287 | static struct GNUNET_SCHEDULER_Task *proof_task; | ||
288 | |||
289 | /** | ||
290 | * Notification context, simplifies client broadcasts. | ||
291 | */ | ||
292 | static struct GNUNET_NotificationContext *nc; | ||
293 | |||
294 | /** | ||
295 | * The next major time. | ||
296 | */ | ||
297 | static struct GNUNET_TIME_Absolute next_timestamp; | ||
298 | |||
299 | /** | ||
300 | * The current major time. | ||
301 | */ | ||
302 | static struct GNUNET_TIME_Absolute current_timestamp; | ||
303 | |||
304 | /** | ||
305 | * The private key of this peer. | ||
306 | */ | ||
307 | static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | ||
308 | |||
309 | /** | ||
310 | * The peer identity of this peer. | ||
311 | */ | ||
312 | static struct GNUNET_PeerIdentity my_identity; | ||
313 | |||
314 | /** | ||
315 | * Proof of work for this peer. | ||
316 | */ | ||
317 | static uint64_t my_proof; | ||
318 | |||
319 | |||
320 | /** | ||
321 | * Initialize a message to clients with the current network | ||
322 | * size estimate. | ||
323 | * | ||
324 | * @param em message to fill in | ||
325 | */ | ||
326 | static void | ||
327 | setup_estimate_message (struct GNUNET_NSE_ClientMessage *em) | ||
328 | { | ||
329 | double mean; | ||
330 | double sum; | ||
331 | double std_dev; | ||
332 | double variance; | ||
333 | double val; | ||
334 | double nsize; | ||
335 | |||
336 | #define WEST 1 | ||
337 | /* Weighted incremental algorithm for stddev according to West (1979) */ | ||
338 | #if WEST | ||
339 | double sumweight; | ||
340 | double weight; | ||
341 | double q; | ||
342 | double r; | ||
343 | double temp; | ||
344 | |||
345 | mean = 0.0; | ||
346 | sum = 0.0; | ||
347 | sumweight = 0.0; | ||
348 | variance = 0.0; | ||
349 | for (unsigned int i = 0; i < estimate_count; i++) | ||
350 | { | ||
351 | unsigned int j = (estimate_index - i + HISTORY_SIZE) % HISTORY_SIZE; | ||
352 | |||
353 | val = htonl (size_estimate_messages[j].matching_bits); | ||
354 | weight = estimate_count + 1 - i; | ||
355 | |||
356 | temp = weight + sumweight; | ||
357 | q = val - mean; | ||
358 | r = q * weight / temp; | ||
359 | mean += r; | ||
360 | sum += sumweight * q * r; | ||
361 | sumweight = temp; | ||
362 | } | ||
363 | if (estimate_count > 0) | ||
364 | variance = (sum / sumweight) * estimate_count / (estimate_count - 1.0); | ||
365 | #else | ||
366 | /* trivial version for debugging */ | ||
367 | double vsq; | ||
368 | |||
369 | /* non-weighted trivial version */ | ||
370 | sum = 0.0; | ||
371 | vsq = 0.0; | ||
372 | variance = 0.0; | ||
373 | mean = 0.0; | ||
374 | |||
375 | for (unsigned int i = 0; i < estimate_count; i++) | ||
376 | { | ||
377 | unsigned int j = (estimate_index - i + HISTORY_SIZE) % HISTORY_SIZE; | ||
378 | |||
379 | val = htonl (size_estimate_messages[j].matching_bits); | ||
380 | sum += val; | ||
381 | vsq += val * val; | ||
382 | } | ||
383 | if (0 != estimate_count) | ||
384 | { | ||
385 | mean = sum / estimate_count; | ||
386 | variance = (vsq - mean * sum) | ||
387 | / (estimate_count - 1.0); // terrible for numerical stability... | ||
388 | } | ||
389 | #endif | ||
390 | if (variance >= 0) | ||
391 | std_dev = sqrt (variance); | ||
392 | else | ||
393 | std_dev = variance; /* return NaN (due to estimate_count == 0 causing 0.0/0.0) */ | ||
394 | current_std_dev = std_dev; | ||
395 | current_size_estimate = mean; | ||
396 | |||
397 | em->header.size = htons (sizeof(struct GNUNET_NSE_ClientMessage)); | ||
398 | em->header.type = htons (GNUNET_MESSAGE_TYPE_NSE_ESTIMATE); | ||
399 | em->reserved = htonl (0); | ||
400 | em->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); | ||
401 | { | ||
402 | double se = mean - 0.332747; | ||
403 | unsigned int j = GNUNET_CONTAINER_multipeermap_size (peers); | ||
404 | if (0 == j) | ||
405 | j = 1; /* Avoid log2(0); can only happen if CORE didn't report | ||
406 | connection to self yet */ | ||
407 | nsize = log2 (j); | ||
408 | em->size_estimate = GNUNET_hton_double (GNUNET_MAX (se, nsize)); | ||
409 | em->std_deviation = GNUNET_hton_double (std_dev); | ||
410 | GNUNET_STATISTICS_set (stats, | ||
411 | "# nodes in the network (estimate)", | ||
412 | (uint64_t) pow (2, GNUNET_MAX (se, nsize)), | ||
413 | GNUNET_NO); | ||
414 | } | ||
415 | } | ||
416 | |||
417 | |||
418 | /** | ||
419 | * Handler for START message from client, triggers an | ||
420 | * immediate current network estimate notification. | ||
421 | * Also, we remember the client for updates upon future | ||
422 | * estimate measurements. | ||
423 | * | ||
424 | * @param cls client who sent the message | ||
425 | * @param message the message received | ||
426 | */ | ||
427 | static void | ||
428 | handle_start (void *cls, const struct GNUNET_MessageHeader *message) | ||
429 | { | ||
430 | struct GNUNET_SERVICE_Client *client = cls; | ||
431 | struct GNUNET_MQ_Handle *mq; | ||
432 | struct GNUNET_NSE_ClientMessage em; | ||
433 | struct GNUNET_MQ_Envelope *env; | ||
434 | |||
435 | (void) message; | ||
436 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received START message from client\n"); | ||
437 | mq = GNUNET_SERVICE_client_get_mq (client); | ||
438 | GNUNET_notification_context_add (nc, mq); | ||
439 | setup_estimate_message (&em); | ||
440 | env = GNUNET_MQ_msg_copy (&em.header); | ||
441 | GNUNET_MQ_send (mq, env); | ||
442 | GNUNET_SERVICE_client_continue (client); | ||
443 | } | ||
444 | |||
445 | |||
446 | /** | ||
447 | * How long should we delay a message to go the given number of | ||
448 | * matching bits? | ||
449 | * | ||
450 | * @param matching_bits number of matching bits to consider | ||
451 | */ | ||
452 | static double | ||
453 | get_matching_bits_delay (uint32_t matching_bits) | ||
454 | { | ||
455 | /* Calculated as: S + f/2 - (f / pi) * (atan(x - p')) */ | ||
456 | // S is next_timestamp (ignored in return value) | ||
457 | // f is frequency (gnunet_nse_interval) | ||
458 | // x is matching_bits | ||
459 | // p' is current_size_estimate | ||
460 | return ((double) gnunet_nse_interval.rel_value_us / (double) 2.0) | ||
461 | - ((gnunet_nse_interval.rel_value_us / M_PI) | ||
462 | * atan (matching_bits - current_size_estimate)); | ||
463 | } | ||
464 | |||
465 | |||
466 | /** | ||
467 | * What delay randomization should we apply for a given number of matching bits? | ||
468 | * | ||
469 | * @param matching_bits number of matching bits | ||
470 | * @return random delay to apply | ||
471 | */ | ||
472 | static struct GNUNET_TIME_Relative | ||
473 | get_delay_randomization (uint32_t matching_bits) | ||
474 | { | ||
475 | #if USE_RANDOM_DELAYS | ||
476 | struct GNUNET_TIME_Relative ret; | ||
477 | uint32_t i; | ||
478 | double d; | ||
479 | |||
480 | d = get_matching_bits_delay (matching_bits); | ||
481 | i = (uint32_t) (d / (double) (hop_count_max + 1)); | ||
482 | ret.rel_value_us = i; | ||
483 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
484 | "Randomizing flood using latencies up to %s\n", | ||
485 | GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); | ||
486 | ret.rel_value_us = | ||
487 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, i + 1); | ||
488 | return ret; | ||
489 | #else | ||
490 | return GNUNET_TIME_UNIT_ZERO; | ||
491 | #endif | ||
492 | } | ||
493 | |||
494 | |||
495 | /** | ||
496 | * Get the number of matching bits that the given timestamp has to the given peer ID. | ||
497 | * | ||
498 | * @param timestamp time to generate key | ||
499 | * @param id peer identity to compare with | ||
500 | * @return number of matching bits | ||
501 | */ | ||
502 | static uint32_t | ||
503 | get_matching_bits (struct GNUNET_TIME_Absolute timestamp, | ||
504 | const struct GNUNET_PeerIdentity *id) | ||
505 | { | ||
506 | struct GNUNET_HashCode timestamp_hash; | ||
507 | struct GNUNET_HashCode pid_hash; | ||
508 | |||
509 | GNUNET_CRYPTO_hash (×tamp.abs_value_us, | ||
510 | sizeof(timestamp.abs_value_us), | ||
511 | ×tamp_hash); | ||
512 | GNUNET_CRYPTO_hash (id, sizeof(struct GNUNET_PeerIdentity), &pid_hash); | ||
513 | return GNUNET_CRYPTO_hash_matching_bits (×tamp_hash, &pid_hash); | ||
514 | } | ||
515 | |||
516 | |||
517 | /** | ||
518 | * Get the transmission delay that should be applied for a | ||
519 | * particular round. | ||
520 | * | ||
521 | * @param round_offset -1 for the previous round (random delay between 0 and 50ms) | ||
522 | * 0 for the current round (based on our proximity to time key) | ||
523 | * @return delay that should be applied | ||
524 | */ | ||
525 | static struct GNUNET_TIME_Relative | ||
526 | get_transmit_delay (int round_offset) | ||
527 | { | ||
528 | struct GNUNET_TIME_Relative ret; | ||
529 | struct GNUNET_TIME_Absolute tgt; | ||
530 | double dist_delay; | ||
531 | uint32_t matching_bits; | ||
532 | |||
533 | switch (round_offset) | ||
534 | { | ||
535 | case -1: | ||
536 | /* previous round is randomized between 0 and 50 ms */ | ||
537 | #if USE_RANDOM_DELAYS | ||
538 | ret.rel_value_us = | ||
539 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, 50); | ||
540 | #else | ||
541 | ret = GNUNET_TIME_UNIT_ZERO; | ||
542 | #endif | ||
543 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
544 | "Transmitting previous round behind schedule in %s\n", | ||
545 | GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); | ||
546 | return ret; | ||
547 | |||
548 | case 0: | ||
549 | /* current round is based on best-known matching_bits */ | ||
550 | matching_bits = | ||
551 | ntohl (size_estimate_messages[estimate_index].matching_bits); | ||
552 | dist_delay = get_matching_bits_delay (matching_bits); | ||
553 | dist_delay += get_delay_randomization (matching_bits).rel_value_us; | ||
554 | ret.rel_value_us = (uint64_t) dist_delay; | ||
555 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
556 | "For round %s, delay for %u matching bits is %s\n", | ||
557 | GNUNET_STRINGS_absolute_time_to_string (current_timestamp), | ||
558 | (unsigned int) matching_bits, | ||
559 | GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); | ||
560 | /* now consider round start time and add delay to it */ | ||
561 | tgt = GNUNET_TIME_absolute_add (current_timestamp, ret); | ||
562 | return GNUNET_TIME_absolute_get_remaining (tgt); | ||
563 | } | ||
564 | GNUNET_break (0); | ||
565 | return GNUNET_TIME_UNIT_FOREVER_REL; | ||
566 | } | ||
567 | |||
568 | |||
569 | /** | ||
570 | * Task that triggers a NSE P2P transmission. | ||
571 | * | ||
572 | * @param cls the `struct NSEPeerEntry *` | ||
573 | */ | ||
574 | static void | ||
575 | transmit_task_cb (void *cls) | ||
576 | { | ||
577 | struct NSEPeerEntry *peer_entry = cls; | ||
578 | unsigned int idx; | ||
579 | struct GNUNET_MQ_Envelope *env; | ||
580 | |||
581 | peer_entry->transmit_task = NULL; | ||
582 | idx = estimate_index; | ||
583 | if (GNUNET_NO == peer_entry->previous_round) | ||
584 | { | ||
585 | idx = (idx + HISTORY_SIZE - 1) % HISTORY_SIZE; | ||
586 | peer_entry->previous_round = GNUNET_YES; | ||
587 | peer_entry->transmit_task = | ||
588 | GNUNET_SCHEDULER_add_delayed (get_transmit_delay (0), | ||
589 | &transmit_task_cb, | ||
590 | peer_entry); | ||
591 | } | ||
592 | if ((0 == ntohl (size_estimate_messages[idx].hop_count)) && | ||
593 | (NULL != proof_task)) | ||
594 | { | ||
595 | GNUNET_STATISTICS_update (stats, | ||
596 | "# flood messages not generated (no proof yet)", | ||
597 | 1, | ||
598 | GNUNET_NO); | ||
599 | return; | ||
600 | } | ||
601 | if (0 == ntohs (size_estimate_messages[idx].header.size)) | ||
602 | { | ||
603 | GNUNET_STATISTICS_update (stats, | ||
604 | "# flood messages not generated (lack of history)", | ||
605 | 1, | ||
606 | GNUNET_NO); | ||
607 | return; | ||
608 | } | ||
609 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
610 | "In round %s, sending to `%s' estimate with %u bits\n", | ||
611 | GNUNET_STRINGS_absolute_time_to_string ( | ||
612 | GNUNET_TIME_absolute_ntoh ( | ||
613 | size_estimate_messages[idx].timestamp)), | ||
614 | GNUNET_i2s (peer_entry->id), | ||
615 | (unsigned int) ntohl (size_estimate_messages[idx].matching_bits)); | ||
616 | if (0 == ntohl (size_estimate_messages[idx].hop_count)) | ||
617 | GNUNET_STATISTICS_update (stats, "# flood messages started", 1, GNUNET_NO); | ||
618 | GNUNET_STATISTICS_update (stats, | ||
619 | "# flood messages transmitted", | ||
620 | 1, | ||
621 | GNUNET_NO); | ||
622 | #if ENABLE_NSE_HISTOGRAM | ||
623 | peer_entry->transmitted_messages++; | ||
624 | peer_entry->last_transmitted_size = | ||
625 | ntohl (size_estimate_messages[idx].matching_bits); | ||
626 | #endif | ||
627 | env = GNUNET_MQ_msg_copy (&size_estimate_messages[idx].header); | ||
628 | GNUNET_MQ_send (peer_entry->mq, env); | ||
629 | } | ||
630 | |||
631 | |||
632 | /** | ||
633 | * We've sent on our flood message or one that we received which was | ||
634 | * validated and closer than ours. Update the global list of recent | ||
635 | * messages and the average. Also re-broadcast the message to any | ||
636 | * clients. | ||
637 | */ | ||
638 | static void | ||
639 | update_network_size_estimate () | ||
640 | { | ||
641 | struct GNUNET_NSE_ClientMessage em; | ||
642 | |||
643 | setup_estimate_message (&em); | ||
644 | GNUNET_notification_context_broadcast (nc, &em.header, GNUNET_YES); | ||
645 | } | ||
646 | |||
647 | |||
648 | /** | ||
649 | * Setup a flood message in our history array at the given | ||
650 | * slot offset for the given timestamp. | ||
651 | * | ||
652 | * @param slot index to use | ||
653 | * @param ts timestamp to use | ||
654 | */ | ||
655 | static void | ||
656 | setup_flood_message (unsigned int slot, struct GNUNET_TIME_Absolute ts) | ||
657 | { | ||
658 | struct GNUNET_NSE_FloodMessage *fm; | ||
659 | uint32_t matching_bits; | ||
660 | |||
661 | matching_bits = get_matching_bits (ts, &my_identity); | ||
662 | fm = &size_estimate_messages[slot]; | ||
663 | fm->header.size = htons (sizeof(struct GNUNET_NSE_FloodMessage)); | ||
664 | fm->header.type = htons (GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD); | ||
665 | fm->hop_count = htonl (0); | ||
666 | fm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_NSE_SEND); | ||
667 | fm->purpose.size = | ||
668 | htonl (sizeof(struct GNUNET_NSE_FloodMessage) | ||
669 | - sizeof(struct GNUNET_MessageHeader) - sizeof(uint32_t) | ||
670 | - sizeof(struct GNUNET_CRYPTO_EddsaSignature)); | ||
671 | fm->matching_bits = htonl (matching_bits); | ||
672 | fm->timestamp = GNUNET_TIME_absolute_hton (ts); | ||
673 | fm->origin = my_identity; | ||
674 | fm->proof_of_work = my_proof; | ||
675 | if (nse_work_required > 0) | ||
676 | GNUNET_assert (GNUNET_OK == | ||
677 | GNUNET_CRYPTO_eddsa_sign_ (my_private_key, | ||
678 | &fm->purpose, | ||
679 | &fm->signature)); | ||
680 | else | ||
681 | memset (&fm->signature, 0, sizeof(fm->signature)); | ||
682 | } | ||
683 | |||
684 | |||
685 | /** | ||
686 | * Schedule transmission for the given peer for the current round based | ||
687 | * on what we know about the desired delay. | ||
688 | * | ||
689 | * @param cls unused | ||
690 | * @param key hash of peer identity | ||
691 | * @param value the `struct NSEPeerEntry` | ||
692 | * @return #GNUNET_OK (continue to iterate) | ||
693 | */ | ||
694 | static int | ||
695 | schedule_current_round (void *cls, | ||
696 | const struct GNUNET_PeerIdentity *key, | ||
697 | void *value) | ||
698 | { | ||
699 | struct NSEPeerEntry *peer_entry = value; | ||
700 | struct GNUNET_TIME_Relative delay; | ||
701 | |||
702 | (void) cls; | ||
703 | (void) key; | ||
704 | if (NULL != peer_entry->transmit_task) | ||
705 | { | ||
706 | GNUNET_SCHEDULER_cancel (peer_entry->transmit_task); | ||
707 | peer_entry->previous_round = GNUNET_NO; | ||
708 | } | ||
709 | #if ENABLE_NSE_HISTOGRAM | ||
710 | if (peer_entry->received_messages > 1) | ||
711 | GNUNET_STATISTICS_update (stats, | ||
712 | "# extra messages", | ||
713 | peer_entry->received_messages - 1, | ||
714 | GNUNET_NO); | ||
715 | peer_entry->transmitted_messages = 0; | ||
716 | peer_entry->last_transmitted_size = 0; | ||
717 | peer_entry->received_messages = 0; | ||
718 | #endif | ||
719 | delay = | ||
720 | get_transmit_delay ((GNUNET_NO == peer_entry->previous_round) ? -1 : 0); | ||
721 | peer_entry->transmit_task = | ||
722 | GNUNET_SCHEDULER_add_delayed (delay, &transmit_task_cb, peer_entry); | ||
723 | return GNUNET_OK; | ||
724 | } | ||
725 | |||
726 | |||
727 | /** | ||
728 | * Update our flood message to be sent (and our timestamps). | ||
729 | * | ||
730 | * @param cls unused | ||
731 | */ | ||
732 | static void | ||
733 | update_flood_message (void *cls) | ||
734 | { | ||
735 | struct GNUNET_TIME_Relative offset; | ||
736 | |||
737 | (void) cls; | ||
738 | flood_task = NULL; | ||
739 | offset = GNUNET_TIME_absolute_get_remaining (next_timestamp); | ||
740 | if (0 != offset.rel_value_us) | ||
741 | { | ||
742 | /* somehow run early, delay more */ | ||
743 | flood_task = | ||
744 | GNUNET_SCHEDULER_add_delayed (offset, &update_flood_message, NULL); | ||
745 | return; | ||
746 | } | ||
747 | estimate_index = (estimate_index + 1) % HISTORY_SIZE; | ||
748 | if (estimate_count < HISTORY_SIZE) | ||
749 | estimate_count++; | ||
750 | current_timestamp = next_timestamp; | ||
751 | next_timestamp = | ||
752 | GNUNET_TIME_absolute_add (current_timestamp, gnunet_nse_interval); | ||
753 | if ((current_timestamp.abs_value_us == | ||
754 | GNUNET_TIME_absolute_ntoh (next_message.timestamp).abs_value_us) && | ||
755 | (get_matching_bits (current_timestamp, &my_identity) < | ||
756 | ntohl (next_message.matching_bits))) | ||
757 | { | ||
758 | /* we received a message for this round way early, use it! */ | ||
759 | size_estimate_messages[estimate_index] = next_message; | ||
760 | size_estimate_messages[estimate_index].hop_count = | ||
761 | htonl (1 + ntohl (next_message.hop_count)); | ||
762 | } | ||
763 | else | ||
764 | setup_flood_message (estimate_index, current_timestamp); | ||
765 | next_message.matching_bits = htonl (0); /* reset for 'next' round */ | ||
766 | hop_count_max = 0; | ||
767 | for (unsigned int i = 0; i < HISTORY_SIZE; i++) | ||
768 | hop_count_max = | ||
769 | GNUNET_MAX (ntohl (size_estimate_messages[i].hop_count), hop_count_max); | ||
770 | GNUNET_CONTAINER_multipeermap_iterate (peers, &schedule_current_round, NULL); | ||
771 | flood_task = | ||
772 | GNUNET_SCHEDULER_add_at (next_timestamp, &update_flood_message, NULL); | ||
773 | } | ||
774 | |||
775 | |||
776 | /** | ||
777 | * Count the leading zeroes in hash. | ||
778 | * | ||
779 | * @param hash to count leading zeros in | ||
780 | * @return the number of leading zero bits. | ||
781 | */ | ||
782 | static unsigned int | ||
783 | count_leading_zeroes (const struct GNUNET_HashCode *hash) | ||
784 | { | ||
785 | unsigned int hash_count; | ||
786 | |||
787 | hash_count = 0; | ||
788 | while (0 == GNUNET_CRYPTO_hash_get_bit_ltr (hash, hash_count)) | ||
789 | hash_count++; | ||
790 | return hash_count; | ||
791 | } | ||
792 | |||
793 | |||
794 | /** | ||
795 | * Check whether the given public key and integer are a valid proof of | ||
796 | * work. | ||
797 | * | ||
798 | * @param pkey the public key | ||
799 | * @param val the integer | ||
800 | * @return #GNUNET_YES if valid, #GNUNET_NO if not | ||
801 | */ | ||
802 | static int | ||
803 | check_proof_of_work (const struct GNUNET_CRYPTO_EddsaPublicKey *pkey, | ||
804 | uint64_t val) | ||
805 | { | ||
806 | char buf[sizeof(struct GNUNET_CRYPTO_EddsaPublicKey) | ||
807 | + sizeof(val)] GNUNET_ALIGN; | ||
808 | struct GNUNET_HashCode result; | ||
809 | |||
810 | GNUNET_memcpy (buf, &val, sizeof(val)); | ||
811 | GNUNET_memcpy (&buf[sizeof(val)], | ||
812 | pkey, | ||
813 | sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)); | ||
814 | GNUNET_CRYPTO_pow_hash (&salt, | ||
815 | buf, | ||
816 | sizeof(buf), | ||
817 | &result); | ||
818 | return (count_leading_zeroes (&result) >= nse_work_required) ? GNUNET_YES | ||
819 | : GNUNET_NO; | ||
820 | } | ||
821 | |||
822 | |||
823 | /** | ||
824 | * Write our current proof to disk. | ||
825 | */ | ||
826 | static void | ||
827 | write_proof (void) | ||
828 | { | ||
829 | char *proof; | ||
830 | |||
831 | if (GNUNET_OK != | ||
832 | GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
833 | "NSE", | ||
834 | "PROOFFILE", | ||
835 | &proof)) | ||
836 | return; | ||
837 | (void) GNUNET_DISK_directory_remove (proof); | ||
838 | if (GNUNET_OK != | ||
839 | GNUNET_DISK_fn_write (proof, | ||
840 | &my_proof, | ||
841 | sizeof(my_proof), | ||
842 | GNUNET_DISK_PERM_USER_READ | ||
843 | | GNUNET_DISK_PERM_USER_WRITE)) | ||
844 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | ||
845 | "write", | ||
846 | proof); | ||
847 | GNUNET_free (proof); | ||
848 | } | ||
849 | |||
850 | |||
851 | /** | ||
852 | * Find our proof of work. | ||
853 | * | ||
854 | * @param cls closure (unused) | ||
855 | */ | ||
856 | static void | ||
857 | find_proof (void *cls) | ||
858 | { | ||
859 | #define ROUND_SIZE 10 | ||
860 | uint64_t counter; | ||
861 | char buf[sizeof(struct GNUNET_CRYPTO_EddsaPublicKey) | ||
862 | + sizeof(uint64_t)] GNUNET_ALIGN; | ||
863 | struct GNUNET_HashCode result; | ||
864 | unsigned int i; | ||
865 | |||
866 | (void) cls; | ||
867 | proof_task = NULL; | ||
868 | GNUNET_memcpy (&buf[sizeof(uint64_t)], | ||
869 | &my_identity, | ||
870 | sizeof(struct GNUNET_PeerIdentity)); | ||
871 | i = 0; | ||
872 | counter = my_proof; | ||
873 | while ((counter != UINT64_MAX) && (i < ROUND_SIZE)) | ||
874 | { | ||
875 | GNUNET_memcpy (buf, &counter, sizeof(uint64_t)); | ||
876 | GNUNET_CRYPTO_pow_hash (&salt, | ||
877 | buf, | ||
878 | sizeof(buf), | ||
879 | &result); | ||
880 | if (nse_work_required <= count_leading_zeroes (&result)) | ||
881 | { | ||
882 | my_proof = counter; | ||
883 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
884 | "Proof of work found: %llu!\n", | ||
885 | (unsigned long long) GNUNET_ntohll (counter)); | ||
886 | write_proof (); | ||
887 | setup_flood_message (estimate_index, current_timestamp); | ||
888 | return; | ||
889 | } | ||
890 | counter++; | ||
891 | i++; | ||
892 | } | ||
893 | if (my_proof / (100 * ROUND_SIZE) < counter / (100 * ROUND_SIZE)) | ||
894 | { | ||
895 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
896 | "Testing proofs currently at %llu\n", | ||
897 | (unsigned long long) counter); | ||
898 | /* remember progress every 100 rounds */ | ||
899 | my_proof = counter; | ||
900 | write_proof (); | ||
901 | } | ||
902 | else | ||
903 | { | ||
904 | my_proof = counter; | ||
905 | } | ||
906 | proof_task = | ||
907 | GNUNET_SCHEDULER_add_delayed_with_priority (proof_find_delay, | ||
908 | GNUNET_SCHEDULER_PRIORITY_IDLE, | ||
909 | &find_proof, | ||
910 | NULL); | ||
911 | } | ||
912 | |||
913 | |||
914 | /** | ||
915 | * An incoming flood message has been received which claims | ||
916 | * to have more bits matching than any we know in this time | ||
917 | * period. Verify the signature and/or proof of work. | ||
918 | * | ||
919 | * @param incoming_flood the message to verify | ||
920 | * @return #GNUNET_YES if the message is verified | ||
921 | * #GNUNET_NO if the key/signature don't verify | ||
922 | */ | ||
923 | static int | ||
924 | verify_message_crypto (const struct GNUNET_NSE_FloodMessage *incoming_flood) | ||
925 | { | ||
926 | if (GNUNET_YES != check_proof_of_work (&incoming_flood->origin.public_key, | ||
927 | incoming_flood->proof_of_work)) | ||
928 | { | ||
929 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
930 | "Proof of work invalid: %llu!\n", | ||
931 | (unsigned long long) GNUNET_ntohll ( | ||
932 | incoming_flood->proof_of_work)); | ||
933 | GNUNET_break_op (0); | ||
934 | return GNUNET_NO; | ||
935 | } | ||
936 | if ((nse_work_required > 0) && | ||
937 | (GNUNET_OK != | ||
938 | GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_NSE_SEND, | ||
939 | &incoming_flood->purpose, | ||
940 | &incoming_flood->signature, | ||
941 | &incoming_flood->origin.public_key))) | ||
942 | { | ||
943 | GNUNET_break_op (0); | ||
944 | return GNUNET_NO; | ||
945 | } | ||
946 | return GNUNET_YES; | ||
947 | } | ||
948 | |||
949 | |||
950 | /** | ||
951 | * Update transmissions for the given peer for the current round based | ||
952 | * on updated proximity information. | ||
953 | * | ||
954 | * @param cls peer entry to exclude from updates | ||
955 | * @param key hash of peer identity | ||
956 | * @param value the `struct NSEPeerEntry *` of a peer to transmit to | ||
957 | * @return #GNUNET_OK (continue to iterate) | ||
958 | */ | ||
959 | static int | ||
960 | update_flood_times (void *cls, | ||
961 | const struct GNUNET_PeerIdentity *key, | ||
962 | void *value) | ||
963 | { | ||
964 | struct NSEPeerEntry *exclude = cls; | ||
965 | struct NSEPeerEntry *peer_entry = value; | ||
966 | struct GNUNET_TIME_Relative delay; | ||
967 | |||
968 | (void) key; | ||
969 | if (peer_entry == exclude) | ||
970 | return GNUNET_OK; /* trigger of the update */ | ||
971 | if (GNUNET_NO == peer_entry->previous_round) | ||
972 | { | ||
973 | /* still stuck in previous round, no point to update, check that | ||
974 | * we are active here though... */ | ||
975 | if (NULL == peer_entry->transmit_task) | ||
976 | { | ||
977 | GNUNET_break (0); | ||
978 | } | ||
979 | return GNUNET_OK; | ||
980 | } | ||
981 | if (NULL != peer_entry->transmit_task) | ||
982 | { | ||
983 | GNUNET_SCHEDULER_cancel (peer_entry->transmit_task); | ||
984 | peer_entry->transmit_task = NULL; | ||
985 | } | ||
986 | delay = get_transmit_delay (0); | ||
987 | peer_entry->transmit_task = | ||
988 | GNUNET_SCHEDULER_add_delayed (delay, &transmit_task_cb, peer_entry); | ||
989 | return GNUNET_OK; | ||
990 | } | ||
991 | |||
992 | |||
993 | /** | ||
994 | * Core handler for size estimate flooding messages. | ||
995 | * | ||
996 | * @param cls peer this message is from | ||
997 | * @param incoming_flood received message | ||
998 | */ | ||
999 | static void | ||
1000 | handle_p2p_estimate (void *cls, | ||
1001 | const struct GNUNET_NSE_FloodMessage *incoming_flood) | ||
1002 | { | ||
1003 | struct NSEPeerEntry *peer_entry = cls; | ||
1004 | struct GNUNET_TIME_Absolute ts; | ||
1005 | uint32_t matching_bits; | ||
1006 | unsigned int idx; | ||
1007 | |||
1008 | #if ENABLE_NSE_HISTOGRAM | ||
1009 | { | ||
1010 | uint64_t t; | ||
1011 | |||
1012 | t = GNUNET_TIME_absolute_get ().abs_value_us; | ||
1013 | if (NULL != lh) | ||
1014 | GNUNET_TESTBED_LOGGER_write (lh, &t, sizeof(uint64_t)); | ||
1015 | if (NULL != histogram) | ||
1016 | GNUNET_BIO_write_int64 (histogram, "histogram-time", t); | ||
1017 | } | ||
1018 | #endif | ||
1019 | GNUNET_STATISTICS_update (stats, "# flood messages received", 1, GNUNET_NO); | ||
1020 | matching_bits = ntohl (incoming_flood->matching_bits); | ||
1021 | #if DEBUG_NSE | ||
1022 | { | ||
1023 | char origin[5]; | ||
1024 | char pred[5]; | ||
1025 | struct GNUNET_PeerIdentity os; | ||
1026 | |||
1027 | GNUNET_snprintf (origin, | ||
1028 | sizeof(origin), | ||
1029 | "%s", | ||
1030 | GNUNET_i2s (&incoming_flood->origin)); | ||
1031 | GNUNET_snprintf (pred, sizeof(pred), "%s", GNUNET_i2s (peer_entry->id)); | ||
1032 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1033 | "Flood at %s from `%s' via `%s' at `%s' with bits %u\n", | ||
1034 | GNUNET_STRINGS_absolute_time_to_string ( | ||
1035 | GNUNET_TIME_absolute_ntoh (incoming_flood->timestamp)), | ||
1036 | origin, | ||
1037 | pred, | ||
1038 | GNUNET_i2s (&my_identity), | ||
1039 | (unsigned int) matching_bits); | ||
1040 | } | ||
1041 | #endif | ||
1042 | |||
1043 | #if ENABLE_NSE_HISTOGRAM | ||
1044 | peer_entry->received_messages++; | ||
1045 | if ((peer_entry->transmitted_messages > 0) && | ||
1046 | (peer_entry->last_transmitted_size >= matching_bits) ) | ||
1047 | GNUNET_STATISTICS_update (stats, "# cross messages", 1, GNUNET_NO); | ||
1048 | #endif | ||
1049 | |||
1050 | ts = GNUNET_TIME_absolute_ntoh (incoming_flood->timestamp); | ||
1051 | if (ts.abs_value_us == current_timestamp.abs_value_us) | ||
1052 | idx = estimate_index; | ||
1053 | else if (ts.abs_value_us == | ||
1054 | current_timestamp.abs_value_us - gnunet_nse_interval.rel_value_us) | ||
1055 | idx = (estimate_index + HISTORY_SIZE - 1) % HISTORY_SIZE; | ||
1056 | else if (ts.abs_value_us == next_timestamp.abs_value_us) | ||
1057 | { | ||
1058 | if (matching_bits <= ntohl (next_message.matching_bits)) | ||
1059 | return; /* ignore, simply too early/late */ | ||
1060 | if (GNUNET_YES != verify_message_crypto (incoming_flood)) | ||
1061 | { | ||
1062 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1063 | "Peer %s is likely ill-configured!\n", | ||
1064 | GNUNET_i2s (peer_entry->id)); | ||
1065 | GNUNET_break_op (0); | ||
1066 | return; | ||
1067 | } | ||
1068 | next_message = *incoming_flood; | ||
1069 | return; | ||
1070 | } | ||
1071 | else | ||
1072 | { | ||
1073 | GNUNET_STATISTICS_update (stats, | ||
1074 | "# flood messages discarded (clock skew too large)", | ||
1075 | 1, | ||
1076 | GNUNET_NO); | ||
1077 | return; | ||
1078 | } | ||
1079 | if (0 == (GNUNET_memcmp (peer_entry->id, &my_identity))) | ||
1080 | { | ||
1081 | /* send to self, update our own estimate IF this also comes from us! */ | ||
1082 | if (0 == GNUNET_memcmp (&incoming_flood->origin, &my_identity)) | ||
1083 | update_network_size_estimate (); | ||
1084 | return; | ||
1085 | } | ||
1086 | if (matching_bits == ntohl (size_estimate_messages[idx].matching_bits)) | ||
1087 | { | ||
1088 | /* Cancel transmission in the other direction, as this peer clearly has | ||
1089 | up-to-date information already. Even if we didn't talk to this peer in | ||
1090 | the previous round, we should no longer send it stale information as it | ||
1091 | told us about the current round! */ | ||
1092 | peer_entry->previous_round = GNUNET_YES; | ||
1093 | if (idx != estimate_index) | ||
1094 | { | ||
1095 | /* do not transmit information for the previous round to this peer | ||
1096 | anymore (but allow current round) */ | ||
1097 | return; | ||
1098 | } | ||
1099 | /* got up-to-date information for current round, cancel transmission to | ||
1100 | * this peer altogether */ | ||
1101 | if (NULL != peer_entry->transmit_task) | ||
1102 | { | ||
1103 | GNUNET_SCHEDULER_cancel (peer_entry->transmit_task); | ||
1104 | peer_entry->transmit_task = NULL; | ||
1105 | } | ||
1106 | return; | ||
1107 | } | ||
1108 | if (matching_bits < ntohl (size_estimate_messages[idx].matching_bits)) | ||
1109 | { | ||
1110 | if ((idx < estimate_index) && (peer_entry->previous_round == GNUNET_YES)) | ||
1111 | { | ||
1112 | peer_entry->previous_round = GNUNET_NO; | ||
1113 | } | ||
1114 | /* push back our result now, that peer is spreading bad information... */ | ||
1115 | if (NULL != peer_entry->transmit_task) | ||
1116 | GNUNET_SCHEDULER_cancel (peer_entry->transmit_task); | ||
1117 | peer_entry->transmit_task = | ||
1118 | GNUNET_SCHEDULER_add_now (&transmit_task_cb, peer_entry); | ||
1119 | /* Not closer than our most recent message, no need to do work here */ | ||
1120 | GNUNET_STATISTICS_update (stats, | ||
1121 | "# flood messages ignored (had closer already)", | ||
1122 | 1, | ||
1123 | GNUNET_NO); | ||
1124 | return; | ||
1125 | } | ||
1126 | if (GNUNET_YES != verify_message_crypto (incoming_flood)) | ||
1127 | { | ||
1128 | GNUNET_break_op (0); | ||
1129 | return; | ||
1130 | } | ||
1131 | GNUNET_assert (matching_bits > | ||
1132 | ntohl (size_estimate_messages[idx].matching_bits)); | ||
1133 | /* Cancel transmission in the other direction, as this peer clearly has | ||
1134 | * up-to-date information already. | ||
1135 | */ | ||
1136 | peer_entry->previous_round = GNUNET_YES; | ||
1137 | if (idx == estimate_index) | ||
1138 | { | ||
1139 | /* cancel any activity for current round */ | ||
1140 | if (NULL != peer_entry->transmit_task) | ||
1141 | { | ||
1142 | GNUNET_SCHEDULER_cancel (peer_entry->transmit_task); | ||
1143 | peer_entry->transmit_task = NULL; | ||
1144 | } | ||
1145 | } | ||
1146 | size_estimate_messages[idx] = *incoming_flood; | ||
1147 | size_estimate_messages[idx].hop_count = | ||
1148 | htonl (ntohl (incoming_flood->hop_count) + 1); | ||
1149 | hop_count_max = | ||
1150 | GNUNET_MAX (ntohl (incoming_flood->hop_count) + 1, hop_count_max); | ||
1151 | GNUNET_STATISTICS_set (stats, | ||
1152 | "# estimated network diameter", | ||
1153 | hop_count_max, | ||
1154 | GNUNET_NO); | ||
1155 | |||
1156 | /* have a new, better size estimate, inform clients */ | ||
1157 | update_network_size_estimate (); | ||
1158 | |||
1159 | /* flood to rest */ | ||
1160 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
1161 | &update_flood_times, | ||
1162 | peer_entry); | ||
1163 | } | ||
1164 | |||
1165 | |||
1166 | /** | ||
1167 | * Method called whenever a peer connects. Sets up the PeerEntry and | ||
1168 | * schedules the initial size info transmission to this peer. | ||
1169 | * | ||
1170 | * @param cls closure | ||
1171 | * @param peer peer identity this notification is about | ||
1172 | */ | ||
1173 | static void * | ||
1174 | handle_core_connect (void *cls, | ||
1175 | const struct GNUNET_PeerIdentity *peer, | ||
1176 | struct GNUNET_MQ_Handle *mq) | ||
1177 | { | ||
1178 | struct NSEPeerEntry *peer_entry; | ||
1179 | |||
1180 | (void) cls; | ||
1181 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1182 | "Peer `%s' connected to us\n", | ||
1183 | GNUNET_i2s (peer)); | ||
1184 | /* set our default transmission options */ | ||
1185 | GNUNET_MQ_set_options (mq, NSE_PRIORITY); | ||
1186 | /* create our peer entry for this peer */ | ||
1187 | peer_entry = GNUNET_new (struct NSEPeerEntry); | ||
1188 | peer_entry->id = peer; | ||
1189 | peer_entry->mq = mq; | ||
1190 | GNUNET_assert (GNUNET_OK == | ||
1191 | GNUNET_CONTAINER_multipeermap_put ( | ||
1192 | peers, | ||
1193 | peer_entry->id, | ||
1194 | peer_entry, | ||
1195 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1196 | peer_entry->transmit_task = | ||
1197 | GNUNET_SCHEDULER_add_delayed (get_transmit_delay (-1), | ||
1198 | &transmit_task_cb, | ||
1199 | peer_entry); | ||
1200 | GNUNET_STATISTICS_update (stats, "# peers connected", 1, GNUNET_NO); | ||
1201 | return peer_entry; | ||
1202 | } | ||
1203 | |||
1204 | |||
1205 | /** | ||
1206 | * Method called whenever a peer disconnects. Deletes the PeerEntry and cancels | ||
1207 | * any pending transmission requests to that peer. | ||
1208 | * | ||
1209 | * @param cls closure | ||
1210 | * @param peer peer identity this notification is about | ||
1211 | * @parma internal_cls the `struct NSEPeerEntry` for the @a peer | ||
1212 | */ | ||
1213 | static void | ||
1214 | handle_core_disconnect (void *cls, | ||
1215 | const struct GNUNET_PeerIdentity *peer, | ||
1216 | void *internal_cls) | ||
1217 | { | ||
1218 | struct NSEPeerEntry *pos = internal_cls; | ||
1219 | |||
1220 | (void) cls; | ||
1221 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1222 | "Peer `%s' disconnected from us\n", | ||
1223 | GNUNET_i2s (peer)); | ||
1224 | GNUNET_assert (GNUNET_YES == | ||
1225 | GNUNET_CONTAINER_multipeermap_remove (peers, peer, pos)); | ||
1226 | if (NULL != pos->transmit_task) | ||
1227 | { | ||
1228 | GNUNET_SCHEDULER_cancel (pos->transmit_task); | ||
1229 | pos->transmit_task = NULL; | ||
1230 | } | ||
1231 | GNUNET_free (pos); | ||
1232 | GNUNET_STATISTICS_update (stats, "# peers connected", -1, GNUNET_NO); | ||
1233 | } | ||
1234 | |||
1235 | |||
1236 | #if ENABLE_NSE_HISTOGRAM | ||
1237 | /** | ||
1238 | * Functions of this type are called to notify a successful transmission of the | ||
1239 | * message to the logger service | ||
1240 | * | ||
1241 | * @param cls NULL | ||
1242 | * @param size the amount of data sent (ignored) | ||
1243 | */ | ||
1244 | static void | ||
1245 | flush_comp_cb (void *cls, size_t size) | ||
1246 | { | ||
1247 | (void) cls; | ||
1248 | (void) size; | ||
1249 | GNUNET_TESTBED_LOGGER_disconnect (lh); | ||
1250 | lh = NULL; | ||
1251 | } | ||
1252 | |||
1253 | |||
1254 | #endif | ||
1255 | |||
1256 | |||
1257 | /** | ||
1258 | * Task run during shutdown. | ||
1259 | * | ||
1260 | * @param cls unused | ||
1261 | */ | ||
1262 | static void | ||
1263 | shutdown_task (void *cls) | ||
1264 | { | ||
1265 | (void) cls; | ||
1266 | if (NULL != flood_task) | ||
1267 | { | ||
1268 | GNUNET_SCHEDULER_cancel (flood_task); | ||
1269 | flood_task = NULL; | ||
1270 | } | ||
1271 | if (NULL != proof_task) | ||
1272 | { | ||
1273 | GNUNET_SCHEDULER_cancel (proof_task); | ||
1274 | proof_task = NULL; | ||
1275 | write_proof (); /* remember progress */ | ||
1276 | } | ||
1277 | if (NULL != nc) | ||
1278 | { | ||
1279 | GNUNET_notification_context_destroy (nc); | ||
1280 | nc = NULL; | ||
1281 | } | ||
1282 | if (NULL != core_api) | ||
1283 | { | ||
1284 | GNUNET_CORE_disconnect (core_api); | ||
1285 | core_api = NULL; | ||
1286 | } | ||
1287 | if (NULL != stats) | ||
1288 | { | ||
1289 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | ||
1290 | stats = NULL; | ||
1291 | } | ||
1292 | if (NULL != peers) | ||
1293 | { | ||
1294 | GNUNET_CONTAINER_multipeermap_destroy (peers); | ||
1295 | peers = NULL; | ||
1296 | } | ||
1297 | if (NULL != my_private_key) | ||
1298 | { | ||
1299 | GNUNET_free (my_private_key); | ||
1300 | my_private_key = NULL; | ||
1301 | } | ||
1302 | #if ENABLE_NSE_HISTOGRAM | ||
1303 | if (NULL != logger_test) | ||
1304 | { | ||
1305 | GNUNET_CLIENT_service_test_cancel (logger_test); | ||
1306 | logger_test = NULL; | ||
1307 | } | ||
1308 | if (NULL != lh) | ||
1309 | { | ||
1310 | GNUNET_TESTBED_LOGGER_flush (lh, &flush_comp_cb, NULL); | ||
1311 | } | ||
1312 | if (NULL != histogram) | ||
1313 | { | ||
1314 | GNUNET_BIO_write_close (histogram, NULL); | ||
1315 | histogram = NULL; | ||
1316 | } | ||
1317 | #endif | ||
1318 | } | ||
1319 | |||
1320 | |||
1321 | /** | ||
1322 | * Called on core init/fail. | ||
1323 | * | ||
1324 | * @param cls service closure | ||
1325 | * @param identity the public identity of this peer | ||
1326 | */ | ||
1327 | static void | ||
1328 | core_init (void *cls, const struct GNUNET_PeerIdentity *identity) | ||
1329 | { | ||
1330 | struct GNUNET_TIME_Absolute now; | ||
1331 | struct GNUNET_TIME_Absolute prev_time; | ||
1332 | |||
1333 | (void) cls; | ||
1334 | if (NULL == identity) | ||
1335 | { | ||
1336 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connection to core FAILED!\n"); | ||
1337 | GNUNET_SCHEDULER_shutdown (); | ||
1338 | return; | ||
1339 | } | ||
1340 | GNUNET_assert (0 == GNUNET_memcmp (&my_identity, identity)); | ||
1341 | now = GNUNET_TIME_absolute_get (); | ||
1342 | current_timestamp.abs_value_us = | ||
1343 | (now.abs_value_us / gnunet_nse_interval.rel_value_us) | ||
1344 | * gnunet_nse_interval.rel_value_us; | ||
1345 | next_timestamp = | ||
1346 | GNUNET_TIME_absolute_add (current_timestamp, gnunet_nse_interval); | ||
1347 | estimate_index = HISTORY_SIZE - 1; | ||
1348 | estimate_count = 0; | ||
1349 | if (GNUNET_YES == check_proof_of_work (&my_identity.public_key, my_proof)) | ||
1350 | { | ||
1351 | int idx = (estimate_index + HISTORY_SIZE - 1) % HISTORY_SIZE; | ||
1352 | prev_time.abs_value_us = | ||
1353 | current_timestamp.abs_value_us - gnunet_nse_interval.rel_value_us; | ||
1354 | setup_flood_message (idx, prev_time); | ||
1355 | setup_flood_message (estimate_index, current_timestamp); | ||
1356 | estimate_count++; | ||
1357 | } | ||
1358 | flood_task = | ||
1359 | GNUNET_SCHEDULER_add_at (next_timestamp, &update_flood_message, NULL); | ||
1360 | } | ||
1361 | |||
1362 | |||
1363 | #if ENABLE_NSE_HISTOGRAM | ||
1364 | /** | ||
1365 | * Function called with the status of the testbed logger service | ||
1366 | * | ||
1367 | * @param cls NULL | ||
1368 | * @param status #GNUNET_YES if the service is running, | ||
1369 | * #GNUNET_NO if the service is not running | ||
1370 | * #GNUNET_SYSERR if the configuration is invalid | ||
1371 | */ | ||
1372 | static void | ||
1373 | status_cb (void *cls, int status) | ||
1374 | { | ||
1375 | (void) cls; | ||
1376 | logger_test = NULL; | ||
1377 | if (GNUNET_YES != status) | ||
1378 | { | ||
1379 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Testbed logger not running\n"); | ||
1380 | return; | ||
1381 | } | ||
1382 | if (NULL == (lh = GNUNET_TESTBED_LOGGER_connect (cfg))) | ||
1383 | { | ||
1384 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1385 | "Cannot connect to the testbed logger. Exiting.\n"); | ||
1386 | GNUNET_SCHEDULER_shutdown (); | ||
1387 | } | ||
1388 | } | ||
1389 | |||
1390 | |||
1391 | #endif | ||
1392 | |||
1393 | |||
1394 | /** | ||
1395 | * Handle network size estimate clients. | ||
1396 | * | ||
1397 | * @param cls closure | ||
1398 | * @param c configuration to use | ||
1399 | * @param service the initialized service | ||
1400 | */ | ||
1401 | static void | ||
1402 | run (void *cls, | ||
1403 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
1404 | struct GNUNET_SERVICE_Handle *service) | ||
1405 | { | ||
1406 | struct GNUNET_MQ_MessageHandler core_handlers[] = | ||
1407 | { GNUNET_MQ_hd_fixed_size (p2p_estimate, | ||
1408 | GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD, | ||
1409 | struct GNUNET_NSE_FloodMessage, | ||
1410 | NULL), | ||
1411 | GNUNET_MQ_handler_end () }; | ||
1412 | char *proof; | ||
1413 | struct GNUNET_CRYPTO_EddsaPrivateKey *pk; | ||
1414 | |||
1415 | (void) cls; | ||
1416 | (void) service; | ||
1417 | cfg = c; | ||
1418 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, | ||
1419 | "NSE", | ||
1420 | "INTERVAL", | ||
1421 | &gnunet_nse_interval)) | ||
1422 | { | ||
1423 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "INTERVAL"); | ||
1424 | GNUNET_SCHEDULER_shutdown (); | ||
1425 | return; | ||
1426 | } | ||
1427 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, | ||
1428 | "NSE", | ||
1429 | "WORKDELAY", | ||
1430 | &proof_find_delay)) | ||
1431 | { | ||
1432 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "WORKDELAY"); | ||
1433 | GNUNET_SCHEDULER_shutdown (); | ||
1434 | return; | ||
1435 | } | ||
1436 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, | ||
1437 | "NSE", | ||
1438 | "WORKBITS", | ||
1439 | &nse_work_required)) | ||
1440 | { | ||
1441 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "WORKBITS"); | ||
1442 | GNUNET_SCHEDULER_shutdown (); | ||
1443 | return; | ||
1444 | } | ||
1445 | if (nse_work_required >= sizeof(struct GNUNET_HashCode) * 8) | ||
1446 | { | ||
1447 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
1448 | "NSE", | ||
1449 | "WORKBITS", | ||
1450 | _ ("Value is too large.\n")); | ||
1451 | GNUNET_SCHEDULER_shutdown (); | ||
1452 | return; | ||
1453 | } | ||
1454 | |||
1455 | #if ENABLE_NSE_HISTOGRAM | ||
1456 | { | ||
1457 | char *histogram_dir; | ||
1458 | char *histogram_fn; | ||
1459 | |||
1460 | if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
1461 | "NSE", | ||
1462 | "HISTOGRAM_DIR", | ||
1463 | &histogram_dir)) | ||
1464 | { | ||
1465 | GNUNET_assert ( | ||
1466 | 0 < GNUNET_asprintf (&histogram_fn, "%s/timestamps", histogram_dir)); | ||
1467 | GNUNET_free (histogram_dir); | ||
1468 | histogram = GNUNET_BIO_write_open_file (histogram_fn); | ||
1469 | if (NULL == histogram) | ||
1470 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1471 | "Unable to open histogram file `%s'\n", | ||
1472 | histogram_fn); | ||
1473 | GNUNET_free (histogram_fn); | ||
1474 | } | ||
1475 | logger_test = GNUNET_CLIENT_service_test ("testbed-logger", | ||
1476 | cfg, | ||
1477 | GNUNET_TIME_UNIT_SECONDS, | ||
1478 | &status_cb, | ||
1479 | NULL); | ||
1480 | } | ||
1481 | #endif | ||
1482 | |||
1483 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | ||
1484 | pk = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg); | ||
1485 | GNUNET_assert (NULL != pk); | ||
1486 | my_private_key = pk; | ||
1487 | GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_identity.public_key); | ||
1488 | if (GNUNET_OK != | ||
1489 | GNUNET_CONFIGURATION_get_value_filename (cfg, "NSE", "PROOFFILE", &proof)) | ||
1490 | { | ||
1491 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "PROOFFILE"); | ||
1492 | GNUNET_free (my_private_key); | ||
1493 | my_private_key = NULL; | ||
1494 | GNUNET_SCHEDULER_shutdown (); | ||
1495 | return; | ||
1496 | } | ||
1497 | if ((GNUNET_YES != GNUNET_DISK_file_test (proof)) || | ||
1498 | (sizeof(my_proof) != | ||
1499 | GNUNET_DISK_fn_read (proof, &my_proof, sizeof(my_proof)))) | ||
1500 | my_proof = 0; | ||
1501 | GNUNET_free (proof); | ||
1502 | proof_task = | ||
1503 | GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, | ||
1504 | &find_proof, | ||
1505 | NULL); | ||
1506 | |||
1507 | peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES); | ||
1508 | nc = GNUNET_notification_context_create (1); | ||
1509 | /* Connect to core service and register core handlers */ | ||
1510 | core_api = | ||
1511 | GNUNET_CORE_connect (cfg, /* Main configuration */ | ||
1512 | NULL, /* Closure passed to functions */ | ||
1513 | &core_init, /* Call core_init once connected */ | ||
1514 | &handle_core_connect, /* Handle connects */ | ||
1515 | &handle_core_disconnect, /* Handle disconnects */ | ||
1516 | core_handlers); /* Register these handlers */ | ||
1517 | if (NULL == core_api) | ||
1518 | { | ||
1519 | GNUNET_SCHEDULER_shutdown (); | ||
1520 | return; | ||
1521 | } | ||
1522 | stats = GNUNET_STATISTICS_create ("nse", cfg); | ||
1523 | } | ||
1524 | |||
1525 | |||
1526 | /** | ||
1527 | * Callback called when a client connects to the service. | ||
1528 | * | ||
1529 | * @param cls closure for the service | ||
1530 | * @param c the new client that connected to the service | ||
1531 | * @param mq the message queue used to send messages to the client | ||
1532 | * @return @a c | ||
1533 | */ | ||
1534 | static void * | ||
1535 | client_connect_cb (void *cls, | ||
1536 | struct GNUNET_SERVICE_Client *c, | ||
1537 | struct GNUNET_MQ_Handle *mq) | ||
1538 | { | ||
1539 | (void) cls; | ||
1540 | (void) mq; | ||
1541 | return c; | ||
1542 | } | ||
1543 | |||
1544 | |||
1545 | /** | ||
1546 | * Callback called when a client disconnected from the service | ||
1547 | * | ||
1548 | * @param cls closure for the service | ||
1549 | * @param c the client that disconnected | ||
1550 | * @param internal_cls should be equal to @a c | ||
1551 | */ | ||
1552 | static void | ||
1553 | client_disconnect_cb (void *cls, | ||
1554 | struct GNUNET_SERVICE_Client *c, | ||
1555 | void *internal_cls) | ||
1556 | { | ||
1557 | (void) cls; | ||
1558 | GNUNET_assert (c == internal_cls); | ||
1559 | } | ||
1560 | |||
1561 | |||
1562 | /** | ||
1563 | * Define "main" method using service macro. | ||
1564 | */ | ||
1565 | GNUNET_SERVICE_MAIN ("nse", | ||
1566 | GNUNET_SERVICE_OPTION_NONE, | ||
1567 | &run, | ||
1568 | &client_connect_cb, | ||
1569 | &client_disconnect_cb, | ||
1570 | NULL, | ||
1571 | GNUNET_MQ_hd_fixed_size (start, | ||
1572 | GNUNET_MESSAGE_TYPE_NSE_START, | ||
1573 | struct GNUNET_MessageHeader, | ||
1574 | NULL), | ||
1575 | GNUNET_MQ_handler_end ()); | ||
1576 | |||
1577 | |||
1578 | #if defined(__linux__) && defined(__GLIBC__) | ||
1579 | #include <malloc.h> | ||
1580 | |||
1581 | /** | ||
1582 | * MINIMIZE heap size (way below 128k) since this process doesn't need much. | ||
1583 | */ | ||
1584 | void __attribute__ ((constructor)) | ||
1585 | GNUNET_ARM_memory_init () | ||
1586 | { | ||
1587 | mallopt (M_TRIM_THRESHOLD, 4 * 1024); | ||
1588 | mallopt (M_TOP_PAD, 1 * 1024); | ||
1589 | malloc_trim (0); | ||
1590 | } | ||
1591 | |||
1592 | |||
1593 | #endif | ||
1594 | |||
1595 | |||
1596 | /* end of gnunet-service-nse.c */ | ||
diff --git a/src/nse/hostkeys.dat b/src/nse/hostkeys.dat deleted file mode 100644 index ab407c167..000000000 --- a/src/nse/hostkeys.dat +++ /dev/null | |||
Binary files differ | |||
diff --git a/src/nse/nse.conf.in b/src/nse/nse.conf.in deleted file mode 100644 index 0ac5621aa..000000000 --- a/src/nse/nse.conf.in +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | [nse] | ||
2 | START_ON_DEMAND = @START_ON_DEMAND@ | ||
3 | IMMEDIATE_START = YES | ||
4 | @JAVAPORT@PORT = 2097 | ||
5 | HOSTNAME = localhost | ||
6 | BINARY = gnunet-service-nse | ||
7 | ACCEPT_FROM = 127.0.0.1; | ||
8 | ACCEPT_FROM6 = ::1; | ||
9 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-nse.sock | ||
10 | UNIX_MATCH_UID = NO | ||
11 | UNIX_MATCH_GID = YES | ||
12 | PROOFFILE = $GNUNET_DATA_HOME/nse/proof.dat | ||
13 | |||
14 | # The directory where the NSE services logs timestamps every time | ||
15 | # a size estime flooding message is received | ||
16 | # This option is only used for benchmarking, not in production. | ||
17 | HISTOGRAM_DIR = $GNUNET_CACHE_HOME/nse/histogram | ||
18 | |||
19 | # How 'slowly' should the proof-of-work be constructed (delay | ||
20 | # between rounds); sane values between 0 and ~1000. | ||
21 | # It should rarely make sense to change this value. | ||
22 | # Only systems with slow CPUs where 5ms is a long time might | ||
23 | # want it to be reduced. | ||
24 | WORKDELAY = 5 ms | ||
25 | |||
26 | # Note: changing any of the values below will make this peer | ||
27 | # completely incompatible with other peers! | ||
28 | |||
29 | # How often do peers exchange network size messages? | ||
30 | # Note that all peers MUST use the same interval. | ||
31 | # DO NOT CHANGE THIS VALUE, doing so will break the protocol! | ||
32 | INTERVAL = 1 h | ||
33 | |||
34 | # 2^22 hash operations take about 2-3h on a first-generation i7 (single-core) | ||
35 | # for SCRYPT; with 2ms/op and 5ms workdelay, we can expect | ||
36 | # the POW calculation to be done by a high-end peer in about 6h | ||
37 | # DO NOT CHANGE THIS VALUE, doing so will break the protocol! | ||
38 | WORKBITS = 15 | ||
diff --git a/src/nse/nse.h b/src/nse/nse.h deleted file mode 100644 index 5d1fccb7e..000000000 --- a/src/nse/nse.h +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2011 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 | * @author Nathan Evans | ||
23 | * @file nse/nse.h | ||
24 | * | ||
25 | * @brief Common type definitions for the network size estimation | ||
26 | * service and API. | ||
27 | */ | ||
28 | #ifndef NSE_H | ||
29 | #define NSE_H | ||
30 | |||
31 | #include "gnunet_common.h" | ||
32 | |||
33 | GNUNET_NETWORK_STRUCT_BEGIN | ||
34 | |||
35 | /** | ||
36 | * Network size estimate sent from the service | ||
37 | * to clients. Contains the current size estimate | ||
38 | * (or 0 if none has been calculated) and the | ||
39 | * standard deviation of known estimates. | ||
40 | * | ||
41 | */ | ||
42 | struct GNUNET_NSE_ClientMessage | ||
43 | { | ||
44 | /** | ||
45 | * Type: GNUNET_MESSAGE_TYPE_NSE_ESTIMATE | ||
46 | */ | ||
47 | struct GNUNET_MessageHeader header; | ||
48 | |||
49 | /** | ||
50 | * For alignment. | ||
51 | */ | ||
52 | uint32_t reserved GNUNET_PACKED; | ||
53 | |||
54 | /** | ||
55 | * Timestamp at which the server received the message. | ||
56 | */ | ||
57 | struct GNUNET_TIME_AbsoluteNBO timestamp; | ||
58 | |||
59 | /** | ||
60 | * The current estimated network size. | ||
61 | */ | ||
62 | double size_estimate GNUNET_PACKED; | ||
63 | |||
64 | /** | ||
65 | * The standard deviation (rounded down | ||
66 | * to the nearest integer) of size | ||
67 | * estimations. | ||
68 | */ | ||
69 | double std_deviation GNUNET_PACKED; | ||
70 | }; | ||
71 | GNUNET_NETWORK_STRUCT_END | ||
72 | |||
73 | #endif | ||
diff --git a/src/nse/nse_api.c b/src/nse/nse_api.c deleted file mode 100644 index 23daa7f12..000000000 --- a/src/nse/nse_api.c +++ /dev/null | |||
@@ -1,209 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009, 2010, 2011, 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 nse/nse_api.c | ||
23 | * @brief api to get information from the network size estimation service | ||
24 | * @author Nathan Evans | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_constants.h" | ||
28 | #include "gnunet_arm_service.h" | ||
29 | #include "gnunet_hello_lib.h" | ||
30 | #include "gnunet_protocols.h" | ||
31 | #include "gnunet_util_lib.h" | ||
32 | #include "gnunet_nse_service.h" | ||
33 | #include "nse.h" | ||
34 | |||
35 | #define LOG(kind, ...) GNUNET_log_from (kind, "nse-api", __VA_ARGS__) | ||
36 | |||
37 | /** | ||
38 | * Handle for talking with the NSE service. | ||
39 | */ | ||
40 | struct GNUNET_NSE_Handle | ||
41 | { | ||
42 | /** | ||
43 | * Configuration to use. | ||
44 | */ | ||
45 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
46 | |||
47 | /** | ||
48 | * Message queue (if available). | ||
49 | */ | ||
50 | struct GNUNET_MQ_Handle *mq; | ||
51 | |||
52 | /** | ||
53 | * Task doing exponential back-off trying to reconnect. | ||
54 | */ | ||
55 | struct GNUNET_SCHEDULER_Task *reconnect_task; | ||
56 | |||
57 | /** | ||
58 | * Time for next connect retry. | ||
59 | */ | ||
60 | struct GNUNET_TIME_Relative reconnect_delay; | ||
61 | |||
62 | /** | ||
63 | * Callback function to call when message is received. | ||
64 | */ | ||
65 | GNUNET_NSE_Callback recv_cb; | ||
66 | |||
67 | /** | ||
68 | * Closure to pass to @e recv_cb callback. | ||
69 | */ | ||
70 | void *recv_cb_cls; | ||
71 | }; | ||
72 | |||
73 | |||
74 | /** | ||
75 | * Try again to connect to network size estimation service. | ||
76 | * | ||
77 | * @param cls closure with the `struct GNUNET_NSE_Handle *` | ||
78 | */ | ||
79 | static void | ||
80 | reconnect (void *cls); | ||
81 | |||
82 | |||
83 | /** | ||
84 | * Generic error handler, called with the appropriate | ||
85 | * error code and the same closure specified at the creation of | ||
86 | * the message queue. | ||
87 | * Not every message queue implementation supports an error handler. | ||
88 | * | ||
89 | * @param cls closure with the `struct GNUNET_NSE_Handle *` | ||
90 | * @param error error code | ||
91 | */ | ||
92 | static void | ||
93 | mq_error_handler (void *cls, enum GNUNET_MQ_Error error) | ||
94 | { | ||
95 | struct GNUNET_NSE_Handle *h = cls; | ||
96 | |||
97 | (void) error; | ||
98 | GNUNET_MQ_destroy (h->mq); | ||
99 | h->mq = NULL; | ||
100 | h->reconnect_task = | ||
101 | GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h); | ||
102 | h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay); | ||
103 | } | ||
104 | |||
105 | |||
106 | /** | ||
107 | * Type of a function to call when we receive a message | ||
108 | * from the service. | ||
109 | * | ||
110 | * @param cls closure | ||
111 | * @param client_msg message received | ||
112 | */ | ||
113 | static void | ||
114 | handle_estimate (void *cls, const struct GNUNET_NSE_ClientMessage *client_msg) | ||
115 | { | ||
116 | struct GNUNET_NSE_Handle *h = cls; | ||
117 | |||
118 | h->reconnect_delay = GNUNET_TIME_UNIT_ZERO; | ||
119 | h->recv_cb (h->recv_cb_cls, | ||
120 | GNUNET_TIME_absolute_ntoh (client_msg->timestamp), | ||
121 | GNUNET_ntoh_double (client_msg->size_estimate), | ||
122 | GNUNET_ntoh_double (client_msg->std_deviation)); | ||
123 | } | ||
124 | |||
125 | |||
126 | /** | ||
127 | * Try again to connect to network size estimation service. | ||
128 | * | ||
129 | * @param cls the `struct GNUNET_NSE_Handle *` | ||
130 | */ | ||
131 | static void | ||
132 | reconnect (void *cls) | ||
133 | { | ||
134 | struct GNUNET_NSE_Handle *h = cls; | ||
135 | struct GNUNET_MQ_MessageHandler handlers[] = | ||
136 | { GNUNET_MQ_hd_fixed_size (estimate, | ||
137 | GNUNET_MESSAGE_TYPE_NSE_ESTIMATE, | ||
138 | struct GNUNET_NSE_ClientMessage, | ||
139 | h), | ||
140 | GNUNET_MQ_handler_end () }; | ||
141 | struct GNUNET_MessageHeader *msg; | ||
142 | struct GNUNET_MQ_Envelope *env; | ||
143 | |||
144 | h->reconnect_task = NULL; | ||
145 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
146 | "Connecting to network size estimation service.\n"); | ||
147 | GNUNET_assert (NULL == h->mq); | ||
148 | h->mq = GNUNET_CLIENT_connect (h->cfg, "nse", handlers, &mq_error_handler, h); | ||
149 | if (NULL == h->mq) | ||
150 | return; | ||
151 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NSE_START); | ||
152 | GNUNET_MQ_send (h->mq, env); | ||
153 | } | ||
154 | |||
155 | |||
156 | /** | ||
157 | * Connect to the network size estimation service. | ||
158 | * | ||
159 | * @param cfg the configuration to use | ||
160 | * @param func function to call with network size estimate | ||
161 | * @param func_cls closure to pass to @a func | ||
162 | * @return handle to use | ||
163 | */ | ||
164 | struct GNUNET_NSE_Handle * | ||
165 | GNUNET_NSE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
166 | GNUNET_NSE_Callback func, | ||
167 | void *func_cls) | ||
168 | { | ||
169 | struct GNUNET_NSE_Handle *h; | ||
170 | |||
171 | GNUNET_assert (NULL != func); | ||
172 | h = GNUNET_new (struct GNUNET_NSE_Handle); | ||
173 | h->cfg = cfg; | ||
174 | h->recv_cb = func; | ||
175 | h->recv_cb_cls = func_cls; | ||
176 | h->reconnect_delay = GNUNET_TIME_UNIT_ZERO; | ||
177 | reconnect (h); | ||
178 | if (NULL == h->mq) | ||
179 | { | ||
180 | GNUNET_free (h); | ||
181 | return NULL; | ||
182 | } | ||
183 | return h; | ||
184 | } | ||
185 | |||
186 | |||
187 | /** | ||
188 | * Disconnect from network size estimation service | ||
189 | * | ||
190 | * @param h handle to destroy | ||
191 | */ | ||
192 | void | ||
193 | GNUNET_NSE_disconnect (struct GNUNET_NSE_Handle *h) | ||
194 | { | ||
195 | if (NULL != h->reconnect_task) | ||
196 | { | ||
197 | GNUNET_SCHEDULER_cancel (h->reconnect_task); | ||
198 | h->reconnect_task = NULL; | ||
199 | } | ||
200 | if (NULL != h->mq) | ||
201 | { | ||
202 | GNUNET_MQ_destroy (h->mq); | ||
203 | h->mq = NULL; | ||
204 | } | ||
205 | GNUNET_free (h); | ||
206 | } | ||
207 | |||
208 | |||
209 | /* end of nse_api.c */ | ||
diff --git a/src/nse/nse_infiniband.conf b/src/nse/nse_infiniband.conf deleted file mode 100644 index d2c97567d..000000000 --- a/src/nse/nse_infiniband.conf +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | [PATHS] | ||
2 | GNUNET_TEST_HOME = $GNUNET_TMP/nse-profiler/ | ||
3 | |||
4 | [testbed] | ||
5 | START_ON_DEMAND = NO | ||
6 | ORT = 12113 | ||
7 | ACCEPT_FROM = 127.0.0.1; 10.6.0.0/16; 192.168.0.0/16; | ||
8 | HOSTNAME = localhost | ||
9 | MAX_PARALLEL_OPERATIONS = 400 | ||
10 | OVERLAY_TOPOLOGY = 2D_TORUS | ||
11 | OVERLAY_RANDOM_LINKS = 1000 | ||
12 | OPERATION_TIMEOUT = 45 s | ||
13 | SETUP_TIMEOUT = 30m | ||
14 | STATS_DIR= /home/totakura/nse/test/load | ||
15 | |||
16 | [nse] | ||
17 | IMMEDIATE_START = YES | ||
18 | # Overriding network settings for faster testing (do NOT use | ||
19 | # these values in production just because they are here) | ||
20 | WORKDELAY = 60 s | ||
21 | INTERVAL = 10 s | ||
22 | WORKBITS = 0 | ||
23 | PROOFFILE = $GNUNET_TEST_HOME/nse.proof | ||
24 | HISTOGRAM_DIR = /home/totakura/nse/test/histograms | ||
25 | |||
26 | [nat] | ||
27 | DISABLEV6 = YES | ||
28 | BINDTO = 127.0.0.1 | ||
29 | ENABLE_UPNP = NO | ||
30 | BEHIND_NAT = NO | ||
31 | ALLOW_NAT = NO | ||
32 | INTERNAL_ADDRESS = 127.0.0.1 | ||
33 | EXTERNAL_ADDRESS = 127.0.0.1 | ||
34 | |||
35 | [transport] | ||
36 | plugins = udp | ||
37 | |||
38 | [transport-udp] | ||
39 | PORT = 12116 | ||
40 | |||
41 | [nse-profiler] | ||
42 | OUTPUT_FILE = nse_output_2000_peers.dat | ||
43 | TOPOLOGY_OUTPUT_FILE = nse_topo_2000_peers | ||
44 | DATA_OUTPUT_FILE = nse_stats_2000_peers | ||
45 | ROUND0 = 1000 | ||
46 | #ROUND1 = 2000 | ||
47 | ROUND2 = 2000 | ||
48 | ROUND3 = 2000 | ||
49 | ROUND4 = 2000 | ||
50 | ROUND5 = 2000 | ||
51 | ROUND6 = 2000 | ||
52 | ROUND7 = 2000 | ||
53 | ROUND8 = 2000 | ||
54 | ROUND9 = 2000 | ||
55 | ROUND10 = 2000 | ||
56 | ROUND11 = 1000 | ||
57 | ROUND12 = 1000 | ||
58 | ROUND13 = 1000 | ||
59 | ROUND14 = 1000 | ||
60 | ROUND15 = 1000 | ||
61 | ROUND16 = 1000 | ||
62 | ROUND17 = 1000 | ||
63 | ROUND18 = 1000 | ||
64 | ROUND19 = 1000 | ||
65 | ROUND20 = 1000 | ||
66 | ROUND21 = 2000 | ||
67 | ROUND22 = 2000 | ||
68 | ROUND23 = 2000 | ||
69 | ROUND24 = 2000 | ||
70 | ROUND25 = 2000 | ||
71 | ROUND26 = 2000 | ||
72 | ROUND27 = 2000 | ||
73 | ROUND28 = 2000 | ||
74 | ROUND29 = 2000 | ||
75 | ROUND30 = 2000 | ||
76 | WAIT_TIME = 1920 s | ||
77 | CONNECTION_LIMIT = 10 | ||
diff --git a/src/nse/nse_profiler_test.conf b/src/nse/nse_profiler_test.conf deleted file mode 100644 index f702faae2..000000000 --- a/src/nse/nse_profiler_test.conf +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | [PATHS] | ||
2 | GNUNET_TEST_HOME = $GNUNET_TMP/nse-profiler/ | ||
3 | |||
4 | [testbed] | ||
5 | START_ON_DEMAND = NO | ||
6 | PORT = 12113 | ||
7 | ACCEPT_FROM = 127.0.0.1; 10.6.0.0/16; | ||
8 | HOSTNAME = localhost | ||
9 | MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 5 | ||
10 | OVERLAY_TOPOLOGY = RANDOM | ||
11 | OVERLAY_RANDOM_LINKS = 1000 | ||
12 | OPERATION_TIMEOUT = 45 s | ||
13 | |||
14 | [nse] | ||
15 | IMMEDIATE_START = YES | ||
16 | START_ON_DEMAND = NO | ||
17 | # Overriding network settings for faster testing (do NOT use | ||
18 | # these values in production just because they are here) | ||
19 | WORKDELAY = 60 s | ||
20 | INTERVAL = 10 s | ||
21 | WORKBITS = 0 | ||
22 | PROOFFILE = $GNUNET_TEST_HOME/nse.proof | ||
23 | |||
24 | [nat] | ||
25 | DISABLEV6 = YES | ||
26 | BINDTO = 127.0.0.1 | ||
27 | ENABLE_UPNP = NO | ||
28 | BEHIND_NAT = NO | ||
29 | ALLOW_NAT = NO | ||
30 | INTERNAL_ADDRESS = 127.0.0.1 | ||
31 | EXTERNAL_ADDRESS = 127.0.0.1 | ||
32 | |||
33 | [transport] | ||
34 | plugins = udp | ||
35 | |||
36 | [nse-profiler] | ||
37 | OUTPUT_FILE = nse_output_2000_peers.dat | ||
38 | TOPOLOGY_OUTPUT_FILE = nse_topo_2000_peers | ||
39 | DATA_OUTPUT_FILE = nse_stats_2000_peers | ||
40 | ROUND0 = 1000 | ||
41 | #ROUND1 = 2000 | ||
42 | ROUND2 = 2000 | ||
43 | ROUND3 = 2000 | ||
44 | ROUND4 = 2000 | ||
45 | ROUND5 = 2000 | ||
46 | ROUND6 = 2000 | ||
47 | ROUND7 = 2000 | ||
48 | ROUND8 = 2000 | ||
49 | ROUND9 = 2000 | ||
50 | ROUND10 = 2000 | ||
51 | ROUND11 = 1000 | ||
52 | ROUND12 = 1000 | ||
53 | ROUND13 = 1000 | ||
54 | ROUND14 = 1000 | ||
55 | ROUND15 = 1000 | ||
56 | ROUND16 = 1000 | ||
57 | ROUND17 = 1000 | ||
58 | ROUND18 = 1000 | ||
59 | ROUND19 = 1000 | ||
60 | ROUND20 = 1000 | ||
61 | ROUND21 = 2000 | ||
62 | ROUND22 = 2000 | ||
63 | ROUND23 = 2000 | ||
64 | ROUND24 = 2000 | ||
65 | ROUND25 = 2000 | ||
66 | ROUND26 = 2000 | ||
67 | ROUND27 = 2000 | ||
68 | ROUND28 = 2000 | ||
69 | ROUND29 = 2000 | ||
70 | ROUND30 = 2000 | ||
71 | WAIT_TIME = 1920 s | ||
72 | CONNECTION_LIMIT = 10 | ||
diff --git a/src/nse/perf_kdf.c b/src/nse/perf_kdf.c deleted file mode 100644 index 10207675f..000000000 --- a/src/nse/perf_kdf.c +++ /dev/null | |||
@@ -1,67 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2002, 2003, 2004, 2006, 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 | * @author Christian Grothoff | ||
23 | * @file nse/perf_kdf.c | ||
24 | * @brief measure performance of KDF hash function | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include <gcrypt.h> | ||
29 | #include <gauger.h> | ||
30 | |||
31 | |||
32 | static void | ||
33 | perfHash () | ||
34 | { | ||
35 | struct GNUNET_HashCode hc; | ||
36 | char buf[64]; | ||
37 | struct GNUNET_CRYPTO_PowSalt salt = { "gnunet-nse-proof" }; | ||
38 | |||
39 | memset (buf, 1, sizeof(buf)); | ||
40 | for (unsigned int i = 0; i < 1024; i++) | ||
41 | GNUNET_CRYPTO_pow_hash (&salt, | ||
42 | buf, | ||
43 | sizeof(buf), | ||
44 | &hc); | ||
45 | } | ||
46 | |||
47 | |||
48 | int | ||
49 | main (int argc, char *argv[]) | ||
50 | { | ||
51 | struct GNUNET_TIME_Absolute start; | ||
52 | |||
53 | start = GNUNET_TIME_absolute_get (); | ||
54 | perfHash (); | ||
55 | printf ("Hash perf took %s\n", | ||
56 | GNUNET_STRINGS_relative_time_to_string ( | ||
57 | GNUNET_TIME_absolute_get_duration (start), | ||
58 | GNUNET_YES)); | ||
59 | GAUGER ("NSE", "Proof-of-work hashing", | ||
60 | 1024.0 / (1.0 | ||
61 | + GNUNET_TIME_absolute_get_duration | ||
62 | (start).rel_value_us / 1000.0), "hashes/ms"); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | |||
67 | /* end of perf_kdf.c */ | ||
diff --git a/src/nse/test_nse.conf b/src/nse/test_nse.conf deleted file mode 100644 index 6b5aaff49..000000000 --- a/src/nse/test_nse.conf +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | @INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf | ||
2 | @INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf | ||
3 | |||
4 | [PATHS] | ||
5 | GNUNET_TEST_HOME = $GNUNET_TMP/test-nse-multipeer/ | ||
6 | |||
7 | [nse] | ||
8 | #PREFIX = valgrind --leak-check=full --log-file=valgrind_nse.%p | ||
9 | IMMEDIATE_START = YES | ||
10 | PROOFFILE = $GNUNET_TEST_HOME/proof.nse | ||
11 | # Overriding network settings for faster testing (do NOT use | ||
12 | # these values in production just because they are here) | ||
13 | WORKDELAY = 1 ms | ||
14 | INTERVAL = 60 s | ||
15 | WORKBITS = 1 | ||
16 | HISTOGRAM = $GNUNET_TEST_HOME/nse-histogram | ||
17 | |||
18 | [nat] | ||
19 | DISABLEV6 = YES | ||
20 | BINDTO = 127.0.0.1 | ||
21 | ENABLE_UPNP = NO | ||
22 | BEHIND_NAT = NO | ||
23 | ALLOW_NAT = NO | ||
24 | INTERNAL_ADDRESS = 127.0.0.1 | ||
25 | EXTERNAL_ADDRESS = 127.0.0.1 | ||
26 | |||
diff --git a/src/nse/test_nse_api.c b/src/nse/test_nse_api.c deleted file mode 100644 index f1b7c652b..000000000 --- a/src/nse/test_nse_api.c +++ /dev/null | |||
@@ -1,107 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011 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 | * @file nse/test_nse_api.c | ||
22 | * @brief testcase for nse_api.c | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_util_lib.h" | ||
26 | #include "gnunet_nse_service.h" | ||
27 | #include "gnunet_testing_lib.h" | ||
28 | |||
29 | |||
30 | static struct GNUNET_NSE_Handle *h; | ||
31 | |||
32 | static struct GNUNET_SCHEDULER_Task *die_task; | ||
33 | |||
34 | |||
35 | /** | ||
36 | * Signature of the main function of a task. | ||
37 | * | ||
38 | * @param cls closure | ||
39 | */ | ||
40 | static void | ||
41 | end_test (void *cls) | ||
42 | { | ||
43 | if (h != NULL) | ||
44 | { | ||
45 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from NSE service.\n"); | ||
46 | GNUNET_NSE_disconnect (h); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | |||
51 | /** | ||
52 | * Callback to call when network size estimate is updated. | ||
53 | * | ||
54 | * @param cls unused | ||
55 | * @param timestamp time when the estimate was received from the server (or created by the server) | ||
56 | * @param estimate the value of the current network size estimate | ||
57 | * @param std_dev standard deviation (rounded down to nearest integer) | ||
58 | * of the size estimation values seen | ||
59 | * | ||
60 | */ | ||
61 | static void | ||
62 | check_nse_message (void *cls, struct GNUNET_TIME_Absolute timestamp, | ||
63 | double estimate, double std_dev) | ||
64 | { | ||
65 | int *ok = cls; | ||
66 | |||
67 | fprintf (stderr, | ||
68 | "Received NSE message, estimate %f, standard deviation %f.\n", | ||
69 | estimate, std_dev); | ||
70 | /* Fantastic check below. Expect NaN, the only thing not equal to itself. */ | ||
71 | (*ok) = 0; | ||
72 | if (die_task != NULL) | ||
73 | GNUNET_SCHEDULER_cancel (die_task); | ||
74 | die_task = GNUNET_SCHEDULER_add_now (&end_test, NULL); | ||
75 | } | ||
76 | |||
77 | |||
78 | static void | ||
79 | run (void *cls, | ||
80 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
81 | struct GNUNET_TESTING_Peer *peer) | ||
82 | { | ||
83 | die_task = | ||
84 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
85 | (GNUNET_TIME_UNIT_MINUTES, 1), &end_test, | ||
86 | NULL); | ||
87 | |||
88 | h = GNUNET_NSE_connect (cfg, &check_nse_message, cls); | ||
89 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to NSE service.\n"); | ||
90 | GNUNET_assert (h != NULL); | ||
91 | } | ||
92 | |||
93 | |||
94 | int | ||
95 | main (int argc, char *argv[]) | ||
96 | { | ||
97 | int ok = 1; | ||
98 | |||
99 | if (0 != GNUNET_TESTING_peer_run ("test_nse_api", | ||
100 | "test_nse.conf", | ||
101 | &run, &ok)) | ||
102 | return 1; | ||
103 | return ok; | ||
104 | } | ||
105 | |||
106 | |||
107 | /* end of test_nse_api.c */ | ||
diff --git a/src/nse/test_nse_multipeer.c b/src/nse/test_nse_multipeer.c deleted file mode 100644 index 6ee03b3fa..000000000 --- a/src/nse/test_nse_multipeer.c +++ /dev/null | |||
@@ -1,235 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009, 2012 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 | * @file nse/test_nse_multipeer.c | ||
22 | * @brief Testcase for the network size estimation service. Starts | ||
23 | * a peergroup with a given number of peers, then waits to | ||
24 | * receive size estimates from each peer. Expects to wait | ||
25 | * for one message from each peer. | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_testbed_service.h" | ||
29 | #include "gnunet_nse_service.h" | ||
30 | |||
31 | |||
32 | /** | ||
33 | * How many peers do we start? | ||
34 | */ | ||
35 | #define NUM_PEERS 4 | ||
36 | |||
37 | /** | ||
38 | * How long do we run the test? | ||
39 | */ | ||
40 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) | ||
41 | |||
42 | |||
43 | /** | ||
44 | * Information we track for each peer. | ||
45 | */ | ||
46 | struct NSEPeer | ||
47 | { | ||
48 | /** | ||
49 | * Handle for NSE connect operation. | ||
50 | */ | ||
51 | struct GNUNET_TESTBED_Operation *op; | ||
52 | |||
53 | /** | ||
54 | * Handle to NSE service. | ||
55 | */ | ||
56 | struct GNUNET_NSE_Handle *nse_handle; | ||
57 | }; | ||
58 | |||
59 | |||
60 | /** | ||
61 | * Information for all the peers. | ||
62 | */ | ||
63 | static struct NSEPeer nse_peers[NUM_PEERS]; | ||
64 | |||
65 | /** | ||
66 | * Return value from 'main'. | ||
67 | */ | ||
68 | static int ok; | ||
69 | |||
70 | |||
71 | /** | ||
72 | * Task run on timeout to shut everything down. | ||
73 | */ | ||
74 | static void | ||
75 | shutdown_task (void *cls) | ||
76 | { | ||
77 | unsigned int i; | ||
78 | |||
79 | for (i = 0; i < NUM_PEERS; i++) | ||
80 | GNUNET_TESTBED_operation_done (nse_peers[i].op); | ||
81 | GNUNET_SCHEDULER_shutdown (); | ||
82 | } | ||
83 | |||
84 | |||
85 | /** | ||
86 | * Callback to call when network size estimate is updated. | ||
87 | * | ||
88 | * @param cls closure | ||
89 | * @param timestamp server timestamp | ||
90 | * @param estimate the value of the current network size estimate | ||
91 | * @param std_dev standard deviation (rounded down to nearest integer) | ||
92 | * of the size estimation values seen | ||
93 | * | ||
94 | */ | ||
95 | static void | ||
96 | handle_estimate (void *cls, struct GNUNET_TIME_Absolute timestamp, | ||
97 | double estimate, double std_dev) | ||
98 | { | ||
99 | struct NSEPeer *peer = cls; | ||
100 | |||
101 | fprintf (stderr, | ||
102 | "Received network size estimate from peer %u. logSize: %f std.dev. %f (%f/%u)\n", | ||
103 | (unsigned int) (peer - nse_peers), | ||
104 | estimate, std_dev, | ||
105 | GNUNET_NSE_log_estimate_to_n (estimate), | ||
106 | NUM_PEERS); | ||
107 | ok = 0; | ||
108 | } | ||
109 | |||
110 | |||
111 | /** | ||
112 | * Callback to be called when NSE service connect operation is completed | ||
113 | * | ||
114 | * @param cls the callback closure from functions generating an operation | ||
115 | * @param op the operation that has been finished | ||
116 | * @param ca_result the NSE service handle returned from nse_connect_adapter | ||
117 | * @param emsg error message in case the operation has failed; will be NULL if | ||
118 | * operation has executed successfully. | ||
119 | */ | ||
120 | static void | ||
121 | nse_connect_complete_cb (void *cls, | ||
122 | struct GNUNET_TESTBED_Operation *op, | ||
123 | void *ca_result, | ||
124 | const char *emsg) | ||
125 | { | ||
126 | struct NSEPeer *peer = cls; | ||
127 | struct GNUNET_NSE_Handle *nse = ca_result; | ||
128 | |||
129 | GNUNET_assert (op == peer->op); | ||
130 | if (NULL != emsg) | ||
131 | { | ||
132 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
133 | "Failed to connect to NSE service: %s\n", | ||
134 | emsg); | ||
135 | ok = 1; | ||
136 | GNUNET_SCHEDULER_shutdown (); | ||
137 | return; | ||
138 | } | ||
139 | peer->nse_handle = nse; | ||
140 | } | ||
141 | |||
142 | |||
143 | /** | ||
144 | * Adapter function called to establish a connection to | ||
145 | * the NSE service. | ||
146 | * | ||
147 | * @param cls closure | ||
148 | * @param cfg configuration of the peer to connect to; will be available until | ||
149 | * GNUNET_TESTBED_operation_done() is called on the operation returned | ||
150 | * from GNUNET_TESTBED_service_connect() | ||
151 | * @return service handle to return in 'op_result', NULL on error | ||
152 | */ | ||
153 | static void * | ||
154 | nse_connect_adapter (void *cls, | ||
155 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
156 | { | ||
157 | return GNUNET_NSE_connect (cfg, | ||
158 | &handle_estimate, | ||
159 | cls); | ||
160 | } | ||
161 | |||
162 | |||
163 | /** | ||
164 | * Adapter function called to destroy connection to | ||
165 | * NSE service. | ||
166 | * | ||
167 | * @param cls closure | ||
168 | * @param op_result service handle returned from the connect adapter | ||
169 | */ | ||
170 | static void | ||
171 | nse_disconnect_adapter (void *cls, | ||
172 | void *op_result) | ||
173 | { | ||
174 | GNUNET_NSE_disconnect (op_result); | ||
175 | } | ||
176 | |||
177 | |||
178 | /** | ||
179 | * Actual "main" function for the testcase. | ||
180 | * | ||
181 | * @param cls closure | ||
182 | * @param h the run handle | ||
183 | * @param num_peers number of peers in 'peers' | ||
184 | * @param peers handle to peers run in the testbed | ||
185 | * @param links_succeeded the number of overlay link connection attempts that | ||
186 | * succeeded | ||
187 | * @param links_failed the number of overlay link connection attempts that | ||
188 | * failed | ||
189 | */ | ||
190 | static void | ||
191 | run (void *cls, | ||
192 | struct GNUNET_TESTBED_RunHandle *h, | ||
193 | unsigned int num_peers, | ||
194 | struct GNUNET_TESTBED_Peer **peers, | ||
195 | unsigned int links_succeeded, | ||
196 | unsigned int links_failed) | ||
197 | { | ||
198 | unsigned int i; | ||
199 | |||
200 | GNUNET_assert (NUM_PEERS == num_peers); | ||
201 | for (i = 0; i < num_peers; i++) | ||
202 | nse_peers[i].op = GNUNET_TESTBED_service_connect (&nse_peers[i], | ||
203 | peers[i], | ||
204 | "nse", | ||
205 | &nse_connect_complete_cb, | ||
206 | &nse_peers[i], | ||
207 | &nse_connect_adapter, | ||
208 | &nse_disconnect_adapter, | ||
209 | &nse_peers[i]); | ||
210 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
211 | &shutdown_task, NULL); | ||
212 | } | ||
213 | |||
214 | |||
215 | /** | ||
216 | * Entry point for the testcase, sets up the testbed. | ||
217 | * | ||
218 | * @param argc unused | ||
219 | * @param argv unused | ||
220 | * @return 0 on success | ||
221 | */ | ||
222 | int | ||
223 | main (int argc, char *argv[]) | ||
224 | { | ||
225 | ok = 1; | ||
226 | (void) GNUNET_TESTBED_test_run ("test-nse-multipeer", | ||
227 | "test_nse.conf", | ||
228 | NUM_PEERS, | ||
229 | 0, NULL, NULL, | ||
230 | &run, NULL); | ||
231 | return ok; | ||
232 | } | ||
233 | |||
234 | |||
235 | /* end of test_nse_multipeer.c */ | ||