diff options
Diffstat (limited to 'src/cadet/test_cadet_new.c')
-rw-r--r-- | src/cadet/test_cadet_new.c | 1048 |
1 files changed, 0 insertions, 1048 deletions
diff --git a/src/cadet/test_cadet_new.c b/src/cadet/test_cadet_new.c deleted file mode 100644 index d32404815..000000000 --- a/src/cadet/test_cadet_new.c +++ /dev/null | |||
@@ -1,1048 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/test_cadet_mq.c | ||
22 | * @author Bart Polot | ||
23 | * @author Christian Grothoff | ||
24 | * @brief Test for the cadet service using mq API. | ||
25 | */ | ||
26 | #include <stdio.h> | ||
27 | #include "platform.h" | ||
28 | #include "cadet_test_lib_new.h" | ||
29 | #include "gnunet_cadet_service.h" | ||
30 | #include "gnunet_statistics_service.h" | ||
31 | #include <gauger.h> | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Ugly workaround to unify data handlers on incoming and outgoing channels. | ||
36 | */ | ||
37 | struct CadetTestChannelWrapper | ||
38 | { | ||
39 | /** | ||
40 | * Channel pointer. | ||
41 | */ | ||
42 | struct GNUNET_CADET_Channel *ch; | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * How many messages to send | ||
47 | */ | ||
48 | #define TOTAL_PACKETS 500 /* Cannot exceed 64k! */ | ||
49 | |||
50 | /** | ||
51 | * How long until we give up on connecting the peers? | ||
52 | */ | ||
53 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) | ||
54 | |||
55 | /** | ||
56 | * Time to wait for stuff that should be rather fast | ||
57 | */ | ||
58 | #define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20) | ||
59 | |||
60 | /** | ||
61 | * DIFFERENT TESTS TO RUN | ||
62 | */ | ||
63 | #define SETUP 0 | ||
64 | #define FORWARD 1 | ||
65 | #define KEEPALIVE 2 | ||
66 | #define SPEED 3 | ||
67 | #define SPEED_ACK 4 | ||
68 | #define SPEED_REL 8 | ||
69 | #define P2P_SIGNAL 10 | ||
70 | |||
71 | /** | ||
72 | * Which test are we running? | ||
73 | */ | ||
74 | static int test; | ||
75 | |||
76 | /** | ||
77 | * String with test name | ||
78 | */ | ||
79 | static char *test_name; | ||
80 | |||
81 | /** | ||
82 | * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic. | ||
83 | */ | ||
84 | static int test_backwards = GNUNET_NO; | ||
85 | |||
86 | /** | ||
87 | * How many events have happened | ||
88 | */ | ||
89 | static int ok; | ||
90 | |||
91 | /** | ||
92 | * Number of events expected to conclude the test successfully. | ||
93 | */ | ||
94 | static int ok_goal; | ||
95 | |||
96 | /** | ||
97 | * Size of each test packet's payload | ||
98 | */ | ||
99 | static size_t size_payload = sizeof (uint32_t); | ||
100 | |||
101 | /** | ||
102 | * Operation to get peer ids. | ||
103 | */ | ||
104 | static struct GNUNET_TESTBED_Operation *t_op[2]; | ||
105 | |||
106 | /** | ||
107 | * Peer ids. | ||
108 | */ | ||
109 | static struct GNUNET_PeerIdentity *p_id[2]; | ||
110 | |||
111 | /** | ||
112 | * Port ID | ||
113 | */ | ||
114 | static struct GNUNET_HashCode port; | ||
115 | |||
116 | /** | ||
117 | * Peer ids counter. | ||
118 | */ | ||
119 | static unsigned int p_ids; | ||
120 | |||
121 | /** | ||
122 | * Is the setup initialized? | ||
123 | */ | ||
124 | static int initialized; | ||
125 | |||
126 | /** | ||
127 | * Number of payload packes sent. | ||
128 | */ | ||
129 | static int data_sent; | ||
130 | |||
131 | /** | ||
132 | * Number of payload packets received. | ||
133 | */ | ||
134 | static int data_received; | ||
135 | |||
136 | /** | ||
137 | * Number of payload packed acknowledgements sent. | ||
138 | */ | ||
139 | static int ack_sent; | ||
140 | |||
141 | /** | ||
142 | * Number of payload packed explicitly (app level) acknowledged. | ||
143 | */ | ||
144 | static int ack_received; | ||
145 | |||
146 | /** | ||
147 | * Total number of peers asked to run. | ||
148 | */ | ||
149 | static unsigned long long peers_requested; | ||
150 | |||
151 | /** | ||
152 | * Number of currently running peers (should be same as @c peers_requested). | ||
153 | */ | ||
154 | static unsigned long long peers_running; | ||
155 | |||
156 | /** | ||
157 | * Test context (to shut down). | ||
158 | */ | ||
159 | struct GNUNET_CADET_TEST_Context *test_ctx; | ||
160 | |||
161 | /** | ||
162 | * Task called to disconnect peers. | ||
163 | */ | ||
164 | static struct GNUNET_SCHEDULER_Task *disconnect_task; | ||
165 | |||
166 | /** | ||
167 | * Task To perform tests | ||
168 | */ | ||
169 | static struct GNUNET_SCHEDULER_Task *test_task; | ||
170 | |||
171 | /** | ||
172 | * Task runnining #send_next_msg(). | ||
173 | */ | ||
174 | static struct GNUNET_SCHEDULER_Task *send_next_msg_task; | ||
175 | |||
176 | /** | ||
177 | * Cadet handle for the root peer | ||
178 | */ | ||
179 | static struct GNUNET_CADET_Handle *h1; | ||
180 | |||
181 | /** | ||
182 | * Cadet handle for the first leaf peer | ||
183 | */ | ||
184 | static struct GNUNET_CADET_Handle *h2; | ||
185 | |||
186 | /** | ||
187 | * Channel handle for the root peer | ||
188 | */ | ||
189 | static struct GNUNET_CADET_Channel *outgoing_ch; | ||
190 | |||
191 | /** | ||
192 | * Channel handle for the dest peer | ||
193 | */ | ||
194 | static struct GNUNET_CADET_Channel *incoming_ch; | ||
195 | |||
196 | /** | ||
197 | * Time we started the data transmission (after channel has been established | ||
198 | * and initilized). | ||
199 | */ | ||
200 | static struct GNUNET_TIME_Absolute start_time; | ||
201 | |||
202 | /** | ||
203 | * Peers handle. | ||
204 | */ | ||
205 | static struct GNUNET_TESTBED_Peer **testbed_peers; | ||
206 | |||
207 | /** | ||
208 | * Statistics operation handle. | ||
209 | */ | ||
210 | static struct GNUNET_TESTBED_Operation *stats_op; | ||
211 | |||
212 | /** | ||
213 | * Keepalives sent. | ||
214 | */ | ||
215 | static unsigned int ka_sent; | ||
216 | |||
217 | /** | ||
218 | * Keepalives received. | ||
219 | */ | ||
220 | static unsigned int ka_received; | ||
221 | |||
222 | /** | ||
223 | * How many messages were dropped by CADET because of full buffers? | ||
224 | */ | ||
225 | static unsigned int msg_dropped; | ||
226 | |||
227 | |||
228 | /******************************************************************************/ | ||
229 | |||
230 | |||
231 | /******************************************************************************/ | ||
232 | |||
233 | |||
234 | /** | ||
235 | * Get the channel considered as the "target" or "receiver", depending on | ||
236 | * the test type and size. | ||
237 | * | ||
238 | * @return Channel handle of the target client, either 0 (for backward tests) | ||
239 | * or the last peer in the line (for other tests). | ||
240 | */ | ||
241 | static struct GNUNET_CADET_Channel * | ||
242 | get_target_channel () | ||
243 | { | ||
244 | if (SPEED == test && GNUNET_YES == test_backwards) | ||
245 | return outgoing_ch; | ||
246 | else | ||
247 | return incoming_ch; | ||
248 | } | ||
249 | |||
250 | |||
251 | /** | ||
252 | * Show the results of the test (banwidth acheived) and log them to GAUGER | ||
253 | */ | ||
254 | static void | ||
255 | show_end_data (void) | ||
256 | { | ||
257 | static struct GNUNET_TIME_Absolute end_time; | ||
258 | static struct GNUNET_TIME_Relative total_time; | ||
259 | |||
260 | end_time = GNUNET_TIME_absolute_get (); | ||
261 | total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time); | ||
262 | FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name); | ||
263 | FPRINTF (stderr, "Test time %s\n", | ||
264 | GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES)); | ||
265 | FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 4 * TOTAL_PACKETS * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms | ||
266 | FPRINTF (stderr, "Test throughput: %f packets/s\n\n", TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms | ||
267 | GAUGER ("CADET", test_name, | ||
268 | TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000), | ||
269 | "packets/s"); | ||
270 | } | ||
271 | |||
272 | |||
273 | /** | ||
274 | * Disconnect from cadet services af all peers, call shutdown. | ||
275 | * | ||
276 | * @param cls Closure (line number from which termination was requested). | ||
277 | * @param tc Task Context. | ||
278 | */ | ||
279 | static void | ||
280 | disconnect_cadet_peers (void *cls) | ||
281 | { | ||
282 | long line = (long) cls; | ||
283 | unsigned int i; | ||
284 | |||
285 | disconnect_task = NULL; | ||
286 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
287 | "disconnecting cadet service of peers, called from line %ld\n", | ||
288 | line); | ||
289 | for (i = 0; i < 2; i++) | ||
290 | { | ||
291 | GNUNET_TESTBED_operation_done (t_op[i]); | ||
292 | } | ||
293 | if (NULL != outgoing_ch) | ||
294 | { | ||
295 | GNUNET_CADET_channel_destroy (outgoing_ch); | ||
296 | outgoing_ch = NULL; | ||
297 | } | ||
298 | if (NULL != incoming_ch) | ||
299 | { | ||
300 | GNUNET_CADET_channel_destroy (incoming_ch); | ||
301 | incoming_ch = NULL; | ||
302 | } | ||
303 | GNUNET_CADET_TEST_cleanup (test_ctx); | ||
304 | GNUNET_SCHEDULER_shutdown (); | ||
305 | } | ||
306 | |||
307 | |||
308 | /** | ||
309 | * Shut down peergroup, clean up. | ||
310 | * | ||
311 | * @param cls Closure (unused). | ||
312 | * @param tc Task Context. | ||
313 | */ | ||
314 | static void | ||
315 | shutdown_task (void *cls) | ||
316 | { | ||
317 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); | ||
318 | if (NULL != send_next_msg_task) | ||
319 | { | ||
320 | GNUNET_SCHEDULER_cancel (send_next_msg_task); | ||
321 | send_next_msg_task = NULL; | ||
322 | } | ||
323 | if (NULL != test_task) | ||
324 | { | ||
325 | GNUNET_SCHEDULER_cancel (test_task); | ||
326 | test_task = NULL; | ||
327 | } | ||
328 | if (NULL != disconnect_task) | ||
329 | { | ||
330 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
331 | disconnect_task = | ||
332 | GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) __LINE__); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | |||
337 | /** | ||
338 | * Stats callback. Finish the stats testbed operation and when all stats have | ||
339 | * been iterated, shutdown the test. | ||
340 | * | ||
341 | * @param cls Closure (line number from which termination was requested). | ||
342 | * @param op the operation that has been finished | ||
343 | * @param emsg error message in case the operation has failed; will be NULL if | ||
344 | * operation has executed successfully. | ||
345 | */ | ||
346 | static void | ||
347 | stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) | ||
348 | { | ||
349 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " KA sent: %u, KA received: %u\n", | ||
350 | ka_sent, ka_received); | ||
351 | if ((KEEPALIVE == test) && ((ka_sent < 2) || (ka_sent > ka_received + 1))) | ||
352 | { | ||
353 | GNUNET_break (0); | ||
354 | ok--; | ||
355 | } | ||
356 | GNUNET_TESTBED_operation_done (stats_op); | ||
357 | |||
358 | if (NULL != disconnect_task) | ||
359 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
360 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, cls); | ||
361 | } | ||
362 | |||
363 | |||
364 | /** | ||
365 | * Process statistic values. | ||
366 | * | ||
367 | * @param cls closure (line number, unused) | ||
368 | * @param peer the peer the statistic belong to | ||
369 | * @param subsystem name of subsystem that created the statistic | ||
370 | * @param name the name of the datum | ||
371 | * @param value the current value | ||
372 | * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not | ||
373 | * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration | ||
374 | */ | ||
375 | static int | ||
376 | stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer, | ||
377 | const char *subsystem, const char *name, uint64_t value, | ||
378 | int is_persistent) | ||
379 | { | ||
380 | static const char *s_sent = "# keepalives sent"; | ||
381 | static const char *s_recv = "# keepalives received"; | ||
382 | static const char *rdrops = "# messages dropped due to full buffer"; | ||
383 | static const char *cdrops = "# messages dropped due to slow client"; | ||
384 | uint32_t i; | ||
385 | |||
386 | i = GNUNET_TESTBED_get_index (peer); | ||
387 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "STATS PEER %u - %s [%s]: %llu\n", i, | ||
388 | subsystem, name, (unsigned long long) value); | ||
389 | if (0 == strncmp (s_sent, name, strlen (s_sent)) && 0 == i) | ||
390 | ka_sent = value; | ||
391 | if (0 == strncmp (s_recv, name, strlen (s_recv)) && peers_requested - 1 == i) | ||
392 | ka_received = value; | ||
393 | if (0 == strncmp (rdrops, name, strlen (rdrops))) | ||
394 | msg_dropped += value; | ||
395 | if (0 == strncmp (cdrops, name, strlen (cdrops))) | ||
396 | msg_dropped += value; | ||
397 | |||
398 | return GNUNET_OK; | ||
399 | } | ||
400 | |||
401 | |||
402 | /** | ||
403 | * Task to gather all statistics. | ||
404 | * | ||
405 | * @param cls Closure (line from which the task was scheduled). | ||
406 | */ | ||
407 | static void | ||
408 | gather_stats_and_exit (void *cls) | ||
409 | { | ||
410 | long l = (long) cls; | ||
411 | |||
412 | disconnect_task = NULL; | ||
413 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
414 | "gathering statistics from line %ld\n", | ||
415 | l); | ||
416 | if (NULL != outgoing_ch) | ||
417 | { | ||
418 | GNUNET_CADET_channel_destroy (outgoing_ch); | ||
419 | outgoing_ch = NULL; | ||
420 | } | ||
421 | stats_op = GNUNET_TESTBED_get_statistics (peers_running, | ||
422 | testbed_peers, | ||
423 | "cadet", | ||
424 | NULL, | ||
425 | &stats_iterator, | ||
426 | stats_cont, | ||
427 | cls); | ||
428 | } | ||
429 | |||
430 | |||
431 | |||
432 | /** | ||
433 | * Abort test: schedule disconnect and shutdown immediately | ||
434 | * | ||
435 | * @param line Line in the code the abort is requested from (__LINE__). | ||
436 | */ | ||
437 | static void | ||
438 | abort_test (long line) | ||
439 | { | ||
440 | if (NULL != disconnect_task) | ||
441 | { | ||
442 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
443 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting test from %ld\n", line); | ||
444 | disconnect_task = | ||
445 | GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) line); | ||
446 | } | ||
447 | } | ||
448 | |||
449 | |||
450 | /** | ||
451 | * Send a message on the channel with the appropriate size and payload. | ||
452 | * | ||
453 | * Update the appropriate *_sent counter. | ||
454 | * | ||
455 | * @param channel Channel to send the message on. | ||
456 | */ | ||
457 | static void | ||
458 | send_test_message (struct GNUNET_CADET_Channel *channel) | ||
459 | { | ||
460 | struct GNUNET_MQ_Envelope *env; | ||
461 | struct GNUNET_MessageHeader *msg; | ||
462 | uint32_t *data; | ||
463 | int *counter; | ||
464 | int size; | ||
465 | |||
466 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
467 | "Sending test message on channel %p\n", | ||
468 | channel); | ||
469 | size = size_payload; | ||
470 | if (GNUNET_NO == initialized) | ||
471 | { | ||
472 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending INITIALIZER\n"); | ||
473 | size += 1000; | ||
474 | counter = &data_sent; | ||
475 | if (SPEED_ACK == test) // FIXME unify SPEED_ACK with an initializer | ||
476 | data_sent++; | ||
477 | } | ||
478 | else if (SPEED == test || SPEED_ACK == test) | ||
479 | { | ||
480 | counter = get_target_channel() == channel ? &ack_sent : &data_sent; | ||
481 | size += *counter; | ||
482 | *counter = *counter + 1; | ||
483 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending message %u\n", *counter); | ||
484 | } | ||
485 | else | ||
486 | { | ||
487 | counter = &ack_sent; | ||
488 | } | ||
489 | env = GNUNET_MQ_msg_extra (msg, size, GNUNET_MESSAGE_TYPE_DUMMY); | ||
490 | |||
491 | data = (uint32_t *) &msg[1]; | ||
492 | *data = htonl (*counter); | ||
493 | GNUNET_MQ_send (GNUNET_CADET_get_mq (channel), env); | ||
494 | } | ||
495 | |||
496 | /** | ||
497 | * Task to request a new data transmission in a SPEED test, without waiting | ||
498 | * for previous messages to be sent/arrrive. | ||
499 | * | ||
500 | * @param cls Closure (unused). | ||
501 | */ | ||
502 | static void | ||
503 | send_next_msg (void *cls) | ||
504 | { | ||
505 | struct GNUNET_CADET_Channel *channel; | ||
506 | |||
507 | send_next_msg_task = NULL; | ||
508 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending next message: %d\n", data_sent); | ||
509 | |||
510 | channel = GNUNET_YES == test_backwards ? incoming_ch : outgoing_ch; | ||
511 | GNUNET_assert (NULL != channel); | ||
512 | GNUNET_assert (SPEED == test); | ||
513 | send_test_message (channel); | ||
514 | if (data_sent < TOTAL_PACKETS) | ||
515 | { | ||
516 | /* SPEED test: Send all messages as soon as possible */ | ||
517 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
518 | "Scheduling message %d\n", | ||
519 | data_sent + 1); | ||
520 | send_next_msg_task = GNUNET_SCHEDULER_add_now (&send_next_msg, NULL); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | |||
525 | /** | ||
526 | * Every few messages cancel the timeout task and re-schedule it again, to | ||
527 | * avoid timing out when traffic keeps coming. | ||
528 | * | ||
529 | * @param line Code line number to log if a timeout occurs. | ||
530 | */ | ||
531 | static void | ||
532 | reschedule_timeout_task (long line) | ||
533 | { | ||
534 | if ((ok % 10) == 0) | ||
535 | { | ||
536 | if (NULL != disconnect_task) | ||
537 | { | ||
538 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
539 | " reschedule timeout every 10 messages\n"); | ||
540 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
541 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
542 | &gather_stats_and_exit, | ||
543 | (void *) line); | ||
544 | } | ||
545 | } | ||
546 | } | ||
547 | |||
548 | |||
549 | /** | ||
550 | * Check if payload is sane (size contains payload). | ||
551 | * | ||
552 | * @param cls should match #ch | ||
553 | * @param message The actual message. | ||
554 | * @return #GNUNET_OK to keep the channel open, | ||
555 | * #GNUNET_SYSERR to close it (signal serious error). | ||
556 | */ | ||
557 | static int | ||
558 | check_data (void *cls, const struct GNUNET_MessageHeader *message) | ||
559 | { | ||
560 | if (sizeof (struct GNUNET_MessageHeader) >= ntohs (message->size)) | ||
561 | return GNUNET_SYSERR; | ||
562 | return GNUNET_OK; /* all is well-formed */ | ||
563 | } | ||
564 | |||
565 | |||
566 | /** | ||
567 | * Function is called whenever a message is received. | ||
568 | * | ||
569 | * @param cls closure (set from GNUNET_CADET_connect(), peer number) | ||
570 | * @param message the actual message | ||
571 | */ | ||
572 | static void | ||
573 | handle_data (void *cls, const struct GNUNET_MessageHeader *message) | ||
574 | { | ||
575 | struct CadetTestChannelWrapper *ch = cls; | ||
576 | struct GNUNET_CADET_Channel *channel = ch->ch; | ||
577 | uint32_t *data; | ||
578 | uint32_t payload; | ||
579 | int *counter; | ||
580 | |||
581 | ok++; | ||
582 | counter = get_target_channel () == channel ? &data_received : &ack_received; | ||
583 | |||
584 | reschedule_timeout_task ((long) __LINE__); | ||
585 | |||
586 | if (channel == outgoing_ch) | ||
587 | { | ||
588 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n"); | ||
589 | } | ||
590 | else if (channel == incoming_ch) | ||
591 | { | ||
592 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client got a message.\n"); | ||
593 | } | ||
594 | else | ||
595 | { | ||
596 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unknown channel %p.\n", channel); | ||
597 | GNUNET_assert (0); | ||
598 | } | ||
599 | |||
600 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal); | ||
601 | data = (uint32_t *) &message[1]; | ||
602 | payload = ntohl (*data); | ||
603 | if (payload == *counter) | ||
604 | { | ||
605 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload as expected: %u\n", payload); | ||
606 | } | ||
607 | else | ||
608 | { | ||
609 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
610 | " payload %u, expected: %u\n", | ||
611 | payload, *counter); | ||
612 | } | ||
613 | |||
614 | if (GNUNET_NO == initialized) | ||
615 | { | ||
616 | initialized = GNUNET_YES; | ||
617 | start_time = GNUNET_TIME_absolute_get (); | ||
618 | if (SPEED == test) | ||
619 | { | ||
620 | GNUNET_assert (incoming_ch == channel); | ||
621 | send_next_msg_task = GNUNET_SCHEDULER_add_now (&send_next_msg, NULL); | ||
622 | return; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | (*counter)++; | ||
627 | if (get_target_channel () == channel) /* Got "data" */ | ||
628 | { | ||
629 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received); | ||
630 | if (SPEED != test || (ok_goal - 2) == ok) | ||
631 | { | ||
632 | /* Send ACK */ | ||
633 | send_test_message (channel); | ||
634 | return; | ||
635 | } | ||
636 | else | ||
637 | { | ||
638 | if (data_received < TOTAL_PACKETS) | ||
639 | return; | ||
640 | } | ||
641 | } | ||
642 | else /* Got "ack" */ | ||
643 | { | ||
644 | if (SPEED_ACK == test || SPEED == test) | ||
645 | { | ||
646 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received); | ||
647 | /* Send more data */ | ||
648 | send_test_message (channel); | ||
649 | if (ack_received < TOTAL_PACKETS && SPEED != test) | ||
650 | return; | ||
651 | if (ok == 2 && SPEED == test) | ||
652 | return; | ||
653 | show_end_data (); | ||
654 | } | ||
655 | if (test == P2P_SIGNAL) | ||
656 | { | ||
657 | GNUNET_CADET_channel_destroy (incoming_ch); | ||
658 | incoming_ch = NULL; | ||
659 | } | ||
660 | else | ||
661 | { | ||
662 | GNUNET_CADET_channel_destroy (outgoing_ch); | ||
663 | outgoing_ch = NULL; | ||
664 | } | ||
665 | } | ||
666 | } | ||
667 | |||
668 | |||
669 | /** | ||
670 | * Method called whenever a peer connects to a port in MQ-based CADET. | ||
671 | * | ||
672 | * @param cls Closure from #GNUNET_CADET_open_porT (peer # as long). | ||
673 | * @param channel New handle to the channel. | ||
674 | * @param source Peer that started this channel. | ||
675 | * @return Closure for the incoming @a channel. It's given to: | ||
676 | * - The #GNUNET_CADET_DisconnectEventHandler (given to | ||
677 | * #GNUNET_CADET_open_porT) when the channel dies. | ||
678 | * - Each the #GNUNET_MQ_MessageCallback handlers for each message | ||
679 | * received on the @a channel. | ||
680 | */ | ||
681 | static void * | ||
682 | connect_handler (void *cls, struct GNUNET_CADET_Channel *channel, | ||
683 | const struct GNUNET_PeerIdentity *source) | ||
684 | { | ||
685 | struct CadetTestChannelWrapper *ch; | ||
686 | long peer = (long) cls; | ||
687 | |||
688 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Incoming channel from %s to peer %ld\n", | ||
689 | GNUNET_i2s (source), peer); | ||
690 | ok++; | ||
691 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); | ||
692 | if (peer == peers_requested - 1) | ||
693 | { | ||
694 | if (NULL != incoming_ch) | ||
695 | { | ||
696 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
697 | "Duplicate incoming channel for client %lu\n", (long) cls); | ||
698 | GNUNET_assert (0); | ||
699 | } | ||
700 | incoming_ch = channel; | ||
701 | } | ||
702 | else | ||
703 | { | ||
704 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
705 | "Incoming channel for unexpected peer #%lu\n", (long) cls); | ||
706 | GNUNET_assert (0); | ||
707 | } | ||
708 | if (NULL != disconnect_task) | ||
709 | { | ||
710 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
711 | disconnect_task = | ||
712 | GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &gather_stats_and_exit, | ||
713 | (void *) __LINE__); | ||
714 | } | ||
715 | |||
716 | /* TODO: cannot return channel as-is, in order to unify the data handlers */ | ||
717 | ch = GNUNET_new (struct CadetTestChannelWrapper); | ||
718 | ch->ch = channel; | ||
719 | |||
720 | return ch; | ||
721 | } | ||
722 | |||
723 | |||
724 | /** | ||
725 | * Function called whenever an MQ-channel is destroyed, even if the destruction | ||
726 | * was requested by #GNUNET_CADET_channel_destroy. | ||
727 | * It must NOT call #GNUNET_CADET_channel_destroy on the channel. | ||
728 | * | ||
729 | * It should clean up any associated state, including cancelling any pending | ||
730 | * transmission on this channel. | ||
731 | * | ||
732 | * @param cls Channel closure (channel wrapper). | ||
733 | * @param channel Connection to the other end (henceforth invalid). | ||
734 | */ | ||
735 | static void | ||
736 | disconnect_handler (void *cls, const struct GNUNET_CADET_Channel *channel) | ||
737 | { | ||
738 | struct CadetTestChannelWrapper *ch_w = cls; | ||
739 | |||
740 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Channel disconnected\n"); | ||
741 | GNUNET_assert (ch_w->ch == channel); | ||
742 | if (channel == incoming_ch) | ||
743 | { | ||
744 | ok++; | ||
745 | incoming_ch = NULL; | ||
746 | } | ||
747 | else if (outgoing_ch == channel | ||
748 | ) | ||
749 | { | ||
750 | if (P2P_SIGNAL == test) | ||
751 | { | ||
752 | ok++; | ||
753 | } | ||
754 | outgoing_ch = NULL; | ||
755 | } | ||
756 | else | ||
757 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unknown channel! %p\n", channel); | ||
758 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); | ||
759 | |||
760 | if (NULL != disconnect_task) | ||
761 | { | ||
762 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
763 | disconnect_task = | ||
764 | GNUNET_SCHEDULER_add_now (&gather_stats_and_exit, (void *) __LINE__); | ||
765 | } | ||
766 | } | ||
767 | |||
768 | |||
769 | /** | ||
770 | * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES. | ||
771 | * | ||
772 | * Testcase continues when the root receives confirmation of connected peers, | ||
773 | * on callback function ch. | ||
774 | * | ||
775 | * @param cls Closure (unused). | ||
776 | */ | ||
777 | static void | ||
778 | start_test (void *cls) | ||
779 | { | ||
780 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
781 | GNUNET_MQ_hd_var_size (data, | ||
782 | GNUNET_MESSAGE_TYPE_DUMMY, | ||
783 | struct GNUNET_MessageHeader, | ||
784 | NULL), | ||
785 | GNUNET_MQ_handler_end () | ||
786 | }; | ||
787 | struct CadetTestChannelWrapper *ch; | ||
788 | enum GNUNET_CADET_ChannelOption flags; | ||
789 | |||
790 | test_task = NULL; | ||
791 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "start_test\n"); | ||
792 | if (NULL != disconnect_task) | ||
793 | { | ||
794 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
795 | disconnect_task = NULL; | ||
796 | } | ||
797 | |||
798 | flags = GNUNET_CADET_OPTION_DEFAULT; | ||
799 | if (SPEED_REL == test) | ||
800 | { | ||
801 | test = SPEED; | ||
802 | flags |= GNUNET_CADET_OPTION_RELIABLE; | ||
803 | } | ||
804 | |||
805 | ch = GNUNET_new (struct CadetTestChannelWrapper); | ||
806 | outgoing_ch = GNUNET_CADET_channel_creatE (h1, | ||
807 | ch, | ||
808 | p_id[1], | ||
809 | &port, | ||
810 | flags, | ||
811 | NULL, | ||
812 | &disconnect_handler, | ||
813 | handlers); | ||
814 | ch->ch = outgoing_ch; | ||
815 | |||
816 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
817 | &gather_stats_and_exit, | ||
818 | (void *) __LINE__); | ||
819 | if (KEEPALIVE == test) | ||
820 | return; /* Don't send any data. */ | ||
821 | |||
822 | |||
823 | data_received = 0; | ||
824 | data_sent = 0; | ||
825 | ack_received = 0; | ||
826 | ack_sent = 0; | ||
827 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending data initializer...\n"); | ||
828 | send_test_message (outgoing_ch); | ||
829 | } | ||
830 | |||
831 | |||
832 | /** | ||
833 | * Callback to be called when the requested peer information is available | ||
834 | * | ||
835 | * @param cls the closure from GNUNET_TESTBED_peer_get_information() | ||
836 | * @param op the operation this callback corresponds to | ||
837 | * @param pinfo the result; will be NULL if the operation has failed | ||
838 | * @param emsg error message if the operation has failed; | ||
839 | * NULL if the operation is successfull | ||
840 | */ | ||
841 | static void | ||
842 | pi_cb (void *cls, struct GNUNET_TESTBED_Operation *op, | ||
843 | const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg) | ||
844 | { | ||
845 | long i = (long) cls; | ||
846 | |||
847 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ID callback for %ld\n", i); | ||
848 | |||
849 | if ((NULL == pinfo) || (NULL != emsg)) | ||
850 | { | ||
851 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg); | ||
852 | abort_test (__LINE__); | ||
853 | return; | ||
854 | } | ||
855 | p_id[i] = pinfo->result.id; | ||
856 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i])); | ||
857 | p_ids++; | ||
858 | if (p_ids < 2) | ||
859 | return; | ||
860 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n"); | ||
861 | test_task = GNUNET_SCHEDULER_add_now (&start_test, NULL); | ||
862 | } | ||
863 | |||
864 | |||
865 | /** | ||
866 | * test main: start test when all peers are connected | ||
867 | * | ||
868 | * @param cls Closure. | ||
869 | * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end. | ||
870 | * @param num_peers Number of peers that are running. | ||
871 | * @param peers Array of peers. | ||
872 | * @param cadets Handle to each of the CADETs of the peers. | ||
873 | */ | ||
874 | static void | ||
875 | tmain (void *cls, | ||
876 | struct GNUNET_CADET_TEST_Context *ctx, | ||
877 | unsigned int num_peers, | ||
878 | struct GNUNET_TESTBED_Peer **peers, | ||
879 | struct GNUNET_CADET_Handle **cadets) | ||
880 | { | ||
881 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n"); | ||
882 | ok = 0; | ||
883 | test_ctx = ctx; | ||
884 | peers_running = num_peers; | ||
885 | GNUNET_assert (peers_running == peers_requested); | ||
886 | testbed_peers = peers; | ||
887 | h1 = cadets[0]; | ||
888 | h2 = cadets[num_peers - 1]; | ||
889 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
890 | &disconnect_cadet_peers, | ||
891 | (void *) __LINE__); | ||
892 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | ||
893 | t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0], | ||
894 | GNUNET_TESTBED_PIT_IDENTITY, | ||
895 | &pi_cb, | ||
896 | (void *) 0L); | ||
897 | t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1], | ||
898 | GNUNET_TESTBED_PIT_IDENTITY, | ||
899 | &pi_cb, | ||
900 | (void *) 1L); | ||
901 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n"); | ||
902 | } | ||
903 | |||
904 | |||
905 | /** | ||
906 | * Main: start test | ||
907 | */ | ||
908 | int | ||
909 | main (int argc, char *argv[]) | ||
910 | { | ||
911 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
912 | GNUNET_MQ_hd_var_size (data, | ||
913 | GNUNET_MESSAGE_TYPE_DUMMY, | ||
914 | struct GNUNET_MessageHeader, | ||
915 | NULL), | ||
916 | GNUNET_MQ_handler_end () | ||
917 | }; | ||
918 | |||
919 | initialized = GNUNET_NO; | ||
920 | static const struct GNUNET_HashCode *ports[2]; | ||
921 | const char *config_file; | ||
922 | char port_id[] = "test port"; | ||
923 | |||
924 | GNUNET_CRYPTO_hash (port_id, sizeof (port_id), &port); | ||
925 | |||
926 | GNUNET_log_setup ("test", "DEBUG", NULL); | ||
927 | config_file = "test_cadet.conf"; | ||
928 | |||
929 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n"); | ||
930 | |||
931 | /* Find out requested size */ | ||
932 | if (strstr (argv[0], "_2_") != NULL) | ||
933 | { | ||
934 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DIRECT CONNECTIONs\n"); | ||
935 | peers_requested = 2; | ||
936 | } | ||
937 | else if (strstr (argv[0], "_5_") != NULL) | ||
938 | { | ||
939 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "5 PEER LINE\n"); | ||
940 | peers_requested = 5; | ||
941 | } | ||
942 | else | ||
943 | { | ||
944 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "SIZE UNKNOWN, USING 2\n"); | ||
945 | peers_requested = 2; | ||
946 | } | ||
947 | |||
948 | /* Find out requested test */ | ||
949 | if (strstr (argv[0], "_forward") != NULL) | ||
950 | { | ||
951 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n"); | ||
952 | test = FORWARD; | ||
953 | test_name = "unicast"; | ||
954 | ok_goal = 4; | ||
955 | } | ||
956 | else if (strstr (argv[0], "_signal") != NULL) | ||
957 | { | ||
958 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n"); | ||
959 | test = P2P_SIGNAL; | ||
960 | test_name = "signal"; | ||
961 | ok_goal = 4; | ||
962 | } | ||
963 | else if (strstr (argv[0], "_speed_ack") != NULL) | ||
964 | { | ||
965 | /* Test is supposed to generate the following callbacks: | ||
966 | * 1 incoming channel (@dest) | ||
967 | * TOTAL_PACKETS received data packet (@dest) | ||
968 | * TOTAL_PACKETS received data packet (@orig) | ||
969 | * 1 received channel destroy (@dest) | ||
970 | */ | ||
971 | ok_goal = TOTAL_PACKETS * 2 + 2; | ||
972 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n"); | ||
973 | test = SPEED_ACK; | ||
974 | test_name = "speed ack"; | ||
975 | } | ||
976 | else if (strstr (argv[0], "_speed") != NULL) | ||
977 | { | ||
978 | /* Test is supposed to generate the following callbacks: | ||
979 | * 1 incoming channel (@dest) | ||
980 | * 1 initial packet (@dest) | ||
981 | * TOTAL_PACKETS received data packet (@dest) | ||
982 | * 1 received data packet (@orig) | ||
983 | * 1 received channel destroy (@dest) | ||
984 | */ | ||
985 | ok_goal = TOTAL_PACKETS + 4; | ||
986 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n"); | ||
987 | if (strstr (argv[0], "_reliable") != NULL) | ||
988 | { | ||
989 | test = SPEED_REL; | ||
990 | test_name = "speed reliable"; | ||
991 | config_file = "test_cadet_drop.conf"; | ||
992 | } | ||
993 | else | ||
994 | { | ||
995 | test = SPEED; | ||
996 | test_name = "speed"; | ||
997 | } | ||
998 | } | ||
999 | else if (strstr (argv[0], "_keepalive") != NULL) | ||
1000 | { | ||
1001 | test = KEEPALIVE; | ||
1002 | /* Test is supposed to generate the following callbacks: | ||
1003 | * 1 incoming channel (@dest) | ||
1004 | * [wait] | ||
1005 | * 1 received channel destroy (@dest) | ||
1006 | */ | ||
1007 | ok_goal = 2; | ||
1008 | } | ||
1009 | else | ||
1010 | { | ||
1011 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n"); | ||
1012 | test = SETUP; | ||
1013 | ok_goal = 0; | ||
1014 | } | ||
1015 | |||
1016 | if (strstr (argv[0], "backwards") != NULL) | ||
1017 | { | ||
1018 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n"); | ||
1019 | test_backwards = GNUNET_YES; | ||
1020 | GNUNET_asprintf (&test_name, "backwards %s", test_name); | ||
1021 | } | ||
1022 | |||
1023 | p_ids = 0; | ||
1024 | ports[0] = &port; | ||
1025 | ports[1] = NULL; | ||
1026 | GNUNET_CADET_TEST_ruN ("test_cadet_small", | ||
1027 | config_file, | ||
1028 | peers_requested, | ||
1029 | &tmain, | ||
1030 | NULL, /* tmain cls */ | ||
1031 | &connect_handler, | ||
1032 | NULL, | ||
1033 | &disconnect_handler, | ||
1034 | handlers, | ||
1035 | ports); | ||
1036 | if (NULL != strstr (argv[0], "_reliable")) | ||
1037 | msg_dropped = 0; /* dropped should be retransmitted */ | ||
1038 | |||
1039 | if (ok_goal > ok - msg_dropped) | ||
1040 | { | ||
1041 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "FAILED! (%d/%d)\n", ok, ok_goal); | ||
1042 | return 1; | ||
1043 | } | ||
1044 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n"); | ||
1045 | return 0; | ||
1046 | } | ||
1047 | |||
1048 | /* end of test_cadet.c */ | ||