aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2010-05-09 15:55:32 +0000
committerNathan S. Evans <evans@in.tum.de>2010-05-09 15:55:32 +0000
commitb94fa4e20a07cddbd1a4fbff283c0d7f6f4a88f9 (patch)
tree2696fdc5962ba6b38e6169b8cf23cee07772077a /src
parentca3d4f99562556e22eeac7f7f198ff12941a9e1e (diff)
downloadgnunet-b94fa4e20a07cddbd1a4fbff283c0d7f6f4a88f9.tar.gz
gnunet-b94fa4e20a07cddbd1a4fbff283c0d7f6f4a88f9.zip
changes to testing... create hostkey using peerinfo before starting peers, better topology creation and more options therein, changes to order of starting peers, connecting peers... new order is hostkey create, topology create, blacklist create, start peers, connect peers
Diffstat (limited to 'src')
-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);