diff options
-rw-r--r-- | src/testing/Makefile.am | 3 | ||||
-rw-r--r-- | src/testing/test_testing_connect.c | 9 | ||||
-rw-r--r-- | src/testing/test_testing_data_topology_clique.conf | 7 | ||||
-rw-r--r-- | src/testing/test_testing_topology_clique.c | 305 | ||||
-rw-r--r-- | src/testing/testing.c | 380 | ||||
-rw-r--r-- | src/testing/testing_group.c | 228 |
6 files changed, 647 insertions, 285 deletions
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am index 4ddcc2b97..934ecc612 100644 --- a/src/testing/Makefile.am +++ b/src/testing/Makefile.am | |||
@@ -60,4 +60,5 @@ test_testing_topology_clique_LDADD = \ | |||
60 | EXTRA_DIST = \ | 60 | EXTRA_DIST = \ |
61 | test_testing_data.conf \ | 61 | test_testing_data.conf \ |
62 | test_testing_connect_peer1.conf \ | 62 | test_testing_connect_peer1.conf \ |
63 | test_testing_connect_peer2.conf | 63 | test_testing_connect_peer2.conf \ |
64 | test_testing_data_topology_clique.conf | ||
diff --git a/src/testing/test_testing_connect.c b/src/testing/test_testing_connect.c index 70fcccd98..5cd6274ea 100644 --- a/src/testing/test_testing_connect.c +++ b/src/testing/test_testing_connect.c | |||
@@ -64,6 +64,12 @@ end1_cb (void *cls, const char *emsg) | |||
64 | d2 = NULL; | 64 | d2 = NULL; |
65 | } | 65 | } |
66 | 66 | ||
67 | static void | ||
68 | finish_testing(void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) | ||
69 | { | ||
70 | GNUNET_TESTING_daemon_stop (d1, &end1_cb, NULL); | ||
71 | d1 = NULL; | ||
72 | } | ||
67 | 73 | ||
68 | static void | 74 | static void |
69 | my_connect_complete (void *cls, | 75 | my_connect_complete (void *cls, |
@@ -75,8 +81,7 @@ my_connect_complete (void *cls, | |||
75 | struct GNUNET_TESTING_Daemon *second_daemon, | 81 | struct GNUNET_TESTING_Daemon *second_daemon, |
76 | const char *emsg) | 82 | const char *emsg) |
77 | { | 83 | { |
78 | GNUNET_TESTING_daemon_stop (d1, &end1_cb, NULL); | 84 | GNUNET_SCHEDULER_add_now (sched, &finish_testing, NULL); |
79 | d1 = NULL; | ||
80 | } | 85 | } |
81 | 86 | ||
82 | 87 | ||
diff --git a/src/testing/test_testing_data_topology_clique.conf b/src/testing/test_testing_data_topology_clique.conf index a015b9b66..6f9a7739e 100644 --- a/src/testing/test_testing_data_topology_clique.conf +++ b/src/testing/test_testing_data_topology_clique.conf | |||
@@ -8,8 +8,9 @@ PORT = 2564 | |||
8 | [transport] | 8 | [transport] |
9 | PORT = 2565 | 9 | PORT = 2565 |
10 | PLUGINS = tcp | 10 | PLUGINS = tcp |
11 | #PREFIX = xterm -e xterm -T transport -e gdb -x cmd --args | 11 | #PREFIX = xterm -e xterm -T transport -e gdb --args |
12 | #PREFIX = valgrind --tool=memcheck --log-file=logs%p | 12 | #PREFIX = valgrind --tool=memcheck --log-file=logs%p |
13 | #DEBUG = YES | ||
13 | 14 | ||
14 | [arm] | 15 | [arm] |
15 | PORT = 2566 | 16 | PORT = 2566 |
@@ -26,8 +27,10 @@ PORT = 2569 | |||
26 | 27 | ||
27 | [core] | 28 | [core] |
28 | PORT = 2570 | 29 | PORT = 2570 |
30 | #DEBUG = YES | ||
29 | 31 | ||
30 | [testing] | 32 | [testing] |
31 | NUM_PEERS = 6 | 33 | NUM_PEERS = 2 |
32 | WEAKRANDOM = YES | 34 | WEAKRANDOM = YES |
33 | TOPOLOGY = 0 | 35 | TOPOLOGY = 0 |
36 | F2F = YES | ||
diff --git a/src/testing/test_testing_topology_clique.c b/src/testing/test_testing_topology_clique.c index 3d37d542b..a51d77f98 100644 --- a/src/testing/test_testing_topology_clique.c +++ b/src/testing/test_testing_topology_clique.c | |||
@@ -23,10 +23,10 @@ | |||
23 | */ | 23 | */ |
24 | #include "platform.h" | 24 | #include "platform.h" |
25 | #include "gnunet_testing_lib.h" | 25 | #include "gnunet_testing_lib.h" |
26 | #include "gnunet_core_service.h" | ||
26 | 27 | ||
27 | #define VERBOSE GNUNET_NO | 28 | #define VERBOSE GNUNET_NO |
28 | 29 | ||
29 | |||
30 | /** | 30 | /** |
31 | * How long until we give up on connecting the peers? | 31 | * How long until we give up on connecting the peers? |
32 | */ | 32 | */ |
@@ -38,7 +38,9 @@ static int ok; | |||
38 | 38 | ||
39 | static unsigned long long num_peers; | 39 | static unsigned long long num_peers; |
40 | 40 | ||
41 | static int total_connections; | 41 | static unsigned int total_connections; |
42 | |||
43 | static unsigned int expected_connections; | ||
42 | 44 | ||
43 | static int peers_left; | 45 | static int peers_left; |
44 | 46 | ||
@@ -50,15 +52,238 @@ const struct GNUNET_CONFIGURATION_Handle *main_cfg; | |||
50 | 52 | ||
51 | GNUNET_SCHEDULER_TaskIdentifier die_task; | 53 | GNUNET_SCHEDULER_TaskIdentifier die_task; |
52 | 54 | ||
55 | static struct GNUNET_CORE_Handle *peer1handle; | ||
56 | |||
57 | static struct GNUNET_CORE_Handle *peer2handle; | ||
58 | |||
59 | #define MTYPE 12345 | ||
53 | 60 | ||
54 | static void | 61 | static void |
55 | finish_testing () | 62 | finish_testing () |
56 | { | 63 | { |
57 | GNUNET_assert (pg != NULL); | 64 | GNUNET_assert (pg != NULL); |
65 | |||
66 | if (peer1handle != NULL) | ||
67 | GNUNET_CORE_disconnect(peer1handle); | ||
68 | if (peer2handle != NULL) | ||
69 | GNUNET_CORE_disconnect(peer2handle); | ||
70 | |||
58 | GNUNET_TESTING_daemons_stop (pg); | 71 | GNUNET_TESTING_daemons_stop (pg); |
59 | ok = 0; | 72 | ok = 0; |
60 | } | 73 | } |
61 | 74 | ||
75 | static int | ||
76 | process_mtype (void *cls, | ||
77 | const struct GNUNET_PeerIdentity *peer, | ||
78 | const struct GNUNET_MessageHeader *message, | ||
79 | struct GNUNET_TIME_Relative latency, | ||
80 | uint32_t distance) | ||
81 | { | ||
82 | #if VERBOSE | ||
83 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
84 | "Receiving message from `%4s'.\n", GNUNET_i2s (peer)); | ||
85 | #endif | ||
86 | GNUNET_SCHEDULER_cancel (sched, die_task); | ||
87 | GNUNET_SCHEDULER_add_now (sched, &finish_testing, NULL); | ||
88 | return GNUNET_OK; | ||
89 | } | ||
90 | |||
91 | |||
92 | static void | ||
93 | connect_notify (void *cls, | ||
94 | const struct GNUNET_PeerIdentity *peer, | ||
95 | struct GNUNET_TIME_Relative latency, | ||
96 | uint32_t distance) | ||
97 | { | ||
98 | #if VERBOSE | ||
99 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
100 | "Encrypted connection established to peer `%4s' with latency %llu\n", | ||
101 | GNUNET_i2s (peer), latency.value); | ||
102 | #endif | ||
103 | } | ||
104 | |||
105 | |||
106 | static void | ||
107 | disconnect_notify (void *cls, | ||
108 | const struct GNUNET_PeerIdentity *peer) | ||
109 | { | ||
110 | #if VERBOSE | ||
111 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
112 | "Encrypted connection to `%4s' cut\n", GNUNET_i2s (peer)); | ||
113 | #endif | ||
114 | } | ||
115 | |||
116 | |||
117 | static int | ||
118 | inbound_notify (void *cls, | ||
119 | const struct GNUNET_PeerIdentity *other, | ||
120 | const struct GNUNET_MessageHeader *message, | ||
121 | struct GNUNET_TIME_Relative latency, | ||
122 | uint32_t distance) | ||
123 | { | ||
124 | #if VERBOSE | ||
125 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
126 | "Core provides inbound data from `%4s'.\n", GNUNET_i2s (other)); | ||
127 | #endif | ||
128 | return GNUNET_OK; | ||
129 | } | ||
130 | |||
131 | |||
132 | static int | ||
133 | outbound_notify (void *cls, | ||
134 | const struct GNUNET_PeerIdentity *other, | ||
135 | const struct GNUNET_MessageHeader *message, | ||
136 | struct GNUNET_TIME_Relative latency, | ||
137 | uint32_t distance) | ||
138 | { | ||
139 | #if VERBOSE | ||
140 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
141 | "Core notifies about outbound data for `%4s'.\n", | ||
142 | GNUNET_i2s (other)); | ||
143 | #endif | ||
144 | return GNUNET_OK; | ||
145 | } | ||
146 | |||
147 | static void | ||
148 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) | ||
149 | { | ||
150 | #if VERBOSE | ||
151 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
152 | "End badly was called... stopping daemons.\n"); | ||
153 | #endif | ||
154 | |||
155 | if (peer1handle != NULL) | ||
156 | { | ||
157 | GNUNET_CORE_disconnect(peer1handle); | ||
158 | peer1handle = NULL; | ||
159 | } | ||
160 | if (peer2handle != NULL) | ||
161 | { | ||
162 | GNUNET_CORE_disconnect(peer2handle); | ||
163 | peer2handle = NULL; | ||
164 | } | ||
165 | |||
166 | if (pg != NULL) | ||
167 | { | ||
168 | GNUNET_TESTING_daemons_stop (pg); | ||
169 | ok = 7331; /* Opposite of leet */ | ||
170 | } | ||
171 | else | ||
172 | ok = 401; /* Never got peers started */ | ||
173 | } | ||
174 | |||
175 | static size_t | ||
176 | transmit_ready (void *cls, size_t size, void *buf) | ||
177 | { | ||
178 | struct GNUNET_MessageHeader *m; | ||
179 | |||
180 | GNUNET_assert (buf != NULL); | ||
181 | m = (struct GNUNET_MessageHeader *) buf; | ||
182 | m->type = htons (MTYPE); | ||
183 | m->size = htons (sizeof (struct GNUNET_MessageHeader)); | ||
184 | GNUNET_SCHEDULER_cancel(sched, die_task); | ||
185 | die_task = | ||
186 | GNUNET_SCHEDULER_add_delayed (sched, | ||
187 | TIMEOUT, &end_badly, "from transmit ready"); | ||
188 | |||
189 | return sizeof (struct GNUNET_MessageHeader); | ||
190 | } | ||
191 | |||
192 | |||
193 | static struct GNUNET_CORE_MessageHandler handlers[] = { | ||
194 | {&process_mtype, MTYPE, sizeof (struct GNUNET_MessageHeader)}, | ||
195 | {NULL, 0, 0} | ||
196 | }; | ||
197 | |||
198 | |||
199 | static void | ||
200 | init_notify (void *cls, | ||
201 | struct GNUNET_CORE_Handle *server, | ||
202 | const struct GNUNET_PeerIdentity *my_identity, | ||
203 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey) | ||
204 | { | ||
205 | struct GNUNET_TESTING_Daemon *connected_peer = cls; | ||
206 | struct GNUNET_TESTING_Daemon *peer1; | ||
207 | struct GNUNET_TESTING_Daemon *peer2; | ||
208 | |||
209 | peer1 = GNUNET_TESTING_daemon_get(pg, 0); | ||
210 | peer2 = GNUNET_TESTING_daemon_get(pg, 1); | ||
211 | #if VERBOSE | ||
212 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
213 | "Core connection to `%4s' established, setting up handles\n", | ||
214 | GNUNET_i2s (my_identity)); | ||
215 | #endif | ||
216 | |||
217 | if (connected_peer == peer1) | ||
218 | { | ||
219 | peer1handle = server; | ||
220 | #if VERBOSE | ||
221 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting core to peer 2\n"); | ||
222 | #endif | ||
223 | /* connect p2 */ | ||
224 | GNUNET_CORE_connect (sched, | ||
225 | peer2->cfg, | ||
226 | TIMEOUT, | ||
227 | peer2, | ||
228 | &init_notify, | ||
229 | NULL, | ||
230 | &connect_notify, | ||
231 | &disconnect_notify, | ||
232 | &inbound_notify, | ||
233 | GNUNET_YES, | ||
234 | &outbound_notify, GNUNET_YES, handlers); | ||
235 | } | ||
236 | else | ||
237 | { | ||
238 | GNUNET_assert(connected_peer == peer2); | ||
239 | peer2handle = server; | ||
240 | #if VERBOSE | ||
241 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
242 | "Asking core (1) for transmission to peer `%4s'\n", | ||
243 | GNUNET_i2s (&peer2->id)); | ||
244 | #endif | ||
245 | |||
246 | if (NULL == GNUNET_CORE_notify_transmit_ready (peer1->server, | ||
247 | 0, | ||
248 | TIMEOUT, | ||
249 | &peer2->id, | ||
250 | sizeof (struct GNUNET_MessageHeader), | ||
251 | &transmit_ready, &peer1)) | ||
252 | { | ||
253 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
254 | "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", | ||
255 | GNUNET_i2s (&peer2->id)); | ||
256 | } | ||
257 | |||
258 | } | ||
259 | } | ||
260 | |||
261 | |||
262 | static void | ||
263 | send_test_messages () | ||
264 | { | ||
265 | struct GNUNET_TESTING_Daemon *peer1; | ||
266 | struct GNUNET_TESTING_Daemon *peer2; | ||
267 | |||
268 | peer1 = GNUNET_TESTING_daemon_get(pg, 0); | ||
269 | peer2 = GNUNET_TESTING_daemon_get(pg, 1); | ||
270 | |||
271 | die_task = GNUNET_SCHEDULER_add_delayed (sched, | ||
272 | TIMEOUT, | ||
273 | &end_badly, "from send test messages"); | ||
274 | |||
275 | /* Send a message from peer 1 to peer 2 */ | ||
276 | GNUNET_CORE_connect (sched, | ||
277 | peer1->cfg, | ||
278 | TIMEOUT, | ||
279 | peer1, | ||
280 | &init_notify, | ||
281 | NULL, | ||
282 | &connect_notify, | ||
283 | &disconnect_notify, | ||
284 | &inbound_notify, | ||
285 | GNUNET_YES, &outbound_notify, GNUNET_YES, handlers); | ||
286 | } | ||
62 | 287 | ||
63 | void | 288 | void |
64 | topology_callback (void *cls, | 289 | topology_callback (void *cls, |
@@ -75,14 +300,17 @@ topology_callback (void *cls, | |||
75 | * even though we know that X peers exist in i... But we may want to | 300 | * even though we know that X peers exist in i... But we may want to |
76 | * know about the peer for logging purposes here (I'm sure we will actually | 301 | * know about the peer for logging purposes here (I'm sure we will actually |
77 | * so the API may need changed). Question, should the API expose what | 302 | * so the API may need changed). Question, should the API expose what |
78 | * a peer group is, or provide convenience/accessor functions? */ | 303 | * a peer group is, or provide convenience/accessor functions? |
304 | * | ||
305 | * For now, I've added accessor functions, which seems like a software | ||
306 | * engineering kind of solution, but who knows/cares. */ | ||
79 | if (emsg == NULL) | 307 | if (emsg == NULL) |
80 | { | 308 | { |
81 | total_connections++; | 309 | total_connections++; |
82 | #if VERBOSE | 310 | #if VERBOSE |
83 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected peer %s to peer %s\n", | 311 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected peer %s to peer %s\n", |
84 | GNUNET_TESTING_daemon_get_shortname (first_daemon), | 312 | first_daemon->shortname, |
85 | GNUNET_TESTING_daemon_get_shortname (second_daemon)); | 313 | second_daemon->shortname); |
86 | #endif | 314 | #endif |
87 | } | 315 | } |
88 | #if VERBOSE | 316 | #if VERBOSE |
@@ -90,78 +318,37 @@ topology_callback (void *cls, | |||
90 | { | 318 | { |
91 | 319 | ||
92 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to connect peer %s to peer %s with error %s\n", | 320 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to connect peer %s to peer %s with error %s\n", |
93 | GNUNET_TESTING_daemon_get_shortname (first_daemon), | 321 | first_daemon->shortname, |
94 | GNUNET_TESTING_daemon_get_shortname (second_daemon), emsg); | 322 | second_daemon->shortname, emsg); |
95 | } | 323 | } |
96 | #endif | 324 | #endif |
97 | 325 | ||
98 | if (total_connections * 2 == num_peers * (num_peers - 1)) | 326 | if (total_connections == expected_connections) |
99 | { | 327 | { |
100 | #if VERBOSE | 328 | #if VERBOSE |
101 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 329 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
102 | "Created %d total connections, which is our target number! Ending test.\n", | 330 | "Created %d total connections, which is our target number! Ending test.\n", |
103 | total_connections * 2); | 331 | total_connections); |
104 | #endif | 332 | #endif |
333 | |||
105 | GNUNET_SCHEDULER_cancel (sched, die_task); | 334 | GNUNET_SCHEDULER_cancel (sched, die_task); |
106 | finish_testing (); | 335 | die_task = GNUNET_SCHEDULER_add_now (sched, &send_test_messages, NULL); |
107 | } | 336 | } |
108 | else | 337 | else |
109 | { | 338 | { |
110 | #if VERBOSE | 339 | #if VERBOSE |
111 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 340 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
112 | "Have %d total connections, Need %d\n", | 341 | "Have %d total connections, Need %d\n", |
113 | total_connections * 2, num_peers * (num_peers - 1)); | 342 | total_connections, expected_connections); |
114 | #endif | 343 | #endif |
115 | } | 344 | } |
116 | } | 345 | } |
117 | 346 | ||
118 | 347 | ||
119 | static void | 348 | static void |
120 | end_badly () | ||
121 | { | ||
122 | GNUNET_SCHEDULER_cancel (sched, die_task); | ||
123 | if (pg != NULL) | ||
124 | { | ||
125 | GNUNET_TESTING_daemons_stop (pg); | ||
126 | ok = 7331; /* Opposite of leet */ | ||
127 | } | ||
128 | else | ||
129 | ok = 401; /* Never got peers started */ | ||
130 | } | ||
131 | |||
132 | |||
133 | static void | ||
134 | create_topology () | 349 | create_topology () |
135 | { | 350 | { |
136 | int expected_connections; /* Is there any way we can use this to check | 351 | expected_connections = -1; |
137 | how many connections we are expecting to | ||
138 | finish the topology? It would be nice so | ||
139 | that we could estimate completion time, | ||
140 | but since GNUNET_TESTING_create_topology | ||
141 | goes off and starts connecting we may get | ||
142 | the topology callback before we have | ||
143 | finished and not know how many! We could | ||
144 | just never touch expected_connections, | ||
145 | and if we get called back when it's still | ||
146 | 0 then we know we can't believe it. I | ||
147 | don't like this though, because it may | ||
148 | technically be possible for all connections | ||
149 | to have been created and the callback | ||
150 | called without us setting | ||
151 | expected_connections! Other options are | ||
152 | doing a trial connection setup, or | ||
153 | calculating the number of connections. | ||
154 | Problem with calculating is that for random | ||
155 | topologies this isn't reliable. Problem | ||
156 | with counting is we then iterate over them | ||
157 | twice instead of once. Probably the best | ||
158 | option though. Grr, also doing trial | ||
159 | connection set up means we need to call | ||
160 | fake_topology_create and then | ||
161 | real_topology_create which is also ugly. | ||
162 | Then we need to maintain state inside pg as | ||
163 | well, which I was trying to avoid. */ | ||
164 | |||
165 | if ((pg != NULL) && (peers_left == 0)) | 352 | if ((pg != NULL) && (peers_left == 0)) |
166 | { | 353 | { |
167 | /* create_topology will read the topology information from | 354 | /* create_topology will read the topology information from |
@@ -178,11 +365,9 @@ create_topology () | |||
178 | } | 365 | } |
179 | 366 | ||
180 | GNUNET_SCHEDULER_cancel (sched, die_task); | 367 | GNUNET_SCHEDULER_cancel (sched, die_task); |
181 | |||
182 | die_task = GNUNET_SCHEDULER_add_delayed (sched, | 368 | die_task = GNUNET_SCHEDULER_add_delayed (sched, |
183 | GNUNET_TIME_relative_multiply | 369 | TIMEOUT, |
184 | (GNUNET_TIME_UNIT_SECONDS, 20), | 370 | &end_badly, NULL); |
185 | &finish_testing, NULL); | ||
186 | } | 371 | } |
187 | 372 | ||
188 | 373 | ||
@@ -259,7 +444,7 @@ run (void *cls, | |||
259 | static int | 444 | static int |
260 | check () | 445 | check () |
261 | { | 446 | { |
262 | char *const argv[] = { "test-testing-topology", | 447 | char *const argv[] = { "test-testing-topology-clique", |
263 | "-c", | 448 | "-c", |
264 | "test_testing_data_topology_clique.conf", | 449 | "test_testing_data_topology_clique.conf", |
265 | #if VERBOSE | 450 | #if VERBOSE |
@@ -271,7 +456,7 @@ check () | |||
271 | GNUNET_GETOPT_OPTION_END | 456 | GNUNET_GETOPT_OPTION_END |
272 | }; | 457 | }; |
273 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, | 458 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, |
274 | argv, "test-testing-topology", "nohelp", | 459 | argv, "test-testing-topology-clique", "nohelp", |
275 | options, &run, &ok); | 460 | options, &run, &ok); |
276 | return ok; | 461 | return ok; |
277 | } | 462 | } |
diff --git a/src/testing/testing.c b/src/testing/testing.c index 8ceaace75..bddd0f30c 100644 --- a/src/testing/testing.c +++ b/src/testing/testing.c | |||
@@ -54,160 +54,6 @@ | |||
54 | */ | 54 | */ |
55 | #define MAX_EXEC_WAIT_RUNS 50 | 55 | #define MAX_EXEC_WAIT_RUNS 50 |
56 | 56 | ||
57 | /** | ||
58 | * Phases of starting GNUnet on a system. | ||
59 | */ | ||
60 | enum StartPhase | ||
61 | { | ||
62 | /** | ||
63 | * Copy the configuration file to the target system. | ||
64 | */ | ||
65 | SP_COPYING, | ||
66 | |||
67 | /** | ||
68 | * Configuration file has been copied, start ARM on target system. | ||
69 | */ | ||
70 | SP_COPIED, | ||
71 | |||
72 | /** | ||
73 | * ARM has been started, check that it has properly daemonized and | ||
74 | * then try to connect to the CORE service (which should be | ||
75 | * auto-started by ARM). | ||
76 | */ | ||
77 | SP_START_ARMING, | ||
78 | |||
79 | /** | ||
80 | * We're waiting for CORE to start. | ||
81 | */ | ||
82 | SP_START_CORE, | ||
83 | |||
84 | /** | ||
85 | * Core has notified us that we've established a connection to the service. | ||
86 | * The main FSM halts here and waits to be moved to UPDATE or CLEANUP. | ||
87 | */ | ||
88 | SP_START_DONE, | ||
89 | |||
90 | /** | ||
91 | * We've been asked to terminate the instance and are now waiting for | ||
92 | * the remote command to delete the configuration file to complete. | ||
93 | */ | ||
94 | SP_CLEANUP, | ||
95 | |||
96 | /** | ||
97 | * We've received a configuration update and are currently waiting for | ||
98 | * the copy process for the update to complete. Once it is, we will | ||
99 | * return to "SP_START_DONE" (and rely on ARM to restart all affected | ||
100 | * services). | ||
101 | */ | ||
102 | SP_CONFIG_UPDATE | ||
103 | }; | ||
104 | |||
105 | |||
106 | /** | ||
107 | * Handle for a GNUnet daemon (technically a set of | ||
108 | * daemons; the handle is really for the master ARM | ||
109 | * daemon) started by the testing library. | ||
110 | */ | ||
111 | struct GNUNET_TESTING_Daemon | ||
112 | { | ||
113 | /** | ||
114 | * Our scheduler. | ||
115 | */ | ||
116 | struct GNUNET_SCHEDULER_Handle *sched; | ||
117 | |||
118 | /** | ||
119 | * Our configuration. | ||
120 | */ | ||
121 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
122 | |||
123 | /** | ||
124 | * Host to run GNUnet on. | ||
125 | */ | ||
126 | char *hostname; | ||
127 | |||
128 | /* Result of GNUNET_i2s of this peer, for printing */ | ||
129 | char *shortname; | ||
130 | |||
131 | /** | ||
132 | * Username we are using. | ||
133 | */ | ||
134 | char *username; | ||
135 | |||
136 | /** | ||
137 | * Name of the configuration file | ||
138 | */ | ||
139 | char *cfgfile; | ||
140 | |||
141 | /** | ||
142 | * Function to call when the peer is running. | ||
143 | */ | ||
144 | GNUNET_TESTING_NotifyDaemonRunning cb; | ||
145 | |||
146 | /** | ||
147 | * Closure for cb. | ||
148 | */ | ||
149 | void *cb_cls; | ||
150 | |||
151 | /** | ||
152 | * Arguments from "daemon_stop" call. | ||
153 | */ | ||
154 | GNUNET_TESTING_NotifyCompletion dead_cb; | ||
155 | |||
156 | /** | ||
157 | * Closure for 'dead_cb'. | ||
158 | */ | ||
159 | void *dead_cb_cls; | ||
160 | |||
161 | /** | ||
162 | * Arguments from "daemon_stop" call. | ||
163 | */ | ||
164 | GNUNET_TESTING_NotifyCompletion update_cb; | ||
165 | |||
166 | /** | ||
167 | * Closure for 'update_cb'. | ||
168 | */ | ||
169 | void *update_cb_cls; | ||
170 | |||
171 | /** | ||
172 | * Identity of this peer (once started). | ||
173 | */ | ||
174 | struct GNUNET_PeerIdentity id; | ||
175 | |||
176 | /** | ||
177 | * Flag to indicate that we've already been asked | ||
178 | * to terminate (but could not because some action | ||
179 | * was still pending). | ||
180 | */ | ||
181 | int dead; | ||
182 | |||
183 | /** | ||
184 | * PID of the process that we started last. | ||
185 | */ | ||
186 | pid_t pid; | ||
187 | |||
188 | /** | ||
189 | * How many iterations have we been waiting for | ||
190 | * the started process to complete? | ||
191 | */ | ||
192 | unsigned int wait_runs; | ||
193 | |||
194 | /** | ||
195 | * In which phase are we during the start of | ||
196 | * this process? | ||
197 | */ | ||
198 | enum StartPhase phase; | ||
199 | |||
200 | /** | ||
201 | * ID of the current task. | ||
202 | */ | ||
203 | GNUNET_SCHEDULER_TaskIdentifier task; | ||
204 | |||
205 | /** | ||
206 | * Handle to the server. | ||
207 | */ | ||
208 | struct GNUNET_CORE_Handle *server; | ||
209 | }; | ||
210 | |||
211 | 57 | ||
212 | /** | 58 | /** |
213 | * Function called after GNUNET_CORE_connect has succeeded | 59 | * Function called after GNUNET_CORE_connect has succeeded |
@@ -793,11 +639,21 @@ struct ConnectContext | |||
793 | */ | 639 | */ |
794 | struct GNUNET_TESTING_Daemon *d1; | 640 | struct GNUNET_TESTING_Daemon *d1; |
795 | 641 | ||
642 | /* | ||
643 | * Handle to core of first daemon (to check connect) | ||
644 | */ | ||
645 | struct GNUNET_CORE_Handle * d1core; | ||
646 | |||
796 | /** | 647 | /** |
797 | * Testing handle to the second daemon. | 648 | * Testing handle to the second daemon. |
798 | */ | 649 | */ |
799 | struct GNUNET_TESTING_Daemon *d2; | 650 | struct GNUNET_TESTING_Daemon *d2; |
800 | 651 | ||
652 | /* | ||
653 | * Handle to core of second daemon (to check connect) | ||
654 | */ | ||
655 | struct GNUNET_CORE_Handle * d2core; | ||
656 | |||
801 | /** | 657 | /** |
802 | * Transport handle to the first daemon. | 658 | * Transport handle to the first daemon. |
803 | */ | 659 | */ |
@@ -830,10 +686,61 @@ struct ConnectContext | |||
830 | */ | 686 | */ |
831 | struct GNUNET_TIME_Absolute timeout; | 687 | struct GNUNET_TIME_Absolute timeout; |
832 | 688 | ||
689 | /* | ||
690 | * Hello timeout task | ||
691 | */ | ||
692 | GNUNET_SCHEDULER_TaskIdentifier hello_send_task; | ||
693 | |||
694 | /* | ||
695 | * Connect timeout task | ||
696 | */ | ||
697 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; | ||
698 | |||
699 | /** | ||
700 | * When should this operation be complete (or we must trigger | ||
701 | * a timeout). | ||
702 | */ | ||
703 | struct GNUNET_TIME_Relative timeout_hello; | ||
704 | |||
705 | /* | ||
706 | * The current hello message we have (for d1) | ||
707 | */ | ||
708 | struct GNUNET_MessageHeader *hello; | ||
709 | |||
710 | /* | ||
711 | * Was the connection successful? | ||
712 | */ | ||
713 | int connected; | ||
833 | }; | 714 | }; |
834 | 715 | ||
835 | 716 | ||
836 | /** | 717 | /** |
718 | * Receive the HELLO from one peer, give it to the other | ||
719 | * and ask them to connect. | ||
720 | * | ||
721 | * @param cls "struct ConnectContext" | ||
722 | * @param message HELLO message of peer | ||
723 | */ | ||
724 | static void | ||
725 | process_hello (void *cls, const struct GNUNET_MessageHeader *message) | ||
726 | { | ||
727 | struct ConnectContext *ctx = cls; | ||
728 | |||
729 | #if DEBUG_TESTING | ||
730 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
731 | "Received `%s' from transport service of `%4s'\n", | ||
732 | "HELLO", GNUNET_i2s (&ctx->d1->id)); | ||
733 | #endif | ||
734 | |||
735 | GNUNET_assert (message != NULL); | ||
736 | GNUNET_free_non_null(ctx->hello); | ||
737 | ctx->hello = GNUNET_malloc(ntohs(message->size)); | ||
738 | memcpy(ctx->hello, message, ntohs(message->size)); | ||
739 | |||
740 | } | ||
741 | |||
742 | |||
743 | /** | ||
837 | * Notify callback about success or failure of the attempt | 744 | * Notify callback about success or failure of the attempt |
838 | * to connect the two peers | 745 | * to connect the two peers |
839 | * | 746 | * |
@@ -846,16 +753,33 @@ notify_connect_result (void *cls, | |||
846 | { | 753 | { |
847 | struct ConnectContext *ctx = cls; | 754 | struct ConnectContext *ctx = cls; |
848 | 755 | ||
756 | GNUNET_TRANSPORT_get_hello_cancel (ctx->d1th, &process_hello, ctx); | ||
757 | GNUNET_SCHEDULER_cancel(ctx->d1->sched, ctx->hello_send_task); | ||
758 | |||
849 | if (ctx->cb != NULL) | 759 | if (ctx->cb != NULL) |
850 | { | 760 | { |
851 | if ((tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT) != 0) | 761 | if (ctx->connected == GNUNET_NO) |
852 | ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->d1->cfg, | 762 | { |
853 | ctx->d2->cfg, ctx->d1, ctx->d2, | 763 | ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->d1->cfg, |
854 | _("Peers failed to connect")); | 764 | ctx->d2->cfg, ctx->d1, ctx->d2, |
765 | _("Peers failed to connect")); | ||
766 | } | ||
855 | else | 767 | else |
856 | ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->d1->cfg, | 768 | { |
857 | ctx->d2->cfg, ctx->d1, ctx->d2, NULL); | 769 | ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->d1->cfg, |
770 | ctx->d2->cfg, ctx->d1, ctx->d2, NULL); | ||
771 | GNUNET_SCHEDULER_cancel(ctx->d1->sched, ctx->timeout_task); | ||
772 | } | ||
858 | } | 773 | } |
774 | |||
775 | ctx->ntr = NULL; | ||
776 | GNUNET_TRANSPORT_disconnect (ctx->d1th); | ||
777 | ctx->d1th = NULL; | ||
778 | GNUNET_TRANSPORT_disconnect (ctx->d2th); | ||
779 | ctx->d2th = NULL; | ||
780 | GNUNET_CORE_disconnect (ctx->d1core); | ||
781 | ctx->d1core = NULL; | ||
782 | |||
859 | GNUNET_free (ctx); | 783 | GNUNET_free (ctx); |
860 | } | 784 | } |
861 | 785 | ||
@@ -868,74 +792,48 @@ notify_connect_result (void *cls, | |||
868 | * @param buf where to copy the message, NULL on error | 792 | * @param buf where to copy the message, NULL on error |
869 | * @return number of bytes copied to buf | 793 | * @return number of bytes copied to buf |
870 | */ | 794 | */ |
871 | static size_t | 795 | static void |
872 | transmit_ready (void *cls, size_t size, void *buf) | 796 | connect_notify (void *cls, const struct GNUNET_PeerIdentity * peer, struct GNUNET_TIME_Relative latency, |
797 | uint32_t distance) | ||
873 | { | 798 | { |
874 | struct ConnectContext *ctx = cls; | 799 | struct ConnectContext *ctx = cls; |
875 | 800 | ||
876 | #if DEBUG_TESTING | 801 | #if DEBUG_TESTING |
877 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 802 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
878 | "Core notified us about readiness to transmit message, connection must be up!\n"); | 803 | "Core notified us about connection to a peer\n\n\n"); |
879 | #endif | 804 | #endif |
880 | ctx->ntr = NULL; | 805 | if (memcmp(&ctx->d2->id, peer, sizeof(struct GNUNET_PeerIdentity)) == 0) |
881 | GNUNET_TRANSPORT_disconnect (ctx->d1th); | 806 | { |
882 | ctx->d1th = NULL; | 807 | #if DEBUG_TESTING |
883 | GNUNET_TRANSPORT_disconnect (ctx->d2th); | 808 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
884 | ctx->d2th = NULL; | 809 | "Core notified us about connection to peer %s\n\n\n", GNUNET_i2s(peer)); |
885 | GNUNET_SCHEDULER_add_continuation (ctx->d1->sched, | ||
886 | ¬ify_connect_result, | ||
887 | ctx, | ||
888 | (buf == NULL) ? | ||
889 | GNUNET_SCHEDULER_REASON_TIMEOUT : | ||
890 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
891 | return 0; | ||
892 | } | ||
893 | |||
894 | |||
895 | #if 0 | ||
896 | static void | ||
897 | timeout_hello_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
898 | { | ||
899 | GNUNET_TRANSPORT_get_hello_cancel (ctx->d1th, &process_hello, ctx); | ||
900 | GNUNET_TRANSPORT_disconnect (ctx->d1th); | ||
901 | GNUNET_TRANSPORT_disconnect (ctx->d2th); | ||
902 | if (NULL != ctx->cb) | ||
903 | ctx->cb (ctx->cb_cls, _("Failed to receive `HELLO' from peer\n")); | ||
904 | GNUNET_free (ctx); | ||
905 | } | ||
906 | #endif | 810 | #endif |
811 | /* | ||
812 | * If we disconnect here, then the hello may never get sent (if it was delayed!) | ||
813 | * However I'm sure there was a reason it was here... so I'm just commenting. | ||
814 | */ | ||
815 | ctx->connected = GNUNET_YES; | ||
816 | GNUNET_SCHEDULER_add_now (ctx->d1->sched, | ||
817 | ¬ify_connect_result, | ||
818 | ctx); | ||
819 | } | ||
907 | 820 | ||
821 | } | ||
908 | 822 | ||
909 | /** | ||
910 | * Receive the HELLO from one peer, give it to the other | ||
911 | * and ask them to connect. | ||
912 | * | ||
913 | * @param cls "struct ConnectContext" | ||
914 | * @param message HELLO message of peer | ||
915 | */ | ||
916 | static void | 823 | static void |
917 | process_hello (void *cls, const struct GNUNET_MessageHeader *message) | 824 | send_hello(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
918 | { | 825 | { |
919 | struct ConnectContext *ctx = cls; | 826 | struct ConnectContext *ctx = cls; |
920 | 827 | ||
921 | /* first of all, stop the notification stuff */ | 828 | GNUNET_assert (ctx->hello != NULL); |
922 | GNUNET_TRANSPORT_get_hello_cancel (ctx->d1th, &process_hello, ctx); | 829 | GNUNET_TRANSPORT_offer_hello (ctx->d2th, ctx->hello); |
923 | #if DEBUG_TESTING | 830 | |
924 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 831 | ctx->timeout_hello = GNUNET_TIME_relative_multiply(ctx->timeout_hello, 2); |
925 | "Received `%s' from transport service of `%4s'\n", | 832 | ctx->hello_send_task = GNUNET_SCHEDULER_add_delayed(ctx->d1->sched, ctx->timeout_hello, &send_hello, ctx); |
926 | "HELLO", GNUNET_i2s (&ctx->d1->id)); | ||
927 | #endif | ||
928 | GNUNET_assert (message != NULL); | ||
929 | GNUNET_TRANSPORT_offer_hello (ctx->d2th, message); | ||
930 | ctx->ntr | ||
931 | = GNUNET_CORE_notify_transmit_ready (ctx->d2->server, | ||
932 | 0, | ||
933 | GNUNET_TIME_absolute_get_remaining | ||
934 | (ctx->timeout), &ctx->d1->id, | ||
935 | sizeof (struct GNUNET_MessageHeader), | ||
936 | &transmit_ready, ctx); | ||
937 | } | 833 | } |
938 | 834 | ||
835 | |||
836 | #if HIDDEN | ||
939 | /* | 837 | /* |
940 | * Accessor function since we have hidden what GNUNET_TESTING_Daemon is | 838 | * Accessor function since we have hidden what GNUNET_TESTING_Daemon is |
941 | * | 839 | * |
@@ -947,6 +845,32 @@ GNUNET_TESTING_daemon_get_shortname (struct GNUNET_TESTING_Daemon *d) | |||
947 | return d->shortname; | 845 | return d->shortname; |
948 | } | 846 | } |
949 | 847 | ||
848 | char * | ||
849 | GNUNET_TESTING_daemon_get_hostname (struct GNUNET_TESTING_Daemon *d) | ||
850 | { | ||
851 | return d->hostname; | ||
852 | } | ||
853 | |||
854 | char * | ||
855 | GNUNET_TESTING_daemon_get_username (struct GNUNET_TESTING_Daemon *d) | ||
856 | { | ||
857 | return d->username; | ||
858 | } | ||
859 | |||
860 | struct GNUNET_PeerIdentity * | ||
861 | GNUNET_TESTING_daemon_get_peer (struct GNUNET_TESTING_Daemon *d) | ||
862 | { | ||
863 | return &d->id; | ||
864 | } | ||
865 | |||
866 | struct GNUNET_CONFIGURATION_Handle * | ||
867 | GNUNET_TESTING_daemon_get_config (struct GNUNET_TESTING_Daemon *d) | ||
868 | { | ||
869 | return d->cfg; | ||
870 | } | ||
871 | #endif | ||
872 | |||
873 | |||
950 | /** | 874 | /** |
951 | * Establish a connection between two GNUnet daemons. | 875 | * Establish a connection between two GNUnet daemons. |
952 | * | 876 | * |
@@ -965,6 +889,7 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, | |||
965 | void *cb_cls) | 889 | void *cb_cls) |
966 | { | 890 | { |
967 | struct ConnectContext *ctx; | 891 | struct ConnectContext *ctx; |
892 | static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} }; | ||
968 | 893 | ||
969 | if ((d1->server == NULL) || (d2->server == NULL)) | 894 | if ((d1->server == NULL) || (d2->server == NULL)) |
970 | { | 895 | { |
@@ -979,6 +904,8 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, | |||
979 | ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); | 904 | ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); |
980 | ctx->cb = cb; | 905 | ctx->cb = cb; |
981 | ctx->cb_cls = cb_cls; | 906 | ctx->cb_cls = cb_cls; |
907 | ctx->timeout_hello = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 800); | ||
908 | ctx->connected = GNUNET_NO; | ||
982 | #if DEBUG_TESTING | 909 | #if DEBUG_TESTING |
983 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 910 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
984 | "Asked to connect peer %s to peer %s\n", | 911 | "Asked to connect peer %s to peer %s\n", |
@@ -986,6 +913,24 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, | |||
986 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 913 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
987 | "Connecting to transport service of peer %s\n", d1->shortname); | 914 | "Connecting to transport service of peer %s\n", d1->shortname); |
988 | #endif | 915 | #endif |
916 | |||
917 | ctx->d1core = GNUNET_CORE_connect (d1->sched, | ||
918 | d1->cfg, | ||
919 | timeout, | ||
920 | ctx, | ||
921 | NULL, | ||
922 | NULL, &connect_notify, NULL, | ||
923 | NULL, GNUNET_NO, | ||
924 | NULL, GNUNET_NO, no_handlers); | ||
925 | if (ctx->d1core == NULL) | ||
926 | { | ||
927 | GNUNET_free (ctx); | ||
928 | if (NULL != cb) | ||
929 | cb (cb_cls, &d1->id, &d2->id, d1->cfg, d2->cfg, d1, d2, | ||
930 | _("Failed to connect to core service of first peer!\n")); | ||
931 | return; | ||
932 | } | ||
933 | |||
989 | ctx->d1th = GNUNET_TRANSPORT_connect (d1->sched, | 934 | ctx->d1th = GNUNET_TRANSPORT_connect (d1->sched, |
990 | d1->cfg, d1, NULL, NULL, NULL); | 935 | d1->cfg, d1, NULL, NULL, NULL); |
991 | if (ctx->d1th == NULL) | 936 | if (ctx->d1th == NULL) |
@@ -1004,6 +949,7 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, | |||
1004 | "Connecting to transport service of peer %s\n", d2->shortname); | 949 | "Connecting to transport service of peer %s\n", d2->shortname); |
1005 | 950 | ||
1006 | #endif | 951 | #endif |
952 | |||
1007 | ctx->d2th = GNUNET_TRANSPORT_connect (d2->sched, | 953 | ctx->d2th = GNUNET_TRANSPORT_connect (d2->sched, |
1008 | d2->cfg, d2, NULL, NULL, NULL); | 954 | d2->cfg, d2, NULL, NULL, NULL); |
1009 | if (ctx->d2th == NULL) | 955 | if (ctx->d2th == NULL) |
@@ -1020,9 +966,13 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, | |||
1020 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 966 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1021 | "Asking for hello from peer %s\n", GNUNET_i2s (&d1->id)); | 967 | "Asking for hello from peer %s\n", GNUNET_i2s (&d1->id)); |
1022 | #endif | 968 | #endif |
1023 | /* FIXME: need to handle timeout: start timeout task | 969 | |
1024 | as well here! (use 'timeout_hello_task') */ | 970 | ctx->timeout_task = GNUNET_SCHEDULER_add_delayed (d1->sched, |
971 | timeout, | ||
972 | ¬ify_connect_result, ctx); | ||
973 | |||
1025 | GNUNET_TRANSPORT_get_hello (ctx->d1th, &process_hello, ctx); | 974 | GNUNET_TRANSPORT_get_hello (ctx->d1th, &process_hello, ctx); |
975 | ctx->hello_send_task = GNUNET_SCHEDULER_add_delayed(ctx->d1->sched, ctx->timeout_hello, &send_hello, ctx); | ||
1026 | } | 976 | } |
1027 | 977 | ||
1028 | 978 | ||
diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c index 424dada34..fd1338e1e 100644 --- a/src/testing/testing_group.c +++ b/src/testing/testing_group.c | |||
@@ -46,6 +46,20 @@ | |||
46 | 46 | ||
47 | #define CONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) | 47 | #define CONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) |
48 | 48 | ||
49 | struct PeerConnection | ||
50 | { | ||
51 | /* | ||
52 | * Linked list | ||
53 | */ | ||
54 | struct PeerConnection *next; | ||
55 | |||
56 | /* | ||
57 | * Pointer to daemon handle | ||
58 | */ | ||
59 | struct GNUNET_TESTING_Daemon *daemon; | ||
60 | |||
61 | }; | ||
62 | |||
49 | /** | 63 | /** |
50 | * Data we keep per peer. | 64 | * Data we keep per peer. |
51 | */ | 65 | */ |
@@ -63,6 +77,12 @@ struct PeerData | |||
63 | * Handle for controlling the daemon. | 77 | * Handle for controlling the daemon. |
64 | */ | 78 | */ |
65 | struct GNUNET_TESTING_Daemon *daemon; | 79 | struct GNUNET_TESTING_Daemon *daemon; |
80 | |||
81 | /* | ||
82 | * Linked list of peer connections (simply indexes of PeerGroup) | ||
83 | * FIXME: Question, store pointer or integer? Pointer for now... | ||
84 | */ | ||
85 | struct PeerConnection *connected_peers; | ||
66 | }; | 86 | }; |
67 | 87 | ||
68 | 88 | ||
@@ -202,6 +222,79 @@ make_config (const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t * port) | |||
202 | return uc.ret; | 222 | return uc.ret; |
203 | } | 223 | } |
204 | 224 | ||
225 | /* | ||
226 | * Add entries to the peers connected list | ||
227 | * | ||
228 | * @param pg the peer group we are working with | ||
229 | * @param first index of the first peer | ||
230 | * @param second index of the second peer | ||
231 | * | ||
232 | * @return the number of connections added (can be 0 1 or 2) | ||
233 | * | ||
234 | * FIXME: add both, or only add one? | ||
235 | * - if both are added, then we have to keep track | ||
236 | * when connecting so we don't double connect | ||
237 | * - if only one is added, we need to iterate over | ||
238 | * both lists to find out if connection already exists | ||
239 | * - having both allows the whitelisting/friend file | ||
240 | * creation to be easier | ||
241 | * | ||
242 | * -- For now, add both, we have to iterate over each to | ||
243 | * check for duplicates anyways, so we'll take the performance | ||
244 | * hit assuming we don't have __too__ many connections | ||
245 | * | ||
246 | */ | ||
247 | static int | ||
248 | add_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second) | ||
249 | { | ||
250 | int added; | ||
251 | struct PeerConnection *first_iter; | ||
252 | struct PeerConnection *second_iter; | ||
253 | int add_first; | ||
254 | int add_second; | ||
255 | struct PeerConnection *new_first; | ||
256 | struct PeerConnection *new_second; | ||
257 | |||
258 | first_iter = pg->peers[first].connected_peers; | ||
259 | add_first = GNUNET_YES; | ||
260 | while (first_iter != NULL) | ||
261 | { | ||
262 | if (first_iter->daemon == pg->peers[second].daemon) | ||
263 | add_first = GNUNET_NO; | ||
264 | first_iter = first_iter->next; | ||
265 | } | ||
266 | |||
267 | second_iter = pg->peers[second].connected_peers; | ||
268 | add_second = GNUNET_YES; | ||
269 | while (second_iter != NULL) | ||
270 | { | ||
271 | if (second_iter->daemon == pg->peers[first].daemon) | ||
272 | add_second = GNUNET_NO; | ||
273 | second_iter = second_iter->next; | ||
274 | } | ||
275 | |||
276 | added = 0; | ||
277 | if (add_first) | ||
278 | { | ||
279 | new_first = GNUNET_malloc(sizeof(struct PeerConnection)); | ||
280 | new_first->daemon = pg->peers[second].daemon; | ||
281 | new_first->next = pg->peers[first].connected_peers; | ||
282 | pg->peers[first].connected_peers = new_first; | ||
283 | added++; | ||
284 | } | ||
285 | |||
286 | if (add_second) | ||
287 | { | ||
288 | new_second = GNUNET_malloc(sizeof(struct PeerConnection)); | ||
289 | new_second->daemon = pg->peers[first].daemon; | ||
290 | new_second->next = pg->peers[second].connected_peers; | ||
291 | pg->peers[second].connected_peers = new_second; | ||
292 | added++; | ||
293 | } | ||
294 | |||
295 | return added; | ||
296 | } | ||
297 | |||
205 | static int | 298 | static int |
206 | create_clique (struct GNUNET_TESTING_PeerGroup *pg) | 299 | create_clique (struct GNUNET_TESTING_PeerGroup *pg) |
207 | { | 300 | { |
@@ -221,12 +314,12 @@ create_clique (struct GNUNET_TESTING_PeerGroup *pg) | |||
221 | "Connecting peer %d to peer %d\n", | 314 | "Connecting peer %d to peer %d\n", |
222 | outer_count, inner_count); | 315 | outer_count, inner_count); |
223 | #endif | 316 | #endif |
224 | GNUNET_TESTING_daemons_connect (pg->peers[outer_count].daemon, | 317 | connect_attempts += add_connections(pg, outer_count, inner_count); |
318 | /*GNUNET_TESTING_daemons_connect (pg->peers[outer_count].daemon, | ||
225 | pg->peers[inner_count].daemon, | 319 | pg->peers[inner_count].daemon, |
226 | CONNECT_TIMEOUT, | 320 | CONNECT_TIMEOUT, |
227 | pg->notify_connection, | 321 | pg->notify_connection, |
228 | pg->notify_connection_cls); | 322 | pg->notify_connection_cls);*/ |
229 | connect_attempts++; | ||
230 | } | 323 | } |
231 | } | 324 | } |
232 | 325 | ||
@@ -235,6 +328,111 @@ create_clique (struct GNUNET_TESTING_PeerGroup *pg) | |||
235 | 328 | ||
236 | 329 | ||
237 | /* | 330 | /* |
331 | * Create the friend files based on the PeerConnection's | ||
332 | * of each peer in the peer group, and copy the files | ||
333 | * to the appropriate place | ||
334 | * | ||
335 | * @param pg the peer group we are dealing with | ||
336 | */ | ||
337 | static void | ||
338 | create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg) | ||
339 | { | ||
340 | FILE *temp_friend_handle; | ||
341 | unsigned int pg_iter; | ||
342 | struct PeerConnection *connection_iter; | ||
343 | struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc; | ||
344 | char *temp_service_path; | ||
345 | pid_t pid; | ||
346 | char *arg; | ||
347 | struct GNUNET_PeerIdentity *temppeer; | ||
348 | const char * mytemp; | ||
349 | |||
350 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
351 | { | ||
352 | mytemp = GNUNET_DISK_mktemp("friends"); | ||
353 | temp_friend_handle = fopen (mytemp, "wt"); | ||
354 | connection_iter = pg->peers[pg_iter].connected_peers; | ||
355 | while (connection_iter != NULL) | ||
356 | { | ||
357 | temppeer = &connection_iter->daemon->id; | ||
358 | GNUNET_CRYPTO_hash_to_enc(&temppeer->hashPubKey, &peer_enc); | ||
359 | fprintf(temp_friend_handle, "%s\n", (char *)&peer_enc); | ||
360 | connection_iter = connection_iter->next; | ||
361 | } | ||
362 | |||
363 | fclose(temp_friend_handle); | ||
364 | |||
365 | GNUNET_CONFIGURATION_get_value_string(pg->peers[pg_iter].daemon->cfg, "PATHS", "SERVICEHOME", &temp_service_path); | ||
366 | |||
367 | if (temp_service_path == NULL) | ||
368 | { | ||
369 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
370 | _("No SERVICEHOME specified in peer configuration, can't copy friends file!\n")); | ||
371 | fclose(temp_friend_handle); | ||
372 | unlink(mytemp); | ||
373 | break; | ||
374 | } | ||
375 | |||
376 | if (pg->peers[pg_iter].daemon->hostname == NULL) /* Local, just copy the file */ | ||
377 | { | ||
378 | GNUNET_asprintf (&arg, "%s/friends", temp_service_path); | ||
379 | pid = GNUNET_OS_start_process ("mv", | ||
380 | "mv", mytemp, arg, NULL); | ||
381 | #if VERBOSE_TESTING | ||
382 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
383 | _("Copying file with command cp %s %s\n"), mytemp, arg); | ||
384 | #endif | ||
385 | GNUNET_free(arg); | ||
386 | } | ||
387 | else /* Remote, scp the file to the correct place */ | ||
388 | { | ||
389 | if (NULL != pg->peers[pg_iter].daemon->username) | ||
390 | GNUNET_asprintf (&arg, "%s@%s:%s/friends", pg->peers[pg_iter].daemon->username, pg->peers[pg_iter].daemon->hostname, temp_service_path); | ||
391 | else | ||
392 | GNUNET_asprintf (&arg, "%s:%s/friends", pg->peers[pg_iter].daemon->hostname, temp_service_path); | ||
393 | pid = GNUNET_OS_start_process ("scp", | ||
394 | "scp", mytemp, arg, NULL); | ||
395 | #if VERBOSE_TESTING | ||
396 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
397 | _("Copying file with command scp %s %s\n"), mytemp, arg); | ||
398 | #endif | ||
399 | GNUNET_free(arg); | ||
400 | } | ||
401 | |||
402 | } | ||
403 | } | ||
404 | |||
405 | |||
406 | |||
407 | /* | ||
408 | * Connect the topology as specified by the PeerConnection's | ||
409 | * of each peer in the peer group | ||
410 | * | ||
411 | * @param pg the peer group we are dealing with | ||
412 | */ | ||
413 | static void | ||
414 | connect_topology (struct GNUNET_TESTING_PeerGroup *pg) | ||
415 | { | ||
416 | unsigned int pg_iter; | ||
417 | struct PeerConnection *connection_iter; | ||
418 | |||
419 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
420 | { | ||
421 | connection_iter = pg->peers[pg_iter].connected_peers; | ||
422 | while (connection_iter != NULL) | ||
423 | { | ||
424 | GNUNET_TESTING_daemons_connect (pg->peers[pg_iter].daemon, | ||
425 | connection_iter->daemon, | ||
426 | CONNECT_TIMEOUT, | ||
427 | pg->notify_connection, | ||
428 | pg->notify_connection_cls); | ||
429 | connection_iter = connection_iter->next; | ||
430 | } | ||
431 | } | ||
432 | } | ||
433 | |||
434 | |||
435 | /* | ||
238 | * Takes a peer group and attempts to create a topology based on the | 436 | * Takes a peer group and attempts to create a topology based on the |
239 | * one specified in the configuration file. Returns the number of connections | 437 | * one specified in the configuration file. Returns the number of connections |
240 | * that will attempt to be created, but this will happen asynchronously(?) so | 438 | * that will attempt to be created, but this will happen asynchronously(?) so |
@@ -247,7 +445,6 @@ create_clique (struct GNUNET_TESTING_PeerGroup *pg) | |||
247 | int | 445 | int |
248 | GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg) | 446 | GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg) |
249 | { | 447 | { |
250 | /* Put stuff at home in here... */ | ||
251 | unsigned long long topology_num; | 448 | unsigned long long topology_num; |
252 | int ret; | 449 | int ret; |
253 | 450 | ||
@@ -330,6 +527,11 @@ GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg) | |||
330 | ret = GNUNET_SYSERR; | 527 | ret = GNUNET_SYSERR; |
331 | break; | 528 | break; |
332 | } | 529 | } |
530 | |||
531 | if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING", "F2F")) | ||
532 | create_and_copy_friend_files(pg); | ||
533 | |||
534 | connect_topology(pg); | ||
333 | } | 535 | } |
334 | else | 536 | else |
335 | { | 537 | { |
@@ -374,6 +576,7 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, | |||
374 | const char *hostname; | 576 | const char *hostname; |
375 | char *baseservicehome; | 577 | char *baseservicehome; |
376 | char *newservicehome; | 578 | char *newservicehome; |
579 | char *tmpdir; | ||
377 | struct GNUNET_CONFIGURATION_Handle *pcfg; | 580 | struct GNUNET_CONFIGURATION_Handle *pcfg; |
378 | unsigned int off; | 581 | unsigned int off; |
379 | unsigned int hostcnt; | 582 | unsigned int hostcnt; |
@@ -475,7 +678,9 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, | |||
475 | } | 678 | } |
476 | else | 679 | else |
477 | { | 680 | { |
478 | tempsize = snprintf (NULL, 0, "%s/%d/", "/tmp/gnunet-testing-test-test", off) + 1; /* FIXME: set a default path, or read the TMPDIR variable or something */ | 681 | tmpdir = getenv ("TMPDIR"); |
682 | tmpdir = tmpdir ? tmpdir : "/tmp"; | ||
683 | tempsize = snprintf (NULL, 0, "%s/%s/%d/", tmpdir, "gnunet-testing-test-test", off) + 1; | ||
479 | newservicehome = GNUNET_malloc (tempsize); | 684 | newservicehome = GNUNET_malloc (tempsize); |
480 | snprintf (newservicehome, tempsize, "%s/%d/", | 685 | snprintf (newservicehome, tempsize, "%s/%d/", |
481 | "/tmp/gnunet-testing-test-test", off); | 686 | "/tmp/gnunet-testing-test-test", off); |
@@ -496,6 +701,18 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, | |||
496 | return pg; | 701 | return pg; |
497 | } | 702 | } |
498 | 703 | ||
704 | /* | ||
705 | * Get a daemon by number, so callers don't have to do nasty | ||
706 | * offsetting operation. | ||
707 | */ | ||
708 | struct GNUNET_TESTING_Daemon * | ||
709 | GNUNET_TESTING_daemon_get (struct GNUNET_TESTING_PeerGroup *pg, unsigned int position) | ||
710 | { | ||
711 | if (position < pg->total) | ||
712 | return pg->peers[position].daemon; | ||
713 | else | ||
714 | return NULL; | ||
715 | } | ||
499 | 716 | ||
500 | /** | 717 | /** |
501 | * Shutdown all peers started in the given group. | 718 | * Shutdown all peers started in the given group. |
@@ -513,6 +730,7 @@ GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg) | |||
513 | continuations to be called here? This | 730 | continuations to be called here? This |
514 | would require us to take a continuation | 731 | would require us to take a continuation |
515 | as well... */ | 732 | as well... */ |
733 | |||
516 | if (NULL != pg->peers[off].daemon) | 734 | if (NULL != pg->peers[off].daemon) |
517 | GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, NULL, NULL); | 735 | GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, NULL, NULL); |
518 | if (NULL != pg->peers[off].cfg) | 736 | if (NULL != pg->peers[off].cfg) |