aboutsummaryrefslogtreecommitdiff
path: root/src/nse
diff options
context:
space:
mode:
Diffstat (limited to 'src/nse')
-rw-r--r--src/nse/.gitignore5
-rw-r--r--src/nse/Makefile.am106
-rw-r--r--src/nse/gnunet-nse-profiler.c921
-rw-r--r--src/nse/gnunet-nse.c130
-rw-r--r--src/nse/gnunet-service-nse.c1587
-rw-r--r--src/nse/hostkeys.datbin10389438 -> 0 bytes
-rw-r--r--src/nse/nse.conf.in38
-rw-r--r--src/nse/nse.h73
-rw-r--r--src/nse/nse_api.c209
-rw-r--r--src/nse/nse_infiniband.conf77
-rw-r--r--src/nse/nse_profiler_test.conf72
-rw-r--r--src/nse/perf_kdf.c67
-rw-r--r--src/nse/test_nse.conf26
-rw-r--r--src/nse/test_nse_api.c107
-rw-r--r--src/nse/test_nse_multipeer.c235
15 files changed, 0 insertions, 3653 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 @@
1gnunet-service-nse
2gnunet-nse
3gnunet-nse-profiler
4test_nse_api
5perf_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
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4if USE_COVERAGE
5 AM_CFLAGS = --coverage -O0
6 XLIB = -lgcov
7endif
8
9pkgcfgdir= $(pkgdatadir)/config.d/
10
11libexecdir= $(pkglibdir)/libexec/
12
13pkgcfg_DATA = \
14 nse.conf
15
16bin_PROGRAMS = gnunet-nse
17
18gnunet_nse_SOURCES = gnunet-nse.c
19gnunet_nse_LDADD = \
20 libgnunetnse.la \
21 $(top_builddir)/src/util/libgnunetutil.la \
22 $(XLIB) $(GN_LIBINTL)
23
24lib_LTLIBRARIES = libgnunetnse.la
25
26libgnunetnse_la_SOURCES = \
27 nse_api.c nse.h
28libgnunetnse_la_LIBADD = \
29 $(top_builddir)/src/util/libgnunetutil.la \
30 $(GN_LIBINTL) $(XLIB)
31libgnunetnse_la_LDFLAGS = \
32 $(GN_LIB_LDFLAGS) \
33 -version-info 0:0:0
34
35
36libexec_PROGRAMS = \
37 gnunet-service-nse
38
39noinst_PROGRAMS = \
40 gnunet-nse-profiler
41
42gnunet_nse_profiler_SOURCES = \
43 gnunet-nse-profiler.c
44gnunet_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
52gnunet_service_nse_SOURCES = \
53 gnunet-service-nse.c
54gnunet_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)
62if ENABLE_NSE_HISTOGRAM
63 gnunet_service_nse_LDADD += \
64 $(top_builddir)/src/testbed-logger/libgnunettestbedlogger.la
65endif
66
67
68if HAVE_BENCHMARKS
69 MULTIPEER_TEST = test_nse_multipeer
70endif
71
72check_PROGRAMS = \
73 test_nse_api \
74 perf_kdf \
75 $(MULTIPEER_TEST)
76
77if ENABLE_TEST_RUN
78AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
79TESTS = $(check_PROGRAMS)
80endif
81
82test_nse_api_SOURCES = \
83 test_nse_api.c
84test_nse_api_LDADD = \
85 libgnunetnse.la \
86 $(top_builddir)/src/testing/libgnunettesting.la \
87 $(top_builddir)/src/util/libgnunetutil.la
88
89test_nse_multipeer_SOURCES = \
90 test_nse_multipeer.c
91test_nse_multipeer_LDADD = \
92 libgnunetnse.la \
93 $(top_builddir)/src/util/libgnunetutil.la \
94 $(top_builddir)/src/testbed/libgnunettestbed.la \
95 -lm
96
97perf_kdf_SOURCES = \
98 perf_kdf.c
99perf_kdf_LDADD = \
100 $(top_builddir)/src/util/libgnunetutil.la \
101 $(LIBGCRYPT_LIBS) \
102 -lgcrypt
103
104EXTRA_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 */
50struct 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 */
87struct 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 */
115static struct NSEPeer *peer_head;
116
117/**
118 * Tail of DLL of peers we monitor closely.
119 */
120static struct NSEPeer *peer_tail;
121
122/**
123 * Return value from 'main' (0 == success)
124 */
125static int ok;
126
127/**
128 * Be verbose (configuration option)
129 */
130static unsigned int verbose;
131
132/**
133 * Name of the file with the hosts to run the test over (configuration option)
134 */
135static char *hosts_file;
136
137/**
138 * Maximum number of peers in the test.
139 */
140static unsigned int num_peers;
141
142/**
143 * Total number of rounds to execute.
144 */
145static unsigned int num_rounds;
146
147/**
148 * Current round we are in.
149 */
150static unsigned int current_round;
151
152/**
153 * Array of size 'num_rounds' with the requested number of peers in the given round.
154 */
155static unsigned int *num_peers_in_round;
156
157/**
158 * How many peers are running right now?
159 */
160static unsigned int peers_running;
161
162/**
163 * Specification for the numbers of peers to have in each round.
164 */
165static char *num_peer_spec;
166
167/**
168 * Handles to all of the running peers.
169 */
170static struct GNUNET_TESTBED_Peer **daemons;
171
172/**
173 * Global configuration file
174 */
175static struct GNUNET_CONFIGURATION_Handle *testing_cfg;
176
177/**
178 * Maximum number of connections to NSE services.
179 */
180static unsigned int connection_limit;
181
182/**
183 * Total number of connections in the whole network.
184 */
185static unsigned int total_connections;
186
187/**
188 * File to report results to.
189 */
190static struct GNUNET_DISK_FileHandle *output_file;
191
192/**
193 * Filename to log results to.
194 */
195static char *output_filename;
196
197/**
198 * File to log connection info, statistics to.
199 */
200static struct GNUNET_DISK_FileHandle *data_file;
201
202/**
203 * Filename to log connection info, statistics to.
204 */
205static char *data_filename;
206
207/**
208 * How long to wait before triggering next round?
209 * Default: 60 s.
210 */
211static struct GNUNET_TIME_Relative wait_time = { 60 * 1000 };
212
213/**
214 * DLL head for operation list
215 */
216static struct OpListEntry *oplist_head;
217
218/**
219 * DLL tail for operation list
220 */
221static struct OpListEntry *oplist_tail;
222
223/**
224 * Task running each round of the experiment.
225 */
226static 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 */
233static void
234close_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 */
262static void
263shutdown_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 */
299static void
300handle_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 */
342static void *
343nse_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 */
358static void
359nse_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 */
375static int
376stat_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 */
423static void *
424stat_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 */
439static void
440stat_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 */
471static void
472stat_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 */
502static void
503connect_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 */
552static void
553next_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 */
563static void
564finish_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 */
577static void
578run_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 */
589static struct OpListEntry *
590make_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 */
607static void
608manage_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 */
634static void
635adjust_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 */
673static void
674next_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 */
703static void
704master_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 */
736static void
737test_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 */
770static void
771run (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 */
848int
849main (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 */
33static struct GNUNET_NSE_Handle *nse;
34
35/**
36 * The program status; 0 for success.
37 */
38static int status;
39
40
41/**
42 * Task to shutdown and clean up all state
43 *
44 * @param cls NULL
45 */
46static void
47do_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 */
67static void
68handle_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 */
92static void
93run (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 */
111int
112main (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 56014752d..000000000
--- a/src/nse/gnunet-service-nse.c
+++ /dev/null
@@ -1,1587 +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 */
85static unsigned long long nse_work_required;
86
87/**
88 * Interval for sending network size estimation flood requests.
89 */
90static struct GNUNET_TIME_Relative gnunet_nse_interval;
91
92/**
93 * Interval between proof find runs.
94 */
95static 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 */
102struct GNUNET_CLIENT_TestHandle *logger_test;
103
104/**
105 * Handle for writing when we received messages to disk.
106 */
107static struct GNUNET_TESTBED_LOGGER_Handle *lh;
108
109/**
110 * Handle for writing message received timestamp information to disk.
111 */
112static struct GNUNET_BIO_WriteHandle *histogram;
113
114#endif
115
116/**
117 * Salt for PoW calcualations.
118 */
119static struct GNUNET_CRYPTO_PowSalt salt = { "gnunet-nse-proof" };
120
121
122/**
123 * Per-peer information.
124 */
125struct 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
168GNUNET_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 */
175struct 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};
220GNUNET_NETWORK_STRUCT_END
221
222/**
223 * Handle to our current configuration.
224 */
225static const struct GNUNET_CONFIGURATION_Handle *cfg;
226
227/**
228 * Handle to the statistics service.
229 */
230static struct GNUNET_STATISTICS_Handle *stats;
231
232/**
233 * Handle to the core service.
234 */
235static struct GNUNET_CORE_Handle *core_api;
236
237/**
238 * Map of all connected peers.
239 */
240static struct GNUNET_CONTAINER_MultiPeerMap *peers;
241
242/**
243 * The current network size estimate. Number of bits matching on
244 * average thus far.
245 */
246static double current_size_estimate;
247
248/**
249 * The standard deviation of the last #HISTORY_SIZE network
250 * size estimates.
251 */
252static double current_std_dev = NAN;
253
254/**
255 * Current hop counter estimate (estimate for network diameter).
256 */
257static uint32_t hop_count_max;
258
259/**
260 * Message for the next round, if we got any.
261 */
262static struct GNUNET_NSE_FloodMessage next_message;
263
264/**
265 * Array of recent size estimate messages.
266 */
267static struct GNUNET_NSE_FloodMessage size_estimate_messages[HISTORY_SIZE];
268
269/**
270 * Index of most recent estimate.
271 */
272static unsigned int estimate_index;
273
274/**
275 * Number of valid entries in the history.
276 */
277static unsigned int estimate_count;
278
279/**
280 * Task scheduled to update our flood message for the next round.
281 */
282static struct GNUNET_SCHEDULER_Task *flood_task;
283
284/**
285 * Task scheduled to compute our proof.
286 */
287static struct GNUNET_SCHEDULER_Task *proof_task;
288
289/**
290 * Notification context, simplifies client broadcasts.
291 */
292static struct GNUNET_NotificationContext *nc;
293
294/**
295 * The next major time.
296 */
297static struct GNUNET_TIME_Absolute next_timestamp;
298
299/**
300 * The current major time.
301 */
302static struct GNUNET_TIME_Absolute current_timestamp;
303
304/**
305 * The private key of this peer.
306 */
307static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
308
309/**
310 * The peer identity of this peer.
311 */
312static struct GNUNET_PeerIdentity my_identity;
313
314/**
315 * Proof of work for this peer.
316 */
317static 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 */
326static void
327setup_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 */
427static void
428handle_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 */
452static double
453get_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 */
472static struct GNUNET_TIME_Relative
473get_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 */
502static uint32_t
503get_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 struct GNUNET_HashCode xor;
509
510 GNUNET_CRYPTO_hash (&timestamp.abs_value_us,
511 sizeof(timestamp.abs_value_us),
512 &timestamp_hash);
513 GNUNET_CRYPTO_hash (id,
514 sizeof(struct GNUNET_PeerIdentity),
515 &pid_hash);
516 GNUNET_CRYPTO_hash_xor (&pid_hash,
517 &timestamp_hash,
518 &xor);
519 return GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
520}
521
522
523/**
524 * Get the transmission delay that should be applied for a
525 * particular round.
526 *
527 * @param round_offset -1 for the previous round (random delay between 0 and 50ms)
528 * 0 for the current round (based on our proximity to time key)
529 * @return delay that should be applied
530 */
531static struct GNUNET_TIME_Relative
532get_transmit_delay (int round_offset)
533{
534 struct GNUNET_TIME_Relative ret;
535 struct GNUNET_TIME_Absolute tgt;
536 double dist_delay;
537 uint32_t matching_bits;
538
539 switch (round_offset)
540 {
541 case -1:
542 /* previous round is randomized between 0 and 50 ms */
543#if USE_RANDOM_DELAYS
544 ret.rel_value_us =
545 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, 50);
546#else
547 ret = GNUNET_TIME_UNIT_ZERO;
548#endif
549 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
550 "Transmitting previous round behind schedule in %s\n",
551 GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES));
552 return ret;
553
554 case 0:
555 /* current round is based on best-known matching_bits */
556 matching_bits =
557 ntohl (size_estimate_messages[estimate_index].matching_bits);
558 dist_delay = get_matching_bits_delay (matching_bits);
559 dist_delay += get_delay_randomization (matching_bits).rel_value_us;
560 ret.rel_value_us = (uint64_t) dist_delay;
561 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
562 "For round %s, delay for %u matching bits is %s\n",
563 GNUNET_STRINGS_absolute_time_to_string (current_timestamp),
564 (unsigned int) matching_bits,
565 GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES));
566 /* now consider round start time and add delay to it */
567 tgt = GNUNET_TIME_absolute_add (current_timestamp, ret);
568 return GNUNET_TIME_absolute_get_remaining (tgt);
569 }
570 GNUNET_break (0);
571 return GNUNET_TIME_UNIT_FOREVER_REL;
572}
573
574
575/**
576 * Task that triggers a NSE P2P transmission.
577 *
578 * @param cls the `struct NSEPeerEntry *`
579 */
580static void
581transmit_task_cb (void *cls)
582{
583 struct NSEPeerEntry *peer_entry = cls;
584 unsigned int idx;
585 struct GNUNET_MQ_Envelope *env;
586
587 peer_entry->transmit_task = NULL;
588 idx = estimate_index;
589 if (GNUNET_NO == peer_entry->previous_round)
590 {
591 idx = (idx + HISTORY_SIZE - 1) % HISTORY_SIZE;
592 peer_entry->previous_round = GNUNET_YES;
593 peer_entry->transmit_task =
594 GNUNET_SCHEDULER_add_delayed (get_transmit_delay (0),
595 &transmit_task_cb,
596 peer_entry);
597 }
598 if ((0 == ntohl (size_estimate_messages[idx].hop_count)) &&
599 (NULL != proof_task))
600 {
601 GNUNET_STATISTICS_update (stats,
602 "# flood messages not generated (no proof yet)",
603 1,
604 GNUNET_NO);
605 return;
606 }
607 if (0 == ntohs (size_estimate_messages[idx].header.size))
608 {
609 GNUNET_STATISTICS_update (stats,
610 "# flood messages not generated (lack of history)",
611 1,
612 GNUNET_NO);
613 return;
614 }
615 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
616 "In round %s, sending to `%s' estimate with %u bits\n",
617 GNUNET_STRINGS_absolute_time_to_string (
618 GNUNET_TIME_absolute_ntoh (
619 size_estimate_messages[idx].timestamp)),
620 GNUNET_i2s (peer_entry->id),
621 (unsigned int) ntohl (size_estimate_messages[idx].matching_bits));
622 if (0 == ntohl (size_estimate_messages[idx].hop_count))
623 GNUNET_STATISTICS_update (stats, "# flood messages started", 1, GNUNET_NO);
624 GNUNET_STATISTICS_update (stats,
625 "# flood messages transmitted",
626 1,
627 GNUNET_NO);
628#if ENABLE_NSE_HISTOGRAM
629 peer_entry->transmitted_messages++;
630 peer_entry->last_transmitted_size =
631 ntohl (size_estimate_messages[idx].matching_bits);
632#endif
633 env = GNUNET_MQ_msg_copy (&size_estimate_messages[idx].header);
634 GNUNET_MQ_send (peer_entry->mq, env);
635}
636
637
638/**
639 * We've sent on our flood message or one that we received which was
640 * validated and closer than ours. Update the global list of recent
641 * messages and the average. Also re-broadcast the message to any
642 * clients.
643 */
644static void
645update_network_size_estimate ()
646{
647 struct GNUNET_NSE_ClientMessage em;
648
649 setup_estimate_message (&em);
650 GNUNET_notification_context_broadcast (nc, &em.header, GNUNET_YES);
651}
652
653
654/**
655 * Setup a flood message in our history array at the given
656 * slot offset for the given timestamp.
657 *
658 * @param slot index to use
659 * @param ts timestamp to use
660 */
661static void
662setup_flood_message (unsigned int slot, struct GNUNET_TIME_Absolute ts)
663{
664 struct GNUNET_NSE_FloodMessage *fm;
665 uint32_t matching_bits;
666
667 matching_bits = get_matching_bits (ts, &my_identity);
668 fm = &size_estimate_messages[slot];
669 fm->header.size = htons (sizeof(struct GNUNET_NSE_FloodMessage));
670 fm->header.type = htons (GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD);
671 fm->hop_count = htonl (0);
672 fm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_NSE_SEND);
673 fm->purpose.size =
674 htonl (sizeof(struct GNUNET_NSE_FloodMessage)
675 - sizeof(struct GNUNET_MessageHeader) - sizeof(uint32_t)
676 - sizeof(struct GNUNET_CRYPTO_EddsaSignature));
677 fm->matching_bits = htonl (matching_bits);
678 fm->timestamp = GNUNET_TIME_absolute_hton (ts);
679 fm->origin = my_identity;
680 fm->proof_of_work = my_proof;
681 if (nse_work_required > 0)
682 GNUNET_assert (GNUNET_OK ==
683 GNUNET_CRYPTO_eddsa_sign_ (my_private_key,
684 &fm->purpose,
685 &fm->signature));
686 else
687 memset (&fm->signature, 0, sizeof(fm->signature));
688}
689
690
691/**
692 * Schedule transmission for the given peer for the current round based
693 * on what we know about the desired delay.
694 *
695 * @param cls unused
696 * @param key hash of peer identity
697 * @param value the `struct NSEPeerEntry`
698 * @return #GNUNET_OK (continue to iterate)
699 */
700static int
701schedule_current_round (void *cls,
702 const struct GNUNET_PeerIdentity *key,
703 void *value)
704{
705 struct NSEPeerEntry *peer_entry = value;
706 struct GNUNET_TIME_Relative delay;
707
708 (void) cls;
709 (void) key;
710 if (NULL != peer_entry->transmit_task)
711 {
712 GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
713 peer_entry->previous_round = GNUNET_NO;
714 }
715#if ENABLE_NSE_HISTOGRAM
716 if (peer_entry->received_messages > 1)
717 GNUNET_STATISTICS_update (stats,
718 "# extra messages",
719 peer_entry->received_messages - 1,
720 GNUNET_NO);
721 peer_entry->transmitted_messages = 0;
722 peer_entry->last_transmitted_size = 0;
723 peer_entry->received_messages = 0;
724#endif
725 delay =
726 get_transmit_delay ((GNUNET_NO == peer_entry->previous_round) ? -1 : 0);
727 peer_entry->transmit_task =
728 GNUNET_SCHEDULER_add_delayed (delay, &transmit_task_cb, peer_entry);
729 return GNUNET_OK;
730}
731
732
733/**
734 * Update our flood message to be sent (and our timestamps).
735 *
736 * @param cls unused
737 */
738static void
739update_flood_message (void *cls)
740{
741 struct GNUNET_TIME_Relative offset;
742
743 (void) cls;
744 flood_task = NULL;
745 offset = GNUNET_TIME_absolute_get_remaining (next_timestamp);
746 if (0 != offset.rel_value_us)
747 {
748 /* somehow run early, delay more */
749 flood_task =
750 GNUNET_SCHEDULER_add_delayed (offset, &update_flood_message, NULL);
751 return;
752 }
753 estimate_index = (estimate_index + 1) % HISTORY_SIZE;
754 if (estimate_count < HISTORY_SIZE)
755 estimate_count++;
756 current_timestamp = next_timestamp;
757 next_timestamp =
758 GNUNET_TIME_absolute_add (current_timestamp, gnunet_nse_interval);
759 if ((current_timestamp.abs_value_us ==
760 GNUNET_TIME_absolute_ntoh (next_message.timestamp).abs_value_us) &&
761 (get_matching_bits (current_timestamp, &my_identity) <
762 ntohl (next_message.matching_bits)))
763 {
764 /* we received a message for this round way early, use it! */
765 size_estimate_messages[estimate_index] = next_message;
766 size_estimate_messages[estimate_index].hop_count =
767 htonl (1 + ntohl (next_message.hop_count));
768 }
769 else
770 setup_flood_message (estimate_index, current_timestamp);
771 next_message.matching_bits = htonl (0); /* reset for 'next' round */
772 hop_count_max = 0;
773 for (unsigned int i = 0; i < HISTORY_SIZE; i++)
774 hop_count_max =
775 GNUNET_MAX (ntohl (size_estimate_messages[i].hop_count), hop_count_max);
776 GNUNET_CONTAINER_multipeermap_iterate (peers, &schedule_current_round, NULL);
777 flood_task =
778 GNUNET_SCHEDULER_add_at (next_timestamp, &update_flood_message, NULL);
779}
780
781
782/**
783 * Check whether the given public key and integer are a valid proof of
784 * work.
785 *
786 * @param pkey the public key
787 * @param val the integer
788 * @return #GNUNET_YES if valid, #GNUNET_NO if not
789 */
790static enum GNUNET_GenericReturnValue
791check_proof_of_work (const struct GNUNET_CRYPTO_EddsaPublicKey *pkey,
792 uint64_t val)
793{
794 char buf[sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)
795 + sizeof(val)] GNUNET_ALIGN;
796 struct GNUNET_HashCode result;
797
798 GNUNET_memcpy (buf, &val, sizeof(val));
799 GNUNET_memcpy (&buf[sizeof(val)],
800 pkey,
801 sizeof(struct GNUNET_CRYPTO_EddsaPublicKey));
802 GNUNET_CRYPTO_pow_hash (&salt,
803 buf,
804 sizeof(buf),
805 &result);
806 return (GNUNET_CRYPTO_hash_count_leading_zeros (&result) >=
807 nse_work_required)
808 ? GNUNET_YES
809 : GNUNET_NO;
810}
811
812
813/**
814 * Write our current proof to disk.
815 */
816static void
817write_proof (void)
818{
819 char *proof;
820
821 if (GNUNET_OK !=
822 GNUNET_CONFIGURATION_get_value_filename (cfg,
823 "NSE",
824 "PROOFFILE",
825 &proof))
826 return;
827 (void) GNUNET_DISK_directory_remove (proof);
828 if (GNUNET_OK !=
829 GNUNET_DISK_fn_write (proof,
830 &my_proof,
831 sizeof(my_proof),
832 GNUNET_DISK_PERM_USER_READ
833 | GNUNET_DISK_PERM_USER_WRITE))
834 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
835 "write",
836 proof);
837 GNUNET_free (proof);
838}
839
840
841/**
842 * Find our proof of work.
843 *
844 * @param cls closure (unused)
845 */
846static void
847find_proof (void *cls)
848{
849#define ROUND_SIZE 10
850 uint64_t counter;
851 char buf[sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)
852 + sizeof(uint64_t)] GNUNET_ALIGN;
853 struct GNUNET_HashCode result;
854 unsigned int i;
855
856 (void) cls;
857 proof_task = NULL;
858 GNUNET_memcpy (&buf[sizeof(uint64_t)],
859 &my_identity,
860 sizeof(struct GNUNET_PeerIdentity));
861 i = 0;
862 counter = my_proof;
863 while ((counter != UINT64_MAX) && (i < ROUND_SIZE))
864 {
865 GNUNET_memcpy (buf, &counter, sizeof(uint64_t));
866 GNUNET_CRYPTO_pow_hash (&salt,
867 buf,
868 sizeof(buf),
869 &result);
870 if (nse_work_required <=
871 GNUNET_CRYPTO_hash_count_leading_zeros (&result))
872 {
873 my_proof = counter;
874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
875 "Proof of work found: %llu!\n",
876 (unsigned long long) GNUNET_ntohll (counter));
877 write_proof ();
878 setup_flood_message (estimate_index, current_timestamp);
879 return;
880 }
881 counter++;
882 i++;
883 }
884 if (my_proof / (100 * ROUND_SIZE) < counter / (100 * ROUND_SIZE))
885 {
886 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
887 "Testing proofs currently at %llu\n",
888 (unsigned long long) counter);
889 /* remember progress every 100 rounds */
890 my_proof = counter;
891 write_proof ();
892 }
893 else
894 {
895 my_proof = counter;
896 }
897 proof_task =
898 GNUNET_SCHEDULER_add_delayed_with_priority (proof_find_delay,
899 GNUNET_SCHEDULER_PRIORITY_IDLE,
900 &find_proof,
901 NULL);
902}
903
904
905/**
906 * An incoming flood message has been received which claims
907 * to have more bits matching than any we know in this time
908 * period. Verify the signature and/or proof of work.
909 *
910 * @param incoming_flood the message to verify
911 * @return #GNUNET_YES if the message is verified
912 * #GNUNET_NO if the key/signature don't verify
913 */
914static int
915verify_message_crypto (const struct GNUNET_NSE_FloodMessage *incoming_flood)
916{
917 if (GNUNET_YES != check_proof_of_work (&incoming_flood->origin.public_key,
918 incoming_flood->proof_of_work))
919 {
920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
921 "Proof of work invalid: %llu!\n",
922 (unsigned long long) GNUNET_ntohll (
923 incoming_flood->proof_of_work));
924 GNUNET_break_op (0);
925 return GNUNET_NO;
926 }
927 if ((nse_work_required > 0) &&
928 (GNUNET_OK !=
929 GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_NSE_SEND,
930 &incoming_flood->purpose,
931 &incoming_flood->signature,
932 &incoming_flood->origin.public_key)))
933 {
934 GNUNET_break_op (0);
935 return GNUNET_NO;
936 }
937 return GNUNET_YES;
938}
939
940
941/**
942 * Update transmissions for the given peer for the current round based
943 * on updated proximity information.
944 *
945 * @param cls peer entry to exclude from updates
946 * @param key hash of peer identity
947 * @param value the `struct NSEPeerEntry *` of a peer to transmit to
948 * @return #GNUNET_OK (continue to iterate)
949 */
950static int
951update_flood_times (void *cls,
952 const struct GNUNET_PeerIdentity *key,
953 void *value)
954{
955 struct NSEPeerEntry *exclude = cls;
956 struct NSEPeerEntry *peer_entry = value;
957 struct GNUNET_TIME_Relative delay;
958
959 (void) key;
960 if (peer_entry == exclude)
961 return GNUNET_OK; /* trigger of the update */
962 if (GNUNET_NO == peer_entry->previous_round)
963 {
964 /* still stuck in previous round, no point to update, check that
965 * we are active here though... */
966 if (NULL == peer_entry->transmit_task)
967 {
968 GNUNET_break (0);
969 }
970 return GNUNET_OK;
971 }
972 if (NULL != peer_entry->transmit_task)
973 {
974 GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
975 peer_entry->transmit_task = NULL;
976 }
977 delay = get_transmit_delay (0);
978 peer_entry->transmit_task =
979 GNUNET_SCHEDULER_add_delayed (delay, &transmit_task_cb, peer_entry);
980 return GNUNET_OK;
981}
982
983
984/**
985 * Core handler for size estimate flooding messages.
986 *
987 * @param cls peer this message is from
988 * @param incoming_flood received message
989 */
990static void
991handle_p2p_estimate (void *cls,
992 const struct GNUNET_NSE_FloodMessage *incoming_flood)
993{
994 struct NSEPeerEntry *peer_entry = cls;
995 struct GNUNET_TIME_Absolute ts;
996 uint32_t matching_bits;
997 unsigned int idx;
998
999#if ENABLE_NSE_HISTOGRAM
1000 {
1001 uint64_t t;
1002
1003 t = GNUNET_TIME_absolute_get ().abs_value_us;
1004 if (NULL != lh)
1005 GNUNET_TESTBED_LOGGER_write (lh, &t, sizeof(uint64_t));
1006 if (NULL != histogram)
1007 GNUNET_BIO_write_int64 (histogram, "histogram-time", t);
1008 }
1009#endif
1010 GNUNET_STATISTICS_update (stats, "# flood messages received", 1, GNUNET_NO);
1011 matching_bits = ntohl (incoming_flood->matching_bits);
1012#if DEBUG_NSE
1013 {
1014 char origin[5];
1015 char pred[5];
1016 struct GNUNET_PeerIdentity os;
1017
1018 GNUNET_snprintf (origin,
1019 sizeof(origin),
1020 "%s",
1021 GNUNET_i2s (&incoming_flood->origin));
1022 GNUNET_snprintf (pred, sizeof(pred), "%s", GNUNET_i2s (peer_entry->id));
1023 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1024 "Flood at %s from `%s' via `%s' at `%s' with bits %u\n",
1025 GNUNET_STRINGS_absolute_time_to_string (
1026 GNUNET_TIME_absolute_ntoh (incoming_flood->timestamp)),
1027 origin,
1028 pred,
1029 GNUNET_i2s (&my_identity),
1030 (unsigned int) matching_bits);
1031 }
1032#endif
1033
1034#if ENABLE_NSE_HISTOGRAM
1035 peer_entry->received_messages++;
1036 if ((peer_entry->transmitted_messages > 0) &&
1037 (peer_entry->last_transmitted_size >= matching_bits) )
1038 GNUNET_STATISTICS_update (stats, "# cross messages", 1, GNUNET_NO);
1039#endif
1040
1041 ts = GNUNET_TIME_absolute_ntoh (incoming_flood->timestamp);
1042 if (ts.abs_value_us == current_timestamp.abs_value_us)
1043 idx = estimate_index;
1044 else if (ts.abs_value_us ==
1045 current_timestamp.abs_value_us - gnunet_nse_interval.rel_value_us)
1046 idx = (estimate_index + HISTORY_SIZE - 1) % HISTORY_SIZE;
1047 else if (ts.abs_value_us == next_timestamp.abs_value_us)
1048 {
1049 if (matching_bits <= ntohl (next_message.matching_bits))
1050 return; /* ignore, simply too early/late */
1051 if (GNUNET_YES != verify_message_crypto (incoming_flood))
1052 {
1053 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1054 "Peer %s is likely ill-configured!\n",
1055 GNUNET_i2s (peer_entry->id));
1056 GNUNET_break_op (0);
1057 return;
1058 }
1059 next_message = *incoming_flood;
1060 return;
1061 }
1062 else
1063 {
1064 GNUNET_STATISTICS_update (stats,
1065 "# flood messages discarded (clock skew too large)",
1066 1,
1067 GNUNET_NO);
1068 return;
1069 }
1070 if (0 == (GNUNET_memcmp (peer_entry->id, &my_identity)))
1071 {
1072 /* send to self, update our own estimate IF this also comes from us! */
1073 if (0 == GNUNET_memcmp (&incoming_flood->origin, &my_identity))
1074 update_network_size_estimate ();
1075 return;
1076 }
1077 if (matching_bits == ntohl (size_estimate_messages[idx].matching_bits))
1078 {
1079 /* Cancel transmission in the other direction, as this peer clearly has
1080 up-to-date information already. Even if we didn't talk to this peer in
1081 the previous round, we should no longer send it stale information as it
1082 told us about the current round! */
1083 peer_entry->previous_round = GNUNET_YES;
1084 if (idx != estimate_index)
1085 {
1086 /* do not transmit information for the previous round to this peer
1087 anymore (but allow current round) */
1088 return;
1089 }
1090 /* got up-to-date information for current round, cancel transmission to
1091 * this peer altogether */
1092 if (NULL != peer_entry->transmit_task)
1093 {
1094 GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
1095 peer_entry->transmit_task = NULL;
1096 }
1097 return;
1098 }
1099 if (matching_bits < ntohl (size_estimate_messages[idx].matching_bits))
1100 {
1101 if ((idx < estimate_index) && (peer_entry->previous_round == GNUNET_YES))
1102 {
1103 peer_entry->previous_round = GNUNET_NO;
1104 }
1105 /* push back our result now, that peer is spreading bad information... */
1106 if (NULL != peer_entry->transmit_task)
1107 GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
1108 peer_entry->transmit_task =
1109 GNUNET_SCHEDULER_add_now (&transmit_task_cb, peer_entry);
1110 /* Not closer than our most recent message, no need to do work here */
1111 GNUNET_STATISTICS_update (stats,
1112 "# flood messages ignored (had closer already)",
1113 1,
1114 GNUNET_NO);
1115 return;
1116 }
1117 if (GNUNET_YES != verify_message_crypto (incoming_flood))
1118 {
1119 GNUNET_break_op (0);
1120 return;
1121 }
1122 GNUNET_assert (matching_bits >
1123 ntohl (size_estimate_messages[idx].matching_bits));
1124 /* Cancel transmission in the other direction, as this peer clearly has
1125 * up-to-date information already.
1126 */
1127 peer_entry->previous_round = GNUNET_YES;
1128 if (idx == estimate_index)
1129 {
1130 /* cancel any activity for current round */
1131 if (NULL != peer_entry->transmit_task)
1132 {
1133 GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
1134 peer_entry->transmit_task = NULL;
1135 }
1136 }
1137 size_estimate_messages[idx] = *incoming_flood;
1138 size_estimate_messages[idx].hop_count =
1139 htonl (ntohl (incoming_flood->hop_count) + 1);
1140 hop_count_max =
1141 GNUNET_MAX (ntohl (incoming_flood->hop_count) + 1, hop_count_max);
1142 GNUNET_STATISTICS_set (stats,
1143 "# estimated network diameter",
1144 hop_count_max,
1145 GNUNET_NO);
1146
1147 /* have a new, better size estimate, inform clients */
1148 update_network_size_estimate ();
1149
1150 /* flood to rest */
1151 GNUNET_CONTAINER_multipeermap_iterate (peers,
1152 &update_flood_times,
1153 peer_entry);
1154}
1155
1156
1157/**
1158 * Method called whenever a peer connects. Sets up the PeerEntry and
1159 * schedules the initial size info transmission to this peer.
1160 *
1161 * @param cls closure
1162 * @param peer peer identity this notification is about
1163 */
1164static void *
1165handle_core_connect (void *cls,
1166 const struct GNUNET_PeerIdentity *peer,
1167 struct GNUNET_MQ_Handle *mq)
1168{
1169 struct NSEPeerEntry *peer_entry;
1170
1171 (void) cls;
1172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1173 "Peer `%s' connected to us\n",
1174 GNUNET_i2s (peer));
1175 /* set our default transmission options */
1176 GNUNET_MQ_set_options (mq, NSE_PRIORITY);
1177 /* create our peer entry for this peer */
1178 peer_entry = GNUNET_new (struct NSEPeerEntry);
1179 peer_entry->id = peer;
1180 peer_entry->mq = mq;
1181 GNUNET_assert (GNUNET_OK ==
1182 GNUNET_CONTAINER_multipeermap_put (
1183 peers,
1184 peer_entry->id,
1185 peer_entry,
1186 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1187 peer_entry->transmit_task =
1188 GNUNET_SCHEDULER_add_delayed (get_transmit_delay (-1),
1189 &transmit_task_cb,
1190 peer_entry);
1191 GNUNET_STATISTICS_update (stats, "# peers connected", 1, GNUNET_NO);
1192 return peer_entry;
1193}
1194
1195
1196/**
1197 * Method called whenever a peer disconnects. Deletes the PeerEntry and cancels
1198 * any pending transmission requests to that peer.
1199 *
1200 * @param cls closure
1201 * @param peer peer identity this notification is about
1202 * @parma internal_cls the `struct NSEPeerEntry` for the @a peer
1203 */
1204static void
1205handle_core_disconnect (void *cls,
1206 const struct GNUNET_PeerIdentity *peer,
1207 void *internal_cls)
1208{
1209 struct NSEPeerEntry *pos = internal_cls;
1210
1211 (void) cls;
1212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1213 "Peer `%s' disconnected from us\n",
1214 GNUNET_i2s (peer));
1215 GNUNET_assert (GNUNET_YES ==
1216 GNUNET_CONTAINER_multipeermap_remove (peers, peer, pos));
1217 if (NULL != pos->transmit_task)
1218 {
1219 GNUNET_SCHEDULER_cancel (pos->transmit_task);
1220 pos->transmit_task = NULL;
1221 }
1222 GNUNET_free (pos);
1223 GNUNET_STATISTICS_update (stats, "# peers connected", -1, GNUNET_NO);
1224}
1225
1226
1227#if ENABLE_NSE_HISTOGRAM
1228/**
1229 * Functions of this type are called to notify a successful transmission of the
1230 * message to the logger service
1231 *
1232 * @param cls NULL
1233 * @param size the amount of data sent (ignored)
1234 */
1235static void
1236flush_comp_cb (void *cls, size_t size)
1237{
1238 (void) cls;
1239 (void) size;
1240 GNUNET_TESTBED_LOGGER_disconnect (lh);
1241 lh = NULL;
1242}
1243
1244
1245#endif
1246
1247
1248/**
1249 * Task run during shutdown.
1250 *
1251 * @param cls unused
1252 */
1253static void
1254shutdown_task (void *cls)
1255{
1256 (void) cls;
1257 if (NULL != flood_task)
1258 {
1259 GNUNET_SCHEDULER_cancel (flood_task);
1260 flood_task = NULL;
1261 }
1262 if (NULL != proof_task)
1263 {
1264 GNUNET_SCHEDULER_cancel (proof_task);
1265 proof_task = NULL;
1266 write_proof (); /* remember progress */
1267 }
1268 if (NULL != nc)
1269 {
1270 GNUNET_notification_context_destroy (nc);
1271 nc = NULL;
1272 }
1273 if (NULL != core_api)
1274 {
1275 GNUNET_CORE_disconnect (core_api);
1276 core_api = NULL;
1277 }
1278 if (NULL != stats)
1279 {
1280 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
1281 stats = NULL;
1282 }
1283 if (NULL != peers)
1284 {
1285 GNUNET_CONTAINER_multipeermap_destroy (peers);
1286 peers = NULL;
1287 }
1288 if (NULL != my_private_key)
1289 {
1290 GNUNET_free (my_private_key);
1291 my_private_key = NULL;
1292 }
1293#if ENABLE_NSE_HISTOGRAM
1294 if (NULL != logger_test)
1295 {
1296 GNUNET_CLIENT_service_test_cancel (logger_test);
1297 logger_test = NULL;
1298 }
1299 if (NULL != lh)
1300 {
1301 GNUNET_TESTBED_LOGGER_flush (lh, &flush_comp_cb, NULL);
1302 }
1303 if (NULL != histogram)
1304 {
1305 GNUNET_BIO_write_close (histogram, NULL);
1306 histogram = NULL;
1307 }
1308#endif
1309}
1310
1311
1312/**
1313 * Called on core init/fail.
1314 *
1315 * @param cls service closure
1316 * @param identity the public identity of this peer
1317 */
1318static void
1319core_init (void *cls, const struct GNUNET_PeerIdentity *identity)
1320{
1321 struct GNUNET_TIME_Absolute now;
1322 struct GNUNET_TIME_Absolute prev_time;
1323
1324 (void) cls;
1325 if (NULL == identity)
1326 {
1327 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connection to core FAILED!\n");
1328 GNUNET_SCHEDULER_shutdown ();
1329 return;
1330 }
1331 GNUNET_assert (0 == GNUNET_memcmp (&my_identity, identity));
1332 now = GNUNET_TIME_absolute_get ();
1333 current_timestamp.abs_value_us =
1334 (now.abs_value_us / gnunet_nse_interval.rel_value_us)
1335 * gnunet_nse_interval.rel_value_us;
1336 next_timestamp =
1337 GNUNET_TIME_absolute_add (current_timestamp, gnunet_nse_interval);
1338 estimate_index = HISTORY_SIZE - 1;
1339 estimate_count = 0;
1340 if (GNUNET_YES == check_proof_of_work (&my_identity.public_key, my_proof))
1341 {
1342 int idx = (estimate_index + HISTORY_SIZE - 1) % HISTORY_SIZE;
1343 prev_time.abs_value_us =
1344 current_timestamp.abs_value_us - gnunet_nse_interval.rel_value_us;
1345 setup_flood_message (idx, prev_time);
1346 setup_flood_message (estimate_index, current_timestamp);
1347 estimate_count++;
1348 }
1349 flood_task =
1350 GNUNET_SCHEDULER_add_at (next_timestamp, &update_flood_message, NULL);
1351}
1352
1353
1354#if ENABLE_NSE_HISTOGRAM
1355/**
1356 * Function called with the status of the testbed logger service
1357 *
1358 * @param cls NULL
1359 * @param status #GNUNET_YES if the service is running,
1360 * #GNUNET_NO if the service is not running
1361 * #GNUNET_SYSERR if the configuration is invalid
1362 */
1363static void
1364status_cb (void *cls, int status)
1365{
1366 (void) cls;
1367 logger_test = NULL;
1368 if (GNUNET_YES != status)
1369 {
1370 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Testbed logger not running\n");
1371 return;
1372 }
1373 if (NULL == (lh = GNUNET_TESTBED_LOGGER_connect (cfg)))
1374 {
1375 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1376 "Cannot connect to the testbed logger. Exiting.\n");
1377 GNUNET_SCHEDULER_shutdown ();
1378 }
1379}
1380
1381
1382#endif
1383
1384
1385/**
1386 * Handle network size estimate clients.
1387 *
1388 * @param cls closure
1389 * @param c configuration to use
1390 * @param service the initialized service
1391 */
1392static void
1393run (void *cls,
1394 const struct GNUNET_CONFIGURATION_Handle *c,
1395 struct GNUNET_SERVICE_Handle *service)
1396{
1397 struct GNUNET_MQ_MessageHandler core_handlers[] =
1398 { GNUNET_MQ_hd_fixed_size (p2p_estimate,
1399 GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD,
1400 struct GNUNET_NSE_FloodMessage,
1401 NULL),
1402 GNUNET_MQ_handler_end () };
1403 char *proof;
1404 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
1405
1406 (void) cls;
1407 (void) service;
1408 cfg = c;
1409 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
1410 "NSE",
1411 "INTERVAL",
1412 &gnunet_nse_interval))
1413 {
1414 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "INTERVAL");
1415 GNUNET_SCHEDULER_shutdown ();
1416 return;
1417 }
1418 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
1419 "NSE",
1420 "WORKDELAY",
1421 &proof_find_delay))
1422 {
1423 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "WORKDELAY");
1424 GNUNET_SCHEDULER_shutdown ();
1425 return;
1426 }
1427 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
1428 "NSE",
1429 "WORKBITS",
1430 &nse_work_required))
1431 {
1432 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "WORKBITS");
1433 GNUNET_SCHEDULER_shutdown ();
1434 return;
1435 }
1436 if (nse_work_required >= sizeof(struct GNUNET_HashCode) * 8)
1437 {
1438 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1439 "NSE",
1440 "WORKBITS",
1441 _ ("Value is too large.\n"));
1442 GNUNET_SCHEDULER_shutdown ();
1443 return;
1444 }
1445
1446#if ENABLE_NSE_HISTOGRAM
1447 {
1448 char *histogram_dir;
1449 char *histogram_fn;
1450
1451 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg,
1452 "NSE",
1453 "HISTOGRAM_DIR",
1454 &histogram_dir))
1455 {
1456 GNUNET_assert (
1457 0 < GNUNET_asprintf (&histogram_fn, "%s/timestamps", histogram_dir));
1458 GNUNET_free (histogram_dir);
1459 histogram = GNUNET_BIO_write_open_file (histogram_fn);
1460 if (NULL == histogram)
1461 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1462 "Unable to open histogram file `%s'\n",
1463 histogram_fn);
1464 GNUNET_free (histogram_fn);
1465 }
1466 logger_test = GNUNET_CLIENT_service_test ("testbed-logger",
1467 cfg,
1468 GNUNET_TIME_UNIT_SECONDS,
1469 &status_cb,
1470 NULL);
1471 }
1472#endif
1473
1474 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1475 pk = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
1476 GNUNET_assert (NULL != pk);
1477 my_private_key = pk;
1478 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_identity.public_key);
1479 if (GNUNET_OK !=
1480 GNUNET_CONFIGURATION_get_value_filename (cfg, "NSE", "PROOFFILE", &proof))
1481 {
1482 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "PROOFFILE");
1483 GNUNET_free (my_private_key);
1484 my_private_key = NULL;
1485 GNUNET_SCHEDULER_shutdown ();
1486 return;
1487 }
1488 if ((GNUNET_YES != GNUNET_DISK_file_test (proof)) ||
1489 (sizeof(my_proof) !=
1490 GNUNET_DISK_fn_read (proof, &my_proof, sizeof(my_proof))))
1491 my_proof = 0;
1492 GNUNET_free (proof);
1493 proof_task =
1494 GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
1495 &find_proof,
1496 NULL);
1497
1498 peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES);
1499 nc = GNUNET_notification_context_create (1);
1500 /* Connect to core service and register core handlers */
1501 core_api =
1502 GNUNET_CORE_connect (cfg, /* Main configuration */
1503 NULL, /* Closure passed to functions */
1504 &core_init, /* Call core_init once connected */
1505 &handle_core_connect, /* Handle connects */
1506 &handle_core_disconnect, /* Handle disconnects */
1507 core_handlers); /* Register these handlers */
1508 if (NULL == core_api)
1509 {
1510 GNUNET_SCHEDULER_shutdown ();
1511 return;
1512 }
1513 stats = GNUNET_STATISTICS_create ("nse", cfg);
1514}
1515
1516
1517/**
1518 * Callback called when a client connects to the service.
1519 *
1520 * @param cls closure for the service
1521 * @param c the new client that connected to the service
1522 * @param mq the message queue used to send messages to the client
1523 * @return @a c
1524 */
1525static void *
1526client_connect_cb (void *cls,
1527 struct GNUNET_SERVICE_Client *c,
1528 struct GNUNET_MQ_Handle *mq)
1529{
1530 (void) cls;
1531 (void) mq;
1532 return c;
1533}
1534
1535
1536/**
1537 * Callback called when a client disconnected from the service
1538 *
1539 * @param cls closure for the service
1540 * @param c the client that disconnected
1541 * @param internal_cls should be equal to @a c
1542 */
1543static void
1544client_disconnect_cb (void *cls,
1545 struct GNUNET_SERVICE_Client *c,
1546 void *internal_cls)
1547{
1548 (void) cls;
1549 GNUNET_assert (c == internal_cls);
1550}
1551
1552
1553/**
1554 * Define "main" method using service macro.
1555 */
1556GNUNET_SERVICE_MAIN ("nse",
1557 GNUNET_SERVICE_OPTION_NONE,
1558 &run,
1559 &client_connect_cb,
1560 &client_disconnect_cb,
1561 NULL,
1562 GNUNET_MQ_hd_fixed_size (start,
1563 GNUNET_MESSAGE_TYPE_NSE_START,
1564 struct GNUNET_MessageHeader,
1565 NULL),
1566 GNUNET_MQ_handler_end ());
1567
1568
1569#if defined(__linux__) && defined(__GLIBC__)
1570#include <malloc.h>
1571
1572/**
1573 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
1574 */
1575void __attribute__ ((constructor))
1576GNUNET_ARM_memory_init ()
1577{
1578 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1579 mallopt (M_TOP_PAD, 1 * 1024);
1580 malloc_trim (0);
1581}
1582
1583
1584#endif
1585
1586
1587/* 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]
2START_ON_DEMAND = @START_ON_DEMAND@
3IMMEDIATE_START = YES
4@JAVAPORT@PORT = 2097
5HOSTNAME = localhost
6BINARY = gnunet-service-nse
7ACCEPT_FROM = 127.0.0.1;
8ACCEPT_FROM6 = ::1;
9UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-nse.sock
10UNIX_MATCH_UID = NO
11UNIX_MATCH_GID = YES
12PROOFFILE = $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.
17HISTOGRAM_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.
24WORKDELAY = 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!
32INTERVAL = 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!
38WORKBITS = 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
33GNUNET_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 */
42struct 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};
71GNUNET_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 */
40struct 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 */
79static void
80reconnect (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 */
92static void
93mq_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 */
113static void
114handle_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 */
131static void
132reconnect (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 */
164struct GNUNET_NSE_Handle *
165GNUNET_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 */
192void
193GNUNET_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]
2GNUNET_TEST_HOME = $GNUNET_TMP/nse-profiler/
3
4[testbed]
5START_ON_DEMAND = NO
6ORT = 12113
7ACCEPT_FROM = 127.0.0.1; 10.6.0.0/16; 192.168.0.0/16;
8HOSTNAME = localhost
9MAX_PARALLEL_OPERATIONS = 400
10OVERLAY_TOPOLOGY = 2D_TORUS
11OVERLAY_RANDOM_LINKS = 1000
12OPERATION_TIMEOUT = 45 s
13SETUP_TIMEOUT = 30m
14STATS_DIR= /home/totakura/nse/test/load
15
16[nse]
17IMMEDIATE_START = YES
18# Overriding network settings for faster testing (do NOT use
19# these values in production just because they are here)
20WORKDELAY = 60 s
21INTERVAL = 10 s
22WORKBITS = 0
23PROOFFILE = $GNUNET_TEST_HOME/nse.proof
24HISTOGRAM_DIR = /home/totakura/nse/test/histograms
25
26[nat]
27DISABLEV6 = YES
28BINDTO = 127.0.0.1
29ENABLE_UPNP = NO
30BEHIND_NAT = NO
31ALLOW_NAT = NO
32INTERNAL_ADDRESS = 127.0.0.1
33EXTERNAL_ADDRESS = 127.0.0.1
34
35[transport]
36plugins = udp
37
38[transport-udp]
39PORT = 12116
40
41[nse-profiler]
42OUTPUT_FILE = nse_output_2000_peers.dat
43TOPOLOGY_OUTPUT_FILE = nse_topo_2000_peers
44DATA_OUTPUT_FILE = nse_stats_2000_peers
45ROUND0 = 1000
46#ROUND1 = 2000
47ROUND2 = 2000
48ROUND3 = 2000
49ROUND4 = 2000
50ROUND5 = 2000
51ROUND6 = 2000
52ROUND7 = 2000
53ROUND8 = 2000
54ROUND9 = 2000
55ROUND10 = 2000
56ROUND11 = 1000
57ROUND12 = 1000
58ROUND13 = 1000
59ROUND14 = 1000
60ROUND15 = 1000
61ROUND16 = 1000
62ROUND17 = 1000
63ROUND18 = 1000
64ROUND19 = 1000
65ROUND20 = 1000
66ROUND21 = 2000
67ROUND22 = 2000
68ROUND23 = 2000
69ROUND24 = 2000
70ROUND25 = 2000
71ROUND26 = 2000
72ROUND27 = 2000
73ROUND28 = 2000
74ROUND29 = 2000
75ROUND30 = 2000
76WAIT_TIME = 1920 s
77CONNECTION_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]
2GNUNET_TEST_HOME = $GNUNET_TMP/nse-profiler/
3
4[testbed]
5START_ON_DEMAND = NO
6PORT = 12113
7ACCEPT_FROM = 127.0.0.1; 10.6.0.0/16;
8HOSTNAME = localhost
9MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 5
10OVERLAY_TOPOLOGY = RANDOM
11OVERLAY_RANDOM_LINKS = 1000
12OPERATION_TIMEOUT = 45 s
13
14[nse]
15IMMEDIATE_START = YES
16START_ON_DEMAND = NO
17# Overriding network settings for faster testing (do NOT use
18# these values in production just because they are here)
19WORKDELAY = 60 s
20INTERVAL = 10 s
21WORKBITS = 0
22PROOFFILE = $GNUNET_TEST_HOME/nse.proof
23
24[nat]
25DISABLEV6 = YES
26BINDTO = 127.0.0.1
27ENABLE_UPNP = NO
28BEHIND_NAT = NO
29ALLOW_NAT = NO
30INTERNAL_ADDRESS = 127.0.0.1
31EXTERNAL_ADDRESS = 127.0.0.1
32
33[transport]
34plugins = udp
35
36[nse-profiler]
37OUTPUT_FILE = nse_output_2000_peers.dat
38TOPOLOGY_OUTPUT_FILE = nse_topo_2000_peers
39DATA_OUTPUT_FILE = nse_stats_2000_peers
40ROUND0 = 1000
41#ROUND1 = 2000
42ROUND2 = 2000
43ROUND3 = 2000
44ROUND4 = 2000
45ROUND5 = 2000
46ROUND6 = 2000
47ROUND7 = 2000
48ROUND8 = 2000
49ROUND9 = 2000
50ROUND10 = 2000
51ROUND11 = 1000
52ROUND12 = 1000
53ROUND13 = 1000
54ROUND14 = 1000
55ROUND15 = 1000
56ROUND16 = 1000
57ROUND17 = 1000
58ROUND18 = 1000
59ROUND19 = 1000
60ROUND20 = 1000
61ROUND21 = 2000
62ROUND22 = 2000
63ROUND23 = 2000
64ROUND24 = 2000
65ROUND25 = 2000
66ROUND26 = 2000
67ROUND27 = 2000
68ROUND28 = 2000
69ROUND29 = 2000
70ROUND30 = 2000
71WAIT_TIME = 1920 s
72CONNECTION_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
32static void
33perfHash ()
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
48int
49main (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]
5GNUNET_TEST_HOME = $GNUNET_TMP/test-nse-multipeer/
6
7[nse]
8#PREFIX = valgrind --leak-check=full --log-file=valgrind_nse.%p
9IMMEDIATE_START = YES
10PROOFFILE = $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)
13WORKDELAY = 1 ms
14INTERVAL = 60 s
15WORKBITS = 1
16HISTOGRAM = $GNUNET_TEST_HOME/nse-histogram
17
18[nat]
19DISABLEV6 = YES
20BINDTO = 127.0.0.1
21ENABLE_UPNP = NO
22BEHIND_NAT = NO
23ALLOW_NAT = NO
24INTERNAL_ADDRESS = 127.0.0.1
25EXTERNAL_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
30static struct GNUNET_NSE_Handle *h;
31
32static struct GNUNET_SCHEDULER_Task *die_task;
33
34
35/**
36 * Signature of the main function of a task.
37 *
38 * @param cls closure
39 */
40static void
41end_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 */
61static void
62check_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
78static void
79run (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
94int
95main (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 */
46struct 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 */
63static struct NSEPeer nse_peers[NUM_PEERS];
64
65/**
66 * Return value from 'main'.
67 */
68static int ok;
69
70
71/**
72 * Task run on timeout to shut everything down.
73 */
74static void
75shutdown_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 */
95static void
96handle_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 */
120static void
121nse_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 */
153static void *
154nse_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 */
170static void
171nse_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 */
190static void
191run (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 */
222int
223main (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 */