diff options
Diffstat (limited to 'src/testing')
-rw-r--r-- | src/testing/test_testing.c | 16 | ||||
-rw-r--r-- | src/testing/test_testing_connect.c | 24 | ||||
-rw-r--r-- | src/testing/test_testing_data_topology_clique.conf | 2 | ||||
-rw-r--r-- | src/testing/test_testing_data_topology_ring.conf | 1 | ||||
-rw-r--r-- | src/testing/test_testing_group.c | 1 | ||||
-rw-r--r-- | src/testing/test_testing_topology.c | 138 | ||||
-rw-r--r-- | src/testing/testing.c | 355 | ||||
-rw-r--r-- | src/testing/testing_group.c | 1195 |
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 | ||
46 | static void | 48 | static 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; | |||
49 | static void | 49 | static void |
50 | end2_cb (void *cls, const char *emsg) | 50 | end2_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 | ||
60 | static void | 68 | static void |
61 | end1_cb (void *cls, const char *emsg) | 69 | end1_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 | ||
68 | static void | 76 | static void |
69 | finish_testing(void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) | 77 | finish_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] |
43 | NUM_PEERS = 3 | 43 | NUM_PEERS = 4 |
44 | WEAKRANDOM = YES | 44 | WEAKRANDOM = YES |
45 | TOPOLOGY = 0 | 45 | TOPOLOGY = 0 |
46 | F2F = YES | 46 | F2F = 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 | |||
34 | WEAKRANDOM = YES | 34 | WEAKRANDOM = YES |
35 | TOPOLOGY = 3 | 35 | TOPOLOGY = 3 |
36 | F2F = YES | 36 | F2F = YES |
37 | BLACKLISTING = 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 | ||
84 | static enum GNUNET_TESTING_Topology topology; | 84 | static enum GNUNET_TESTING_Topology topology; |
85 | 85 | ||
86 | static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* Don't do any blacklisting */ | ||
87 | |||
88 | static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */ | ||
89 | |||
90 | static enum GNUNET_TESTING_TopologyOption connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; | ||
91 | |||
92 | static double connect_topology_option_modifier = 0.0; | ||
93 | |||
86 | static char *test_directory; | 94 | static 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 | |||
513 | static void | 520 | static void |
514 | create_topology () | 521 | connect_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 | |||
545 | static void | ||
546 | create_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 | ||
544 | static void | 570 | static void |
545 | my_cb (void *cls, | 571 | peers_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 | */ | ||
615 | void 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 | ||
576 | static void | 650 | static void |
577 | run (void *cls, | 651 | run (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 | ||
55 | static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} }; | 55 | static 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 | */ | ||
647 | void | ||
648 | GNUNET_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 * | |||
471 | GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, | 673 | GNUNET_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 | */ | ||
789 | void | ||
790 | GNUNET_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 | */ |
583 | void | 890 | void |
584 | GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d, | 891 | GNUNET_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 | */ | ||
57 | typedef int (*GNUNET_TESTING_ConnectionProcessor) | ||
58 | (struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second); | ||
59 | |||
60 | struct 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 | |||
89 | struct 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 | ||
53 | struct PeerConnection | 104 | struct 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 | */ | ||
250 | static void | ||
251 | hash_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 | */ | ||
264 | static void | ||
265 | uid_from_hash (const GNUNET_HashCode *hash, uint32_t *uid) | ||
266 | { | ||
267 | memcpy (uid, hash, sizeof(uint32_t)); | ||
268 | } | ||
168 | 269 | ||
169 | struct UpdateContext | 270 | struct 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 | */ | ||
397 | static int | ||
398 | add_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 | */ |
304 | static int | 452 | static int |
305 | add_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second) | 453 | add_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 | */ | ||
541 | static int | ||
542 | blacklist_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 | */ | ||
591 | static int | ||
592 | unblacklist_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 | */ |
371 | static int | 636 | static int |
372 | create_scale_free (struct GNUNET_TESTING_PeerGroup *pg) | 637 | create_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 | ||
415 | int | 680 | int |
416 | create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg) | 681 | create_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 | ||
527 | static int | 792 | static int |
528 | create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg) | 793 | create_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 | ||
580 | static int | 845 | static int |
581 | create_small_world (struct GNUNET_TESTING_PeerGroup *pg) | 846 | create_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 | ||
723 | static int | 988 | static int |
724 | create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg) | 989 | create_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 | ||
770 | static int | 1035 | static int |
771 | create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg) | 1036 | create_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 | ||
848 | static int | 1113 | static int |
849 | create_clique (struct GNUNET_TESTING_PeerGroup *pg) | 1114 | create_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 | ||
875 | static int | 1140 | static int |
876 | create_ring (struct GNUNET_TESTING_PeerGroup *pg) | 1141 | create_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 | */ | ||
1183 | static int | ||
1184 | friend_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 | */ | ||
1210 | static int | ||
1211 | blacklist_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 | */ | ||
1357 | static int | ||
1358 | create_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 | */ | ||
1535 | static int | ||
1536 | connect_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 | */ | ||
1563 | static int | ||
1564 | copy_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 | */ | ||
1581 | static int | ||
1582 | copy_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, ©_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 | */ |
1090 | static void | 1610 | static int |
1091 | connect_topology (struct GNUNET_TESTING_PeerGroup *pg) | 1611 | connect_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 | */ |
1127 | int | 1665 | int |
1128 | GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, enum GNUNET_TESTING_Topology topology) | 1666 | GNUNET_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 | ||
1863 | struct 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 | |||
1886 | struct 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 | */ | ||
1918 | static int | ||
1919 | random_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 | */ | ||
1951 | static int | ||
1952 | minimum_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 | */ | ||
1984 | void | ||
1985 | choose_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 | */ | ||
2011 | void | ||
2012 | choose_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 | */ | ||
2057 | int | ||
2058 | GNUNET_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 | */ | ||
2160 | void | ||
2161 | GNUNET_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 * | |||
1238 | GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, | 2194 | GNUNET_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 | */ | ||
2365 | void 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 | */ | ||
2403 | void | ||
2404 | GNUNET_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 | |||
1399 | GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg) | 2430 | GNUNET_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); |