aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dht/Makefile.am73
-rw-r--r--src/dht/dht.conf.in10
-rw-r--r--src/dht/test_dht_2dtorus.conf67
-rw-r--r--src/dht/test_dht_line.conf67
-rw-r--r--src/dht/test_dht_monitor.c235
-rw-r--r--src/dht/test_dht_multipeer.c859
-rw-r--r--src/dht/test_dht_multipeer.conf (renamed from src/dht/test_dht_twopeer_data.conf)47
-rw-r--r--src/dht/test_dht_multipeer_data.conf130
-rw-r--r--src/dht/test_dht_multipeer_topology.dat (renamed from src/dht/multipeer_topo.dat)0
-rw-r--r--src/dht/test_dht_topo.c160
-rw-r--r--src/dht/test_dht_twopeer.c494
-rw-r--r--src/dht/test_dht_twopeer_get_put.c590
-rw-r--r--src/dht/test_dht_twopeer_path_tracking.c522
-rw-r--r--src/dht/test_dht_twopeer_put_get.c510
14 files changed, 216 insertions, 3548 deletions
diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am
index 982c33815..0baf6b00e 100644
--- a/src/dht/Makefile.am
+++ b/src/dht/Makefile.am
@@ -123,27 +123,23 @@ libgnunetdhttest_a_DEPENDENCIES = \
123check_PROGRAMS = \ 123check_PROGRAMS = \
124 test_dht_api \ 124 test_dht_api \
125 test_dht_twopeer \ 125 test_dht_twopeer \
126 test_dht_twopeer_put_get \
127 test_dht_twopeer_get_put \
128 test_dht_twopeer_path_tracking \
129 test_dht_multipeer \ 126 test_dht_multipeer \
130 test_dht_line \ 127 test_dht_line \
131 test_dht_2dtorus \ 128 test_dht_2dtorus
132 test_dht_monitor 129# test_dht_monitor
133 130
134if HAVE_EXPERIMENTAL 131if HAVE_EXPERIMENTAL
135 NEW_TESTS = test_dht_line test_dht_2dtorus 132# These tests still do not work as testbed does
133# not support the respective topology op
134 NEW_TESTS = test_dht_2dtorus test_dht_multipeer
136endif 135endif
137 136
138if ENABLE_TEST_RUN 137if ENABLE_TEST_RUN
139TESTS = test_dht_api $(check_SCRIPTS) \ 138TESTS = test_dht_api $(check_SCRIPTS) \
140 test_dht_twopeer \ 139 test_dht_twopeer \
141 test_dht_twopeer_put_get \ 140 test_dht_line \
142 test_dht_twopeer_get_put \ 141 $(NEW_TESTS)
143 test_dht_twopeer_path_tracking \ 142# test_dht_monitor
144 test_dht_multipeer \
145 $(NEW_TESTS) \
146 test_dht_monitor
147endif 143endif
148 144
149test_dht_api_SOURCES = \ 145test_dht_api_SOURCES = \
@@ -156,9 +152,8 @@ test_dht_api_LDADD = \
156test_dht_api_DEPENDENCIES = \ 152test_dht_api_DEPENDENCIES = \
157 libgnunetdht.la 153 libgnunetdht.la
158 154
159# twopeer is obsolete once new test_dht_topo works...
160test_dht_twopeer_SOURCES = \ 155test_dht_twopeer_SOURCES = \
161 test_dht_twopeer.c 156 test_dht_topo.c
162test_dht_twopeer_LDADD = \ 157test_dht_twopeer_LDADD = \
163 $(top_builddir)/src/util/libgnunetutil.la \ 158 $(top_builddir)/src/util/libgnunetutil.la \
164 $(top_builddir)/src/testing_old/libgnunettesting_old.la \ 159 $(top_builddir)/src/testing_old/libgnunettesting_old.la \
@@ -166,42 +161,6 @@ test_dht_twopeer_LDADD = \
166test_dht_twopeer_DEPENDENCIES = \ 161test_dht_twopeer_DEPENDENCIES = \
167 libgnunetdht.la 162 libgnunetdht.la
168 163
169# twopeer_put_get is obsolete once new test_dht_topo works...
170test_dht_twopeer_put_get_SOURCES = \
171 test_dht_twopeer_put_get.c
172test_dht_twopeer_put_get_LDADD = \
173 $(top_builddir)/src/util/libgnunetutil.la \
174 $(top_builddir)/src/testing_old/libgnunettesting_old.la \
175 $(top_builddir)/src/dht/libgnunetdht.la
176
177# twopeer_get_put is obsolete once new test_dht_topo works...
178test_dht_twopeer_get_put_SOURCES = \
179 test_dht_twopeer_get_put.c
180test_dht_twopeer_get_put_LDADD = \
181 $(top_builddir)/src/util/libgnunetutil.la \
182 $(top_builddir)/src/testing_old/libgnunettesting_old.la \
183 $(top_builddir)/src/dht/libgnunetdht.la
184
185# twopeer_path_tracking is obsolete once new test_dht_topo works...
186test_dht_twopeer_path_tracking_SOURCES = \
187 test_dht_twopeer_path_tracking.c
188test_dht_twopeer_path_tracking_LDADD = \
189 $(top_builddir)/src/util/libgnunetutil.la \
190 $(top_builddir)/src/testing_old/libgnunettesting_old.la \
191 $(top_builddir)/src/dht/libgnunetdht.la
192
193# statistics functions should be integrated with test_dht_topo,
194# then this one also becomes obsolete...
195test_dht_multipeer_SOURCES = \
196 test_dht_multipeer.c
197test_dht_multipeer_LDADD = \
198 $(top_builddir)/src/util/libgnunetutil.la \
199 $(top_builddir)/src/statistics/libgnunetstatistics.la \
200 $(top_builddir)/src/testing_old/libgnunettesting_old.la \
201 $(top_builddir)/src/dht/libgnunetdht.la
202test_dht_multipeer_DEPENDENCIES = \
203 libgnunetdht.la
204
205test_dht_2dtorus_SOURCES = \ 164test_dht_2dtorus_SOURCES = \
206 test_dht_topo.c 165 test_dht_topo.c
207test_dht_2dtorus_LDADD = \ 166test_dht_2dtorus_LDADD = \
@@ -222,6 +181,16 @@ test_dht_line_LDADD = \
222test_dht_line_DEPENDENCIES = \ 181test_dht_line_DEPENDENCIES = \
223 libgnunetdht.la 182 libgnunetdht.la
224 183
184test_dht_multipeer_SOURCES = \
185 test_dht_topo.c
186test_dht_multipeer_LDADD = \
187 $(top_builddir)/src/util/libgnunetutil.la \
188 $(top_builddir)/src/statistics/libgnunetstatistics.la \
189 $(top_builddir)/src/testing_old/libgnunettesting_old.la \
190 $(top_builddir)/src/dht/libgnunetdht.la
191test_dht_multipeer_DEPENDENCIES = \
192 libgnunetdht.la
193
225# fixme, rewrite based on test_dht_topo.c! 194# fixme, rewrite based on test_dht_topo.c!
226test_dht_monitor_SOURCES = test_dht_monitor.c 195test_dht_monitor_SOURCES = test_dht_monitor.c
227test_dht_monitor_LDADD = \ 196test_dht_monitor_LDADD = \
@@ -236,11 +205,11 @@ EXTRA_DIST = \
236 test_dht_api_data.conf \ 205 test_dht_api_data.conf \
237 test_dht_api_peer1.conf \ 206 test_dht_api_peer1.conf \
238 test_dht_twopeer_data.conf \ 207 test_dht_twopeer_data.conf \
239 test_dht_multipeer_data.conf \ 208 test_dht_multipeer.conf \
240 test_dht_2dtorus.conf \ 209 test_dht_2dtorus.conf \
241 test_dht_line.conf \ 210 test_dht_line.conf \
242 test_dht_tools.py.in \ 211 test_dht_tools.py.in \
243 multipeer_topo.dat 212 test_dht_multipeer_topology.dat
244 213
245check_SCRIPTS = \ 214check_SCRIPTS = \
246 test_dht_tools.py 215 test_dht_tools.py
diff --git a/src/dht/dht.conf.in b/src/dht/dht.conf.in
index bcc0192ab..553429dc8 100644
--- a/src/dht/dht.conf.in
+++ b/src/dht/dht.conf.in
@@ -21,15 +21,7 @@ UNIX_MATCH_GID = YES
21# REJECT_FROM = 21# REJECT_FROM =
22# REJECT_FROM6 = 22# REJECT_FROM6 =
23# PREFIX = 23# PREFIX =
24# DO_FIND_PEER = 24
25# STRICT_KADEMLIA =
26# USE_MAX_HOPS =
27# MAX_HOPS =
28# REPUBLISH = YES
29# REPLICATION_FREQUENCY = 60
30# STOP_ON_CLOSEST =
31# STOP_FOUND =
32# CONVERGE_MODIFIER =
33 25
34# Special option to disable DHT calling 'try_connect' (for testing) 26# Special option to disable DHT calling 'try_connect' (for testing)
35DISABLE_TRY_CONNECT = NO 27DISABLE_TRY_CONNECT = NO
diff --git a/src/dht/test_dht_2dtorus.conf b/src/dht/test_dht_2dtorus.conf
index fa8c25011..29188cbe4 100644
--- a/src/dht/test_dht_2dtorus.conf
+++ b/src/dht/test_dht_2dtorus.conf
@@ -1,34 +1,15 @@
1[PATHS] 1[PATHS]
2SERVICEHOME = /tmp/test_dht_topo/ 2SERVICEHOME = /tmp/test_dht_2dtorus/
3 3
4[arm] 4[arm]
5PORT = 10010
6DEFAULTSERVICES = core dht 5DEFAULTSERVICES = core dht
7#DEBUG = YES
8
9[statistics]
10AUTOSTART = YES
11PORT = 10000
12
13[dht]
14DEBUG = NO
15AUTOSTART = YES
16ACCEPT_FROM6 = ::1;
17ACCEPT_FROM = 127.0.0.1;
18HOSTNAME = localhost
19PORT = 10001
20 6
21[dns] 7[dns]
22AUTOSTART = NO 8AUTOSTART = NO
23PORT = 10011
24
25[transport]
26PORT = 10002
27AUTOSTART = YES
28 9
29[nat] 10[nat]
30DISABLEV6 = YES 11DISABLEV6 = YES
31BINDTO = 127.0.0.1 12RETURN_LOCAL_ADDRESSES = YES
32ENABLE_UPNP = NO 13ENABLE_UPNP = NO
33BEHIND_NAT = NO 14BEHIND_NAT = NO
34ALLOW_NAT = NO 15ALLOW_NAT = NO
@@ -39,54 +20,18 @@ EXTERNAL_ADDRESS = 127.0.0.1
39WAN_QUOTA_IN = 1 GB 20WAN_QUOTA_IN = 1 GB
40WAN_QUOTA_OUT = 1 GB 21WAN_QUOTA_OUT = 1 GB
41 22
42[core]
43AUTOSTART = YES
44PORT = 10003
45
46[peerinfo]
47AUTOSTART = YES
48PORT = 10004
49
50[testing] 23[testing]
51WEAKRANDOM = YES 24WEAKRANDOM = YES
52 25
53[testing_old] 26[testbed]
54NUM_PEERS = 16 27OVERLAY_TOPOLOGY = 2D_TORUS
55TOPOLOGY = NONE
56CONNECT_TOPOLOGY = 2D_TORUS
57BLACKLIST_TOPOLOGY = 2D_TORUS
58#TOPOLOGY_FILE = small.dat
59#CONNECT_TOPOLOGY = ERDOS_RENYI
60#CONNECT_TOPOLOGY_OPTION = CONNECT_MINIMUM
61#CONNECT_TOPOLOGY_OPTION_MODIFIER = 25
62#PERCENTAGE = 3
63#PROBABILITY = .1
64F2F = NO
65CONNECT_TIMEOUT = 60 s
66CONNECT_ATTEMPTS = 3
67DEBUG = YES
68HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat
69MAX_CONCURRENT_SSH = 20
70USE_PROGRESSBARS = YES
71PEERGROUP_TIMEOUT = 2400 s
72TOPOLOGY_OUTPUT_FILE = 2dtorus_topo_initial
73MAX_OUTSTANDING_CONNECTIONS = 75
74#SINGLE_PEERINFO_PER_HOST = YES
75#NUM_PEERINFO_PER_HOST = 10
76#SINGLE_STATISTICS_PER_HOST = YES
77#NUM_STATISTICS_PER_HOST = 10
78DELETE_FILES = YES
79
80[test_dht_topo]
81CONNECTION_LIMIT = 20
82#DATA_OUTPUT_FILE=data_output
83
84 28
85[nse] 29[nse]
86WORKDELAY = 500 ms 30WORKDELAY = 500 ms
87INTERVAL = 60 s 31INTERVAL = 60 s
88WORKBITS = 0 32WORKBITS = 0
33
89[vpn] 34[vpn]
90AUTOSTART=NO 35AUTOSTART = NO
91 36
92 37
diff --git a/src/dht/test_dht_line.conf b/src/dht/test_dht_line.conf
index 12c682d2d..e2bb54f1b 100644
--- a/src/dht/test_dht_line.conf
+++ b/src/dht/test_dht_line.conf
@@ -1,34 +1,15 @@
1[PATHS] 1[PATHS]
2SERVICEHOME = /tmp/test_dht_topo/ 2SERVICEHOME = /tmp/test_dht_line/
3 3
4[arm] 4[arm]
5PORT = 10010
6DEFAULTSERVICES = core dht 5DEFAULTSERVICES = core dht
7#DEBUG = YES
8
9[statistics]
10AUTOSTART = YES
11PORT = 10000
12
13[dht]
14DEBUG = NO
15AUTOSTART = YES
16ACCEPT_FROM6 = ::1;
17ACCEPT_FROM = 127.0.0.1;
18HOSTNAME = localhost
19PORT = 10001
20 6
21[dns] 7[dns]
22AUTOSTART = NO 8AUTOSTART = NO
23PORT = 10011
24
25[transport]
26PORT = 10002
27AUTOSTART = YES
28 9
29[nat] 10[nat]
30DISABLEV6 = YES 11DISABLEV6 = YES
31BINDTO = 127.0.0.1 12RETURN_LOCAL_ADDRESSES = YES
32ENABLE_UPNP = NO 13ENABLE_UPNP = NO
33BEHIND_NAT = NO 14BEHIND_NAT = NO
34ALLOW_NAT = NO 15ALLOW_NAT = NO
@@ -39,48 +20,11 @@ EXTERNAL_ADDRESS = 127.0.0.1
39WAN_QUOTA_IN = 1 GB 20WAN_QUOTA_IN = 1 GB
40WAN_QUOTA_OUT = 1 GB 21WAN_QUOTA_OUT = 1 GB
41 22
42[core]
43AUTOSTART = YES
44PORT = 10003
45
46[peerinfo]
47AUTOSTART = YES
48PORT = 10004
49
50[testing] 23[testing]
51WEAKRANDOM = YES 24WEAKRANDOM = YES
52 25
53[testing_old] 26[testbed]
54NUM_PEERS = 5 27OVERLAY_TOPOLOGY = LINE
55TOPOLOGY = NONE
56CONNECT_TOPOLOGY = LINE
57BLACKLIST_TOPOLOGY = LINE
58BLACKLIST_TRANSPORTS = tcp udp http unix
59#TOPOLOGY_FILE = small.dat
60#CONNECT_TOPOLOGY = ERDOS_RENYI
61#CONNECT_TOPOLOGY_OPTION = CONNECT_MINIMUM
62#CONNECT_TOPOLOGY_OPTION_MODIFIER = 25
63#PERCENTAGE = 3
64#PROBABILITY = .1
65F2F = NO
66CONNECT_TIMEOUT = 60 s
67CONNECT_ATTEMPTS = 3
68DEBUG = YES
69HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat
70MAX_CONCURRENT_SSH = 10
71USE_PROGRESSBARS = YES
72PEERGROUP_TIMEOUT = 2400 s
73TOPOLOGY_OUTPUT_FILE = line_topo_initial
74MAX_OUTSTANDING_CONNECTIONS = 75
75#SINGLE_PEERINFO_PER_HOST = YES
76#NUM_PEERINFO_PER_HOST = 10
77#SINGLE_STATISTICS_PER_HOST = YES
78#NUM_STATISTICS_PER_HOST = 10
79DELETE_FILES = YES
80
81[test_dht_topo]
82CONNECTION_LIMIT = 5
83#DATA_OUTPUT_FILE=data_output
84 28
85[namestore] 29[namestore]
86AUTOSTART = NO 30AUTOSTART = NO
@@ -89,7 +33,8 @@ AUTOSTART = NO
89WORKDELAY = 500 ms 33WORKDELAY = 500 ms
90INTERVAL = 60 s 34INTERVAL = 60 s
91WORKBITS = 0 35WORKBITS = 0
36
92[vpn] 37[vpn]
93AUTOSTART=NO 38AUTOSTART = NO
94 39
95 40
diff --git a/src/dht/test_dht_monitor.c b/src/dht/test_dht_monitor.c
index f6474a37e..e8be7e49c 100644
--- a/src/dht/test_dht_monitor.c
+++ b/src/dht/test_dht_monitor.c
@@ -426,71 +426,38 @@ monitor_res_cb (void *cls,
426 426
427 427
428/** 428/**
429 * peergroup_ready: start test when all peers are connected 429 * Main function of the test.
430 * 430 *
431 * @param cls closure 431 * @param cls closure (NULL)
432 * @param emsg error message 432 * @param ctx argument to give to GNUNET_DHT_TEST_cleanup on test end
433 * @param num_peers number of peers that are running
434 * @param peers array of peers
435 * @param dhts handle to each of the DHTs of the peers
433 */ 436 */
434static void 437static void
435peergroup_ready (void *cls, const char *emsg) 438run (void *cls,
439 struct GNUNET_DHT_TEST_Context *ctx,
440 unsigned int num_peers,
441 struct GNUNET_TESTBED_Peer **peers,
442 struct GNUNET_DHT_Handle **dhts)
436{ 443{
437 struct GNUNET_TESTING_Daemon *d;
438 char *buf;
439 int buf_len;
440 unsigned int i; 444 unsigned int i;
441 445
442 if (emsg != NULL) 446 GNUNET_assert (NUM_PEERS == num_peers);
443 { 447 my_peers = peers;
444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
445 "test: Peergroup callback called with error, aborting test!\n");
446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Error from testing: `%s'\n",
447 emsg);
448 ok++;
449 GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
450 return;
451 }
452 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
453 "test: Peer Group started successfully with %u connections\n",
454 total_connections);
455 if (data_file != NULL)
456 {
457 buf = NULL;
458 buf_len = GNUNET_asprintf (&buf, "CONNECTIONS_0: %u\n", total_connections);
459 if (buf_len > 0)
460 GNUNET_DISK_file_write (data_file, buf, buf_len);
461 GNUNET_free (buf);
462 }
463 peers_running = GNUNET_TESTING_daemons_running (pg);
464
465 GNUNET_assert (peers_running == num_peers);
466 hs = GNUNET_malloc (num_peers * sizeof (struct GNUNET_DHT_Handle *));
467 mhs = GNUNET_malloc (num_peers * sizeof (struct GNUNET_DHT_MonitorHandle *)); 448 mhs = GNUNET_malloc (num_peers * sizeof (struct GNUNET_DHT_MonitorHandle *));
468 d_far = o = NULL;
469 o = GNUNET_TESTING_daemon_get (pg, 0);
470 d_far = GNUNET_TESTING_daemon_get (pg, 4);
471
472 for (i = 0; i < num_peers; i++) 449 for (i = 0; i < num_peers; i++)
473 { 450 {
474 d = GNUNET_TESTING_daemon_get (pg, i); 451 d = GNUNET_TESTING_daemon_get (pg, i);
475 hs[i] = GNUNET_DHT_connect (d->cfg, 32); 452 hs[i] = GNUNET_DHT_connect (d->cfg, 32);
476 mhs[i] = GNUNET_DHT_monitor_start(hs[i], 453 mhs[i] = GNUNET_DHT_monitor_start (hs[i],
477 GNUNET_BLOCK_TYPE_ANY, 454 GNUNET_BLOCK_TYPE_ANY,
478 NULL, 455 NULL,
479 &monitor_get_cb, 456 &monitor_get_cb,
480 &monitor_res_cb, 457 &monitor_res_cb,
481 &monitor_put_cb, 458 &monitor_put_cb,
482 (void *)(long)i); 459 (void *)(long)i);
483 } 460 }
484
485 if ((NULL == o) || (NULL == d_far))
486 {
487 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
488 "test: Error getting daemons from pg\n");
489 GNUNET_SCHEDULER_cancel (disconnect_task);
490 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL);
491 return;
492 }
493 monitor_counter = 0;
494 put_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply 461 put_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
495 (GNUNET_TIME_UNIT_SECONDS, 3), 462 (GNUNET_TIME_UNIT_SECONDS, 3),
496 &put_id, NULL); 463 &put_id, NULL);
@@ -500,173 +467,21 @@ peergroup_ready (void *cls, const char *emsg)
500 NULL); 467 NULL);
501 disconnect_task = 468 disconnect_task =
502 GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &disconnect_peers, NULL); 469 GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &disconnect_peers, NULL);
503
504}
505
506
507/**
508 * Function that will be called whenever two daemons are connected by
509 * the testing library.
510 *
511 * @param cls closure
512 * @param first peer id for first daemon
513 * @param second peer id for the second daemon
514 * @param distance distance between the connected peers
515 * @param first_cfg config for the first daemon
516 * @param second_cfg config for the second daemon
517 * @param first_daemon handle for the first daemon
518 * @param second_daemon handle for the second daemon
519 * @param emsg error message (NULL on success)
520 */
521static void
522connect_cb (void *cls, const struct GNUNET_PeerIdentity *first,
523 const struct GNUNET_PeerIdentity *second, uint32_t distance,
524 const struct GNUNET_CONFIGURATION_Handle *first_cfg,
525 const struct GNUNET_CONFIGURATION_Handle *second_cfg,
526 struct GNUNET_TESTING_Daemon *first_daemon,
527 struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg)
528{
529
530 if (emsg == NULL)
531 {
532 total_connections++;
533 GNUNET_PEER_intern (first);
534 GNUNET_PEER_intern (second);
535 }
536 else
537 {
538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
539 "test: Problem with new connection (%s)\n", emsg);
540 }
541} 470}
542 471
543 472
544/** 473/**
545 * run: load configuration options and schedule test to run (start peergroup)
546 * @param cls closure
547 * @param args argv
548 * @param cfgfile configuration file name (can be NULL)
549 * @param cfg configuration handle
550 */
551static void
552run (void *cls, char *const *args, const char *cfgfile,
553 const struct GNUNET_CONFIGURATION_Handle *cfg)
554{
555 char *temp_str;
556 struct GNUNET_TESTING_Host *hosts;
557 char *data_filename;
558
559 ok = 1;
560 testing_cfg = GNUNET_CONFIGURATION_dup (cfg);
561
562 GNUNET_log_setup ("test_dht_monitor",
563 "WARNING",
564 NULL);
565
566 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Starting daemons.\n");
567 GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing_old",
568 "use_progressbars", "YES");
569 if (GNUNET_OK !=
570 GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing_old",
571 "num_peers", &num_peers))
572 {
573 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
574 "Option TESTING:NUM_PEERS is required!\n");
575 return;
576 }
577
578 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (testing_cfg, "testing_old",
579 "topology_output_file",
580 &topology_file))
581 {
582 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
583 "Option test_dht_monitor:topology_output_file is required!\n");
584 return;
585 }
586
587 if (GNUNET_OK ==
588 GNUNET_CONFIGURATION_get_value_string (testing_cfg, "test_dht_topo",
589 "data_output_file",
590 &data_filename))
591 {
592 data_file =
593 GNUNET_DISK_file_open (data_filename,
594 GNUNET_DISK_OPEN_READWRITE |
595 GNUNET_DISK_OPEN_CREATE,
596 GNUNET_DISK_PERM_USER_READ |
597 GNUNET_DISK_PERM_USER_WRITE);
598 if (data_file == NULL)
599 {
600 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n",
601 data_filename);
602 GNUNET_free (data_filename);
603 }
604 }
605
606 if (GNUNET_YES ==
607 GNUNET_CONFIGURATION_get_value_string (cfg, "test_dht_topo",
608 "output_file", &temp_str))
609 {
610 output_file =
611 GNUNET_DISK_file_open (temp_str,
612 GNUNET_DISK_OPEN_READWRITE |
613 GNUNET_DISK_OPEN_CREATE,
614 GNUNET_DISK_PERM_USER_READ |
615 GNUNET_DISK_PERM_USER_WRITE);
616 if (output_file == NULL)
617 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n",
618 temp_str);
619 }
620 GNUNET_free_non_null (temp_str);
621
622 hosts = GNUNET_TESTING_hosts_load (testing_cfg);
623
624 pg = GNUNET_TESTING_peergroup_start (testing_cfg, num_peers, TIMEOUT,
625 &connect_cb, &peergroup_ready, NULL,
626 hosts);
627 GNUNET_assert (pg != NULL);
628 shutdown_handle =
629 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
630 &shutdown_task, NULL);
631}
632
633
634/**
635 * test_dht_monitor command line options
636 */
637static struct GNUNET_GETOPT_CommandLineOption options[] = {
638 {'V', "verbose", NULL,
639 gettext_noop ("be verbose (print progress information)"),
640 0, &GNUNET_GETOPT_set_one, &verbose},
641 GNUNET_GETOPT_OPTION_END
642};
643
644
645/**
646 * Main: start test 474 * Main: start test
647 */ 475 */
648int 476int
649main (int xargc, char *xargv[]) 477main (int xargc, char *xargv[])
650{ 478{
651 char *const argv[] = { "test-dht-monitor", 479 GNUNET_DHT_TEST_run ("test-dht-monitor",
652 "-c", 480 "test_dht_monitor.conf",
653 "test_dht_line.conf", 481 NUM_PEERS,
654 NULL 482 &run, NULL);
655 };
656
657 in_test = GNUNET_NO;
658 GNUNET_PROGRAM_run (sizeof (argv) / sizeof (char *) - 1, argv,
659 "test_dht_monitor",
660 gettext_noop ("Test dht monitoring in a line."),
661 options, &run, NULL);
662#if REMOVE_DIR
663 GNUNET_DISK_directory_remove ("/tmp/test_dht_monitor");
664#endif
665 if (0 != ok)
666 {
667 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: FAILED!\n");
668 }
669 return ok; 483 return ok;
670} 484}
671 485
486
672/* end of test_dht_monitor.c */ 487/* end of test_dht_monitor.c */
diff --git a/src/dht/test_dht_multipeer.c b/src/dht/test_dht_multipeer.c
deleted file mode 100644
index 656b4ac06..000000000
--- a/src/dht/test_dht_multipeer.c
+++ /dev/null
@@ -1,859 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file dht/test_dht_multipeer.c
22 * @brief testcase for testing DHT service with
23 * multiple peers.
24 */
25#include "platform.h"
26#include "gnunet_testing_lib.h"
27#include "gnunet_core_service.h"
28#include "gnunet_dht_service.h"
29
30/* Timeout for entire testcase */
31#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 30)
32
33/* Timeout for waiting for replies to get requests */
34#define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 300)
35
36/* */
37#define START_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
38
39/* Timeout for waiting for gets to complete */
40#define GET_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 50)
41
42/* Timeout for waiting for puts to complete */
43#define PUT_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 50)
44
45/* If number of peers not in config file, use this number */
46#define DEFAULT_NUM_PEERS 10
47
48#define TEST_DATA_SIZE 8
49
50#define MAX_OUTSTANDING_PUTS 100
51
52#define MAX_OUTSTANDING_GETS 100
53
54#define PATH_TRACKING GNUNET_NO
55
56
57
58struct TestPutContext
59{
60 /**
61 * This is a linked list
62 */
63 struct TestPutContext *next;
64
65 /**
66 * This is a linked list
67 */
68 struct TestPutContext *prev;
69
70 /**
71 * Handle to the first peers DHT service (via the API)
72 */
73 struct GNUNET_DHT_Handle *dht_handle;
74
75 /**
76 * Handle to the PUT peer daemon
77 */
78 struct GNUNET_TESTING_Daemon *daemon;
79
80 /**
81 * Identifier for this PUT
82 */
83 uint32_t uid;
84
85 /**
86 * Task handle for processing of the put.
87 */
88 GNUNET_SCHEDULER_TaskIdentifier task;
89};
90
91
92struct TestGetContext
93{
94 /**
95 * This is a linked list
96 */
97 struct TestGetContext *next;
98
99 /**
100 * This is a linked list
101 */
102 struct TestGetContext *prev;
103
104 /**
105 * Handle to the first peers DHT service (via the API)
106 */
107 struct GNUNET_DHT_Handle *dht_handle;
108
109 /**
110 * Handle for the DHT get request
111 */
112 struct GNUNET_DHT_GetHandle *get_handle;
113
114 /**
115 * Handle to the GET peer daemon
116 */
117 struct GNUNET_TESTING_Daemon *daemon;
118
119 /**
120 * Identifier for this GET
121 */
122 uint32_t uid;
123
124 /**
125 * Task for disconnecting DHT handles (and stopping GET)
126 */
127 GNUNET_SCHEDULER_TaskIdentifier task;
128
129 /**
130 * Whether or not this request has been fulfilled already.
131 */
132 int succeeded;
133};
134
135
136/**
137 * List of GETS to perform
138 */
139static struct TestGetContext *all_gets_head;
140
141/**
142 * List of GETS to perform
143 */
144static struct TestGetContext *all_gets_tail;
145
146/**
147 * List of PUTS to perform
148 */
149static struct TestPutContext *all_puts_head;
150
151/**
152 * List of PUTS to perform
153 */
154static struct TestPutContext *all_puts_tail;
155
156/**
157 * Handle to the set of all peers run for this test.
158 */
159static struct GNUNET_TESTING_PeerGroup *pg;
160
161/**
162 * Total number of peers to run, set based on config file.
163 */
164static unsigned long long num_peers;
165
166/**
167 * How many puts do we currently have in flight?
168 */
169static unsigned long long outstanding_puts;
170
171/**
172 * How many puts are done?
173 */
174static unsigned long long puts_completed;
175
176/**
177 * How many puts do we currently have in flight?
178 */
179static unsigned long long outstanding_gets;
180
181/**
182 * How many gets are done?
183 */
184static unsigned long long gets_completed;
185
186/**
187 * How many gets failed?
188 */
189static unsigned long long gets_failed;
190
191/**
192 * Directory to remove on shutdown.
193 */
194static char *test_directory;
195
196/**
197 * Option to use when routing.
198 */
199static enum GNUNET_DHT_RouteOption route_option;
200
201/**
202 * Task handle to use to schedule test failure / success.
203 */
204static GNUNET_SCHEDULER_TaskIdentifier die_task;
205
206/**
207 * Task handle to use to schedule test shutdown
208 */
209GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
210
211/**
212 * Global return value (0 for success, anything else for failure)
213 */
214static int ok;
215
216
217/**
218 * Check whether peers successfully shut down.
219 */
220static void
221shutdown_callback (void *cls, const char *emsg)
222{
223 if (emsg != NULL)
224 {
225 FPRINTF (stderr, "Failed to shutdown testing topology: %s\n", emsg);
226 if (ok == 0)
227 ok = 2;
228 }
229 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown callback completed.\n");
230}
231
232static void
233do_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
234{
235 if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) == 0)
236 {
237 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
238 {
239 GNUNET_SCHEDULER_cancel(shutdown_task);
240 shutdown_task = GNUNET_SCHEDULER_NO_TASK;
241 }
242 }
243 else
244 {
245 shutdown_task = GNUNET_SCHEDULER_NO_TASK ;
246 }
247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown requested.\n");
248 if (NULL != pg)
249 GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
250 pg = NULL;
251}
252
253
254/**
255 * Master context for 'stat_run'.
256 */
257struct StatMaster
258{
259 struct GNUNET_STATISTICS_Handle *stat;
260 unsigned int daemon;
261 unsigned int value;
262};
263
264struct StatValues
265{
266 const char *subsystem;
267 const char *name;
268 unsigned long long total;
269};
270
271/**
272 * Statistics we print out.
273 */
274static struct StatValues stats[] = {
275 {"core", "# bytes decrypted", 0},
276 {"core", "# bytes encrypted", 0},
277 {"core", "# type maps received", 0},
278 {"core", "# session keys confirmed via PONG", 0},
279 {"core", "# peers connected", 0},
280 {"core", "# key exchanges initiated", 0},
281 {"core", "# send requests dropped (disconnected)", 0},
282 {"core", "# transmissions delayed due to corking", 0},
283 {"core", "# messages discarded (expired prior to transmission)", 0},
284 {"core", "# messages discarded (disconnected)", 0},
285 {"core", "# discarded CORE_SEND requests", 0},
286 {"core", "# discarded lower priority CORE_SEND requests", 0},
287 {"transport", "# bytes received via TCP", 0},
288 {"transport", "# bytes transmitted via TCP", 0},
289 {"dht", "# PUT messages queued for transmission", 0},
290 {"dht", "# P2P PUT requests received", 0},
291 {"dht", "# GET messages queued for transmission", 0},
292 {"dht", "# P2P GET requests received", 0},
293 {"dht", "# RESULT messages queued for transmission", 0},
294 {"dht", "# P2P RESULTS received", 0},
295 {"dht", "# Queued messages discarded (peer disconnected)", 0},
296 {"dht", "# Peers excluded from routing due to Bloomfilter", 0},
297 {"dht", "# Peer selection failed", 0},
298 {"dht", "# FIND PEER requests ignored due to Bloomfilter", 0},
299 {"dht", "# FIND PEER requests ignored due to lack of HELLO", 0},
300 {"dht", "# P2P FIND PEER requests processed", 0},
301 {"dht", "# P2P GET requests ONLY routed", 0},
302 {"dht", "# Preference updates given to core", 0},
303 {"dht", "# REPLIES ignored for CLIENTS (no match)", 0},
304 {"dht", "# GET requests from clients injected", 0},
305 {"dht", "# GET requests received from clients", 0},
306 {"dht", "# GET STOP requests received from clients", 0},
307 {"dht", "# ITEMS stored in datacache", 0},
308 {"dht", "# Good RESULTS found in datacache", 0},
309 {"dht", "# GET requests given to datacache", 0},
310 {NULL, NULL, 0}
311};
312
313
314/**
315 * Callback function to process statistic values.
316 *
317 * @param cls closure
318 * @param subsystem name of subsystem that created the statistic
319 * @param name the name of the datum
320 * @param value the current value
321 * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
322 * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
323 */
324static int
325print_stat (void *cls, const char *subsystem, const char *name, uint64_t value,
326 int is_persistent)
327{
328 struct StatMaster *sm = cls;
329
330 stats[sm->value].total += value;
331 FPRINTF (stderr, "Peer %2u: %12s/%50s = %12llu\n", sm->daemon, subsystem,
332 name, (unsigned long long) value);
333 return GNUNET_OK;
334}
335
336
337/**
338 * Function that gathers stats from all daemons.
339 */
340static void
341stat_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
342
343
344/**
345 * Function called when GET operation on stats is done.
346 */
347static void
348get_done (void *cls, int success)
349{
350 struct StatMaster *sm = cls;
351
352 GNUNET_break (GNUNET_OK == success);
353 sm->value++;
354 GNUNET_SCHEDULER_add_now (&stat_run, sm);
355}
356
357
358/**
359 * Function that gathers stats from all daemons.
360 */
361static void
362stat_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
363{
364 struct StatMaster *sm = cls;
365 unsigned int i;
366
367 die_task = GNUNET_SCHEDULER_NO_TASK;
368 if (stats[sm->value].name != NULL)
369 {
370 GNUNET_STATISTICS_get (sm->stat,
371#if 0
372 NULL, NULL,
373#else
374 stats[sm->value].subsystem, stats[sm->value].name,
375#endif
376 GNUNET_TIME_UNIT_FOREVER_REL, &get_done, &print_stat,
377 sm);
378 return;
379 }
380 GNUNET_STATISTICS_destroy (sm->stat, GNUNET_NO);
381 sm->value = 0;
382 sm->daemon++;
383 if (sm->daemon == num_peers)
384 {
385 GNUNET_free (sm);
386 i = 0;
387 while (stats[i].name != NULL)
388 {
389 FPRINTF (stderr, "Total : %12s/%50s = %12llu\n", stats[i].subsystem,
390 stats[i].name, (unsigned long long) stats[i].total);
391 i++;
392 }
393 die_task = GNUNET_SCHEDULER_add_now (&do_stop, NULL);
394 return;
395 }
396 sm->stat =
397 GNUNET_STATISTICS_create ("<driver>",
398 GNUNET_TESTING_daemon_get (pg,
399 sm->daemon)->cfg);
400 die_task = GNUNET_SCHEDULER_add_now (&stat_run, sm);
401}
402
403
404/**
405 * Function scheduled to be run on the successful completion of this
406 * testcase.
407 */
408static void
409finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
410{
411 struct TestPutContext *test_put;
412 struct TestGetContext *test_get;
413 struct StatMaster *sm;
414
415 die_task = GNUNET_SCHEDULER_NO_TASK;
416 while (NULL != (test_put = all_puts_head))
417 {
418 if (test_put->task != GNUNET_SCHEDULER_NO_TASK)
419 GNUNET_SCHEDULER_cancel (test_put->task);
420 if (test_put->dht_handle != NULL)
421 GNUNET_DHT_disconnect (test_put->dht_handle);
422 GNUNET_CONTAINER_DLL_remove (all_puts_head, all_puts_tail, test_put);
423 GNUNET_free (test_put);
424 }
425
426 while (NULL != (test_get = all_gets_head))
427 {
428 if (test_get->task != GNUNET_SCHEDULER_NO_TASK)
429 GNUNET_SCHEDULER_cancel (test_get->task);
430 if (test_get->get_handle != NULL)
431 GNUNET_DHT_get_stop (test_get->get_handle);
432 if (test_get->dht_handle != NULL)
433 GNUNET_DHT_disconnect (test_get->dht_handle);
434 GNUNET_CONTAINER_DLL_remove (all_gets_head, all_gets_tail, test_get);
435 GNUNET_free (test_get);
436 }
437 sm = GNUNET_malloc (sizeof (struct StatMaster));
438 sm->stat =
439 GNUNET_STATISTICS_create ("<driver>",
440 GNUNET_TESTING_daemon_get (pg,
441 sm->daemon)->cfg);
442 die_task = GNUNET_SCHEDULER_add_now (&stat_run, sm);
443}
444
445
446/**
447 * Check if the get_handle is being used, if so stop the request. Either
448 * way, schedule the end_badly_cont function which actually shuts down the
449 * test.
450 */
451static void
452end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
453{
454 const char *emsg = cls;
455 struct TestPutContext *test_put;
456 struct TestGetContext *test_get;
457
458 die_task = GNUNET_SCHEDULER_NO_TASK;
459 FPRINTF (stderr, "Failing test with error: `%s'!\n", emsg);
460 while (NULL != (test_put = all_puts_head))
461 {
462 if (test_put->task != GNUNET_SCHEDULER_NO_TASK)
463 GNUNET_SCHEDULER_cancel (test_put->task);
464 if (test_put->dht_handle != NULL)
465 GNUNET_DHT_disconnect (test_put->dht_handle);
466 GNUNET_CONTAINER_DLL_remove (all_puts_head, all_puts_tail, test_put);
467 GNUNET_free (test_put);
468 }
469
470 while (NULL != (test_get = all_gets_head))
471 {
472 if (test_get->task != GNUNET_SCHEDULER_NO_TASK)
473 GNUNET_SCHEDULER_cancel (test_get->task);
474 if (test_get->get_handle != NULL)
475 GNUNET_DHT_get_stop (test_get->get_handle);
476 if (test_get->dht_handle != NULL)
477 GNUNET_DHT_disconnect (test_get->dht_handle);
478 GNUNET_CONTAINER_DLL_remove (all_gets_head, all_gets_tail, test_get);
479 GNUNET_free (test_get);
480 }
481 ok = 1;
482 /* testing_peergroup will do that in its own end_badly() handler */
483 /*GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); */
484 pg = NULL;
485}
486
487
488/**
489 * Task to release get handle.
490 */
491static void
492get_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
493{
494 struct TestGetContext *test_get = cls;
495 struct GNUNET_HashCode search_key; /* Key stored under */
496 char original_data[TEST_DATA_SIZE]; /* Made up data to store */
497
498 test_get->task = GNUNET_SCHEDULER_NO_TASK;
499 memset (original_data, test_get->uid, sizeof (original_data));
500 GNUNET_CRYPTO_hash (original_data, TEST_DATA_SIZE, &search_key);
501 if (test_get->succeeded != GNUNET_YES)
502 {
503 gets_failed++;
504 FPRINTF (stderr, "Get from peer %s for key %s failed!\n",
505 GNUNET_i2s (&test_get->daemon->id), GNUNET_h2s (&search_key));
506 }
507 GNUNET_assert (test_get->get_handle != NULL);
508 GNUNET_DHT_get_stop (test_get->get_handle);
509 test_get->get_handle = NULL;
510
511 outstanding_gets--; /* GET is really finished */
512 GNUNET_DHT_disconnect (test_get->dht_handle);
513 test_get->dht_handle = NULL;
514
515 GNUNET_CONTAINER_DLL_remove (all_gets_head, all_gets_tail, test_get);
516 GNUNET_free (test_get);
517 if ((gets_failed > 10) && (outstanding_gets == 0))
518 {
519 /* Had more than 10% failures */
520 FPRINTF (stderr, "%llu gets succeeded, %llu gets failed!\n", gets_completed,
521 gets_failed);
522 GNUNET_SCHEDULER_cancel (die_task);
523 ok = 1;
524 die_task =
525 GNUNET_SCHEDULER_add_now (&finish_testing, "not all gets succeeded");
526 return;
527 }
528 if ((gets_completed + gets_failed == num_peers * num_peers) && (outstanding_gets == 0)) /* All gets successful */
529 {
530 FPRINTF (stderr, "%llu gets succeeded, %llu gets failed!\n", gets_completed,
531 gets_failed);
532 GNUNET_SCHEDULER_cancel (die_task);
533 ok = 0;
534 die_task = GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
535 }
536}
537
538
539/**
540 * Iterator called if the GET request initiated returns a response.
541 *
542 * @param cls closure
543 * @param exp when will this value expire
544 * @param key key of the result
545 * @param type type of the result
546 * @param size number of bytes in data
547 * @param data pointer to the result data
548 */
549static void
550get_result_iterator (void *cls, struct GNUNET_TIME_Absolute exp,
551 const struct GNUNET_HashCode * key,
552 const struct GNUNET_PeerIdentity *get_path,
553 unsigned int get_path_length,
554 const struct GNUNET_PeerIdentity *put_path,
555 unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
556 size_t size, const void *data)
557{
558 struct TestGetContext *test_get = cls;
559 struct GNUNET_HashCode search_key; /* Key stored under */
560 char original_data[TEST_DATA_SIZE]; /* Made up data to store */
561
562 memset (original_data, test_get->uid, sizeof (original_data));
563 GNUNET_CRYPTO_hash (original_data, TEST_DATA_SIZE, &search_key);
564 if (test_get->succeeded == GNUNET_YES)
565 return; /* Get has already been successful, probably ending now */
566
567#if PATH_TRACKING
568 if (put_path != NULL)
569 {
570 unsigned int i;
571
572 FPRINTF (stderr, "PUT (%u) Path: ", test_get->uid);
573 for (i = 0; i < put_path_length; i++)
574 FPRINTF (stderr, "%s%s", i == 0 ? "" : "->", GNUNET_i2s (&put_path[i]));
575 FPRINTF (stderr, "%s", "\n");
576 }
577 if (get_path != NULL)
578 {
579 unsigned int i;
580
581 FPRINTF (stderr, "GET (%u) Path: ", test_get->uid);
582 for (i = 0; i < get_path_length; i++)
583 FPRINTF (stderr, "%s%s", i == 0 ? "" : "->", GNUNET_i2s (&get_path[i]));
584 FPRINTF (stderr, "%s%s\n", get_path_length > 0 ? "->" : "",
585 GNUNET_i2s (&test_get->daemon->id));
586 }
587#endif
588
589 if ((0 != memcmp (&search_key, key, sizeof (struct GNUNET_HashCode))) ||
590 (0 != memcmp (original_data, data, sizeof (original_data))))
591 {
592 FPRINTF (stderr, "%s", "Key or data is not the same as was inserted!\n");
593 return;
594 }
595 gets_completed++;
596 test_get->succeeded = GNUNET_YES;
597 GNUNET_SCHEDULER_cancel (test_get->task);
598 test_get->task = GNUNET_SCHEDULER_add_now (&get_stop_task, test_get);
599}
600
601
602/**
603 * Set up some data, and call API PUT function
604 */
605static void
606do_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
607{
608 struct TestGetContext *test_get = cls;
609 struct GNUNET_HashCode key; /* Made up key to store data under */
610 char data[TEST_DATA_SIZE]; /* Made up data to store */
611
612 if (outstanding_gets > MAX_OUTSTANDING_GETS)
613 {
614 test_get->task =
615 GNUNET_SCHEDULER_add_delayed (GET_DELAY, &do_get, test_get);
616 return;
617 }
618 memset (data, test_get->uid, sizeof (data));
619 GNUNET_CRYPTO_hash (data, TEST_DATA_SIZE, &key);
620 test_get->dht_handle = GNUNET_DHT_connect (test_get->daemon->cfg, 10);
621 GNUNET_assert (test_get->dht_handle != NULL);
622 outstanding_gets++;
623 test_get->get_handle =
624 GNUNET_DHT_get_start (test_get->dht_handle,
625 GNUNET_BLOCK_TYPE_TEST, &key, 1, route_option, NULL,
626 0, &get_result_iterator, test_get);
627 test_get->task =
628 GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &get_stop_task, test_get);
629}
630
631
632/**
633 * Task to release DHT handles for PUT
634 */
635static void
636put_disconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
637{
638 struct TestPutContext *test_put = cls;
639
640 test_put->task = GNUNET_SCHEDULER_NO_TASK;
641 GNUNET_DHT_disconnect (test_put->dht_handle);
642 test_put->dht_handle = NULL;
643 GNUNET_CONTAINER_DLL_remove (all_puts_head, all_puts_tail, test_put);
644 GNUNET_free (test_put);
645}
646
647
648/**
649 * Schedule the GET requests
650 */
651static void
652start_gets (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
653{
654 unsigned long long i;
655 unsigned long long j;
656 struct TestGetContext *test_get;
657
658 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
659 "Issuing %llu GETs\n",
660 (unsigned long long) (num_peers * num_peers));
661 for (i = 0; i < num_peers; i++)
662 for (j = 0; j < num_peers; j++)
663 {
664 test_get = GNUNET_malloc (sizeof (struct TestGetContext));
665 test_get->uid = i + j * num_peers;
666 test_get->daemon = GNUNET_TESTING_daemon_get (pg, j);
667 GNUNET_CONTAINER_DLL_insert (all_gets_head, all_gets_tail, test_get);
668 test_get->task = GNUNET_SCHEDULER_add_now (&do_get, test_get);
669 }
670}
671
672
673/**
674 * Called when the PUT request has been transmitted to the DHT service.
675 */
676static void
677put_finished (void *cls, int success)
678{
679 struct TestPutContext *test_put = cls;
680
681 outstanding_puts--;
682 puts_completed++;
683 if (GNUNET_SCHEDULER_NO_TASK != test_put->task)
684 {
685 GNUNET_SCHEDULER_cancel (test_put->task);
686 }
687 test_put->task = GNUNET_SCHEDULER_add_now (&put_disconnect_task, test_put);
688 if (puts_completed != num_peers * num_peers)
689 return;
690
691 GNUNET_assert (outstanding_puts == 0);
692 GNUNET_SCHEDULER_add_delayed (START_DELAY, &start_gets, NULL);
693}
694
695
696/**
697 * Set up some data, and call API PUT function
698 */
699static void
700do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
701{
702 struct TestPutContext *test_put = cls;
703 struct GNUNET_HashCode key; /* Made up key to store data under */
704 char data[TEST_DATA_SIZE]; /* Made up data to store */
705
706 test_put->task = GNUNET_SCHEDULER_NO_TASK;
707 if (outstanding_puts > MAX_OUTSTANDING_PUTS)
708 {
709 test_put->task =
710 GNUNET_SCHEDULER_add_delayed (PUT_DELAY, &do_put, test_put);
711 return;
712 }
713 memset (data, test_put->uid, sizeof (data));
714 GNUNET_CRYPTO_hash (data, TEST_DATA_SIZE, &key);
715 test_put->dht_handle = GNUNET_DHT_connect (test_put->daemon->cfg, 10);
716 GNUNET_assert (test_put->dht_handle != NULL);
717 outstanding_puts++;
718 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
719 "PUT %u at `%s'\n", test_put->uid,
720 GNUNET_i2s (&test_put->daemon->id));
721 GNUNET_DHT_put (test_put->dht_handle, &key, 1, route_option,
722 GNUNET_BLOCK_TYPE_TEST, sizeof (data), data,
723 GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_REL,
724 &put_finished, test_put);
725 test_put->task =
726 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
727 &put_disconnect_task, test_put);
728}
729
730
731static void
732run_dht_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
733{
734 unsigned long long i;
735 struct TestPutContext *test_put;
736
737 if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
738 {
739 ok = 1;
740 return;
741 }
742#if PATH_TRACKING
743 route_option =
744 GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE;
745#else
746 route_option = GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE;
747#endif
748 die_task =
749 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
750 "from setup puts/gets");
751 FPRINTF (stderr, "Issuing %llu PUTs (one per peer)\n",
752 (unsigned long long) (num_peers * num_peers));
753 for (i = 0; i < num_peers * num_peers; i++)
754 {
755 test_put = GNUNET_malloc (sizeof (struct TestPutContext));
756 test_put->uid = i;
757 test_put->daemon = GNUNET_TESTING_daemon_get (pg, i % num_peers);
758 test_put->task = GNUNET_SCHEDULER_add_now (&do_put, test_put);
759 GNUNET_CONTAINER_DLL_insert (all_puts_head, all_puts_tail, test_put);
760 }
761}
762
763
764/**
765 * This function is called once testing has finished setting up the topology.
766 *
767 * @param cls unused
768 * @param emsg variable is NULL on success (peers connected), and non-NULL on
769 * failure (peers failed to connect).
770 */
771static void
772startup_done (void *cls, const char *emsg)
773{
774 if (emsg != NULL)
775 {
776 FPRINTF (stderr, "Failed to setup topology: %s\n", emsg);
777 die_task = GNUNET_SCHEDULER_add_now (&end_badly, "topology setup failed");
778 return;
779 }
780 die_task =
781 GNUNET_SCHEDULER_add_delayed (START_DELAY, &run_dht_test,
782 "from setup puts/gets");
783}
784
785
786static void
787run (void *cls, char *const *args, const char *cfgfile,
788 const struct GNUNET_CONFIGURATION_Handle *cfg)
789{
790 /* Get path from configuration file */
791 if (GNUNET_YES !=
792 GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
793 &test_directory))
794 {
795 GNUNET_break (0);
796 ok = 404;
797 return;
798 }
799 if (GNUNET_SYSERR ==
800 GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "num_peers",
801 &num_peers))
802 num_peers = DEFAULT_NUM_PEERS;
803 pg = GNUNET_TESTING_peergroup_start (cfg, num_peers, TIMEOUT, NULL,
804 &startup_done, NULL, NULL);
805 GNUNET_assert (NULL != pg);
806 shutdown_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_FOREVER_REL,
807 &do_stop, NULL);
808}
809
810
811static int
812check ()
813{
814 int ret;
815
816 /* Arguments for GNUNET_PROGRAM_run */
817 char *const argv[] = { "test-dht-multipeer", /* Name to give running binary */
818 "-c",
819 "test_dht_multipeer_data.conf", /* Config file to use */
820 NULL
821 };
822 struct GNUNET_GETOPT_CommandLineOption options[] = {
823 GNUNET_GETOPT_OPTION_END
824 };
825 /* Run the run function as a new program */
826 ret =
827 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
828 "test-dht-multipeer", "nohelp", options, &run, &ok);
829 if (ret != GNUNET_OK)
830 {
831 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
832 "`test-dht-multipeer': Failed with error code %d\n", ret);
833 }
834 return ok;
835}
836
837
838int
839main (int argc, char *argv[])
840{
841 int ret;
842
843 GNUNET_log_setup ("test-dht-multipeer",
844 "WARNING",
845 NULL);
846 ret = check ();
847 /**
848 * Need to remove base directory, subdirectories taken care
849 * of by the testing framework.
850 */
851 if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
852 {
853 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
854 "Failed to remove testing directory %s\n", test_directory);
855 }
856 return ret;
857}
858
859/* end of test_dht_multipeer.c */
diff --git a/src/dht/test_dht_twopeer_data.conf b/src/dht/test_dht_multipeer.conf
index 51e7a6b8e..497510ce5 100644
--- a/src/dht/test_dht_twopeer_data.conf
+++ b/src/dht/test_dht_multipeer.conf
@@ -1,18 +1,11 @@
1[PATHS] 1[fs]
2SERVICEHOME = /tmp/test-dht-twopeer/ 2AUTOSTART = NO
3 3
4[resolver] 4[resolver]
5AUTOSTART = YES 5AUTOSTART = NO
6
7[dht]
8DEBUG = NO
9AUTOSTART = YES
10#PREFIX = xterm -T dht -e gdb --args
11PORT = 12100
12BINARY = gnunet-service-dht
13 6
14[block] 7[block]
15plugins = test dht dns 8plugins = test dht
16 9
17[dhtcache] 10[dhtcache]
18QUOTA = 1 MB 11QUOTA = 1 MB
@@ -20,38 +13,27 @@ DATABASE = sqlite
20 13
21[transport] 14[transport]
22PLUGINS = tcp 15PLUGINS = tcp
23DEBUG = NO
24NEIGHBOUR_LIMIT = 50
25PORT = 12365
26 16
27[ats] 17[ats]
28WAN_QUOTA_IN = 1 GB 18WAN_QUOTA_IN = 1 GB
29WAN_QUOTA_OUT = 1 GB 19WAN_QUOTA_OUT = 1 GB
30 20
31[core]
32HOSTNAME = localhost
33PORT = 12092
34
35[arm] 21[arm]
36DEFAULTSERVICES = core dht 22DEFAULTSERVICES = dht core
37PORT = 12366
38DEBUG = NO
39
40[transport-tcp]
41TIMEOUT = 300 s
42PORT = 12368
43BINDTO = 127.0.0.1
44 23
45[TESTING] 24[TESTING]
46WEAKRANDOM = YES 25WEAKRANDOM = YES
47 26
48[testing_old] 27[testbed]
49NUM_PEERS = 2 28OVERLAY_TOPOLOGY = FROM_FILE
50HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat 29OVERLAY_TOPOLOGY_FILE = test_dht_multipeer_topology.dat
51 30
52[gnunetd] 31[gnunetd]
53HOSTKEY = $SERVICEHOME/.hostkey 32HOSTKEY = $SERVICEHOME/.hostkey
54 33
34[PATHS]
35SERVICEHOME = /tmp/test-dht-multipeer/
36
55[nat] 37[nat]
56DISABLEV6 = YES 38DISABLEV6 = YES
57ENABLE_UPNP = NO 39ENABLE_UPNP = NO
@@ -64,17 +46,12 @@ USE_LOCALADDR = YES
64[dns] 46[dns]
65AUTOSTART = NO 47AUTOSTART = NO
66 48
67[mesh] 49[namestore]
68AUTOSTART = NO 50AUTOSTART = NO
69 51
70[nse] 52[nse]
71AUTOSTART = NO 53AUTOSTART = NO
72 54
73[fs]
74AUTOSTART = NO
75
76[namestore]
77AUTOSTART = NO
78[vpn] 55[vpn]
79AUTOSTART=NO 56AUTOSTART=NO
80 57
diff --git a/src/dht/test_dht_multipeer_data.conf b/src/dht/test_dht_multipeer_data.conf
deleted file mode 100644
index 999ed3807..000000000
--- a/src/dht/test_dht_multipeer_data.conf
+++ /dev/null
@@ -1,130 +0,0 @@
1[fs]
2AUTOSTART = NO
3
4[resolver]
5AUTOSTART = NO
6
7[dht]
8DEBUG = NO
9STOP_ON_CLOSEST = YES
10AUTOSTART = YES
11ACCEPT_FROM6 = ::1;
12ACCEPT_FROM = 127.0.0.1;
13#BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/dht/.libs/gnunet-service-dht
14#PREFIX = xterm -T dht -e gdb --args
15#PREFIX = valgrind --log-file=dht_%p
16HOME = $SERVICEHOME
17HOSTNAME = localhost
18PORT = 12100
19STOP_FOUND = YES
20USE_MAX_HOPS = YES
21MAX_HOPS = 16
22CONVERGE_BINARY = YES
23CONVERGE_MODIFIER = 4
24
25[block]
26plugins = test dht
27
28[dhtcache]
29QUOTA = 1 MB
30DATABASE = sqlite
31
32[transport]
33PLUGINS = tcp
34DEBUG = NO
35ACCEPT_FROM6 = ::1;
36ACCEPT_FROM = 127.0.0.1;
37NEIGHBOUR_LIMIT = 50
38BINARY = gnunet-service-transport
39HOME = $SERVICEHOME
40HOSTNAME = localhost
41PORT = 12365
42
43[DHTLOG]
44PLUGIN = mysql_dump
45
46[ats]
47WAN_QUOTA_IN = 1 GB
48WAN_QUOTA_OUT = 1 GB
49
50[core]
51ACCEPT_FROM6 = ::1;
52ACCEPT_FROM = 127.0.0.1;
53BINARY = gnunet-service-core
54HOME = $SERVICEHOME
55HOSTNAME = localhost
56PORT = 12092
57DEBUG = NO
58
59[arm]
60DEFAULTSERVICES = dht core
61ACCEPT_FROM6 = ::1;
62ACCEPT_FROM = 127.0.0.1;
63BINARY = gnunet-service-arm
64HOME = $SERVICEHOME
65HOSTNAME = localhost
66PORT = 12366
67DEBUG = NO
68
69[transport-tcp]
70TIMEOUT = 300 s
71PORT = 12368
72BINDTO = 127.0.0.1
73
74[DHT_TESTING]
75MYSQL_LOGGING_EXTENDED = NO
76MYSQL_LOGGING = NO
77NUM_GETS = 5
78NUM_PUTS = 5
79
80[TESTING]
81WEAKRANDOM = YES
82
83[testing_old]
84TOPOLOGY = FROM_FILE
85# file contains a ring
86CONNECT_TOPOLOGY = NONE
87# None == use all allowed connections
88# BLACKLIST_TOPOLOGY = X
89# No additional restrictions...
90
91TOPOLOGY_FILE = multipeer_topo.dat
92MAX_CONCURRENT_SSH = 1
93PEERGROUP_TIMEOUT = 2400 s
94USE_PROGRESSBARS = YES
95#CONNECT_TOPOLOGY_OPTION = CONNECT_RANDOM_SUBSET
96#CONNECT_TOPOLOGY_OPTION_MODIFIER = 2
97#LOGNMODIFIER = .65
98#PERCENTAGE = .75
99NUM_PEERS = 10
100HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat
101
102[gnunetd]
103HOSTKEY = $SERVICEHOME/.hostkey
104
105[PATHS]
106SERVICEHOME = /tmp/test-dht-multipeer/
107
108[nat]
109DISABLEV6 = YES
110ENABLE_UPNP = NO
111BEHIND_NAT = NO
112ALLOW_NAT = NO
113INTERNAL_ADDRESS = 127.0.0.1
114EXTERNAL_ADDRESS = 127.0.0.1
115USE_LOCALADDR = YES
116
117[dns]
118AUTOSTART = NO
119
120[namestore]
121AUTOSTART = NO
122
123[nse]
124AUTOSTART = NO
125
126
127[vpn]
128AUTOSTART=NO
129
130
diff --git a/src/dht/multipeer_topo.dat b/src/dht/test_dht_multipeer_topology.dat
index 1233e6b66..1233e6b66 100644
--- a/src/dht/multipeer_topo.dat
+++ b/src/dht/test_dht_multipeer_topology.dat
diff --git a/src/dht/test_dht_topo.c b/src/dht/test_dht_topo.c
index 0934d7abd..c9036d2c1 100644
--- a/src/dht/test_dht_topo.c
+++ b/src/dht/test_dht_topo.c
@@ -30,11 +30,6 @@
30#include "dht_test_lib.h" 30#include "dht_test_lib.h"
31 31
32/** 32/**
33 * Number of peers to run.
34 */
35#define NUM_PEERS 5
36
37/**
38 * How long until we give up on fetching the data? 33 * How long until we give up on fetching the data?
39 */ 34 */
40#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) 35#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
@@ -93,6 +88,131 @@ static struct GetOperation *get_head;
93 */ 88 */
94static struct GetOperation *get_tail; 89static struct GetOperation *get_tail;
95 90
91/**
92 * Array of the testbed's peers.
93 */
94static struct GNUNET_TESTBED_Peer **my_peers;
95
96/**
97 * Number of peers to run.
98 */
99static unsigned int NUM_PEERS;
100
101
102/**
103 * Statistics we print out.
104 */
105static struct
106{
107 const char *subsystem;
108 const char *name;
109 unsigned long long total;
110} stats[] = {
111 {"core", "# bytes decrypted", 0},
112 {"core", "# bytes encrypted", 0},
113 {"core", "# type maps received", 0},
114 {"core", "# session keys confirmed via PONG", 0},
115 {"core", "# peers connected", 0},
116 {"core", "# key exchanges initiated", 0},
117 {"core", "# send requests dropped (disconnected)", 0},
118 {"core", "# transmissions delayed due to corking", 0},
119 {"core", "# messages discarded (expired prior to transmission)", 0},
120 {"core", "# messages discarded (disconnected)", 0},
121 {"core", "# discarded CORE_SEND requests", 0},
122 {"core", "# discarded lower priority CORE_SEND requests", 0},
123 {"transport", "# bytes received via TCP", 0},
124 {"transport", "# bytes transmitted via TCP", 0},
125 {"dht", "# PUT messages queued for transmission", 0},
126 {"dht", "# P2P PUT requests received", 0},
127 {"dht", "# GET messages queued for transmission", 0},
128 {"dht", "# P2P GET requests received", 0},
129 {"dht", "# RESULT messages queued for transmission", 0},
130 {"dht", "# P2P RESULTS received", 0},
131 {"dht", "# Queued messages discarded (peer disconnected)", 0},
132 {"dht", "# Peers excluded from routing due to Bloomfilter", 0},
133 {"dht", "# Peer selection failed", 0},
134 {"dht", "# FIND PEER requests ignored due to Bloomfilter", 0},
135 {"dht", "# FIND PEER requests ignored due to lack of HELLO", 0},
136 {"dht", "# P2P FIND PEER requests processed", 0},
137 {"dht", "# P2P GET requests ONLY routed", 0},
138 {"dht", "# Preference updates given to core", 0},
139 {"dht", "# REPLIES ignored for CLIENTS (no match)", 0},
140 {"dht", "# GET requests from clients injected", 0},
141 {"dht", "# GET requests received from clients", 0},
142 {"dht", "# GET STOP requests received from clients", 0},
143 {"dht", "# ITEMS stored in datacache", 0},
144 {"dht", "# Good RESULTS found in datacache", 0},
145 {"dht", "# GET requests given to datacache", 0},
146 {NULL, NULL, 0}
147};
148
149
150/**
151 * Function called once we're done processing stats.
152 *
153 * @param cls the test context
154 * @param op the stats operation
155 * @param emsg error message on failure
156 */
157static void
158stats_finished (void *cls,
159 struct GNUNET_TESTBED_Operation *op,
160 const char *emsg)
161{
162 struct GNUNET_DHT_TEST_Context *ctx = cls;
163 unsigned int i;
164
165 if (NULL != op)
166 GNUNET_TESTBED_operation_done (op); // needed?
167 if (NULL != emsg)
168 {
169 fprintf (stderr, _("Gathering statistics failed: %s\n"),
170 emsg);
171 GNUNET_SCHEDULER_cancel (put_task);
172 GNUNET_DHT_TEST_cleanup (ctx);
173 return;
174 }
175 for (i = 0; NULL != stats[i].name; i++)
176 FPRINTF (stderr,
177 "%6s/%60s = %12llu\n",
178 stats[i].subsystem,
179 stats[i].name,
180 stats[i].total);
181 GNUNET_SCHEDULER_cancel (put_task);
182 GNUNET_DHT_TEST_cleanup (ctx);
183}
184
185
186/**
187 * Function called to process statistic values from all peers.
188 *
189 * @param cls closure
190 * @param peer the peer the statistic belong to
191 * @param subsystem name of subsystem that created the statistic
192 * @param name the name of the datum
193 * @param value the current value
194 * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
195 * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
196 */
197static int
198handle_stats (void *cls,
199 const struct GNUNET_TESTBED_Peer *peer,
200 const char *subsystem,
201 const char *name,
202 uint64_t value,
203 int is_persistent)
204{
205 unsigned int i;
206
207 for (i = 0; NULL != stats[i].name; i++)
208 if ( (0 == strcasecmp (subsystem,
209 stats[i].subsystem)) &&
210 (0 == strcasecmp (name,
211 stats[i].name)) )
212 stats[i].total += value;
213 return GNUNET_OK;
214}
215
96 216
97/** 217/**
98 * Task run on success or timeout to clean up. 218 * Task run on success or timeout to clean up.
@@ -117,8 +237,11 @@ shutdown_task (void *cls,
117 get_op); 237 get_op);
118 GNUNET_free (get_op); 238 GNUNET_free (get_op);
119 } 239 }
120 GNUNET_SCHEDULER_cancel (put_task); 240 (void) GNUNET_TESTBED_get_statistics (NUM_PEERS,
121 GNUNET_DHT_TEST_cleanup (ctx); 241 my_peers,
242 &handle_stats,
243 &stats_finished,
244 ctx);
122} 245}
123 246
124 247
@@ -249,16 +372,9 @@ run (void *cls,
249 struct GetOperation *get_op; 372 struct GetOperation *get_op;
250 373
251 GNUNET_assert (NUM_PEERS == num_peers); 374 GNUNET_assert (NUM_PEERS == num_peers);
375 my_peers = peers;
252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 376 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
253 "Peers setup, starting test\n"); 377 "Peers setup, starting test\n");
254 /* FIXME: once testbed is finished, this call should
255 no longer be needed */
256 GNUNET_TESTBED_overlay_configure_topology (NULL,
257 num_peers,
258 peers,
259 GNUNET_TESTBED_TOPOLOGY_LINE,
260 GNUNET_TESTBED_TOPOLOGY_OPTION_END);
261
262 put_task = GNUNET_SCHEDULER_add_now (&do_puts, dhts); 378 put_task = GNUNET_SCHEDULER_add_now (&do_puts, dhts);
263 for (i=0;i<num_peers;i++) 379 for (i=0;i<num_peers;i++)
264 { 380 {
@@ -297,11 +413,25 @@ main (int xargc, char *xargv[])
297 { 413 {
298 cfg_filename = "test_dht_2dtorus.conf"; 414 cfg_filename = "test_dht_2dtorus.conf";
299 test_name = "test-dht-2dtorus"; 415 test_name = "test-dht-2dtorus";
416 NUM_PEERS = 16;
300 } 417 }
301 else if (NULL != strstr (xargv[0], "test_dht_line")) 418 else if (NULL != strstr (xargv[0], "test_dht_line"))
302 { 419 {
303 cfg_filename = "test_dht_line.conf"; 420 cfg_filename = "test_dht_line.conf";
304 test_name = "test-dht-line"; 421 test_name = "test-dht-line";
422 NUM_PEERS = 5;
423 }
424 else if (NULL != strstr (xargv[0], "test_dht_twopeer"))
425 {
426 cfg_filename = "test_dht_line.conf";
427 test_name = "test-dht-twopeer";
428 NUM_PEERS = 2;
429 }
430 else if (NULL != strstr (xargv[0], "test_dht_multipeer"))
431 {
432 cfg_filename = "test_dht_multipeer.conf";
433 test_name = "test-dht-multipeer";
434 NUM_PEERS = 10;
305 } 435 }
306 else 436 else
307 { 437 {
diff --git a/src/dht/test_dht_twopeer.c b/src/dht/test_dht_twopeer.c
deleted file mode 100644
index 8579013e3..000000000
--- a/src/dht/test_dht_twopeer.c
+++ /dev/null
@@ -1,494 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file dht/test_dht_twopeer.c
22 * @brief base testcase for testing DHT service with
23 * two running peers
24 */
25#include "platform.h"
26#include "gnunet_testing_lib.h"
27#include "gnunet_core_service.h"
28#include "gnunet_dht_service.h"
29
30/* DEFINES */
31#define MAX_GET_ATTEMPTS 10
32
33#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
34
35#define DEFAULT_NUM_PEERS 2
36
37/* Structs */
38
39struct PeerGetContext
40{
41 struct GNUNET_PeerIdentity *peer;
42
43 struct GNUNET_DHT_Handle *dht_handle;
44
45 struct GNUNET_DHT_GetHandle *get_handle;
46
47 unsigned int get_attempts;
48
49 GNUNET_SCHEDULER_TaskIdentifier retry_task;
50};
51
52/* Globals */
53static char *test_directory;
54
55static struct PeerGetContext curr_get_ctx;
56
57static unsigned int expected_connections;
58
59static unsigned long long peers_left;
60
61static struct GNUNET_TESTING_PeerGroup *pg;
62
63static unsigned long long num_peers;
64
65static unsigned int total_gets;
66
67static unsigned int gets_succeeded;
68
69static unsigned int total_connections;
70
71static unsigned int failed_connections;
72
73static GNUNET_SCHEDULER_TaskIdentifier die_task;
74
75static int ok;
76
77static struct GNUNET_PeerIdentity peer1id;
78
79static struct GNUNET_PeerIdentity peer2id;
80
81static struct GNUNET_DHT_Handle *peer1dht;
82
83static struct GNUNET_DHT_Handle *peer2dht;
84
85/**
86 * Check whether peers successfully shut down.
87 */
88static void
89shutdown_callback (void *cls, const char *emsg)
90{
91 if (emsg != NULL)
92 {
93 if (ok == 0)
94 ok = 2;
95 }
96}
97
98static void
99finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
100{
101 GNUNET_assert (pg != NULL);
102 GNUNET_assert (peer1dht != NULL);
103 GNUNET_assert (peer2dht != NULL);
104 GNUNET_DHT_disconnect (peer1dht);
105 GNUNET_DHT_disconnect (peer2dht);
106 GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
107 pg = NULL;
108 ok = 0;
109}
110
111static void
112end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
113{
114 if (peer1dht != NULL)
115 GNUNET_DHT_disconnect (peer1dht);
116
117 if (peer2dht != NULL)
118 GNUNET_DHT_disconnect (peer2dht);
119
120 if (pg != NULL)
121 {
122 GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
123 pg = NULL;
124 }
125
126 if (curr_get_ctx.retry_task != GNUNET_SCHEDULER_NO_TASK)
127 {
128 GNUNET_SCHEDULER_cancel (curr_get_ctx.retry_task);
129 curr_get_ctx.retry_task = GNUNET_SCHEDULER_NO_TASK;
130 }
131}
132
133
134static void
135end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
136{
137 const char *emsg = cls;
138
139 FPRINTF (stderr, "Error: %s\n", emsg);
140 if (curr_get_ctx.retry_task != GNUNET_SCHEDULER_NO_TASK)
141 {
142 GNUNET_SCHEDULER_cancel (curr_get_ctx.retry_task);
143 curr_get_ctx.retry_task = GNUNET_SCHEDULER_NO_TASK;
144 }
145 if (curr_get_ctx.get_handle != NULL)
146 {
147 GNUNET_DHT_get_stop (curr_get_ctx.get_handle);
148 }
149
150 GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
151 ok = 1;
152}
153
154
155/* Forward declaration */
156static void
157do_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
158
159/**
160 * Iterator called on each result obtained for a DHT
161 * operation that expects a reply
162 *
163 * @param cls closure
164 * @param exp when will this value expire
165 * @param key key of the result
166 * @param type type of the result
167 * @param size number of bytes in data
168 * @param data pointer to the result data
169 */
170static void
171get_result_iterator (void *cls, struct GNUNET_TIME_Absolute exp,
172 const struct GNUNET_HashCode * key,
173 const struct GNUNET_PeerIdentity *get_path,
174 unsigned int get_path_length,
175 const struct GNUNET_PeerIdentity *put_path,
176 unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
177 size_t size, const void *data)
178{
179 struct PeerGetContext *get_context = cls;
180
181 if (0 !=
182 memcmp (&get_context->peer->hashPubKey, key, sizeof (struct GNUNET_HashCode)))
183 {
184 FPRINTF (stderr, "%s", "??\n");
185 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
186 "Key returned is not the same key as was searched for!\n");
187 GNUNET_SCHEDULER_cancel (die_task);
188 die_task =
189 GNUNET_SCHEDULER_add_now (&end_badly,
190 "key mismatch in get response!\n");
191 return;
192 }
193 if (get_context->retry_task != GNUNET_SCHEDULER_NO_TASK)
194 {
195 GNUNET_SCHEDULER_cancel (get_context->retry_task);
196 get_context->retry_task = GNUNET_SCHEDULER_NO_TASK;
197 }
198
199 if (get_context->peer == &peer2id)
200 {
201 get_context->peer = &peer1id;
202 get_context->dht_handle = peer2dht;
203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
204 "Received first correct GET request response!\n");
205 GNUNET_DHT_get_stop (get_context->get_handle);
206 GNUNET_SCHEDULER_add_now (&do_get, get_context);
207 }
208 else
209 {
210 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
211 "Received second correct GET request response!\n");
212 GNUNET_SCHEDULER_cancel (die_task);
213 GNUNET_DHT_get_stop (get_context->get_handle);
214 die_task = GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
215 }
216
217}
218
219static void
220stop_retry_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
221
222
223static void
224get_stop_finished (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
225{
226 struct PeerGetContext *get_context = cls;
227
228 if (get_context->get_attempts >= MAX_GET_ATTEMPTS)
229 {
230 FPRINTF (stderr, "%s", "?\n");
231 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
232 "Too many attempts failed, ending test!\n",
233 get_context->get_attempts);
234 GNUNET_SCHEDULER_cancel (die_task);
235 die_task =
236 GNUNET_SCHEDULER_add_now (&end_badly,
237 "GET attempt failed, ending test!\n");
238 return;
239 }
240 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
241 "Get attempt %u failed, retrying request!\n",
242 get_context->get_attempts);
243 FPRINTF (stderr, "%s", ".");
244 get_context->get_attempts++;
245 get_context->retry_task =
246 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
247 (GNUNET_TIME_UNIT_SECONDS, 60),
248 &stop_retry_get, get_context);
249 get_context->get_handle =
250 GNUNET_DHT_get_start (get_context->dht_handle,
251 GNUNET_BLOCK_TYPE_DHT_HELLO,
252 &get_context->peer->hashPubKey, 1,
253 GNUNET_DHT_RO_NONE, NULL, 0, &get_result_iterator,
254 get_context);
255}
256
257
258static void
259stop_retry_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
260{
261 struct PeerGetContext *get_context = cls;
262
263 get_context->retry_task = GNUNET_SCHEDULER_NO_TASK;
264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
265 "Get attempt %u failed, canceling request!\n",
266 get_context->get_attempts);
267 GNUNET_DHT_get_stop (get_context->get_handle);
268 get_context->get_handle = NULL;
269 GNUNET_SCHEDULER_add_now (&get_stop_finished, get_context);
270}
271
272
273static void
274do_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
275{
276 struct PeerGetContext *get_context = cls;
277
278 get_context->retry_task =
279 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
280 (GNUNET_TIME_UNIT_SECONDS, 10),
281 &stop_retry_get, get_context);
282 get_context->get_handle =
283 GNUNET_DHT_get_start (get_context->dht_handle,
284 GNUNET_BLOCK_TYPE_DHT_HELLO,
285 &get_context->peer->hashPubKey, 1,
286 GNUNET_DHT_RO_FIND_PEER, NULL, 0,
287 &get_result_iterator, get_context);
288}
289
290
291static void
292topology_callback (void *cls, const struct GNUNET_PeerIdentity *first,
293 const struct GNUNET_PeerIdentity *second, uint32_t distance,
294 const struct GNUNET_CONFIGURATION_Handle *first_cfg,
295 const struct GNUNET_CONFIGURATION_Handle *second_cfg,
296 struct GNUNET_TESTING_Daemon *first_daemon,
297 struct GNUNET_TESTING_Daemon *second_daemon,
298 const char *emsg)
299{
300 if (emsg == NULL)
301 {
302 total_connections++;
303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
304 "connected peer %s to peer %s, distance %u\n",
305 first_daemon->shortname, second_daemon->shortname, distance);
306 }
307 else
308 {
309 failed_connections++;
310 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
311 "Failed to connect peer %s to peer %s with error :\n%s\n",
312 first_daemon->shortname, second_daemon->shortname, emsg);
313 }
314
315 if (total_connections == expected_connections)
316 {
317 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
318 "Created %d total connections, which is our target number! Starting next phase of testing.\n",
319 total_connections);
320 GNUNET_SCHEDULER_cancel (die_task);
321 die_task =
322 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
323 "Timeout trying to GET");
324
325 curr_get_ctx.dht_handle = peer1dht;
326 curr_get_ctx.peer = &peer2id;
327 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
328 (GNUNET_TIME_UNIT_SECONDS, 2), &do_get,
329 &curr_get_ctx);
330 }
331 else if (total_connections + failed_connections == expected_connections)
332 {
333 GNUNET_SCHEDULER_cancel (die_task);
334 die_task =
335 GNUNET_SCHEDULER_add_now (&end_badly,
336 "from topology_callback (too many failed connections)");
337 }
338}
339
340
341static void
342connect_topology (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
343{
344 expected_connections = -1;
345 if ((pg != NULL) && (peers_left == 0))
346 expected_connections =
347 GNUNET_TESTING_connect_topology (pg, GNUNET_TESTING_TOPOLOGY_CLIQUE,
348 GNUNET_TESTING_TOPOLOGY_OPTION_ALL,
349 0.0, TIMEOUT, 12, NULL, NULL);
350
351 GNUNET_SCHEDULER_cancel (die_task);
352 if (expected_connections == GNUNET_SYSERR)
353 die_task =
354 GNUNET_SCHEDULER_add_now (&end_badly,
355 "from connect topology (bad return)");
356 else
357 die_task =
358 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
359 "from connect topology (timeout)");
360}
361
362
363static void
364peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id,
365 const struct GNUNET_CONFIGURATION_Handle *cfg,
366 struct GNUNET_TESTING_Daemon *d, const char *emsg)
367{
368 if (emsg != NULL)
369 {
370 FPRINTF (stderr, "Failed to start daemon: `%s'\n", emsg);
371 return;
372 }
373 GNUNET_assert (id != NULL);
374 if (peers_left == num_peers)
375 {
376 memcpy (&peer1id, id, sizeof (struct GNUNET_PeerIdentity));
377 peer1dht = GNUNET_DHT_connect (cfg, 100);
378 if (peer1dht == NULL)
379 {
380 GNUNET_SCHEDULER_cancel (die_task);
381 die_task =
382 GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n");
383 }
384 }
385 else
386 {
387 memcpy (&peer2id, id, sizeof (struct GNUNET_PeerIdentity));
388 peer2dht = GNUNET_DHT_connect (cfg, 100);
389 if (peer2dht == NULL)
390 {
391 GNUNET_SCHEDULER_cancel (die_task);
392 die_task =
393 GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n");
394 }
395 }
396
397
398 peers_left--;
399
400 if (peers_left == 0)
401 {
402 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
403 "All %d daemons started, now connecting peers!\n", num_peers);
404 GNUNET_SCHEDULER_cancel (die_task);
405 /* Set up task in case topology creation doesn't finish
406 * within a reasonable amount of time */
407 die_task =
408 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
409 "from peers_started_callback");
410
411 GNUNET_SCHEDULER_add_now (&connect_topology, NULL);
412 ok = 0;
413 }
414}
415
416
417static void
418run (void *cls, char *const *args, const char *cfgfile,
419 const struct GNUNET_CONFIGURATION_Handle *cfg)
420{
421
422 if (GNUNET_YES !=
423 GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
424 &test_directory))
425 {
426 ok = 404;
427 return;
428 }
429
430 if (GNUNET_SYSERR ==
431 GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "num_peers",
432 &num_peers))
433 num_peers = DEFAULT_NUM_PEERS;
434
435 peers_left = num_peers;
436 total_gets = num_peers;
437 gets_succeeded = 0;
438 /* Set up a task to end testing if peer start fails */
439 die_task =
440 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
441 "didn't start all daemons in reasonable amount of time!!!");
442
443 pg = GNUNET_TESTING_daemons_start (cfg, num_peers, 10, num_peers, TIMEOUT,
444 NULL, NULL, &peers_started_callback, NULL,
445 &topology_callback, NULL, NULL);
446
447}
448
449static int
450check ()
451{
452 int ret;
453
454 char *const argv[] = { "test-dht-twopeer",
455 "-c",
456 "test_dht_twopeer_data.conf",
457 NULL
458 };
459 struct GNUNET_GETOPT_CommandLineOption options[] = {
460 GNUNET_GETOPT_OPTION_END
461 };
462 ret =
463 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
464 "test-dht-twopeer", "nohelp", options, &run, &ok);
465 if (ret != GNUNET_OK)
466 {
467 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
468 "`test-dht-twopeer': Failed with error code %d\n", ret);
469 }
470 return ok;
471}
472
473int
474main (int argc, char *argv[])
475{
476 int ret;
477
478 GNUNET_log_setup ("test-dht-twopeer",
479 "WARNING",
480 NULL);
481 ret = check ();
482 /**
483 * Need to remove base directory, subdirectories taken care
484 * of by the testing framework.
485 */
486 if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
487 {
488 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
489 "Failed to remove testing directory %s\n", test_directory);
490 }
491 return ret;
492}
493
494/* end of test_dht_twopeer.c */
diff --git a/src/dht/test_dht_twopeer_get_put.c b/src/dht/test_dht_twopeer_get_put.c
deleted file mode 100644
index 3a27db21b..000000000
--- a/src/dht/test_dht_twopeer_get_put.c
+++ /dev/null
@@ -1,590 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file dht/test_dht_twopeer_get_put.c
22 * @brief base testcase for testing DHT service with
23 * two running peers.
24 *
25 * This testcase starts peers using the GNUNET_TESTING_daemons_start
26 * function call. On peer start, connects to the peers DHT service
27 * by calling GNUNET_DHT_connected. Once notified about all peers
28 * being started (by the peers_started_callback function), calls
29 * GNUNET_TESTING_connect_topology, which connects the peers in a
30 * "straight line" topology. On notification that all peers have
31 * been properly connected, calls the do_get function which initiates
32 * a GNUNET_DHT_get from the *second* peer. Once the GNUNET_DHT_get
33 * function starts, runs the do_put function to insert data at the first peer.
34 * If the GET is successful, schedules finish_testing
35 * to stop the test and shut down peers. If GET is unsuccessful
36 * after GET_TIMEOUT seconds, prints an error message and shuts down
37 * the peers.
38 */
39#include "platform.h"
40#include "gnunet_testing_lib.h"
41#include "gnunet_core_service.h"
42#include "gnunet_dht_service.h"
43#include "block_dns.h"
44#include "gnunet_signatures.h"
45
46/* DEFINES */
47#define VERBOSE GNUNET_NO
48
49/* Timeout for entire testcase */
50#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 40)
51
52/* Timeout for waiting for replies to get requests */
53#define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
54
55/* If number of peers not in config file, use this number */
56#define DEFAULT_NUM_PEERS 2
57
58#define DNS GNUNET_NO
59
60/* Globals */
61
62/**
63 * Directory to store temp data in, defined in config file
64 */
65static char *test_directory;
66
67/**
68 * Variable used to store the number of connections we should wait for.
69 */
70static unsigned int expected_connections;
71
72/**
73 * Variable used to keep track of how many peers aren't yet started.
74 */
75static unsigned long long peers_left;
76
77/**
78 * Handle to the set of all peers run for this test.
79 */
80static struct GNUNET_TESTING_PeerGroup *pg;
81
82/**
83 * Global handle we will use for GET requests.
84 */
85struct GNUNET_DHT_GetHandle *global_get_handle;
86
87
88/**
89 * Total number of peers to run, set based on config file.
90 */
91static unsigned long long num_peers;
92
93/**
94 * Global used to count how many connections we have currently
95 * been notified about (how many times has topology_callback been called
96 * with success?)
97 */
98static unsigned int total_connections;
99
100/**
101 * Global used to count how many failed connections we have
102 * been notified about (how many times has topology_callback
103 * been called with failure?)
104 */
105static unsigned int failed_connections;
106
107/* Task handle to use to schedule test failure */
108GNUNET_SCHEDULER_TaskIdentifier die_task;
109
110/* Global return value (0 for success, anything else for failure) */
111static int ok;
112
113#if DNS
114struct GNUNET_DNS_Record data;
115#endif
116
117/**
118 * Peer identity of the first peer started.
119 */
120static struct GNUNET_PeerIdentity peer1id;
121
122/**
123 * Peer identity of the second peer started.
124 */
125static struct GNUNET_PeerIdentity peer2id;
126
127/**
128 * Handle to the first peers DHT service (via the API)
129 */
130static struct GNUNET_DHT_Handle *peer1dht;
131
132/**
133 * Handle to the second peers DHT service (via the API)
134 */
135static struct GNUNET_DHT_Handle *peer2dht;
136
137static void
138do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
139
140/**
141 * Check whether peers successfully shut down.
142 */
143void
144shutdown_callback (void *cls, const char *emsg)
145{
146 if (emsg != NULL)
147 {
148 if (ok == 0)
149 ok = 2;
150 }
151}
152
153/**
154 * Function scheduled to be run on the successful completion of this
155 * testcase. Specifically, called when our get request completes.
156 */
157static void
158finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
159{
160 GNUNET_assert (pg != NULL);
161 GNUNET_assert (peer1dht != NULL);
162 GNUNET_assert (peer2dht != NULL);
163 GNUNET_DHT_disconnect (peer1dht);
164 GNUNET_DHT_disconnect (peer2dht);
165 GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
166 ok = 0;
167}
168
169/**
170 * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
171 * down the peers without freeing memory associated with GET request.
172 */
173static void
174end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
175{
176 if (peer1dht != NULL)
177 GNUNET_DHT_disconnect (peer1dht);
178
179 if (peer2dht != NULL)
180 GNUNET_DHT_disconnect (peer2dht);
181
182 if (pg != NULL)
183 GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
184}
185
186/**
187 * Check if the get_handle is being used, if so stop the request. Either
188 * way, schedule the end_badly_cont function which actually shuts down the
189 * test.
190 */
191static void
192end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
193{
194 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failing test with error: `%s'!\n",
195 (char *) cls);
196 if (global_get_handle != NULL)
197 {
198 GNUNET_DHT_get_stop (global_get_handle);
199 global_get_handle = NULL;
200 }
201 GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
202 ok = 1;
203}
204
205/**
206 * Iterator called if the GET request initiated returns a response.
207 *
208 * @param cls closure
209 * @param exp when will this value expire
210 * @param key key of the result
211 * @param type type of the result
212 * @param size number of bytes in data
213 * @param data pointer to the result data
214 */
215void
216get_result_iterator (void *cls, struct GNUNET_TIME_Absolute exp,
217 const struct GNUNET_HashCode * key,
218 const struct GNUNET_PeerIdentity *get_path,
219 unsigned int get_path_size,
220 const struct GNUNET_PeerIdentity *put_path,
221 unsigned int put_path_size, enum GNUNET_BLOCK_Type type,
222 size_t size, const void *result_data)
223{
224 struct GNUNET_HashCode original_key; /* Key data was stored data under */
225 char original_data[4]; /* Made up data that was stored */
226
227 memset (&original_key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to what it was set to previously */
228 memset (original_data, 43, sizeof (original_data));
229
230#if DNS
231 if ((sizeof (original_data) != size) ||
232 (0 != memcmp (&data.service_descriptor, key, sizeof (struct GNUNET_HashCode))) ||
233 (0 != memcmp ((char *) &data, result_data, sizeof (original_data))))
234 {
235 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
236 "Key or data is not the same as was inserted!\n");
237 GNUNET_SCHEDULER_cancel (die_task);
238 GNUNET_SCHEDULER_add_now (&end_badly,
239 "key or data mismatch in get response!\n");
240 return;
241 }
242#else
243 if ((sizeof (original_data) != size) ||
244 (0 != memcmp (&original_key, key, sizeof (struct GNUNET_HashCode))) ||
245 (0 != memcmp (original_data, result_data, sizeof (original_data))))
246 {
247 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
248 "Key or data is not the same as was inserted!\n");
249 GNUNET_SCHEDULER_cancel (die_task);
250 GNUNET_SCHEDULER_add_now (&end_badly,
251 "key or data mismatch in get response!\n");
252 return;
253 }
254#endif
255
256 GNUNET_SCHEDULER_cancel (die_task);
257 GNUNET_DHT_get_stop (global_get_handle);
258 GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
259}
260
261/**
262 * Start the GET request for the same key/data that was inserted.
263 */
264static void
265do_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
266{
267 struct GNUNET_HashCode key; /* Key for data lookup */
268
269#if DNS
270 memcpy (&key, &data.service_descriptor, sizeof (struct GNUNET_HashCode));
271#else
272 memset (&key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to the same thing as when data was inserted */
273#endif
274 global_get_handle =
275 GNUNET_DHT_get_start (peer2dht,
276#if DNS
277 GNUNET_BLOCK_TYPE_DNS,
278#else
279 GNUNET_BLOCK_TYPE_TEST,
280#endif
281 &key, 1, GNUNET_DHT_RO_NONE, NULL, 0,
282 &get_result_iterator, NULL);
283 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
284 (GNUNET_TIME_UNIT_SECONDS, 10), &do_put, NULL);
285}
286
287/**
288 * Called when the PUT request has been transmitted to the DHT service.
289 * Schedule the GET request for some time in the future.
290 */
291static void
292put_finished (void *cls, int success)
293{
294 GNUNET_SCHEDULER_cancel (die_task);
295 die_task =
296 GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &end_badly,
297 "waiting for get response (data not found)");
298}
299
300
301#if !DNS
302/**
303 * Set up some data, and call API PUT function
304 */
305static void
306do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
307{
308 struct GNUNET_HashCode key; /* Made up key to store data under */
309 char data[4]; /* Made up data to store */
310
311 memset (&key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to something simple so we can issue GET request */
312 memset (data, 43, sizeof (data));
313
314 /* Insert the data at the first peer */
315 GNUNET_DHT_put (peer1dht, &key, 1, GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_TEST,
316 sizeof (data), data, GNUNET_TIME_UNIT_FOREVER_ABS,
317 GNUNET_TIME_UNIT_FOREVER_REL, &put_finished, NULL);
318}
319#else
320
321/**
322 * Set up some data, and call API PUT function
323 */
324static void
325do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
326{
327 char *name = "philipptoelke.gnunet.";
328 size_t size = sizeof (struct GNUNET_DNS_Record);
329
330 memset (&data, 0, size);
331
332 data.purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_RsaSignature));
333 data.purpose.purpose = GNUNET_SIGNATURE_PURPOSE_DNS_RECORD;
334
335 GNUNET_CRYPTO_hash (name, strlen (name) + 1, &data.service_descriptor);
336
337 data.service_type = htonl (GNUNET_DNS_SERVICE_TYPE_UDP);
338 data.ports = htons (69);
339
340 char *keyfile;
341
342 GNUNET_asprintf (&keyfile, "/tmp/test_dns_data_key");
343 struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key =
344 GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
345 GNUNET_free (keyfile);
346 GNUNET_assert (my_private_key != NULL);
347
348 GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &data.peer);
349
350 data.expiration_time =
351 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS);
352
353 /* Sign the block */
354 if (GNUNET_OK !=
355 GNUNET_CRYPTO_rsa_sign (my_private_key, &data.purpose, &data.signature))
356 {
357 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not sign DNS_Record\n");
358 return;
359 }
360 GNUNET_CRYPTO_rsa_key_free (my_private_key);
361
362 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting with key %08x\n",
363 *((unsigned int *) &data.service_descriptor));
364
365 GNUNET_DHT_put (peer1dht, &data.service_descriptor, DEFAULT_PUT_REPLICATION,
366 GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_DNS, size,
367 (char *) &data,
368 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS),
369 GNUNET_TIME_UNIT_MINUTES, &put_finished, NULL);
370}
371#endif
372
373/**
374 * This function is called whenever a connection attempt is finished between two of
375 * the started peers (started with GNUNET_TESTING_daemons_start). The total
376 * number of times this function is called should equal the number returned
377 * from the GNUNET_TESTING_connect_topology call.
378 *
379 * The emsg variable is NULL on success (peers connected), and non-NULL on
380 * failure (peers failed to connect).
381 */
382void
383topology_callback (void *cls, const struct GNUNET_PeerIdentity *first,
384 const struct GNUNET_PeerIdentity *second, uint32_t distance,
385 const struct GNUNET_CONFIGURATION_Handle *first_cfg,
386 const struct GNUNET_CONFIGURATION_Handle *second_cfg,
387 struct GNUNET_TESTING_Daemon *first_daemon,
388 struct GNUNET_TESTING_Daemon *second_daemon,
389 const char *emsg)
390{
391 if (emsg == NULL)
392 {
393 total_connections++;
394 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
395 "connected peer %s to peer %s, distance %u\n",
396 first_daemon->shortname, second_daemon->shortname, distance);
397 }
398 else
399 {
400 failed_connections++;
401 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
402 "Failed to connect peer %s to peer %s with error :\n%s\n",
403 first_daemon->shortname, second_daemon->shortname, emsg);
404 }
405
406 if (total_connections == expected_connections)
407 {
408 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
409 "Created %d total connections, which is our target number! Starting next phase of testing.\n",
410 total_connections);
411 GNUNET_SCHEDULER_cancel (die_task);
412 die_task =
413 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from test gets");
414
415 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
416 (GNUNET_TIME_UNIT_SECONDS, 2), &do_get, NULL);
417 }
418 else if (total_connections + failed_connections == expected_connections)
419 {
420 GNUNET_SCHEDULER_cancel (die_task);
421 die_task =
422 GNUNET_SCHEDULER_add_now (&end_badly,
423 "from topology_callback (too many failed connections)");
424 }
425}
426
427
428/**
429 * Callback which is called whenever a peer is started (as a result of the
430 * GNUNET_TESTING_daemons_start call.
431 *
432 * @param cls closure argument given to GNUNET_TESTING_daemons_start
433 * @param id the GNUNET_PeerIdentity of the started peer
434 * @param cfg the configuration for this specific peer (needed to connect
435 * to the DHT)
436 * @param d the handle to the daemon started
437 * @param emsg NULL if peer started, non-NULL on error
438 */
439static void
440peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id,
441 const struct GNUNET_CONFIGURATION_Handle *cfg,
442 struct GNUNET_TESTING_Daemon *d, const char *emsg)
443{
444 if (emsg != NULL)
445 {
446 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
447 "Failed to start daemon with error: `%s'\n", emsg);
448 return;
449 }
450 GNUNET_assert (id != NULL);
451
452 /* This is the first peer started */
453 if (peers_left == num_peers)
454 {
455 memcpy (&peer1id, id, sizeof (struct GNUNET_PeerIdentity)); /* Save the peer id */
456 peer1dht = GNUNET_DHT_connect (cfg, 100); /* Connect to the first peers DHT service */
457 if (peer1dht == NULL) /* If DHT connect failed */
458 {
459 GNUNET_SCHEDULER_cancel (die_task);
460 GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n");
461 }
462 }
463 else /* This is the second peer started */
464 {
465 memcpy (&peer2id, id, sizeof (struct GNUNET_PeerIdentity)); /* Same as for first peer... */
466 peer2dht = GNUNET_DHT_connect (cfg, 100);
467 if (peer2dht == NULL)
468 {
469 GNUNET_SCHEDULER_cancel (die_task);
470 GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n");
471 }
472 }
473
474 /* Decrement number of peers left to start */
475 peers_left--;
476
477 if (peers_left == 0) /* Indicates all peers started */
478 {
479 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
480 "All %d daemons started, now connecting peers!\n", num_peers);
481 expected_connections = -1;
482 if ((pg != NULL)) /* Sanity check */
483 {
484 /* Connect peers in a "straight line" topology, return the number of expected connections */
485 expected_connections =
486 GNUNET_TESTING_connect_topology (pg, GNUNET_TESTING_TOPOLOGY_LINE,
487 GNUNET_TESTING_TOPOLOGY_OPTION_ALL,
488 0.0, TIMEOUT, 12, NULL, NULL);
489 }
490
491 /* Cancel current timeout fail task */
492 GNUNET_SCHEDULER_cancel (die_task);
493 if (expected_connections == GNUNET_SYSERR) /* Some error happened */
494 die_task =
495 GNUNET_SCHEDULER_add_now (&end_badly,
496 "from connect topology (bad return)");
497
498 /* Schedule timeout on failure task */
499 die_task =
500 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
501 "from connect topology (timeout)");
502 ok = 0;
503 }
504}
505
506static void
507run (void *cls, char *const *args, const char *cfgfile,
508 const struct GNUNET_CONFIGURATION_Handle *cfg)
509{
510
511 /* Get path from configuration file */
512 if (GNUNET_YES !=
513 GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
514 &test_directory))
515 {
516 ok = 404;
517 return;
518 }
519
520 /* Get number of peers to start from configuration (should be two) */
521 if (GNUNET_SYSERR ==
522 GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "num_peers",
523 &num_peers))
524 num_peers = DEFAULT_NUM_PEERS;
525
526 /* Set peers_left so we know when all peers started */
527 peers_left = num_peers;
528
529 /* Set up a task to end testing if peer start fails */
530 die_task =
531 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
532 "didn't start all daemons in reasonable amount of time!!!");
533
534 /* Start num_peers peers, call peers_started_callback on peer start, topology_callback on peer connect */
535 /* Read the API documentation for other parameters! */
536 pg = GNUNET_TESTING_daemons_start (cfg, num_peers, 2, 2, TIMEOUT, NULL, NULL,
537 &peers_started_callback, NULL,
538 &topology_callback, NULL, NULL);
539
540}
541
542static int
543check ()
544{
545 int ret;
546
547 /* Arguments for GNUNET_PROGRAM_run */
548 char *const argv[] = { "test-dht-twopeer-get-put", /* Name to give running binary */
549 "-c",
550 "test_dht_twopeer_data.conf", /* Config file to use */
551 NULL
552 };
553 struct GNUNET_GETOPT_CommandLineOption options[] = {
554 GNUNET_GETOPT_OPTION_END
555 };
556 /* Run the run function as a new program */
557 ret =
558 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
559 "test-dht-twopeer-get-put", "nohelp", options, &run,
560 &ok);
561 if (ret != GNUNET_OK)
562 {
563 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
564 "`test-dht-twopeer': Failed with error code %d\n", ret);
565 }
566 return ok;
567}
568
569int
570main (int argc, char *argv[])
571{
572 int ret;
573
574 GNUNET_log_setup ("test-dht-twopeer",
575 "WARNING",
576 NULL);
577 ret = check ();
578 /**
579 * Need to remove base directory, subdirectories taken care
580 * of by the testing framework.
581 */
582 if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
583 {
584 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
585 "Failed to remove testing directory %s\n", test_directory);
586 }
587 return ret;
588}
589
590/* end of test_dht_twopeer_get_put.c */
diff --git a/src/dht/test_dht_twopeer_path_tracking.c b/src/dht/test_dht_twopeer_path_tracking.c
deleted file mode 100644
index 86086b806..000000000
--- a/src/dht/test_dht_twopeer_path_tracking.c
+++ /dev/null
@@ -1,522 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file dht/test_dht_twopeer_path_tracking.c
22 * @brief testcase for testing DHT service with
23 * two running peers, logging the path of the dht requests.
24 */
25#include "platform.h"
26#include "gnunet_testing_lib.h"
27#include "gnunet_core_service.h"
28#include "gnunet_dht_service.h"
29
30/* DEFINES */
31#define VERBOSE GNUNET_NO
32
33/* Timeout for entire testcase */
34#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
35
36/* Timeout for waiting for replies to get requests */
37#define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
38
39/* If number of peers not in config file, use this number */
40#define DEFAULT_NUM_PEERS 2
41
42/* Globals */
43
44/**
45 * Directory to store temp data in, defined in config file
46 */
47static char *test_directory;
48
49/**
50 * Variable used to store the number of connections we should wait for.
51 */
52static unsigned int expected_connections;
53
54/**
55 * Variable used to keep track of how many peers aren't yet started.
56 */
57static unsigned long long peers_left;
58
59/**
60 * Handle to the set of all peers run for this test.
61 */
62static struct GNUNET_TESTING_PeerGroup *pg;
63
64/**
65 * Global handle we will use for GET requests.
66 */
67struct GNUNET_DHT_GetHandle *global_get_handle;
68
69
70/**
71 * Total number of peers to run, set based on config file.
72 */
73static unsigned long long num_peers;
74
75/**
76 * Global used to count how many connections we have currently
77 * been notified about (how many times has topology_callback been called
78 * with success?)
79 */
80static unsigned int total_connections;
81
82/**
83 * Global used to count how many failed connections we have
84 * been notified about (how many times has topology_callback
85 * been called with failure?)
86 */
87static unsigned int failed_connections;
88
89/**
90 * Task handle to use to schedule test failure
91 */
92GNUNET_SCHEDULER_TaskIdentifier die_task;
93
94/**
95 * Global return value (0 for success, anything else for failure)
96 */
97static int ok;
98
99/**
100 * Peer identity of the first peer started.
101 */
102static struct GNUNET_PeerIdentity peer1id;
103
104/**
105 * Peer identity of the second peer started.
106 */
107static struct GNUNET_PeerIdentity peer2id;
108
109/**
110 * Handle to the first peers DHT service (via the API)
111 */
112static struct GNUNET_DHT_Handle *peer1dht;
113
114/**
115 * Handle to the second peers DHT service (via the API)
116 */
117static struct GNUNET_DHT_Handle *peer2dht;
118
119/**
120 * Check whether peers successfully shut down.
121 */
122void
123shutdown_callback (void *cls, const char *emsg)
124{
125 if (emsg != NULL)
126 {
127 if (ok == 0)
128 ok = 2;
129 }
130}
131
132/**
133 * Function scheduled to be run on the successful completion of this
134 * testcase. Specifically, called when our get request completes.
135 */
136static void
137finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
138{
139 GNUNET_assert (pg != NULL);
140 GNUNET_assert (peer1dht != NULL);
141 GNUNET_assert (peer2dht != NULL);
142 GNUNET_DHT_disconnect (peer1dht);
143 GNUNET_DHT_disconnect (peer2dht);
144 GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
145 ok = 0;
146}
147
148/**
149 * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
150 * down the peers without freeing memory associated with GET request.
151 */
152static void
153end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
154{
155 if (peer1dht != NULL)
156 GNUNET_DHT_disconnect (peer1dht);
157
158 if (peer2dht != NULL)
159 GNUNET_DHT_disconnect (peer2dht);
160
161 if (pg != NULL)
162 GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
163}
164
165/**
166 * Check if the get_handle is being used, if so stop the request. Either
167 * way, schedule the end_badly_cont function which actually shuts down the
168 * test.
169 */
170static void
171end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
172{
173 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failing test with error: `%s'!\n",
174 (char *) cls);
175 if (global_get_handle != NULL)
176 {
177 GNUNET_DHT_get_stop (global_get_handle);
178 global_get_handle = NULL;
179 }
180 GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
181 ok = 1;
182}
183
184/**
185 * Iterator called if the GET request initiated returns a response.
186 *
187 * @param cls closure
188 * @param exp when will this value expire
189 * @param key key of the result
190 * @param type type of the result
191 * @param size number of bytes in data
192 * @param data pointer to the result data
193 */
194static void
195get_result_iterator (void *cls, struct GNUNET_TIME_Absolute exp,
196 const struct GNUNET_HashCode * key,
197 const struct GNUNET_PeerIdentity *get_path,
198 unsigned int get_path_length,
199 const struct GNUNET_PeerIdentity *put_path,
200 unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
201 size_t size, const void *data)
202{
203 struct GNUNET_HashCode original_key; /* Key data was stored data under */
204 char original_data[4]; /* Made up data that was stored */
205
206 memset (&original_key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to what it was set to previously */
207 memset (original_data, 43, sizeof (original_data));
208#if VERBOSE
209 unsigned int i;
210#endif
211
212 if ((0 != memcmp (&original_key, key, sizeof (struct GNUNET_HashCode))) ||
213 (0 != memcmp (original_data, data, sizeof (original_data))))
214 {
215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
216 "Key or data is not the same as was inserted!\n");
217 GNUNET_SCHEDULER_cancel (die_task);
218 GNUNET_SCHEDULER_add_now (&end_badly,
219 "key or data mismatch in get response!\n");
220 return;
221 }
222
223#if VERBOSE
224 if (put_path != NULL)
225 {
226 FPRINTF (stderr, "%s", "PUT Path: ");
227 for (i = 0; i < put_path_length; i++)
228 FPRINTF (stderr, "%s%s", i == 0 ? "" : "->", GNUNET_i2s (&put_path[i]));
229 FPRINTF (stderr, "%s", "\n");
230 }
231 if (get_path != NULL)
232 {
233 FPRINTF (stderr, "%s", "GET Path: ");
234 for (i = 0; i < get_path_length; i++)
235 FPRINTF (stderr, "%s%s", i == 0 ? "" : "->", GNUNET_i2s (&get_path[i]));
236 FPRINTF (stderr, "%s", "\n");
237 }
238#endif
239
240 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received correct GET response!\n");
241 GNUNET_SCHEDULER_cancel (die_task);
242 GNUNET_DHT_get_stop (global_get_handle);
243 GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
244}
245
246
247/**
248 * Called when the PUT request has been transmitted to the DHT service.
249 * Schedule the GET request for some time in the future.
250 */
251static void
252put_finished (void *cls, int success)
253{
254 struct GNUNET_HashCode key; /* Key for data lookup */
255
256 GNUNET_SCHEDULER_cancel (die_task);
257 die_task =
258 GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &end_badly,
259 "waiting for get response (data not found)");
260 memset (&key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to the same thing as when data was inserted */
261 global_get_handle =
262 GNUNET_DHT_get_start (peer2dht,
263 GNUNET_BLOCK_TYPE_TEST, &key, 1,
264 GNUNET_DHT_RO_RECORD_ROUTE, NULL, 0,
265 &get_result_iterator, NULL);
266}
267
268/**
269 * Set up some data, and call API PUT function
270 */
271static void
272do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
273{
274 struct GNUNET_HashCode key; /* Made up key to store data under */
275 char data[4]; /* Made up data to store */
276
277 memset (&key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to something simple so we can issue GET request */
278 memset (data, 43, sizeof (data));
279
280 /* Insert the data at the first peer */
281 GNUNET_DHT_put (peer1dht, &key, 1, GNUNET_DHT_RO_RECORD_ROUTE,
282 GNUNET_BLOCK_TYPE_TEST, sizeof (data), data,
283 GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_REL,
284 &put_finished, NULL);
285}
286
287/**
288 * This function is called whenever a connection attempt is finished between two of
289 * the started peers (started with GNUNET_TESTING_daemons_start). The total
290 * number of times this function is called should equal the number returned
291 * from the GNUNET_TESTING_connect_topology call.
292 *
293 * The emsg variable is NULL on success (peers connected), and non-NULL on
294 * failure (peers failed to connect).
295 */
296static void
297topology_callback (void *cls, const struct GNUNET_PeerIdentity *first,
298 const struct GNUNET_PeerIdentity *second, uint32_t distance,
299 const struct GNUNET_CONFIGURATION_Handle *first_cfg,
300 const struct GNUNET_CONFIGURATION_Handle *second_cfg,
301 struct GNUNET_TESTING_Daemon *first_daemon,
302 struct GNUNET_TESTING_Daemon *second_daemon,
303 const char *emsg)
304{
305 if (emsg == NULL)
306 {
307 total_connections++;
308#if VERBOSE
309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
310 "connected peer %s to peer %s, distance %u\n",
311 first_daemon->shortname, second_daemon->shortname, distance);
312#endif
313 }
314#if VERBOSE
315 else
316 {
317 failed_connections++;
318 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
319 "Failed to connect peer %s to peer %s with error :\n%s\n",
320 first_daemon->shortname, second_daemon->shortname, emsg);
321 }
322#endif
323
324 if (total_connections == expected_connections)
325 {
326#if VERBOSE
327 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
328 "Created %d total connections, which is our target number! Starting next phase of testing.\n",
329 total_connections);
330#endif
331 GNUNET_SCHEDULER_cancel (die_task);
332 die_task =
333 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from test gets");
334
335 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
336 (GNUNET_TIME_UNIT_SECONDS, 2), &do_put, NULL);
337 }
338 else if (total_connections + failed_connections == expected_connections)
339 {
340 GNUNET_SCHEDULER_cancel (die_task);
341 die_task =
342 GNUNET_SCHEDULER_add_now (&end_badly,
343 "from topology_callback (too many failed connections)");
344 }
345}
346
347
348/**
349 * Callback which is called whenever a peer is started (as a result of the
350 * GNUNET_TESTING_daemons_start call.
351 *
352 * @param cls closure argument given to GNUNET_TESTING_daemons_start
353 * @param id the GNUNET_PeerIdentity of the started peer
354 * @param cfg the configuration for this specific peer (needed to connect
355 * to the DHT)
356 * @param d the handle to the daemon started
357 * @param emsg NULL if peer started, non-NULL on error
358 */
359static void
360peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id,
361 const struct GNUNET_CONFIGURATION_Handle *cfg,
362 struct GNUNET_TESTING_Daemon *d, const char *emsg)
363{
364 if (emsg != NULL)
365 {
366 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
367 "Failed to start daemon with error: `%s'\n", emsg);
368 return;
369 }
370 GNUNET_assert (id != NULL);
371
372 /* This is the first peer started */
373 if (peers_left == num_peers)
374 {
375 memcpy (&peer1id, id, sizeof (struct GNUNET_PeerIdentity)); /* Save the peer id */
376 peer1dht = GNUNET_DHT_connect (cfg, 100); /* Connect to the first peers DHT service */
377 if (peer1dht == NULL) /* If DHT connect failed */
378 {
379 GNUNET_SCHEDULER_cancel (die_task);
380 GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n");
381 }
382 }
383 else /* This is the second peer started */
384 {
385 memcpy (&peer2id, id, sizeof (struct GNUNET_PeerIdentity)); /* Same as for first peer... */
386 peer2dht = GNUNET_DHT_connect (cfg, 100);
387 if (peer2dht == NULL)
388 {
389 GNUNET_SCHEDULER_cancel (die_task);
390 GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n");
391 }
392 }
393
394 /* Decrement number of peers left to start */
395 peers_left--;
396
397 if (peers_left == 0) /* Indicates all peers started */
398 {
399#if VERBOSE
400 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
401 "All %d daemons started, now connecting peers!\n", num_peers);
402#endif
403 expected_connections = -1;
404 if ((pg != NULL)) /* Sanity check */
405 {
406 /* Connect peers in a "straight line" topology, return the number of expected connections */
407 expected_connections =
408 GNUNET_TESTING_connect_topology (pg, GNUNET_TESTING_TOPOLOGY_LINE,
409 GNUNET_TESTING_TOPOLOGY_OPTION_ALL,
410 0.0, TIMEOUT, 2, NULL, NULL);
411 }
412
413 /* Cancel current timeout fail task */
414 GNUNET_SCHEDULER_cancel (die_task);
415 if (expected_connections == GNUNET_SYSERR) /* Some error happened */
416 die_task =
417 GNUNET_SCHEDULER_add_now (&end_badly,
418 "from connect topology (bad return)");
419
420 /* Schedule timeout on failure task */
421 die_task =
422 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
423 "from connect topology (timeout)");
424 ok = 0;
425 }
426}
427
428static void
429run (void *cls, char *const *args, const char *cfgfile,
430 const struct GNUNET_CONFIGURATION_Handle *cfg)
431{
432
433 /* Get path from configuration file */
434 if (GNUNET_YES !=
435 GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
436 &test_directory))
437 {
438 ok = 404;
439 return;
440 }
441
442 /* Get number of peers to start from configuration (should be two) */
443 if (GNUNET_SYSERR ==
444 GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "num_peers",
445 &num_peers))
446 num_peers = DEFAULT_NUM_PEERS;
447
448 /* Set peers_left so we know when all peers started */
449 peers_left = num_peers;
450
451 /* Set up a task to end testing if peer start fails */
452 die_task =
453 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
454 "didn't start all daemons in reasonable amount of time!!!");
455
456 /* Start num_peers peers, call peers_started_callback on peer start, topology_callback on peer connect */
457 /* Read the API documentation for other parameters! */
458 pg = GNUNET_TESTING_daemons_start (cfg, peers_left, /* Total number of peers */
459 peers_left, /* Number of outstanding connections */
460 peers_left, /* Number of parallel ssh connections, or peers being started at once */
461 TIMEOUT, NULL, NULL,
462 &peers_started_callback, NULL,
463 &topology_callback, NULL, NULL);
464
465}
466
467static int
468check ()
469{
470 int ret;
471
472 /* Arguments for GNUNET_PROGRAM_run */
473 char *const argv[] = { "test-dht-twopeer-put-get", /* Name to give running binary */
474 "-c",
475 "test_dht_twopeer_data.conf", /* Config file to use */
476#if VERBOSE
477 "-L", "DEBUG",
478#endif
479 NULL
480 };
481 struct GNUNET_GETOPT_CommandLineOption options[] = {
482 GNUNET_GETOPT_OPTION_END
483 };
484 /* Run the run function as a new program */
485 ret =
486 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
487 "test-dht-twopeer-put-get", "nohelp", options, &run,
488 &ok);
489 if (ret != GNUNET_OK)
490 {
491 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
492 "`test-dht-twopeer': Failed with error code %d\n", ret);
493 }
494 return ok;
495}
496
497int
498main (int argc, char *argv[])
499{
500 int ret;
501
502 GNUNET_log_setup ("test-dht-twopeer",
503#if VERBOSE
504 "DEBUG",
505#else
506 "WARNING",
507#endif
508 NULL);
509 ret = check ();
510 /**
511 * Need to remove base directory, subdirectories taken care
512 * of by the testing framework.
513 */
514 if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
515 {
516 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
517 "Failed to remove testing directory %s\n", test_directory);
518 }
519 return ret;
520}
521
522/* end of test_dht_twopeer_put_get.c */
diff --git a/src/dht/test_dht_twopeer_put_get.c b/src/dht/test_dht_twopeer_put_get.c
deleted file mode 100644
index d577a856a..000000000
--- a/src/dht/test_dht_twopeer_put_get.c
+++ /dev/null
@@ -1,510 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file dht/test_dht_twopeer_put_get.c
22 * @brief base testcase for testing DHT service with
23 * two running peers.
24 *
25 * This testcase starts peers using the GNUNET_TESTING_daemons_start
26 * function call. On peer start, connects to the peers DHT service
27 * by calling GNUNET_DHT_connected. Once notified about all peers
28 * being started (by the peers_started_callback function), calls
29 * GNUNET_TESTING_connect_topology, which connects the peers in a
30 * "straight line" topology. On notification that all peers have
31 * been properly connected, runs the do_put function to insert data
32 * at the first peer. Once the GNUNET_DHT_put function completes,
33 * calls the do_get function which initiates a GNUNET_DHT_get from
34 * the *second* peer. If the GET is successful, schedules finish_testing
35 * to stop the test and shut down peers. If GET is unsuccessful
36 * after GET_TIMEOUT seconds, prints an error message and shuts down
37 * the peers.
38 */
39#include "platform.h"
40#include "gnunet_testing_lib.h"
41#include "gnunet_core_service.h"
42#include "gnunet_dht_service.h"
43#include "block_dns.h"
44#include "gnunet_signatures.h"
45
46/* DEFINES */
47#define VERBOSE GNUNET_NO
48
49/* Timeout for entire testcase */
50#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
51
52/* Timeout for waiting for replies to get requests */
53#define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
54
55/* If number of peers not in config file, use this number */
56#define DEFAULT_NUM_PEERS 2
57
58/* Globals */
59
60/**
61 * Directory to store temp data in, defined in config file
62 */
63static char *test_directory;
64
65/**
66 * Variable used to store the number of connections we should wait for.
67 */
68static unsigned int expected_connections;
69
70/**
71 * Variable used to keep track of how many peers aren't yet started.
72 */
73static unsigned long long peers_left;
74
75/**
76 * Handle to the set of all peers run for this test.
77 */
78static struct GNUNET_TESTING_PeerGroup *pg;
79
80/**
81 * Global handle we will use for GET requests.
82 */
83struct GNUNET_DHT_GetHandle *global_get_handle;
84
85
86/**
87 * Total number of peers to run, set based on config file.
88 */
89static unsigned long long num_peers;
90
91/**
92 * Global used to count how many connections we have currently
93 * been notified about (how many times has topology_callback been called
94 * with success?)
95 */
96static unsigned int total_connections;
97
98/**
99 * Global used to count how many failed connections we have
100 * been notified about (how many times has topology_callback
101 * been called with failure?)
102 */
103static unsigned int failed_connections;
104
105/* Task handle to use to schedule test failure */
106static GNUNET_SCHEDULER_TaskIdentifier die_task;
107
108/* Global return value (0 for success, anything else for failure) */
109static int ok;
110
111/**
112 * Peer identity of the first peer started.
113 */
114static struct GNUNET_PeerIdentity peer1id;
115
116/**
117 * Peer identity of the second peer started.
118 */
119static struct GNUNET_PeerIdentity peer2id;
120
121/**
122 * Handle to the first peers DHT service (via the API)
123 */
124static struct GNUNET_DHT_Handle *peer1dht;
125
126/**
127 * Handle to the second peers DHT service (via the API)
128 */
129static struct GNUNET_DHT_Handle *peer2dht;
130
131/**
132 * Handle for our PUT operation.
133 */
134static struct GNUNET_DHT_PutHandle *put_op;
135
136
137/**
138 * Check whether peers successfully shut down.
139 */
140static void
141shutdown_callback (void *cls, const char *emsg)
142{
143 if (emsg != NULL)
144 {
145 if (ok == 0)
146 ok = 2;
147 }
148}
149
150/**
151 * Function scheduled to be run on the successful completion of this
152 * testcase. Specifically, called when our get request completes.
153 */
154static void
155finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
156{
157 GNUNET_assert (pg != NULL);
158 GNUNET_assert (peer1dht != NULL);
159 GNUNET_assert (peer2dht != NULL);
160 GNUNET_DHT_disconnect (peer1dht);
161 GNUNET_DHT_disconnect (peer2dht);
162 GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
163 ok = 0;
164}
165
166/**
167 * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
168 * down the peers without freeing memory associated with GET request.
169 */
170static void
171end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
172{
173 if (NULL != put_op)
174 {
175 GNUNET_DHT_put_cancel (put_op);
176 put_op = NULL;
177 }
178 if (peer1dht != NULL)
179 GNUNET_DHT_disconnect (peer1dht);
180
181 if (peer2dht != NULL)
182 GNUNET_DHT_disconnect (peer2dht);
183
184 if (pg != NULL)
185 GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
186}
187
188
189/**
190 * Check if the get_handle is being used, if so stop the request. Either
191 * way, schedule the end_badly_cont function which actually shuts down the
192 * test.
193 */
194static void
195end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
196{
197 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failing test with error: `%s'!\n",
198 (char *) cls);
199 if (global_get_handle != NULL)
200 {
201 GNUNET_DHT_get_stop (global_get_handle);
202 global_get_handle = NULL;
203 }
204 GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
205 ok = 1;
206}
207
208/**
209 * Iterator called if the GET request initiated returns a response.
210 *
211 * @param cls closure
212 * @param exp when will this value expire
213 * @param key key of the result
214 * @param type type of the result
215 * @param size number of bytes in data
216 * @param data pointer to the result data
217 */
218static void
219get_result_iterator (void *cls, struct GNUNET_TIME_Absolute exp,
220 const struct GNUNET_HashCode * key,
221 const struct GNUNET_PeerIdentity *get_path,
222 unsigned int get_path_size,
223 const struct GNUNET_PeerIdentity *put_path,
224 unsigned int put_path_size, enum GNUNET_BLOCK_Type type,
225 size_t size, const void *result_data)
226{
227 struct GNUNET_HashCode original_key; /* Key data was stored data under */
228 char original_data[4]; /* Made up data that was stored */
229
230 memset (&original_key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to what it was set to previously */
231 memset (original_data, 43, sizeof (original_data));
232
233 if ((sizeof (original_data) != size) ||
234 (0 != memcmp (&original_key, key, sizeof (struct GNUNET_HashCode))) ||
235 (0 != memcmp (original_data, result_data, sizeof (original_data))))
236 {
237 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
238 "Key or data is not the same as was inserted!\n");
239 GNUNET_SCHEDULER_cancel (die_task);
240 GNUNET_SCHEDULER_add_now (&end_badly,
241 "key or data mismatch in get response!\n");
242 return;
243 }
244
245 GNUNET_SCHEDULER_cancel (die_task);
246 GNUNET_DHT_get_stop (global_get_handle);
247 global_get_handle = NULL;
248 GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
249}
250
251
252/**
253 * Called when the PUT request has been transmitted to the DHT service.
254 * Schedule the GET request for some time in the future.
255 */
256static void
257put_finished (void *cls, int success)
258{
259 struct GNUNET_HashCode key; /* Key for data lookup */
260
261 put_op = NULL;
262 GNUNET_SCHEDULER_cancel (die_task);
263 die_task =
264 GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &end_badly,
265 "waiting for get response (data not found)");
266
267 memset (&key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to the same thing as when data was inserted */
268 global_get_handle =
269 GNUNET_DHT_get_start (peer2dht,
270 GNUNET_BLOCK_TYPE_TEST, &key, 1, GNUNET_DHT_RO_NONE,
271 NULL, 0, &get_result_iterator, NULL);
272}
273
274
275/**
276 * Set up some data, and call API PUT function
277 */
278static void
279do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
280{
281 struct GNUNET_HashCode key; /* Made up key to store data under */
282 char data[4]; /* Made up data to store */
283
284 memset (&key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to something simple so we can issue GET request */
285 memset (data, 43, sizeof (data));
286
287 /* Insert the data at the first peer */
288 put_op = GNUNET_DHT_put (peer1dht, &key, 1, GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_TEST,
289 sizeof (data), data, GNUNET_TIME_UNIT_FOREVER_ABS,
290 GNUNET_TIME_UNIT_FOREVER_REL, &put_finished, NULL);
291}
292
293
294/**
295 * This function is called whenever a connection attempt is finished between two of
296 * the started peers (started with GNUNET_TESTING_daemons_start). The total
297 * number of times this function is called should equal the number returned
298 * from the GNUNET_TESTING_connect_topology call.
299 *
300 * The emsg variable is NULL on success (peers connected), and non-NULL on
301 * failure (peers failed to connect).
302 */
303static void
304topology_callback (void *cls, const struct GNUNET_PeerIdentity *first,
305 const struct GNUNET_PeerIdentity *second, uint32_t distance,
306 const struct GNUNET_CONFIGURATION_Handle *first_cfg,
307 const struct GNUNET_CONFIGURATION_Handle *second_cfg,
308 struct GNUNET_TESTING_Daemon *first_daemon,
309 struct GNUNET_TESTING_Daemon *second_daemon,
310 const char *emsg)
311{
312 if (emsg == NULL)
313 {
314 total_connections++;
315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
316 "connected peer %s to peer %s, distance %u\n",
317 first_daemon->shortname, second_daemon->shortname, distance);
318 }
319 else
320 {
321 failed_connections++;
322 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
323 "Failed to connect peer %s to peer %s with error :\n%s\n",
324 first_daemon->shortname, second_daemon->shortname, emsg);
325 }
326
327 if (total_connections == expected_connections)
328 {
329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
330 "Created %d total connections, which is our target number! Starting next phase of testing.\n",
331 total_connections);
332 GNUNET_SCHEDULER_cancel (die_task);
333 die_task =
334 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from test gets");
335
336 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_put, NULL);
337 }
338 else if (total_connections + failed_connections == expected_connections)
339 {
340 GNUNET_SCHEDULER_cancel (die_task);
341 die_task =
342 GNUNET_SCHEDULER_add_now (&end_badly,
343 "from topology_callback (too many failed connections)");
344 }
345}
346
347
348/**
349 * Callback which is called whenever a peer is started (as a result of the
350 * GNUNET_TESTING_daemons_start call.
351 *
352 * @param cls closure argument given to GNUNET_TESTING_daemons_start
353 * @param id the GNUNET_PeerIdentity of the started peer
354 * @param cfg the configuration for this specific peer (needed to connect
355 * to the DHT)
356 * @param d the handle to the daemon started
357 * @param emsg NULL if peer started, non-NULL on error
358 */
359static void
360peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id,
361 const struct GNUNET_CONFIGURATION_Handle *cfg,
362 struct GNUNET_TESTING_Daemon *d, const char *emsg)
363{
364 if (emsg != NULL)
365 {
366 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
367 "Failed to start daemon with error: `%s'\n", emsg);
368 return;
369 }
370 GNUNET_assert (id != NULL);
371
372 /* This is the first peer started */
373 if (peers_left == num_peers)
374 {
375 memcpy (&peer1id, id, sizeof (struct GNUNET_PeerIdentity)); /* Save the peer id */
376 peer1dht = GNUNET_DHT_connect (cfg, 100); /* Connect to the first peers DHT service */
377 if (peer1dht == NULL) /* If DHT connect failed */
378 {
379 GNUNET_SCHEDULER_cancel (die_task);
380 GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n");
381 }
382 }
383 else /* This is the second peer started */
384 {
385 memcpy (&peer2id, id, sizeof (struct GNUNET_PeerIdentity)); /* Same as for first peer... */
386 peer2dht = GNUNET_DHT_connect (cfg, 100);
387 if (peer2dht == NULL)
388 {
389 GNUNET_SCHEDULER_cancel (die_task);
390 GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n");
391 }
392 }
393
394 /* Decrement number of peers left to start */
395 peers_left--;
396
397 if (peers_left == 0) /* Indicates all peers started */
398 {
399 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
400 "All %d daemons started, now connecting peers!\n", num_peers);
401 expected_connections = -1;
402 if ((pg != NULL)) /* Sanity check */
403 {
404 /* Connect peers in a "straight line" topology, return the number of expected connections */
405 expected_connections =
406 GNUNET_TESTING_connect_topology (pg, GNUNET_TESTING_TOPOLOGY_LINE,
407 GNUNET_TESTING_TOPOLOGY_OPTION_ALL,
408 0.0, TIMEOUT, 12, NULL, NULL);
409 }
410
411 /* Cancel current timeout fail task */
412 GNUNET_SCHEDULER_cancel (die_task);
413 if (expected_connections == GNUNET_SYSERR) /* Some error happened */
414 die_task =
415 GNUNET_SCHEDULER_add_now (&end_badly,
416 "from connect topology (bad return)");
417
418 /* Schedule timeout on failure task */
419 die_task =
420 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
421 "from connect topology (timeout)");
422 ok = 0;
423 }
424}
425
426static void
427run (void *cls, char *const *args, const char *cfgfile,
428 const struct GNUNET_CONFIGURATION_Handle *cfg)
429{
430
431 /* Get path from configuration file */
432 if (GNUNET_YES !=
433 GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
434 &test_directory))
435 {
436 ok = 404;
437 return;
438 }
439
440 /* Get number of peers to start from configuration (should be two) */
441 if (GNUNET_SYSERR ==
442 GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "num_peers",
443 &num_peers))
444 num_peers = DEFAULT_NUM_PEERS;
445
446 /* Set peers_left so we know when all peers started */
447 peers_left = num_peers;
448
449 /* Set up a task to end testing if peer start fails */
450 die_task =
451 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
452 "didn't start all daemons in reasonable amount of time!!!");
453
454 /* Start num_peers peers, call peers_started_callback on peer start, topology_callback on peer connect */
455 /* Read the API documentation for other parameters! */
456 pg = GNUNET_TESTING_daemons_start (cfg, num_peers, 2, 2, TIMEOUT, NULL, NULL,
457 &peers_started_callback, NULL,
458 &topology_callback, NULL, NULL);
459
460}
461
462static int
463check ()
464{
465 int ret;
466
467 /* Arguments for GNUNET_PROGRAM_run */
468 char *const argv[] = { "test-dht-twopeer-put-get", /* Name to give running binary */
469 "-c",
470 "test_dht_twopeer_data.conf", /* Config file to use */
471 NULL
472 };
473 struct GNUNET_GETOPT_CommandLineOption options[] = {
474 GNUNET_GETOPT_OPTION_END
475 };
476 /* Run the run function as a new program */
477 ret =
478 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
479 "test-dht-twopeer-put-get", "nohelp", options, &run,
480 &ok);
481 if (ret != GNUNET_OK)
482 {
483 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
484 "`test-dht-twopeer': Failed with error code %d\n", ret);
485 }
486 return ok;
487}
488
489int
490main (int argc, char *argv[])
491{
492 int ret;
493
494 GNUNET_log_setup ("test-dht-twopeer",
495 "WARNING",
496 NULL);
497 ret = check ();
498 /**
499 * Need to remove base directory, subdirectories taken care
500 * of by the testing framework.
501 */
502 if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
503 {
504 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
505 "Failed to remove testing directory %s\n", test_directory);
506 }
507 return ret;
508}
509
510/* end of test_dht_twopeer_put_get.c */