aboutsummaryrefslogtreecommitdiff
path: root/src/testing
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing')
-rw-r--r--src/testing/test_testing.c16
-rw-r--r--src/testing/test_testing_connect.c24
-rw-r--r--src/testing/test_testing_data_topology_clique.conf2
-rw-r--r--src/testing/test_testing_data_topology_ring.conf1
-rw-r--r--src/testing/test_testing_group.c1
-rw-r--r--src/testing/test_testing_topology.c138
-rw-r--r--src/testing/testing.c355
-rw-r--r--src/testing/testing_group.c1195
8 files changed, 1598 insertions, 134 deletions
diff --git a/src/testing/test_testing.c b/src/testing/test_testing.c
index 925579a71..b33f3ee1b 100644
--- a/src/testing/test_testing.c
+++ b/src/testing/test_testing.c
@@ -33,14 +33,16 @@ end_cb (void *cls, const char *emsg)
33{ 33{
34 if (emsg != NULL) 34 if (emsg != NULL)
35 { 35 {
36 fprintf (stderr, "Error terminaing daemon: `%s'\n", 36 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg);
37 emsg); 37 ok = 1;
38 return;
39 } 38 }
39 else
40 {
40#if VERBOSE 41#if VERBOSE
41 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon terminated, will now exit.\n"); 42 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon terminated, will now exit.\n");
42#endif 43#endif
43 ok = 0; 44 ok = 0;
45 }
44} 46}
45 47
46static void 48static void
@@ -54,7 +56,7 @@ my_cb (void *cls,
54 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 56 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
55 "Daemon `%s' started, will now stop it.\n", GNUNET_i2s (id)); 57 "Daemon `%s' started, will now stop it.\n", GNUNET_i2s (id));
56#endif 58#endif
57 GNUNET_TESTING_daemon_stop (d, &end_cb, NULL); 59 GNUNET_TESTING_daemon_stop (d, &end_cb, NULL, GNUNET_YES);
58} 60}
59 61
60 62
@@ -70,7 +72,7 @@ run (void *cls,
70#if VERBOSE 72#if VERBOSE
71 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n"); 73 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n");
72#endif 74#endif
73 d = GNUNET_TESTING_daemon_start (sched, cfg, NULL, &my_cb, NULL); 75 d = GNUNET_TESTING_daemon_start (sched, cfg, NULL, NULL, NULL, &my_cb, NULL);
74 GNUNET_assert (d != NULL); 76 GNUNET_assert (d != NULL);
75} 77}
76 78
diff --git a/src/testing/test_testing_connect.c b/src/testing/test_testing_connect.c
index 60721298e..a55207cec 100644
--- a/src/testing/test_testing_connect.c
+++ b/src/testing/test_testing_connect.c
@@ -49,26 +49,34 @@ static struct GNUNET_SCHEDULER_Handle *sched;
49static void 49static void
50end2_cb (void *cls, const char *emsg) 50end2_cb (void *cls, const char *emsg)
51{ 51{
52 GNUNET_assert (emsg == NULL); 52
53 if (emsg != NULL)
54 {
55 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg);
56 ok = 1;
57 }
58 else
59 {
53#if VERBOSE 60#if VERBOSE
54 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 61 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
55 "Both daemons terminated, will now exit.\n"); 62 "Both daemons terminated, will now exit.\n");
56#endif 63#endif
57 ok = 0; 64 ok = 0;
65 }
58} 66}
59 67
60static void 68static void
61end1_cb (void *cls, const char *emsg) 69end1_cb (void *cls, const char *emsg)
62{ 70{
63 GNUNET_assert (emsg == NULL); 71 GNUNET_assert (emsg == NULL);
64 GNUNET_TESTING_daemon_stop (d2, &end2_cb, NULL); 72 GNUNET_TESTING_daemon_stop (d2, &end2_cb, NULL, GNUNET_YES);
65 d2 = NULL; 73 d2 = NULL;
66} 74}
67 75
68static void 76static void
69finish_testing(void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) 77finish_testing(void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
70{ 78{
71 GNUNET_TESTING_daemon_stop (d1, &end1_cb, NULL); 79 GNUNET_TESTING_daemon_stop (d1, &end1_cb, NULL, GNUNET_YES);
72 d1 = NULL; 80 d1 = NULL;
73} 81}
74 82
@@ -113,7 +121,7 @@ my_cb1 (void *cls,
113 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 121 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
114 "Daemon `%s' started.\n", GNUNET_i2s (id)); 122 "Daemon `%s' started.\n", GNUNET_i2s (id));
115#endif 123#endif
116 d2 = GNUNET_TESTING_daemon_start (sched, c2, NULL, &my_cb2, NULL); 124 d2 = GNUNET_TESTING_daemon_start (sched, c2, NULL, NULL, NULL, &my_cb2, NULL);
117 GNUNET_assert (d2 != NULL); 125 GNUNET_assert (d2 != NULL);
118 126
119} 127}
@@ -134,7 +142,7 @@ run (void *cls,
134 GNUNET_CONFIGURATION_parse (c1, "test_testing_connect_peer1.conf"); 142 GNUNET_CONFIGURATION_parse (c1, "test_testing_connect_peer1.conf");
135 c2 = GNUNET_CONFIGURATION_create (); 143 c2 = GNUNET_CONFIGURATION_create ();
136 GNUNET_CONFIGURATION_parse (c2, "test_testing_connect_peer2.conf"); 144 GNUNET_CONFIGURATION_parse (c2, "test_testing_connect_peer2.conf");
137 d1 = GNUNET_TESTING_daemon_start (sched, c1, NULL, &my_cb1, NULL); 145 d1 = GNUNET_TESTING_daemon_start (sched, c1, NULL, NULL, NULL, &my_cb1, NULL);
138 GNUNET_assert (d1 != NULL); 146 GNUNET_assert (d1 != NULL);
139} 147}
140 148
diff --git a/src/testing/test_testing_data_topology_clique.conf b/src/testing/test_testing_data_topology_clique.conf
index 11a017c87..689a45d74 100644
--- a/src/testing/test_testing_data_topology_clique.conf
+++ b/src/testing/test_testing_data_topology_clique.conf
@@ -40,7 +40,7 @@ PORT = 2570
40#DEBUG = YES 40#DEBUG = YES
41 41
42[testing] 42[testing]
43NUM_PEERS = 3 43NUM_PEERS = 4
44WEAKRANDOM = YES 44WEAKRANDOM = YES
45TOPOLOGY = 0 45TOPOLOGY = 0
46F2F = YES 46F2F = YES
diff --git a/src/testing/test_testing_data_topology_ring.conf b/src/testing/test_testing_data_topology_ring.conf
index 41493887c..480eb6392 100644
--- a/src/testing/test_testing_data_topology_ring.conf
+++ b/src/testing/test_testing_data_topology_ring.conf
@@ -34,3 +34,4 @@ NUM_PEERS = 5
34WEAKRANDOM = YES 34WEAKRANDOM = YES
35TOPOLOGY = 3 35TOPOLOGY = 3
36F2F = YES 36F2F = YES
37BLACKLISTING = YES
diff --git a/src/testing/test_testing_group.c b/src/testing/test_testing_group.c
index d9d22dd02..8458bfbd6 100644
--- a/src/testing/test_testing_group.c
+++ b/src/testing/test_testing_group.c
@@ -80,6 +80,7 @@ run (void *cls,
80 peers_left = NUM_PEERS; 80 peers_left = NUM_PEERS;
81 pg = GNUNET_TESTING_daemons_start (sched, cfg, 81 pg = GNUNET_TESTING_daemons_start (sched, cfg,
82 peers_left, 82 peers_left,
83 NULL, NULL,
83 &my_cb, NULL, NULL, NULL, NULL); 84 &my_cb, NULL, NULL, NULL, NULL);
84 GNUNET_assert (pg != NULL); 85 GNUNET_assert (pg != NULL);
85} 86}
diff --git a/src/testing/test_testing_topology.c b/src/testing/test_testing_topology.c
index 784c850f3..62ffb9a76 100644
--- a/src/testing/test_testing_topology.c
+++ b/src/testing/test_testing_topology.c
@@ -25,7 +25,7 @@
25#include "gnunet_testing_lib.h" 25#include "gnunet_testing_lib.h"
26#include "gnunet_core_service.h" 26#include "gnunet_core_service.h"
27 27
28#define VERBOSE GNUNET_YES 28#define VERBOSE GNUNET_NO
29 29
30/** 30/**
31 * How long until we fail the whole testcase? 31 * How long until we fail the whole testcase?
@@ -83,6 +83,14 @@ static int transmit_ready_called;
83 83
84static enum GNUNET_TESTING_Topology topology; 84static enum GNUNET_TESTING_Topology topology;
85 85
86static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* Don't do any blacklisting */
87
88static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */
89
90static enum GNUNET_TESTING_TopologyOption connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL;
91
92static double connect_topology_option_modifier = 0.0;
93
86static char *test_directory; 94static char *test_directory;
87 95
88#define MTYPE 12345 96#define MTYPE 12345
@@ -509,20 +517,13 @@ topology_callback (void *cls,
509 } 517 }
510} 518}
511 519
512
513static void 520static void
514create_topology () 521connect_topology ()
515{ 522{
516 expected_connections = -1; 523 expected_connections = -1;
517 if ((pg != NULL) && (peers_left == 0)) 524 if ((pg != NULL) && (peers_left == 0))
518 { 525 {
519 /* create_topology will read the topology information from 526 expected_connections = GNUNET_TESTING_connect_topology (pg, connection_topology, connect_topology_option, connect_topology_option_modifier);
520 the config already contained in the peer group, so should
521 we have create_topology called from start peers? I think
522 maybe this way is best so that the client can know both
523 when peers are started, and when they are connected.
524 */
525 expected_connections = GNUNET_TESTING_create_topology (pg, topology);
526#if VERBOSE 527#if VERBOSE
527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
528 "Have %d expected connections\n", expected_connections); 529 "Have %d expected connections\n", expected_connections);
@@ -533,20 +534,51 @@ create_topology ()
533 if (expected_connections == GNUNET_SYSERR) 534 if (expected_connections == GNUNET_SYSERR)
534 { 535 {
535 die_task = GNUNET_SCHEDULER_add_now (sched, 536 die_task = GNUNET_SCHEDULER_add_now (sched,
537 &end_badly, "from connect topology (bad return)");
538 }
539
540 die_task = GNUNET_SCHEDULER_add_delayed (sched,
541 TEST_TIMEOUT,
542 &end_badly, "from connect topology (timeout)");
543}
544
545static void
546create_topology ()
547{
548 peers_left = num_peers; /* Reset counter */
549 if (GNUNET_TESTING_create_topology (pg, topology, blacklist_topology) != GNUNET_SYSERR)
550 {
551#if VERBOSE
552 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
553 "Topology set up, now starting peers!\n");
554#endif
555 GNUNET_TESTING_daemons_continue_startup(pg);
556 }
557 else
558 {
559 GNUNET_SCHEDULER_cancel (sched, die_task);
560 die_task = GNUNET_SCHEDULER_add_now (sched,
536 &end_badly, "from create topology (bad return)"); 561 &end_badly, "from create topology (bad return)");
537 } 562 }
563 GNUNET_SCHEDULER_cancel (sched, die_task);
538 die_task = GNUNET_SCHEDULER_add_delayed (sched, 564 die_task = GNUNET_SCHEDULER_add_delayed (sched,
539 TEST_TIMEOUT, 565 TEST_TIMEOUT,
540 &end_badly, "from create topology (timeout)"); 566 &end_badly, "from continue startup (timeout)");
541} 567}
542 568
543 569
544static void 570static void
545my_cb (void *cls, 571peers_started_callback (void *cls,
546 const struct GNUNET_PeerIdentity *id, 572 const struct GNUNET_PeerIdentity *id,
547 const struct GNUNET_CONFIGURATION_Handle *cfg, 573 const struct GNUNET_CONFIGURATION_Handle *cfg,
548 struct GNUNET_TESTING_Daemon *d, const char *emsg) 574 struct GNUNET_TESTING_Daemon *d, const char *emsg)
549{ 575{
576 if (emsg != NULL)
577 {
578 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to start daemon with error: `%s'\n",
579 emsg);
580 return;
581 }
550 GNUNET_assert (id != NULL); 582 GNUNET_assert (id != NULL);
551#if VERBOSE 583#if VERBOSE
552 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n", 584 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
@@ -566,12 +598,54 @@ my_cb (void *cls,
566 die_task = GNUNET_SCHEDULER_add_delayed (sched, 598 die_task = GNUNET_SCHEDULER_add_delayed (sched,
567 GNUNET_TIME_relative_multiply 599 GNUNET_TIME_relative_multiply
568 (GNUNET_TIME_UNIT_MINUTES, 5), 600 (GNUNET_TIME_UNIT_MINUTES, 5),
569 &end_badly, "from my_cb"); 601 &end_badly, "from peers_started_callback");
570 create_topology (); 602 connect_topology ();
571 ok = 0; 603 ok = 0;
572 } 604 }
573} 605}
574 606
607/**
608 * Callback indicating that the hostkey was created for a peer.
609 *
610 * @param cls NULL
611 * @param id the peer identity
612 * @param d the daemon handle (pretty useless at this point, remove?)
613 * @param emsg non-null on failure
614 */
615void hostkey_callback (void *cls,
616 const struct GNUNET_PeerIdentity *id,
617 struct GNUNET_TESTING_Daemon *d,
618 const char *emsg)
619{
620 if (emsg != NULL)
621 {
622 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Hostkey callback received error: %s\n", emsg);
623 }
624
625#if VERBOSE
626 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
627 "Hostkey created for peer `%s'\n",
628 GNUNET_i2s(id));
629#endif
630 peers_left--;
631 if (peers_left == 0)
632 {
633#if VERBOSE
634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
635 "All %d hostkeys created, now creating topology!\n",
636 num_peers);
637#endif
638 GNUNET_SCHEDULER_cancel (sched, die_task);
639 /* Set up task in case topology creation doesn't finish
640 * within a reasonable amount of time */
641 die_task = GNUNET_SCHEDULER_add_delayed (sched,
642 GNUNET_TIME_relative_multiply
643 (GNUNET_TIME_UNIT_MINUTES, 5),
644 &end_badly, "from hostkey_callback");
645 GNUNET_SCHEDULER_add_now(sched, &create_topology, NULL);
646 ok = 0;
647 }
648}
575 649
576static void 650static void
577run (void *cls, 651run (void *cls,
@@ -580,6 +654,10 @@ run (void *cls,
580 const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) 654 const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
581{ 655{
582 unsigned long long topology_num; 656 unsigned long long topology_num;
657 unsigned long long connect_topology_num;
658 unsigned long long blacklist_topology_num;
659 unsigned long long connect_topology_option_num;
660 char *connect_topology_option_modifier_string;
583 sched = s; 661 sched = s;
584 ok = 1; 662 ok = 1;
585 663
@@ -605,6 +683,36 @@ run (void *cls,
605 &topology_num)) 683 &topology_num))
606 topology = topology_num; 684 topology = topology_num;
607 685
686 if (GNUNET_YES ==
687 GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_topology",
688 &connect_topology_num))
689 connection_topology = connect_topology_num;
690
691 if (GNUNET_YES ==
692 GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_topology_option",
693 &connect_topology_option_num))
694 connect_topology_option = connect_topology_option_num;
695
696 if (GNUNET_YES ==
697 GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "connect_topology_option_modifier",
698 &connect_topology_option_modifier_string))
699 {
700 if (sscanf(connect_topology_option_modifier_string, "%lf", &connect_topology_option_modifier) != 1)
701 {
702 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
703 _("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
704 connect_topology_option_modifier_string,
705 "connect_topology_option_modifier",
706 "TESTING");
707 GNUNET_free (connect_topology_option_modifier_string);
708 }
709 }
710
711 if (GNUNET_YES ==
712 GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "blacklist_topology",
713 &blacklist_topology_num))
714 blacklist_topology = blacklist_topology_num;
715
608 if (GNUNET_SYSERR == 716 if (GNUNET_SYSERR ==
609 GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers", 717 GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
610 &num_peers)) 718 &num_peers))
@@ -621,7 +729,7 @@ run (void *cls,
621 &end_badly, "didn't start all daemons in reasonable amount of time!!!"); 729 &end_badly, "didn't start all daemons in reasonable amount of time!!!");
622 730
623 pg = GNUNET_TESTING_daemons_start (sched, cfg, 731 pg = GNUNET_TESTING_daemons_start (sched, cfg,
624 peers_left, &my_cb, NULL, 732 peers_left, &hostkey_callback, NULL, &peers_started_callback, NULL,
625 &topology_callback, NULL, NULL); 733 &topology_callback, NULL, NULL);
626 734
627} 735}
diff --git a/src/testing/testing.c b/src/testing/testing.c
index fcc8c9767..65441c188 100644
--- a/src/testing/testing.c
+++ b/src/testing/testing.c
@@ -37,7 +37,7 @@
37#include "gnunet_transport_service.h" 37#include "gnunet_transport_service.h"
38#include "gnunet_hello_lib.h" 38#include "gnunet_hello_lib.h"
39 39
40#define DEBUG_TESTING GNUNET_NO 40#define DEBUG_TESTING GNUNET_YES
41#define DEBUG_TESTING_RECONNECT GNUNET_YES 41#define DEBUG_TESTING_RECONNECT GNUNET_YES
42 42
43/** 43/**
@@ -50,7 +50,7 @@
50 * How many times are we willing to try to wait for "scp" or 50 * How many times are we willing to try to wait for "scp" or
51 * "gnunet-service-arm" to complete (waitpid) before giving up? 51 * "gnunet-service-arm" to complete (waitpid) before giving up?
52 */ 52 */
53#define MAX_EXEC_WAIT_RUNS 50 53#define MAX_EXEC_WAIT_RUNS 250
54 54
55static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} }; 55static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} };
56 56
@@ -126,7 +126,7 @@ testing_init (void *cls,
126 { 126 {
127 d->server = NULL; 127 d->server = NULL;
128 if (GNUNET_YES == d->dead) 128 if (GNUNET_YES == d->dead)
129 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls); 129 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls, GNUNET_YES);
130 else if (NULL != cb) 130 else if (NULL != cb)
131 cb (d->cb_cls, NULL, d->cfg, d, 131 cb (d->cb_cls, NULL, d->cfg, d,
132 _("Failed to connect to core service\n")); 132 _("Failed to connect to core service\n"));
@@ -141,7 +141,7 @@ testing_init (void *cls,
141 d->server = server; 141 d->server = server;
142 d->running = GNUNET_YES; 142 d->running = GNUNET_YES;
143 if (GNUNET_YES == d->dead) 143 if (GNUNET_YES == d->dead)
144 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls); 144 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls, GNUNET_YES);
145 else if (NULL != cb) 145 else if (NULL != cb)
146 cb (d->cb_cls, my_identity, d->cfg, d, NULL); 146 cb (d->cb_cls, my_identity, d->cfg, d, NULL);
147#if DEBUG_TESTING 147#if DEBUG_TESTING
@@ -155,7 +155,7 @@ testing_init (void *cls,
155 if (d->th == NULL) 155 if (d->th == NULL)
156 { 156 {
157 if (GNUNET_YES == d->dead) 157 if (GNUNET_YES == d->dead)
158 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls); 158 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls, GNUNET_YES);
159 else if (NULL != d->cb) 159 else if (NULL != d->cb)
160 d->cb (d->cb_cls, &d->id, d->cfg, d, 160 d->cb (d->cb_cls, &d->id, d->cfg, d,
161 _("Failed to connect to transport service!\n")); 161 _("Failed to connect to transport service!\n"));
@@ -180,6 +180,9 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
180 enum GNUNET_OS_ProcessStatusType type; 180 enum GNUNET_OS_ProcessStatusType type;
181 unsigned long code; 181 unsigned long code;
182 char *dst; 182 char *dst;
183 int bytes_read;
184 static char hostkeybuf[105];
185 static const char temphostkey[104];
183 186
184#if DEBUG_TESTING 187#if DEBUG_TESTING
185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -227,6 +230,187 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
227 d->phase = SP_COPIED; 230 d->phase = SP_COPIED;
228 /* fall-through */ 231 /* fall-through */
229 case SP_COPIED: 232 case SP_COPIED:
233 /* Start create hostkey process */
234 d->pipe_stdout = GNUNET_DISK_pipe(GNUNET_NO);
235 if (d->pipe_stdout == NULL)
236 {
237 cb = d->cb;
238 d->cb = NULL;
239 if (NULL != cb)
240 cb (d->cb_cls,
241 NULL,
242 d->cfg,
243 d,
244 (NULL == d->hostname)
245 ? _("Failed to create pipe for `gnunet-peerinfo' process.\n")
246 : _("Failed to create pipe for `ssh' process.\n"));
247 return;
248 }
249 if (NULL == d->hostname)
250 {
251#if DEBUG_TESTING
252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
253 "Starting `%s', with command `%s %s %s %s'.\n",
254 "gnunet-peerinfo", "gnunet-peerinfo", "-c", d->cfgfile,
255 "-sq");
256#endif
257 d->pid = GNUNET_OS_start_process (NULL, d->pipe_stdout, "gnunet-peerinfo",
258 "gnunet-peerinfo",
259 "-c", d->cfgfile,
260 "-sq", NULL);
261 GNUNET_DISK_pipe_close_end(d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
262 }
263 else
264 {
265 if (d->username != NULL)
266 GNUNET_asprintf (&dst, "%s@%s", d->username, d->hostname);
267 else
268 dst = GNUNET_strdup (d->hostname);
269
270#if DEBUG_TESTING
271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
272 "Starting `%s', with command `%s %s %s %s %s %s'.\n",
273 "gnunet-peerinfo", "ssh", dst, "gnunet-peerinfo", "-c", d->cfgfile,
274 "-sq");
275#endif
276 d->pid = GNUNET_OS_start_process (NULL, d->pipe_stdout, "ssh",
277 "ssh",
278 dst,
279 "gnunet-peerinfo",
280 "-c", d->cfgfile, "-sq", NULL);
281 GNUNET_DISK_pipe_close_end(d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
282 GNUNET_free (dst);
283 }
284 if (-1 == d->pid)
285 {
286 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
287 _("Could not start `%s' process to create hostkey.\n"),
288 (NULL == d->hostname) ? "gnunet-peerinfo" : "ssh");
289 cb = d->cb;
290 d->cb = NULL;
291 if (NULL != cb)
292 cb (d->cb_cls,
293 NULL,
294 d->cfg,
295 d,
296 (NULL == d->hostname)
297 ? _("Failed to start `gnunet-peerinfo' process.\n")
298 : _("Failed to start `ssh' process.\n"));
299 GNUNET_DISK_pipe_close(d->pipe_stdout);
300 return;
301 }
302#if DEBUG_TESTING
303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
304 "Started `%s', waiting for hostkey.\n",
305 "gnunet-peerinfo");
306#endif
307 d->phase = SP_HOSTKEY_CREATE;
308 d->wait_runs = 0;
309 d->task
310 = GNUNET_SCHEDULER_add_delayed (d->sched,
311 GNUNET_CONSTANTS_EXEC_WAIT,
312 &start_fsm, d);
313 break;
314 case SP_HOSTKEY_CREATE:
315
316 bytes_read = GNUNET_DISK_file_read(GNUNET_DISK_pipe_handle(d->pipe_stdout, GNUNET_DISK_PIPE_END_READ), &hostkeybuf, sizeof(hostkeybuf));
317 if (bytes_read == 104) /* Success, we have read in the hostkey */
318 {
319 if (hostkeybuf[103] == '\n')
320 hostkeybuf[103] = '\0';
321 else
322 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Malformed output from gnunet-peerinfo!\n");
323 memcpy(&temphostkey, &hostkeybuf, bytes_read);
324
325 if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (&temphostkey[0],
326 &d->id.hashPubKey))
327 {
328 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Failed to convert string to peer identity!\n");
329 }
330 else
331 {
332 GNUNET_DISK_pipe_close(d->pipe_stdout);
333 d->pipe_stdout = NULL;
334 }
335 }
336
337 if (GNUNET_OK != GNUNET_OS_process_status (d->pid, &type, &code))
338 {
339 d->wait_runs++;
340 if (d->wait_runs > MAX_EXEC_WAIT_RUNS)
341 {
342 cb = d->cb;
343 d->cb = NULL;
344 if (NULL != cb)
345 cb (d->cb_cls,
346 NULL,
347 d->cfg,
348 d,
349 (NULL == d->hostname)
350 ? _("`gnunet-peerinfo' does not seem to terminate.\n")
351 : _("`ssh' does not seem to terminate.\n"));
352
353 GNUNET_DISK_pipe_close(d->pipe_stdout);
354 return;
355 }
356 /* wait some more */
357 d->task
358 = GNUNET_SCHEDULER_add_delayed (d->sched,
359 GNUNET_CONSTANTS_EXEC_WAIT,
360 &start_fsm, d);
361 return;
362 }
363#if DEBUG_TESTING
364 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
365 "Successfully got hostkey!\n");
366#endif
367 if (d->pipe_stdout != NULL)
368 {
369 cb = d->cb;
370 d->cb = NULL;
371 if (NULL != cb)
372 cb (d->cb_cls,
373 NULL,
374 d->cfg,
375 d,
376 _("`Failed to get hostkey!\n"));
377 GNUNET_DISK_pipe_close(d->pipe_stdout);
378 return;
379 }
380
381 if (d->hostkey_callback != NULL)
382 {
383 d->hostkey_callback(d->hostkey_cls, &d->id, d, NULL);
384 d->phase = SP_HOSTKEY_CREATED;
385 }
386 else
387 {
388 d->phase = SP_TOPOLOGY_SETUP;
389 }
390
391 /* Fall through */
392 case SP_HOSTKEY_CREATED:
393 /* wait for topology finished */
394 d->wait_runs++;
395 if ((GNUNET_YES == d->dead) || (d->wait_runs > MAX_EXEC_WAIT_RUNS))
396 {
397 cb = d->cb;
398 d->cb = NULL;
399 if (NULL != cb)
400 cb (d->cb_cls,
401 NULL,
402 d->cfg,
403 d,
404 _("`Failed while waiting for topology setup!\n"));
405 return;
406 }
407
408 d->task
409 = GNUNET_SCHEDULER_add_delayed (d->sched,
410 GNUNET_CONSTANTS_EXEC_WAIT,
411 &start_fsm, d);
412 break;
413 case SP_TOPOLOGY_SETUP:
230 /* start GNUnet on remote host */ 414 /* start GNUnet on remote host */
231 if (NULL == d->hostname) 415 if (NULL == d->hostname)
232 { 416 {
@@ -283,6 +467,7 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
283 (NULL == d->hostname) 467 (NULL == d->hostname)
284 ? _("Failed to start `gnunet-arm' process.\n") 468 ? _("Failed to start `gnunet-arm' process.\n")
285 : _("Failed to start `ssh' process.\n")); 469 : _("Failed to start `ssh' process.\n"));
470 return;
286 } 471 }
287#if DEBUG_TESTING 472#if DEBUG_TESTING
288 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 473 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -452,6 +637,19 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
452 } 637 }
453} 638}
454 639
640/**
641 * Continues GNUnet daemon startup when user wanted to be notified
642 * once a hostkey was generated (for creating friends files, blacklists,
643 * etc.).
644 *
645 * @param daemon the daemon to finish starting
646 */
647void
648GNUNET_TESTING_daemon_continue_startup(struct GNUNET_TESTING_Daemon *daemon)
649{
650 GNUNET_assert(daemon->phase == SP_HOSTKEY_CREATED);
651 daemon->phase = SP_TOPOLOGY_SETUP;
652}
455 653
456/** 654/**
457 * Starts a GNUnet daemon. GNUnet must be installed on the target 655 * Starts a GNUnet daemon. GNUnet must be installed on the target
@@ -463,6 +661,10 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
463 * @param cfg configuration to use 661 * @param cfg configuration to use
464 * @param hostname name of the machine where to run GNUnet 662 * @param hostname name of the machine where to run GNUnet
465 * (use NULL for localhost). 663 * (use NULL for localhost).
664 * @param hostkey_callback function to call once the hostkey has been
665 * generated for this peer, but it hasn't yet been started
666 * (NULL to start immediately, otherwise waits on GNUNET_TESTING_daemon_continue_start)
667 * @param hostkey_cls closure for hostkey callback
466 * @param cb function to call with the result 668 * @param cb function to call with the result
467 * @param cb_cls closure for cb 669 * @param cb_cls closure for cb
468 * @return handle to the daemon (actual start will be completed asynchronously) 670 * @return handle to the daemon (actual start will be completed asynchronously)
@@ -471,6 +673,8 @@ struct GNUNET_TESTING_Daemon *
471GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, 673GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
472 const struct GNUNET_CONFIGURATION_Handle *cfg, 674 const struct GNUNET_CONFIGURATION_Handle *cfg,
473 const char *hostname, 675 const char *hostname,
676 GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback,
677 void *hostkey_cls,
474 GNUNET_TESTING_NotifyDaemonRunning cb, 678 GNUNET_TESTING_NotifyDaemonRunning cb,
475 void *cb_cls) 679 void *cb_cls)
476{ 680{
@@ -493,6 +697,8 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
493 GNUNET_free (ret); 697 GNUNET_free (ret);
494 return NULL; 698 return NULL;
495 } 699 }
700 ret->hostkey_callback = hostkey_callback;
701 ret->hostkey_cls = hostkey_cls;
496 ret->cb = cb; 702 ret->cb = cb;
497 ret->cb_cls = cb_cls; 703 ret->cb_cls = cb_cls;
498 ret->cfg = GNUNET_CONFIGURATION_dup (cfg); 704 ret->cfg = GNUNET_CONFIGURATION_dup (cfg);
@@ -574,26 +780,139 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
574 780
575 781
576/** 782/**
783 * Restart (stop and start) a GNUnet daemon.
784 *
785 * @param d the daemon that should be restarted
786 * @param cb function called once the daemon is (re)started
787 * @param cb_cls closure for cb
788 */
789void
790GNUNET_TESTING_daemon_restart (struct GNUNET_TESTING_Daemon *d,
791 GNUNET_TESTING_NotifyDaemonRunning cb, void *cb_cls)
792{
793 char *arg;
794 char *del_arg;
795
796 del_arg = NULL;
797 if (NULL != d->cb)
798 {
799 d->dead = GNUNET_YES;
800 return;
801 }
802
803 d->cb = cb;
804 d->cb_cls = cb_cls;
805
806 if (d->phase == SP_CONFIG_UPDATE)
807 {
808 GNUNET_SCHEDULER_cancel (d->sched, d->task);
809 d->phase = SP_START_DONE;
810 }
811 if (d->server != NULL)
812 {
813 GNUNET_CORE_disconnect (d->server);
814 d->server = NULL;
815 }
816
817 if (d->th != NULL)
818 {
819 GNUNET_TRANSPORT_get_hello_cancel(d->th, &process_hello, d);
820 GNUNET_TRANSPORT_disconnect(d->th);
821 d->th = NULL;
822 }
823 /* state clean up and notifications */
824 GNUNET_free_non_null(d->hello);
825
826#if DEBUG_TESTING
827 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
828 _("Terminating peer `%4s'\n"), GNUNET_i2s (&d->id));
829#endif
830
831 d->phase = SP_START_ARMING;
832
833 /* Check if this is a local or remote process */
834 if (NULL != d->hostname)
835 {
836#if DEBUG_TESTING
837 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
838 "Stopping gnunet-arm with config `%s' on host `%s'.\n", d->cfgfile, d->hostname);
839#endif
840
841 if (d->username != NULL)
842 GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
843 else
844 arg = GNUNET_strdup (d->hostname);
845
846 d->pid = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh",
847 arg, "gnunet-arm",
848#if DEBUG_TESTING
849 "-L", "DEBUG",
850#endif
851 "-c", d->cfgfile, "-e", "-r", NULL);
852 /* Use -r to restart arm and all services */
853
854 GNUNET_free (arg);
855 }
856 else
857 {
858#if DEBUG_TESTING
859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
860 "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile);
861#endif
862 d->pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm",
863 "gnunet-arm",
864#if DEBUG_TESTING
865 "-L", "DEBUG",
866#endif
867 "-c", d->cfgfile, "-e", "-r", NULL);
868 }
869
870 GNUNET_free_non_null(del_arg);
871 d->wait_runs = 0;
872 d->task
873 = GNUNET_SCHEDULER_add_delayed (d->sched,
874 GNUNET_CONSTANTS_EXEC_WAIT,
875 &start_fsm, d);
876
877}
878
879
880/**
577 * Stops a GNUnet daemon. 881 * Stops a GNUnet daemon.
578 * 882 *
579 * @param d the daemon that should be stopped 883 * @param d the daemon that should be stopped
580 * @param cb function called once the daemon was stopped 884 * @param cb function called once the daemon was stopped
581 * @param cb_cls closure for cb 885 * @param cb_cls closure for cb
886 * @param delete_files GNUNET_YES to remove files, GNUNET_NO
887 * to leave them (i.e. for restarting at a later time,
888 * or logfile inspection once finished)
582 */ 889 */
583void 890void
584GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d, 891GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
585 GNUNET_TESTING_NotifyCompletion cb, void *cb_cls) 892 GNUNET_TESTING_NotifyCompletion cb, void *cb_cls,
893 int delete_files)
586{ 894{
587 char *arg; 895 char *arg;
588 896 char *del_arg;
589 d->dead_cb = cb; 897 d->dead_cb = cb;
590 d->dead_cb_cls = cb_cls; 898 d->dead_cb_cls = cb_cls;
591 899
592 if (NULL != d->cb) 900 if (NULL != d->cb)
593 { 901 {
902#if DEBUG_TESTING
903 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
904 _("Setting d->dead on peer `%4s'\n"), GNUNET_i2s (&d->id));
905#endif
594 d->dead = GNUNET_YES; 906 d->dead = GNUNET_YES;
595 return; 907 return;
596 } 908 }
909
910 del_arg = NULL;
911 if (delete_files == GNUNET_YES)
912 {
913 GNUNET_asprintf(&del_arg, "-d");
914 }
915
597 if (d->phase == SP_CONFIG_UPDATE) 916 if (d->phase == SP_CONFIG_UPDATE)
598 { 917 {
599 GNUNET_SCHEDULER_cancel (d->sched, d->task); 918 GNUNET_SCHEDULER_cancel (d->sched, d->task);
@@ -608,10 +927,9 @@ GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
608#if DEBUG_TESTING 927#if DEBUG_TESTING
609 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 928 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
610 _("Terminating peer `%4s'\n"), GNUNET_i2s (&d->id)); 929 _("Terminating peer `%4s'\n"), GNUNET_i2s (&d->id));
611 /* sleep(15); Manual check for running */
612#endif 930#endif
613 931
614 d->phase = SP_SHUTDOWN_START; 932 d->phase = SP_SHUTDOWN_START;
615 933
616 /* Check if this is a local or remote process */ 934 /* Check if this is a local or remote process */
617 if (NULL != d->hostname) 935 if (NULL != d->hostname)
@@ -627,29 +945,30 @@ GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
627 arg = GNUNET_strdup (d->hostname); 945 arg = GNUNET_strdup (d->hostname);
628 946
629 d->pid = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh", 947 d->pid = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh",
630 arg, "gnunet-arm", 948 arg, "gnunet-arm",
631#if DEBUG_TESTING 949#if DEBUG_TESTING
632 "-L", "DEBUG", 950 "-L", "DEBUG",
633#endif 951#endif
634 "-c", d->cfgfile, "-e", "-d", "-q", NULL); 952 "-c", d->cfgfile, "-e", "-q", del_arg, NULL);
635 /* Use -e to end arm, and -d to remove temp files */ 953 /* Use -e to end arm, and -d to remove temp files */
636 954
637 GNUNET_free (arg); 955 GNUNET_free (arg);
638 } 956 }
639 else 957 else
640 { 958 {
641#if DEBUG_TESTING 959#if DEBUG_TESTING
642 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 960 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
643 "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile); 961 "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile);
644#endif 962#endif
645 d->pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm", 963 d->pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm",
646 "gnunet-arm", 964 "gnunet-arm",
647#if DEBUG_TESTING 965#if DEBUG_TESTING
648 "-L", "DEBUG", 966 "-L", "DEBUG",
649#endif 967#endif
650 "-c", d->cfgfile, "-e", "-d", "-q", NULL); 968 "-c", d->cfgfile, "-e", "-q", del_arg, NULL);
651 } 969 }
652 970
971 GNUNET_free_non_null(del_arg);
653 d->wait_runs = 0; 972 d->wait_runs = 0;
654 d->task 973 d->task
655 = GNUNET_SCHEDULER_add_delayed (d->sched, 974 = GNUNET_SCHEDULER_add_delayed (d->sched,
diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c
index e617bc113..e9bc05a74 100644
--- a/src/testing/testing_group.c
+++ b/src/testing/testing_group.c
@@ -50,6 +50,57 @@
50 50
51#define CONNECT_ATTEMPTS 8 51#define CONNECT_ATTEMPTS 8
52 52
53/**
54 * Prototype of a function called whenever two peers would be connected
55 * in a certain topology.
56 */
57typedef int (*GNUNET_TESTING_ConnectionProcessor)
58(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second);
59
60struct RestartContext
61{
62 /**
63 * The group of peers being restarted
64 */
65 struct GNUNET_TESTING_PeerGroup *peer_group;
66
67 /**
68 * How many peers have been restarted thus far
69 */
70 unsigned int peers_restarted;
71
72 /**
73 * How many peers got an error when restarting
74 */
75 unsigned int peers_restart_failed;
76
77 /**
78 * The function to call once all peers have been restarted
79 */
80 GNUNET_TESTING_NotifyCompletion callback;
81
82 /**
83 * Closure for callback function
84 */
85 void *callback_cls;
86
87};
88
89struct CreateTopologyContext
90{
91
92 /**
93 * Function to call with number of connections
94 */
95 GNUNET_TESTING_NotifyConnections cont;
96
97 /**
98 * Closure for connection notification
99 */
100 void *cls;
101};
102
103#if OLD
53struct PeerConnection 104struct PeerConnection
54{ 105{
55 /* 106 /*
@@ -63,6 +114,7 @@ struct PeerConnection
63 struct GNUNET_TESTING_Daemon *daemon; 114 struct GNUNET_TESTING_Daemon *daemon;
64 115
65}; 116};
117#endif
66 118
67/** 119/**
68 * Data we keep per peer. 120 * Data we keep per peer.
@@ -83,9 +135,33 @@ struct PeerData
83 struct GNUNET_TESTING_Daemon *daemon; 135 struct GNUNET_TESTING_Daemon *daemon;
84 136
85 /** 137 /**
86 * Linked list of peer connections (simply indexes of PeerGroup) 138 * The peergroup this peer belongs to.
139 */
140 struct GNUNET_TESTING_PeerGroup *pg;
141
142 /**
143 * Linked list of peer connections (pointers)
144 */
145 //struct PeerConnection *connected_peers;
146 /**
147 * Hash map of allowed peer connections (F2F created topology)
148 */
149 struct GNUNET_CONTAINER_MultiHashMap *allowed_peers;
150
151 /**
152 * Hash map of blacklisted peers
153 */
154 struct GNUNET_CONTAINER_MultiHashMap *blacklisted_peers;
155
156 /**
157 * Hash map of peer connections
158 */
159 struct GNUNET_CONTAINER_MultiHashMap *connect_peers;
160
161 /**
162 * Temporary hash map of peer connections
87 */ 163 */
88 struct PeerConnection *connected_peers; 164 struct GNUNET_CONTAINER_MultiHashMap *connect_peers_working_set;
89 165
90 /** 166 /**
91 * Total number of connections this peer has 167 * Total number of connections this peer has
@@ -165,6 +241,31 @@ struct GNUNET_TESTING_PeerGroup
165 241
166}; 242};
167 243
244/**
245 * Convert unique ID to hash code.
246 *
247 * @param uid unique ID to convert
248 * @param hash set to uid (extended with zeros)
249 */
250static void
251hash_from_uid (uint32_t uid,
252 GNUNET_HashCode *hash)
253{
254 memset (hash, 0, sizeof(GNUNET_HashCode));
255 *((uint32_t*)hash) = uid;
256}
257
258/**
259 * Convert hash code to unique ID.
260 *
261 * @param uid unique ID to convert
262 * @param hash set to uid (extended with zeros)
263 */
264static void
265uid_from_hash (const GNUNET_HashCode *hash, uint32_t *uid)
266{
267 memcpy (uid, hash, sizeof(uint32_t));
268}
168 269
169struct UpdateContext 270struct UpdateContext
170{ 271{
@@ -279,41 +380,107 @@ make_config (const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t * port, con
279 return uc.ret; 380 return uc.ret;
280} 381}
281 382
383
282/* 384/*
283 * Add entries to the peers connected list 385 * Add entries to the peers connect list
284 * 386 *
285 * @param pg the peer group we are working with 387 * @param pg the peer group we are working with
286 * @param first index of the first peer 388 * @param first index of the first peer
287 * @param second index of the second peer 389 * @param second index of the second peer
288 * 390 *
289 * @return the number of connections added (can be 0, 1 or 2) 391 * @return the number of connections added (can be 0, 1 or 2)
392 * technically should only be 0 or 2, but the small price
393 * of iterating over the lists (hashmaps in the future)
394 * for being sure doesn't bother me!
395 *
396 */
397static int
398add_actual_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second)
399{
400 int added;
401 int add_first;
402 int add_second;
403
404 GNUNET_HashCode hash_first;
405 GNUNET_HashCode hash_second;
406
407 hash_from_uid(first, &hash_first);
408 hash_from_uid(second, &hash_second);
409
410 add_first = GNUNET_NO;
411 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[first].connect_peers, &hash_second))
412 {
413 add_first = GNUNET_YES;
414 }
415
416 add_second = GNUNET_NO;
417 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[second].connect_peers, &hash_first))
418 {
419 add_second = GNUNET_YES;
420 }
421
422 added = 0;
423 if (add_first)
424 {
425 GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[first].connect_peers, &hash_second, pg->peers[second].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
426 added++;
427 }
428
429 if (add_second)
430 {
431 GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[second].connect_peers, &hash_first, pg->peers[first].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
432 added++;
433 }
434
435 return added;
436}
437
438
439/*
440 * Add entries to the peers allowed connections list
290 * 441 *
291 * FIXME: add both, or only add one? 442 * @param pg the peer group we are working with
292 * - if both are added, then we have to keep track 443 * @param first index of the first peer
293 * when connecting so we don't double connect 444 * @param second index of the second peer
294 * - if only one is added, we need to iterate over
295 * both lists to find out if connection already exists
296 * - having both allows the whitelisting/friend file
297 * creation to be easier
298 * 445 *
299 * -- For now, add both, we have to iterate over each to 446 * @return the number of connections added (can be 0, 1 or 2)
300 * check for duplicates anyways, so we'll take the performance 447 * technically should only be 0 or 2, but the small price
301 * hit assuming we don't have __too__ many connections 448 * of iterating over the lists (hashmaps in the future)
449 * for being sure doesn't bother me!
302 * 450 *
303 */ 451 */
304static int 452static int
305add_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second) 453add_allowed_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second)
306{ 454{
307 int added; 455 int added;
456#if OLD
308 struct PeerConnection *first_iter; 457 struct PeerConnection *first_iter;
309 struct PeerConnection *second_iter; 458 struct PeerConnection *second_iter;
310 int add_first;
311 int add_second;
312 struct PeerConnection *new_first; 459 struct PeerConnection *new_first;
313 struct PeerConnection *new_second; 460 struct PeerConnection *new_second;
461#endif
462 int add_first;
463 int add_second;
464
465 GNUNET_HashCode hash_first;
466 GNUNET_HashCode hash_second;
314 467
468 hash_from_uid(first, &hash_first);
469 hash_from_uid(second, &hash_second);
470
471 add_first = GNUNET_NO;
472 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[first].allowed_peers, &hash_second))
473 {
474 add_first = GNUNET_YES;
475 }
476
477 add_second = GNUNET_NO;
478 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[second].allowed_peers, &hash_first))
479 {
480 add_second = GNUNET_YES;
481 }
482#if OLD
315 first_iter = pg->peers[first].connected_peers; 483 first_iter = pg->peers[first].connected_peers;
316 add_first = GNUNET_YES;
317 while (first_iter != NULL) 484 while (first_iter != NULL)
318 { 485 {
319 if (first_iter->daemon == pg->peers[second].daemon) 486 if (first_iter->daemon == pg->peers[second].daemon)
@@ -329,31 +496,129 @@ add_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigne
329 add_second = GNUNET_NO; 496 add_second = GNUNET_NO;
330 second_iter = second_iter->next; 497 second_iter = second_iter->next;
331 } 498 }
499#endif
332 500
333 added = 0; 501 added = 0;
334 if (add_first) 502 if (add_first)
335 { 503 {
504 GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[first].allowed_peers, &hash_second, pg->peers[second].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
505#if OLD
336 new_first = GNUNET_malloc(sizeof(struct PeerConnection)); 506 new_first = GNUNET_malloc(sizeof(struct PeerConnection));
337 new_first->daemon = pg->peers[second].daemon; 507 new_first->daemon = pg->peers[second].daemon;
338 new_first->next = pg->peers[first].connected_peers; 508 new_first->next = pg->peers[first].connected_peers;
339 pg->peers[first].connected_peers = new_first; 509 pg->peers[first].connected_peers = new_first;
340 pg->peers[first].num_connections++; 510 pg->peers[first].num_connections++;
511#endif
341 added++; 512 added++;
342 } 513 }
343 514
344 if (add_second) 515 if (add_second)
345 { 516 {
517 GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[second].allowed_peers, &hash_first, pg->peers[first].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
518#if OLD
346 new_second = GNUNET_malloc(sizeof(struct PeerConnection)); 519 new_second = GNUNET_malloc(sizeof(struct PeerConnection));
347 new_second->daemon = pg->peers[first].daemon; 520 new_second->daemon = pg->peers[first].daemon;
348 new_second->next = pg->peers[second].connected_peers; 521 new_second->next = pg->peers[second].connected_peers;
349 pg->peers[second].connected_peers = new_second; 522 pg->peers[second].connected_peers = new_second;
350 pg->peers[first].num_connections++; 523 pg->peers[first].num_connections++;
524#endif
351 added++; 525 added++;
352 } 526 }
353 527
354 return added; 528 return added;
355} 529}
356 530
531/*
532 * Add entries to the peers blacklisted list
533 *
534 * @param pg the peer group we are working with
535 * @param first index of the first peer
536 * @param second index of the second peer
537 *
538 * @return the number of connections added (can be 0, 1 or 2)
539 *
540 */
541static int
542blacklist_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second)
543{
544 int added;
545 int add_first;
546 int add_second;
547 GNUNET_HashCode hash_first;
548 GNUNET_HashCode hash_second;
549
550 hash_from_uid(first, &hash_first);
551 hash_from_uid(second, &hash_second);
552
553 add_first = GNUNET_NO;
554 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[first].blacklisted_peers, &hash_second))
555 {
556 add_first = GNUNET_YES;
557 }
558
559 add_second = GNUNET_NO;
560 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[second].blacklisted_peers, &hash_first))
561 {
562 add_second = GNUNET_YES;
563 }
564
565 added = 0;
566 if (add_first)
567 {
568 GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[first].blacklisted_peers, &hash_second, pg->peers[second].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
569 added++;
570 }
571
572 if (add_second)
573 {
574 GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[second].blacklisted_peers, &hash_first, pg->peers[first].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
575 added++;
576 }
577
578 return added;
579}
580
581/*
582 * Remove entries from the peers blacklisted list
583 *
584 * @param pg the peer group we are working with
585 * @param first index of the first peer
586 * @param second index of the second peer
587 *
588 * @return the number of connections removed (can be 0, 1 or 2)
589 *
590 */
591static int
592unblacklist_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second)
593{
594 int removed;
595 int remove_first;
596 int remove_second;
597 GNUNET_HashCode hash_first;
598 GNUNET_HashCode hash_second;
599
600 hash_from_uid(first, &hash_first);
601 hash_from_uid(second, &hash_second);
602
603 remove_first = GNUNET_CONTAINER_multihashmap_contains(pg->peers[first].blacklisted_peers, &hash_second);
604 remove_second = GNUNET_CONTAINER_multihashmap_contains(pg->peers[second].blacklisted_peers, &hash_first);
605
606 removed = 0;
607 if (remove_first)
608 {
609 GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(pg->peers[first].blacklisted_peers, &hash_second, pg->peers[second].daemon));
610 removed++;
611 }
612
613 if (remove_second)
614 {
615 GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(pg->peers[second].blacklisted_peers, &hash_first, pg->peers[first].daemon));
616 removed++;
617 }
618
619 return removed;
620}
621
357/** 622/**
358 * Scale free network construction as described in: 623 * Scale free network construction as described in:
359 * 624 *
@@ -369,7 +634,7 @@ add_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigne
369 * @return the number of connections created 634 * @return the number of connections created
370 */ 635 */
371static int 636static int
372create_scale_free (struct GNUNET_TESTING_PeerGroup *pg) 637create_scale_free (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
373{ 638{
374 639
375 unsigned int total_connections; 640 unsigned int total_connections;
@@ -382,7 +647,7 @@ create_scale_free (struct GNUNET_TESTING_PeerGroup *pg)
382 GNUNET_assert(pg->total > 1); 647 GNUNET_assert(pg->total > 1);
383 648
384 /* Add a connection between the first two nodes */ 649 /* Add a connection between the first two nodes */
385 total_connections = add_connections(pg, 0, 1); 650 total_connections = proc(pg, 0, 1);
386 651
387 for (outer_count = 1; outer_count < pg->total; outer_count++) 652 for (outer_count = 1; outer_count < pg->total; outer_count++)
388 { 653 {
@@ -404,7 +669,7 @@ create_scale_free (struct GNUNET_TESTING_PeerGroup *pg)
404 "Connecting peer %d to peer %d\n", 669 "Connecting peer %d to peer %d\n",
405 outer_count, i); 670 outer_count, i);
406#endif 671#endif
407 total_connections += add_connections(pg, outer_count, i); 672 total_connections += proc(pg, outer_count, i);
408 } 673 }
409 } 674 }
410 } 675 }
@@ -413,7 +678,7 @@ create_scale_free (struct GNUNET_TESTING_PeerGroup *pg)
413} 678}
414 679
415int 680int
416create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg) 681create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
417{ 682{
418 unsigned int i, j; 683 unsigned int i, j;
419 int nodeToConnect; 684 int nodeToConnect;
@@ -502,7 +767,7 @@ create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg)
502 pg->total); 767 pg->total);
503 } 768 }
504 smallWorldConnections += 769 smallWorldConnections +=
505 add_connections (pg, i, randomPeer); 770 proc (pg, i, randomPeer);
506 } 771 }
507 else 772 else
508 { 773 {
@@ -512,7 +777,7 @@ create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg)
512 nodeToConnect = nodeToConnect - pg->total; 777 nodeToConnect = nodeToConnect - pg->total;
513 } 778 }
514 connect_attempts += 779 connect_attempts +=
515 add_connections (pg, i, nodeToConnect); 780 proc (pg, i, nodeToConnect);
516 } 781 }
517 } 782 }
518 783
@@ -525,7 +790,7 @@ create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg)
525 790
526 791
527static int 792static int
528create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg) 793create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
529{ 794{
530 unsigned int outer_count, inner_count; 795 unsigned int outer_count, inner_count;
531 unsigned int cutoff; 796 unsigned int cutoff;
@@ -566,7 +831,7 @@ create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg)
566 "Connecting peer %d to peer %d\n", 831 "Connecting peer %d to peer %d\n",
567 outer_count, inner_count); 832 outer_count, inner_count);
568#endif 833#endif
569 connect_attempts += add_connections(pg, outer_count, inner_count); 834 connect_attempts += proc(pg, outer_count, inner_count);
570 } 835 }
571 } 836 }
572 } 837 }
@@ -578,7 +843,7 @@ create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg)
578 843
579 844
580static int 845static int
581create_small_world (struct GNUNET_TESTING_PeerGroup *pg) 846create_small_world (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
582{ 847{
583 unsigned int i, j, k; 848 unsigned int i, j, k;
584 unsigned int square; 849 unsigned int square;
@@ -662,7 +927,7 @@ create_small_world (struct GNUNET_TESTING_PeerGroup *pg)
662 else 927 else
663 nodeToConnect = i - cols + 1; 928 nodeToConnect = i - cols + 1;
664 929
665 connect_attempts += add_connections (pg, i, nodeToConnect); 930 connect_attempts += proc (pg, i, nodeToConnect);
666 931
667 if (i < cols) 932 if (i < cols)
668 nodeToConnect = (rows * cols) - cols + i; 933 nodeToConnect = (rows * cols) - cols + i;
@@ -670,7 +935,7 @@ create_small_world (struct GNUNET_TESTING_PeerGroup *pg)
670 nodeToConnect = i - cols; 935 nodeToConnect = i - cols;
671 936
672 if (nodeToConnect < pg->total) 937 if (nodeToConnect < pg->total)
673 connect_attempts += add_connections (pg, i, nodeToConnect); 938 connect_attempts += proc (pg, i, nodeToConnect);
674 } 939 }
675 natLog = log (pg->total); 940 natLog = log (pg->total);
676#if VERBOSE_TESTING > 2 941#if VERBOSE_TESTING > 2
@@ -703,7 +968,7 @@ create_small_world (struct GNUNET_TESTING_PeerGroup *pg)
703 (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL); 968 (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL);
704 /* If random < probability, then connect the two nodes */ 969 /* If random < probability, then connect the two nodes */
705 if (random < probability) 970 if (random < probability)
706 smallWorldConnections += add_connections (pg, j, k); 971 smallWorldConnections += proc (pg, j, k);
707 972
708 } 973 }
709 } 974 }
@@ -721,7 +986,7 @@ create_small_world (struct GNUNET_TESTING_PeerGroup *pg)
721 986
722 987
723static int 988static int
724create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg) 989create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
725{ 990{
726 double temp_rand; 991 double temp_rand;
727 unsigned int outer_count; 992 unsigned int outer_count;
@@ -759,7 +1024,7 @@ create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg)
759#endif 1024#endif
760 if (temp_rand < probability) 1025 if (temp_rand < probability)
761 { 1026 {
762 connect_attempts += add_connections (pg, outer_count, inner_count); 1027 connect_attempts += proc (pg, outer_count, inner_count);
763 } 1028 }
764 } 1029 }
765 } 1030 }
@@ -768,7 +1033,7 @@ create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg)
768} 1033}
769 1034
770static int 1035static int
771create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg) 1036create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
772{ 1037{
773 unsigned int i; 1038 unsigned int i;
774 unsigned int square; 1039 unsigned int square;
@@ -820,7 +1085,7 @@ create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg)
820 "Connecting peer %d to peer %d\n", 1085 "Connecting peer %d to peer %d\n",
821 i, nodeToConnect); 1086 i, nodeToConnect);
822#endif 1087#endif
823 connect_attempts += add_connections(pg, i, nodeToConnect); 1088 connect_attempts += proc(pg, i, nodeToConnect);
824 1089
825 /* Second connect to the node immediately above */ 1090 /* Second connect to the node immediately above */
826 if (i < cols) 1091 if (i < cols)
@@ -835,7 +1100,7 @@ create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg)
835 "Connecting peer %d to peer %d\n", 1100 "Connecting peer %d to peer %d\n",
836 i, nodeToConnect); 1101 i, nodeToConnect);
837#endif 1102#endif
838 connect_attempts += add_connections(pg, i, nodeToConnect); 1103 connect_attempts += proc(pg, i, nodeToConnect);
839 } 1104 }
840 1105
841 } 1106 }
@@ -846,7 +1111,7 @@ create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg)
846 1111
847 1112
848static int 1113static int
849create_clique (struct GNUNET_TESTING_PeerGroup *pg) 1114create_clique (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
850{ 1115{
851 unsigned int outer_count; 1116 unsigned int outer_count;
852 unsigned int inner_count; 1117 unsigned int inner_count;
@@ -864,7 +1129,7 @@ create_clique (struct GNUNET_TESTING_PeerGroup *pg)
864 "Connecting peer %d to peer %d\n", 1129 "Connecting peer %d to peer %d\n",
865 outer_count, inner_count); 1130 outer_count, inner_count);
866#endif 1131#endif
867 connect_attempts += add_connections(pg, outer_count, inner_count); 1132 connect_attempts += proc(pg, outer_count, inner_count);
868 } 1133 }
869 } 1134 }
870 1135
@@ -873,7 +1138,7 @@ create_clique (struct GNUNET_TESTING_PeerGroup *pg)
873 1138
874 1139
875static int 1140static int
876create_ring (struct GNUNET_TESTING_PeerGroup *pg) 1141create_ring (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
877{ 1142{
878 unsigned int count; 1143 unsigned int count;
879 int connect_attempts; 1144 int connect_attempts;
@@ -888,16 +1153,77 @@ create_ring (struct GNUNET_TESTING_PeerGroup *pg)
888 "Connecting peer %d to peer %d\n", 1153 "Connecting peer %d to peer %d\n",
889 count, count + 1); 1154 count, count + 1);
890#endif 1155#endif
891 connect_attempts += add_connections(pg, count, count + 1); 1156 connect_attempts += proc(pg, count, count + 1);
892 } 1157 }
893 1158
894 /* Connect the last peer to the first peer */ 1159 /* Connect the last peer to the first peer */
895 connect_attempts += add_connections(pg, pg->total - 1, 0); 1160 connect_attempts += proc(pg, pg->total - 1, 0);
896 1161
897 return connect_attempts; 1162 return connect_attempts;
898} 1163}
899 1164
900 1165
1166/**
1167 * Iterator for writing friends of a peer to a file.
1168 *
1169 * @param cls closure, an open writable file handle
1170 * @param key the key the daemon was stored under
1171 * @param value the GNUNET_TESTING_Daemon that needs to be written.
1172 *
1173 * @return GNUNET_YES to continue iteration
1174 *
1175 * TODO: Could replace friend_file_iterator and blacklist_file_iterator
1176 * with a single file_iterator that takes a closure which contains
1177 * the prefix to write before the peer. Then this could be used
1178 * for blacklisting multiple transports and writing the friend
1179 * file. I'm sure *someone* will complain loudly about other
1180 * things that negate these functions even existing so no point in
1181 * "fixing" now.
1182 */
1183static int
1184friend_file_iterator (void *cls,
1185 const GNUNET_HashCode * key,
1186 void *value)
1187{
1188 FILE *temp_friend_handle = cls;
1189 struct GNUNET_TESTING_Daemon *peer = value;
1190 struct GNUNET_PeerIdentity *temppeer;
1191 struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
1192
1193 temppeer = &peer->id;
1194 GNUNET_CRYPTO_hash_to_enc(&temppeer->hashPubKey, &peer_enc);
1195 fprintf(temp_friend_handle, "%s\n", (char *)&peer_enc);
1196
1197 return GNUNET_YES;
1198}
1199
1200
1201/**
1202 * Iterator for writing blacklist data to appropriate files.
1203 *
1204 * @param cls closure, an open writable file handle
1205 * @param key the key the daemon was stored under
1206 * @param value the GNUNET_TESTING_Daemon that needs to be written.
1207 *
1208 * @return GNUNET_YES to continue iteration
1209 */
1210static int
1211blacklist_file_iterator (void *cls,
1212 const GNUNET_HashCode * key,
1213 void *value)
1214{
1215 FILE *temp_blacklist_handle = cls;
1216 struct GNUNET_TESTING_Daemon *peer = value;
1217 struct GNUNET_PeerIdentity *temppeer;
1218 struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
1219
1220 temppeer = &peer->id;
1221 GNUNET_CRYPTO_hash_to_enc(&temppeer->hashPubKey, &peer_enc);
1222 fprintf(temp_blacklist_handle, "tcp:%s\n", (char *)&peer_enc);
1223
1224 return GNUNET_YES;
1225}
1226
901/* 1227/*
902 * Create the friend files based on the PeerConnection's 1228 * Create the friend files based on the PeerConnection's
903 * of each peer in the peer group, and copy the files 1229 * of each peer in the peer group, and copy the files
@@ -910,12 +1236,9 @@ create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg)
910{ 1236{
911 FILE *temp_friend_handle; 1237 FILE *temp_friend_handle;
912 unsigned int pg_iter; 1238 unsigned int pg_iter;
913 struct PeerConnection *connection_iter;
914 struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
915 char *temp_service_path; 1239 char *temp_service_path;
916 pid_t *pidarr; 1240 pid_t *pidarr;
917 char *arg; 1241 char *arg;
918 struct GNUNET_PeerIdentity *temppeer;
919 char * mytemp; 1242 char * mytemp;
920 enum GNUNET_OS_ProcessStatusType type; 1243 enum GNUNET_OS_ProcessStatusType type;
921 unsigned long return_code; 1244 unsigned long return_code;
@@ -927,16 +1250,10 @@ create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg)
927 for (pg_iter = 0; pg_iter < pg->total; pg_iter++) 1250 for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
928 { 1251 {
929 mytemp = GNUNET_DISK_mktemp("friends"); 1252 mytemp = GNUNET_DISK_mktemp("friends");
1253 GNUNET_assert(mytemp != NULL);
930 temp_friend_handle = fopen (mytemp, "wt"); 1254 temp_friend_handle = fopen (mytemp, "wt");
931 connection_iter = pg->peers[pg_iter].connected_peers; 1255 GNUNET_assert(temp_friend_handle != NULL);
932 while (connection_iter != NULL) 1256 GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].allowed_peers, &friend_file_iterator, temp_friend_handle);
933 {
934 temppeer = &connection_iter->daemon->id;
935 GNUNET_CRYPTO_hash_to_enc(&temppeer->hashPubKey, &peer_enc);
936 fprintf(temp_friend_handle, "%s\n", (char *)&peer_enc);
937 connection_iter = connection_iter->next;
938 }
939
940 fclose(temp_friend_handle); 1257 fclose(temp_friend_handle);
941 1258
942 if (GNUNET_OK != 1259 if (GNUNET_OK !=
@@ -1029,6 +1346,130 @@ create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg)
1029 return ret; 1346 return ret;
1030} 1347}
1031 1348
1349
1350/*
1351 * Create the blacklist files based on the PeerConnection's
1352 * of each peer in the peer group, and copy the files
1353 * to the appropriate place.
1354 *
1355 * @param pg the peer group we are dealing with
1356 */
1357static int
1358create_and_copy_blacklist_files (struct GNUNET_TESTING_PeerGroup *pg)
1359{
1360 FILE *temp_friend_handle;
1361 unsigned int pg_iter;
1362 char *temp_service_path;
1363 pid_t *pidarr;
1364 char *arg;
1365 char *mytemp;
1366 enum GNUNET_OS_ProcessStatusType type;
1367 unsigned long return_code;
1368 int count;
1369 int ret;
1370 int max_wait = 10;
1371
1372 pidarr = GNUNET_malloc(sizeof(pid_t) * pg->total);
1373 for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
1374 {
1375 mytemp = GNUNET_DISK_mktemp("blacklist");
1376 GNUNET_assert(mytemp != NULL);
1377 temp_friend_handle = fopen (mytemp, "wt");
1378 GNUNET_assert(temp_friend_handle != NULL);
1379 GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].blacklisted_peers, &blacklist_file_iterator, temp_friend_handle);
1380 fclose(temp_friend_handle);
1381
1382 if (GNUNET_OK !=
1383 GNUNET_CONFIGURATION_get_value_string(pg->peers[pg_iter].daemon->cfg, "PATHS", "SERVICEHOME", &temp_service_path))
1384 {
1385 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1386 _("No `%s' specified in peer configuration in section `%s', cannot copy friends file!\n"),
1387 "SERVICEHOME",
1388 "PATHS");
1389 if (UNLINK (mytemp) != 0)
1390 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", mytemp);
1391 GNUNET_free (mytemp);
1392 break;
1393 }
1394
1395 if (pg->peers[pg_iter].daemon->hostname == NULL) /* Local, just copy the file */
1396 {
1397 GNUNET_asprintf (&arg, "%s/blacklist", temp_service_path);
1398 pidarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "mv",
1399 "mv", mytemp, arg, NULL);
1400#if VERBOSE_TESTING
1401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1402 _("Copying file with command cp %s %s\n"), mytemp, arg);
1403#endif
1404
1405 GNUNET_free(arg);
1406 }
1407 else /* Remote, scp the file to the correct place */
1408 {
1409 if (NULL != pg->peers[pg_iter].daemon->username)
1410 GNUNET_asprintf (&arg, "%s@%s:%s/blacklist", pg->peers[pg_iter].daemon->username, pg->peers[pg_iter].daemon->hostname, temp_service_path);
1411 else
1412 GNUNET_asprintf (&arg, "%s:%s/blacklist", pg->peers[pg_iter].daemon->hostname, temp_service_path);
1413 pidarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "scp",
1414 "scp", mytemp, arg, NULL);
1415
1416#if VERBOSE_TESTING
1417 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1418 _("Copying file with command scp %s %s\n"), mytemp, arg);
1419#endif
1420 GNUNET_free(arg);
1421 }
1422 GNUNET_free (temp_service_path);
1423 GNUNET_free (mytemp);
1424 }
1425
1426 count = 0;
1427 ret = GNUNET_SYSERR;
1428 while ((count < max_wait) && (ret != GNUNET_OK))
1429 {
1430 ret = GNUNET_OK;
1431 for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
1432 {
1433#if VERBOSE_TESTING
1434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1435 _("Checking copy status of file %d\n"), pg_iter);
1436#endif
1437 if (pidarr[pg_iter] != 0) /* Check for already completed! */
1438 {
1439 if (GNUNET_OS_process_status(pidarr[pg_iter], &type, &return_code) != GNUNET_OK)
1440 {
1441 ret = GNUNET_SYSERR;
1442 }
1443 else if ((type != GNUNET_OS_PROCESS_EXITED) || (return_code != 0))
1444 {
1445 ret = GNUNET_SYSERR;
1446 }
1447 else
1448 {
1449 pidarr[pg_iter] = 0;
1450#if VERBOSE_TESTING
1451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1452 _("File %d copied\n"), pg_iter);
1453#endif
1454 }
1455 }
1456 }
1457 count++;
1458 if (ret == GNUNET_SYSERR)
1459 {
1460 sleep(1);
1461 }
1462 }
1463
1464#if VERBOSE_TESTING
1465 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1466 _("Finished copying all blacklist files!\n"));
1467#endif
1468 GNUNET_free(pidarr);
1469 return ret;
1470}
1471
1472
1032/** 1473/**
1033 * Internal notification of a connection, kept so that we can ensure some connections 1474 * Internal notification of a connection, kept so that we can ensure some connections
1034 * happen instead of flooding all testing daemons with requests to connect. 1475 * happen instead of flooding all testing daemons with requests to connect.
@@ -1081,54 +1522,154 @@ static void schedule_connect(void *cls, const struct GNUNET_SCHEDULER_TaskContex
1081 } 1522 }
1082} 1523}
1083 1524
1525/**
1526 * Iterator for actually scheduling connections to be created
1527 * between two peers.
1528 *
1529 * @param cls closure, a GNUNET_TESTING_Daemon
1530 * @param key the key the second Daemon was stored under
1531 * @param value the GNUNET_TESTING_Daemon that the first is to connect to
1532 *
1533 * @return GNUNET_YES to continue iteration
1534 */
1535static int
1536connect_iterator (void *cls,
1537 const GNUNET_HashCode * key,
1538 void *value)
1539{
1540 struct PeerData *first = cls;
1541 struct GNUNET_TESTING_Daemon *second = value;
1542 struct ConnectContext *connect_context;
1543
1544 connect_context = GNUNET_malloc(sizeof(struct ConnectContext));
1545 connect_context->pg = first->pg;
1546 connect_context->first = first->daemon;
1547 connect_context->second = second;
1548 GNUNET_SCHEDULER_add_now(first->pg->sched, &schedule_connect, connect_context);
1549
1550 return GNUNET_YES;
1551}
1552
1553/**
1554 * Iterator for copying all entries in the allowed hashmap to the
1555 * connect hashmap.
1556 *
1557 * @param cls closure, a GNUNET_TESTING_Daemon
1558 * @param key the key the second Daemon was stored under
1559 * @param value the GNUNET_TESTING_Daemon that the first is to connect to
1560 *
1561 * @return GNUNET_YES to continue iteration
1562 */
1563static int
1564copy_topology_iterator (void *cls,
1565 const GNUNET_HashCode * key,
1566 void *value)
1567{
1568 struct PeerData *first = cls;
1569
1570 GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(first->connect_peers, key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1571
1572 return GNUNET_YES;
1573}
1574
1575/**
1576 * Make the peers to connect the same as those that are allowed to be
1577 * connected.
1578 *
1579 * @param pg the peer group
1580 */
1581static int
1582copy_allowed_topology (struct GNUNET_TESTING_PeerGroup *pg)
1583{
1584 unsigned int pg_iter;
1585 int ret;
1586 int total;
1587
1588 total = 0;
1589 for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
1590 {
1591 ret = GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].allowed_peers, &copy_topology_iterator, &pg->peers[pg_iter]);
1592 if (GNUNET_SYSERR == ret)
1593 return GNUNET_SYSERR;
1594
1595 total = total + ret;
1596 }
1597
1598 return total;
1599}
1600
1601
1084/* 1602/*
1085 * Connect the topology as specified by the PeerConnection's 1603 * Connect the topology as specified by the PeerConnection's
1086 * of each peer in the peer group 1604 * of each peer in the peer group
1087 * 1605 *
1088 * @param pg the peer group we are dealing with 1606 * @param pg the peer group we are dealing with
1607 *
1608 * @return the number of connections that will be attempted
1089 */ 1609 */
1090static void 1610static int
1091connect_topology (struct GNUNET_TESTING_PeerGroup *pg) 1611connect_topology (struct GNUNET_TESTING_PeerGroup *pg)
1092{ 1612{
1093 unsigned int pg_iter; 1613 unsigned int pg_iter;
1614 int ret;
1615 int total;
1616#if OLD
1094 struct PeerConnection *connection_iter; 1617 struct PeerConnection *connection_iter;
1095 struct ConnectContext *connect_context; 1618 struct ConnectContext *connect_context;
1619#endif
1096 1620
1621 total = 0;
1097 for (pg_iter = 0; pg_iter < pg->total; pg_iter++) 1622 for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
1098 { 1623 {
1099 connection_iter = pg->peers[pg_iter].connected_peers; 1624 ret = GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].connect_peers, &connect_iterator, &pg->peers[pg_iter]);
1625 if (GNUNET_SYSERR == ret)
1626 return GNUNET_SYSERR;
1627
1628 total = total + ret;
1629
1630#if OLD
1631 connection_iter = ;
1100 while (connection_iter != NULL) 1632 while (connection_iter != NULL)
1101 { 1633 {
1102 connect_context = GNUNET_malloc(sizeof(struct ConnectContext)); 1634 connect_context = GNUNET_malloc(sizeof(struct ConnectContext));
1103 connect_context->pg = pg; 1635 connect_context->pg = pg;
1104 connect_context->first = pg->peers[pg_iter].daemon; 1636 connect_context->first = ;
1105 connect_context->second = connection_iter->daemon; 1637 connect_context->second = connection_iter->daemon;
1106 GNUNET_SCHEDULER_add_now(pg->sched, &schedule_connect, connect_context); 1638 GNUNET_SCHEDULER_add_now(pg->sched, &schedule_connect, connect_context);
1107 connection_iter = connection_iter->next; 1639 connection_iter = connection_iter->next;
1108 } 1640 }
1641#endif
1109 } 1642 }
1643 return total;
1110} 1644}
1111 1645
1112 1646
1113/* 1647/*
1114 * Takes a peer group and attempts to create a topology based on the 1648 * Takes a peer group and creates a topology based on the
1115 * one specified in the configuration file. Returns the number of connections 1649 * one specified. Creates a topology means generates friend
1116 * that will attempt to be created, but this will happen asynchronously(?) so 1650 * files for the peers so they can only connect to those allowed
1117 * the caller will have to keep track (via the callback) of whether or not 1651 * by the topology. This will only have an effect once peers
1118 * the connection actually happened. 1652 * are started if the FRIENDS_ONLY option is set in the base
1653 * config. Also takes an optional restrict topology which
1654 * disallows direct TCP connections UNLESS they are specified in
1655 * the restricted topology.
1119 * 1656 *
1120 * @param pg the peer group struct representing the running peers 1657 * @param pg the peer group struct representing the running peers
1121 * @param topology which topology to connect the peers in 1658 * @param topology which topology to connect the peers in
1659 * @param restrict_topology allow only direct TCP connections in this topology
1660 * use GNUNET_TESTING_TOPOLOGY_NONE for no restrictions
1122 * 1661 *
1123 * @return the number of connections should be created by the topology, so the 1662 * @return the maximum number of connections were all allowed peers
1124 * caller knows how many to wait for (if it so chooses) 1663 * connected to each other
1125 *
1126 */ 1664 */
1127int 1665int
1128GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, enum GNUNET_TESTING_Topology topology) 1666GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg,
1667 enum GNUNET_TESTING_Topology topology,
1668 enum GNUNET_TESTING_Topology restrict_topology)
1129{ 1669{
1130 int ret; 1670 int ret;
1131 int num_connections; 1671 int num_connections;
1672 int unblacklisted_connections;
1132 1673
1133 GNUNET_assert (pg->notify_connection != NULL); 1674 GNUNET_assert (pg->notify_connection != NULL);
1134 ret = GNUNET_OK; 1675 ret = GNUNET_OK;
@@ -1140,56 +1681,56 @@ GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, enum GNUNET
1140 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1681 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1141 _("Creating clique topology\n")); 1682 _("Creating clique topology\n"));
1142#endif 1683#endif
1143 num_connections = create_clique (pg); 1684 num_connections = create_clique (pg, &add_allowed_connections);
1144 break; 1685 break;
1145 case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING: 1686 case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
1146#if VERBOSE_TESTING 1687#if VERBOSE_TESTING
1147 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1688 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1148 _("Creating small world (ring) topology\n")); 1689 _("Creating small world (ring) topology\n"));
1149#endif 1690#endif
1150 num_connections = create_small_world_ring (pg); 1691 num_connections = create_small_world_ring (pg, &add_allowed_connections);
1151 break; 1692 break;
1152 case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD: 1693 case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
1153#if VERBOSE_TESTING 1694#if VERBOSE_TESTING
1154 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1695 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1155 _("Creating small world (2d-torus) topology\n")); 1696 _("Creating small world (2d-torus) topology\n"));
1156#endif 1697#endif
1157 num_connections = create_small_world (pg); 1698 num_connections = create_small_world (pg, &add_allowed_connections);
1158 break; 1699 break;
1159 case GNUNET_TESTING_TOPOLOGY_RING: 1700 case GNUNET_TESTING_TOPOLOGY_RING:
1160#if VERBOSE_TESTING 1701#if VERBOSE_TESTING
1161 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1702 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1162 _("Creating ring topology\n")); 1703 _("Creating ring topology\n"));
1163#endif 1704#endif
1164 num_connections = create_ring (pg); 1705 num_connections = create_ring (pg, &add_allowed_connections);
1165 break; 1706 break;
1166 case GNUNET_TESTING_TOPOLOGY_2D_TORUS: 1707 case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
1167#if VERBOSE_TESTING 1708#if VERBOSE_TESTING
1168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1709 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1169 _("Creating 2d torus topology\n")); 1710 _("Creating 2d torus topology\n"));
1170#endif 1711#endif
1171 num_connections = create_2d_torus (pg); 1712 num_connections = create_2d_torus (pg, &add_allowed_connections);
1172 break; 1713 break;
1173 case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI: 1714 case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
1174#if VERBOSE_TESTING 1715#if VERBOSE_TESTING
1175 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1176 _("Creating Erdos-Renyi topology\n")); 1717 _("Creating Erdos-Renyi topology\n"));
1177#endif 1718#endif
1178 num_connections = create_erdos_renyi (pg); 1719 num_connections = create_erdos_renyi (pg, &add_allowed_connections);
1179 break; 1720 break;
1180 case GNUNET_TESTING_TOPOLOGY_INTERNAT: 1721 case GNUNET_TESTING_TOPOLOGY_INTERNAT:
1181#if VERBOSE_TESTING 1722#if VERBOSE_TESTING
1182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1183 _("Creating InterNAT topology\n")); 1724 _("Creating InterNAT topology\n"));
1184#endif 1725#endif
1185 num_connections = create_nated_internet (pg); 1726 num_connections = create_nated_internet (pg, &add_allowed_connections);
1186 break; 1727 break;
1187 case GNUNET_TESTING_TOPOLOGY_SCALE_FREE: 1728 case GNUNET_TESTING_TOPOLOGY_SCALE_FREE:
1188#if VERBOSE_TESTING 1729#if VERBOSE_TESTING
1189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1730 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1190 _("Creating Scale Free topology\n")); 1731 _("Creating Scale Free topology\n"));
1191#endif 1732#endif
1192 num_connections = create_scale_free (pg); 1733 num_connections = create_scale_free (pg, &add_allowed_connections);
1193 break; 1734 break;
1194 case GNUNET_TESTING_TOPOLOGY_NONE: 1735 case GNUNET_TESTING_TOPOLOGY_NONE:
1195 num_connections = 0; 1736 num_connections = 0;
@@ -1202,10 +1743,11 @@ GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, enum GNUNET
1202 return GNUNET_SYSERR; 1743 return GNUNET_SYSERR;
1203 1744
1204 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING", "F2F")) 1745 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING", "F2F"))
1205 ret = create_and_copy_friend_files(pg); 1746 {
1206 if (ret == GNUNET_OK) 1747 ret = create_and_copy_friend_files(pg);
1207 connect_topology(pg); 1748 }
1208 else 1749
1750 if (ret != GNUNET_OK)
1209 { 1751 {
1210#if VERBOSE_TESTING 1752#if VERBOSE_TESTING
1211 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1753 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1213,10 +1755,419 @@ GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, enum GNUNET
1213#endif 1755#endif
1214 return GNUNET_SYSERR; 1756 return GNUNET_SYSERR;
1215 } 1757 }
1758 else
1759 {
1760#if VERBOSE_TESTING
1761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1762 _("Friend files created/copied successfully!\n"));
1763#endif
1764 }
1765
1766 /**
1767 * Use the create clique method to initially set all connections
1768 * as blacklisted.
1769 */
1770 create_clique (pg, &blacklist_connections);
1771 unblacklisted_connections = 0;
1772 /**
1773 * Un-blacklist connections as per the topology specified
1774 */
1775 switch (restrict_topology)
1776 {
1777 case GNUNET_TESTING_TOPOLOGY_CLIQUE:
1778#if VERBOSE_TESTING
1779 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1780 _("Blacklisting all but clique topology\n"));
1781#endif
1782 unblacklisted_connections = create_clique (pg, &unblacklist_connections);
1783 break;
1784 case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
1785#if VERBOSE_TESTING
1786 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1787 _("Blacklisting all but small world (ring) topology\n"));
1788#endif
1789 unblacklisted_connections = create_small_world_ring (pg, &unblacklist_connections);
1790 break;
1791 case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
1792#if VERBOSE_TESTING
1793 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1794 _("Blacklisting all but small world (2d-torus) topology\n"));
1795#endif
1796 unblacklisted_connections = create_small_world (pg, &unblacklist_connections);
1797 break;
1798 case GNUNET_TESTING_TOPOLOGY_RING:
1799#if VERBOSE_TESTING
1800 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1801 _("Blacklisting all but ring topology\n"));
1802#endif
1803 unblacklisted_connections = create_ring (pg, &unblacklist_connections);
1804 break;
1805 case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
1806#if VERBOSE_TESTING
1807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1808 _("Blacklisting all but 2d torus topology\n"));
1809#endif
1810 unblacklisted_connections = create_2d_torus (pg, &unblacklist_connections);
1811 break;
1812 case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
1813#if VERBOSE_TESTING
1814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1815 _("Blacklisting all but Erdos-Renyi topology\n"));
1816#endif
1817 unblacklisted_connections = create_erdos_renyi (pg, &unblacklist_connections);
1818 break;
1819 case GNUNET_TESTING_TOPOLOGY_INTERNAT:
1820#if VERBOSE_TESTING
1821 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1822 _("Blacklisting all but InterNAT topology\n"));
1823#endif
1824 unblacklisted_connections = create_nated_internet (pg, &unblacklist_connections);
1825 break;
1826 case GNUNET_TESTING_TOPOLOGY_SCALE_FREE:
1827#if VERBOSE_TESTING
1828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1829 _("Blacklisting all but Scale Free topology\n"));
1830#endif
1831 unblacklisted_connections = create_scale_free (pg, &unblacklist_connections);
1832 break;
1833 case GNUNET_TESTING_TOPOLOGY_NONE:
1834 /* Fall through */
1835 default:
1836 break;
1837 }
1838
1839 if (unblacklisted_connections > 0)
1840 {
1841 ret = create_and_copy_blacklist_files(pg);
1842 if (ret != GNUNET_OK)
1843 {
1844#if VERBOSE_TESTING
1845 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1846 _("Failed during blacklist file copying!\n"));
1847#endif
1848 return GNUNET_SYSERR;
1849 }
1850 else
1851 {
1852#if VERBOSE_TESTING
1853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1854 _("Blacklist files created/copied successfully!\n"));
1855#endif
1856 }
1857 }
1858
1216 1859
1217 return num_connections; 1860 return num_connections;
1218} 1861}
1219 1862
1863struct RandomContext
1864{
1865 /**
1866 * The peergroup
1867 */
1868 struct GNUNET_TESTING_PeerGroup *pg;
1869
1870 /**
1871 * uid of the first peer
1872 */
1873 uint32_t first_uid;
1874
1875 /**
1876 * Peer data for first peer.
1877 */
1878 struct PeerData *first;
1879
1880 /**
1881 * Random percentage to use
1882 */
1883 double percentage;
1884};
1885
1886struct MinimumContext
1887{
1888 /**
1889 * The peergroup
1890 */
1891 struct GNUNET_TESTING_PeerGroup *pg;
1892
1893 /**
1894 * uid of the first peer
1895 */
1896 uint32_t first_uid;
1897
1898 /**
1899 * Peer data for first peer.
1900 */
1901 struct PeerData *first;
1902
1903 /**
1904 * Number of conns per peer
1905 */
1906 unsigned int num_to_add;
1907};
1908
1909/**
1910 * Iterator for choosing random peers to connect.
1911 *
1912 * @param cls closure, a RandomContext
1913 * @param key the key the second Daemon was stored under
1914 * @param value the GNUNET_TESTING_Daemon that the first is to connect to
1915 *
1916 * @return GNUNET_YES to continue iteration
1917 */
1918static int
1919random_connect_iterator (void *cls,
1920 const GNUNET_HashCode * key,
1921 void *value)
1922{
1923 struct RandomContext *random_ctx = cls;
1924 double random_number;
1925 uint32_t second_pos;
1926 GNUNET_HashCode first_hash;
1927 random_number = ((double) GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK,
1928 (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL);
1929 if (random_number < random_ctx->percentage)
1930 {
1931 GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(random_ctx->first->connect_peers_working_set, key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1932 }
1933 /* Now we have considered this particular connection, remove it from the second peer so it's not double counted */
1934 uid_from_hash(key, &second_pos);
1935 hash_from_uid(random_ctx->first_uid, &first_hash);
1936 GNUNET_assert(random_ctx->pg->total > second_pos);
1937 GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(random_ctx->pg->peers[second_pos].connect_peers, &first_hash, random_ctx->first->daemon));
1938
1939 return GNUNET_YES;
1940}
1941
1942/**
1943 * Iterator for adding at least X peers to a peers connection set.
1944 *
1945 * @param cls closure, MinimumContext
1946 * @param key the key the second Daemon was stored under
1947 * @param value the GNUNET_TESTING_Daemon that the first is to connect to
1948 *
1949 * @return GNUNET_YES to continue iteration
1950 */
1951static int
1952minimum_connect_iterator (void *cls,
1953 const GNUNET_HashCode * key,
1954 void *value)
1955{
1956 struct MinimumContext *min_ctx = cls;
1957 uint32_t second_pos;
1958 GNUNET_HashCode first_hash;
1959
1960 if (GNUNET_CONTAINER_multihashmap_size(min_ctx->first->connect_peers_working_set) < min_ctx->num_to_add)
1961 {
1962 GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(min_ctx->first->connect_peers_working_set, key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1963 GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(min_ctx->first->connect_peers_working_set, key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1964 /* Now we have added this particular connection, remove it from the second peer's map so it's not double counted */
1965 uid_from_hash(key, &second_pos);
1966 hash_from_uid(min_ctx->first_uid, &first_hash);
1967 GNUNET_assert(min_ctx->pg->total > second_pos);
1968 GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(min_ctx->pg->peers[second_pos].connect_peers, &first_hash, min_ctx->first->daemon));
1969 return GNUNET_YES;
1970 }
1971 else
1972 return GNUNET_NO; /* We can stop iterating, we have enough peers! */
1973
1974
1975}
1976
1977/**
1978 * From the set of connections possible, choose percentage percent of connections
1979 * to actually connect.
1980 *
1981 * @param pg the peergroup we are dealing with
1982 * @param percentage what percent of total connections to make
1983 */
1984void
1985choose_random_connections(struct GNUNET_TESTING_PeerGroup *pg, double percentage)
1986{
1987 struct RandomContext random_ctx;
1988 uint32_t pg_iter;
1989
1990 for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
1991 {
1992 random_ctx.first_uid = pg_iter;
1993 random_ctx.first = &pg->peers[pg_iter];
1994 random_ctx.percentage = percentage;
1995 pg->peers[pg_iter].connect_peers_working_set = GNUNET_CONTAINER_multihashmap_create(pg->total);
1996 GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].connect_peers, &random_connect_iterator, &random_ctx);
1997 /* Now remove the old connections */
1998 GNUNET_CONTAINER_multihashmap_destroy(pg->peers[pg_iter].connect_peers);
1999 /* And replace with the random set */
2000 pg->peers[pg_iter].connect_peers = pg->peers[pg_iter].connect_peers_working_set;
2001 }
2002}
2003
2004/**
2005 * From the set of connections possible, choose at least num connections per
2006 * peer.
2007 *
2008 * @param pg the peergroup we are dealing with
2009 * @param num how many connections at least should each peer have (if possible)?
2010 */
2011void
2012choose_minimum(struct GNUNET_TESTING_PeerGroup *pg, unsigned int num)
2013{
2014 struct MinimumContext minimum_ctx;
2015 uint32_t pg_iter;
2016
2017 for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
2018 {
2019 pg->peers[pg_iter].connect_peers_working_set = GNUNET_CONTAINER_multihashmap_create(num);
2020 }
2021
2022 for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
2023 {
2024 minimum_ctx.first_uid = pg_iter;
2025 minimum_ctx.first = &pg->peers[pg_iter];
2026 minimum_ctx.num_to_add = num;
2027 pg->peers[pg_iter].connect_peers_working_set = GNUNET_CONTAINER_multihashmap_create(pg->total);
2028 GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].connect_peers, &minimum_connect_iterator, &minimum_ctx);
2029 }
2030
2031 for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
2032 {
2033 /* Remove the "old" connections */
2034 GNUNET_CONTAINER_multihashmap_destroy(pg->peers[pg_iter].connect_peers);
2035 /* And replace with the working set */
2036 pg->peers[pg_iter].connect_peers = pg->peers[pg_iter].connect_peers_working_set;
2037 }
2038
2039}
2040
2041
2042/*
2043 * @param pg the peer group struct representing the running peers
2044 * @param topology which topology to connect the peers in
2045 * @param options options for connecting the topology
2046 * @param option_modifier modifier for options that take a parameter
2047 *
2048 * There are many ways to connect peers that are supported by this function.
2049 * To connect peers in the same topology that was created via the
2050 * GNUNET_TESTING_create_topology, the topology variable must be set to
2051 * GNUNET_TESTING_TOPOLOGY_NONE. If the topology variable is specified,
2052 * a new instance of that topology will be generated and attempted to be
2053 * connected. This could result in some connections being impossible,
2054 * because some topologies are non-deterministic.
2055 *
2056 */
2057int
2058GNUNET_TESTING_connect_topology (struct GNUNET_TESTING_PeerGroup *pg,
2059 enum GNUNET_TESTING_Topology topology,
2060 enum GNUNET_TESTING_TopologyOption options,
2061 double option_modifier)
2062{
2063 int num_connections;
2064
2065 switch (topology)
2066 {
2067 case GNUNET_TESTING_TOPOLOGY_CLIQUE:
2068 #if VERBOSE_TESTING
2069 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2070 _("Creating clique topology\n"));
2071 #endif
2072 num_connections = create_clique (pg, &add_actual_connections);
2073 break;
2074 case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
2075 #if VERBOSE_TESTING
2076 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2077 _("Creating small world (ring) topology\n"));
2078 #endif
2079 num_connections = create_small_world_ring (pg, &add_actual_connections);
2080 break;
2081 case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
2082 #if VERBOSE_TESTING
2083 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2084 _("Creating small world (2d-torus) topology\n"));
2085 #endif
2086 num_connections = create_small_world (pg, &add_actual_connections);
2087 break;
2088 case GNUNET_TESTING_TOPOLOGY_RING:
2089 #if VERBOSE_TESTING
2090 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2091 _("Creating ring topology\n"));
2092 #endif
2093 num_connections = create_ring (pg, &add_actual_connections);
2094 break;
2095 case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
2096 #if VERBOSE_TESTING
2097 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2098 _("Creating 2d torus topology\n"));
2099 #endif
2100 num_connections = create_2d_torus (pg, &add_actual_connections);
2101 break;
2102 case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
2103 #if VERBOSE_TESTING
2104 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2105 _("Creating Erdos-Renyi topology\n"));
2106 #endif
2107 num_connections = create_erdos_renyi (pg, &add_actual_connections);
2108 break;
2109 case GNUNET_TESTING_TOPOLOGY_INTERNAT:
2110 #if VERBOSE_TESTING
2111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2112 _("Creating InterNAT topology\n"));
2113 #endif
2114 num_connections = create_nated_internet (pg, &add_actual_connections);
2115 break;
2116 case GNUNET_TESTING_TOPOLOGY_SCALE_FREE:
2117 #if VERBOSE_TESTING
2118 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2119 _("Creating Scale Free topology\n"));
2120 #endif
2121 num_connections = create_scale_free (pg, &add_actual_connections);
2122 break;
2123 case GNUNET_TESTING_TOPOLOGY_NONE:
2124 num_connections = copy_allowed_topology(pg);
2125 break;
2126 default:
2127 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Unknown topology specification, can't connect peers!\n");
2128 return GNUNET_SYSERR;
2129 }
2130
2131 switch (options)
2132 {
2133 case GNUNET_TESTING_TOPOLOGY_OPTION_RANDOM: /* Create a random subset of total connections based on parameter */
2134 choose_random_connections(pg, option_modifier);
2135 break;
2136 case GNUNET_TESTING_TOPOLOGY_OPTION_MINIMUM: /* Create at least X connections per peer (if possible!) */
2137 choose_minimum(pg, (unsigned int)option_modifier);
2138 break;
2139 case GNUNET_TESTING_TOPOLOGY_OPTION_DFS: /* Choose a random starting point, randomly walk graph, try to get each peer X connections */
2140 //choose_dfs(pg, (int)option_modifier);
2141 break;
2142 case GNUNET_TESTING_TOPOLOGY_OPTION_NONE:
2143 /* Fall through */
2144 case GNUNET_TESTING_TOPOLOGY_OPTION_ALL:
2145 /* Fall through */
2146 default:
2147 break;
2148 }
2149
2150 return connect_topology(pg);
2151}
2152
2153/**
2154 * Function which continues a peer group starting up
2155 * after successfully generating hostkeys for each peer.
2156 *
2157 * @param pg the peer group to continue starting
2158 *
2159 */
2160void
2161GNUNET_TESTING_daemons_continue_startup(struct GNUNET_TESTING_PeerGroup *pg)
2162{
2163 unsigned int i;
2164
2165 for (i = 0; i < pg->total; i++)
2166 {
2167 GNUNET_TESTING_daemon_continue_startup(pg->peers[i].daemon);
2168 }
2169}
2170
1220/** 2171/**
1221 * Start count gnunetd processes with the same set of transports and 2172 * Start count gnunetd processes with the same set of transports and
1222 * applications. The port numbers (any option called "PORT") will be 2173 * applications. The port numbers (any option called "PORT") will be
@@ -1226,6 +2177,11 @@ GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, enum GNUNET
1226 * @param sched scheduler to use 2177 * @param sched scheduler to use
1227 * @param cfg configuration template to use 2178 * @param cfg configuration template to use
1228 * @param total number of daemons to start 2179 * @param total number of daemons to start
2180 * @param hostkey_callback function to call on each peers hostkey generation
2181 * if NULL, peers will be started by this call, if non-null,
2182 * GNUNET_TESTING_daemons_continue_startup must be called after
2183 * successful hostkey generation
2184 * @param hostkey_cls closure for hostkey callback
1229 * @param cb function to call on each daemon that was started 2185 * @param cb function to call on each daemon that was started
1230 * @param cb_cls closure for cb 2186 * @param cb_cls closure for cb
1231 * @param connect_callback function to call each time two hosts are connected 2187 * @param connect_callback function to call each time two hosts are connected
@@ -1238,6 +2194,8 @@ struct GNUNET_TESTING_PeerGroup *
1238GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, 2194GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
1239 const struct GNUNET_CONFIGURATION_Handle *cfg, 2195 const struct GNUNET_CONFIGURATION_Handle *cfg,
1240 unsigned int total, 2196 unsigned int total,
2197 GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback,
2198 void *hostkey_cls,
1241 GNUNET_TESTING_NotifyDaemonRunning cb, 2199 GNUNET_TESTING_NotifyDaemonRunning cb,
1242 void *cb_cls, 2200 void *cb_cls,
1243 GNUNET_TESTING_NotifyConnection 2201 GNUNET_TESTING_NotifyConnection
@@ -1366,13 +2324,20 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
1366 "SERVICEHOME", newservicehome); 2324 "SERVICEHOME", newservicehome);
1367 GNUNET_free (newservicehome); 2325 GNUNET_free (newservicehome);
1368 pg->peers[off].cfg = pcfg; 2326 pg->peers[off].cfg = pcfg;
2327 pg->peers[off].allowed_peers = GNUNET_CONTAINER_multihashmap_create(total);
2328 pg->peers[off].connect_peers = GNUNET_CONTAINER_multihashmap_create(total);
2329 pg->peers[off].blacklisted_peers = GNUNET_CONTAINER_multihashmap_create(total);
2330 pg->peers[off].pg = pg;
1369 pg->peers[off].daemon = GNUNET_TESTING_daemon_start (sched, 2331 pg->peers[off].daemon = GNUNET_TESTING_daemon_start (sched,
1370 pcfg, 2332 pcfg,
1371 hostname, 2333 hostname,
2334 hostkey_callback,
2335 hostkey_cls,
1372 cb, cb_cls); 2336 cb, cb_cls);
1373 if (NULL == pg->peers[off].daemon) 2337 if (NULL == pg->peers[off].daemon)
1374 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2338 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1375 _("Could not start peer number %u!\n"), off); 2339 _("Could not start peer number %u!\n"), off);
2340
1376 } 2341 }
1377 return pg; 2342 return pg;
1378} 2343}
@@ -1391,6 +2356,72 @@ GNUNET_TESTING_daemon_get (struct GNUNET_TESTING_PeerGroup *pg, unsigned int pos
1391} 2356}
1392 2357
1393/** 2358/**
2359 * Prototype of a function that will be called when a
2360 * particular operation was completed the testing library.
2361 *
2362 * @param cls closure
2363 * @param emsg NULL on success
2364 */
2365void restart_callback (void *cls,
2366 const struct GNUNET_PeerIdentity *id,
2367 const struct GNUNET_CONFIGURATION_Handle *cfg,
2368 struct GNUNET_TESTING_Daemon *d,
2369 const char *emsg)
2370{
2371 struct RestartContext *restart_context = cls;
2372
2373 if (emsg == NULL)
2374 {
2375 restart_context->peers_restarted++;
2376 }
2377 else
2378 {
2379 restart_context->peers_restart_failed++;
2380 }
2381
2382 if (restart_context->peers_restarted == restart_context->peer_group->total)
2383 {
2384 restart_context->callback(restart_context->callback_cls, NULL);
2385 GNUNET_free(restart_context);
2386 }
2387 else if (restart_context->peers_restart_failed + restart_context->peers_restarted == restart_context->peer_group->total)
2388 {
2389 restart_context->callback(restart_context->callback_cls, "Failed to restart peers!");
2390 GNUNET_free(restart_context);
2391 }
2392
2393}
2394
2395/**
2396 * Restart all peers in the given group.
2397 *
2398 * @param pg the handle to the peer group
2399 * @param timeout how long to wait on failure
2400 * @param callback function to call on completion (or failure)
2401 * @param callback_cls closure for the callback function
2402 */
2403void
2404GNUNET_TESTING_daemons_restart (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_NotifyCompletion callback, void *callback_cls)
2405{
2406 struct RestartContext *restart_context;
2407 unsigned int off;
2408
2409 if (pg->total > 0)
2410 {
2411 restart_context = GNUNET_malloc(sizeof(struct RestartContext));
2412 restart_context->peer_group = pg;
2413 restart_context->peers_restarted = 0;
2414 restart_context->callback = callback;
2415 restart_context->callback_cls = callback_cls;
2416
2417 for (off = 0; off < pg->total; off++)
2418 {
2419 GNUNET_TESTING_daemon_restart (pg->peers[off].daemon, &restart_callback, restart_context);
2420 }
2421 }
2422}
2423
2424/**
1394 * Shutdown all peers started in the given group. 2425 * Shutdown all peers started in the given group.
1395 * 2426 *
1396 * @param pg handle to the peer group 2427 * @param pg handle to the peer group
@@ -1399,8 +2430,6 @@ void
1399GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg) 2430GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg)
1400{ 2431{
1401 unsigned int off; 2432 unsigned int off;
1402 struct PeerConnection *pos;
1403 struct PeerConnection *next;
1404 2433
1405 for (off = 0; off < pg->total; off++) 2434 for (off = 0; off < pg->total; off++)
1406 { 2435 {
@@ -1410,17 +2439,13 @@ GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg)
1410 as well... */ 2439 as well... */
1411 2440
1412 if (NULL != pg->peers[off].daemon) 2441 if (NULL != pg->peers[off].daemon)
1413 GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, NULL, NULL); 2442 GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, NULL, NULL, GNUNET_YES);
1414 if (NULL != pg->peers[off].cfg) 2443 if (NULL != pg->peers[off].cfg)
1415 GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg); 2444 GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg);
1416 2445
1417 pos = pg->peers[off].connected_peers; 2446 GNUNET_CONTAINER_multihashmap_destroy(pg->peers[off].allowed_peers);
1418 while (pos != NULL) 2447 GNUNET_CONTAINER_multihashmap_destroy(pg->peers[off].connect_peers);
1419 { 2448 GNUNET_CONTAINER_multihashmap_destroy(pg->peers[off].blacklisted_peers);
1420 next = pos->next;
1421 GNUNET_free(pos);
1422 pos = next;
1423 }
1424 2449
1425 } 2450 }
1426 GNUNET_free (pg->peers); 2451 GNUNET_free (pg->peers);