Merge branch 'master' of ssh://gnunet.org/gnunet
[oweals/gnunet.git] / src / cadet / test_cadet_flow.c
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 it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 /**
19  * @file cadet/test_cadet_flow.c
20  * @author Bart Polot
21  * @author Christian Grothoff
22  * @brief Test for flow control of CADET service
23  */
24 #include <stdio.h>
25 #include "platform.h"
26 #include "cadet_test_lib.h"
27 #include "gnunet_cadet_service.h"
28 #include "gnunet_statistics_service.h"
29 #include <gauger.h>
30
31
32 /**
33  * Ugly workaround to unify data handlers on incoming and outgoing channels.
34  */
35 struct CadetTestChannelWrapper
36 {
37   /**
38    * Channel pointer.
39    */
40   struct GNUNET_CADET_Channel *ch;
41 };
42
43 /**
44  * How many messages to send by default.
45  */
46 #define TOTAL_PACKETS_DEFAULT 500
47
48 /**
49  * How long until we give up on connecting the peers?
50  */
51 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
52
53 /**
54  * Time to wait by default  for stuff that should be rather fast.
55  */
56 #define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
57
58 /**
59  * How fast do we send messages?
60  */
61 #define SEND_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 10)
62
63
64 /**
65  * How many packets to send.
66  */
67 static unsigned int total_packets = TOTAL_PACKETS_DEFAULT;
68
69 /**
70  * Time to wait for fast operations.
71  */
72 static struct GNUNET_TIME_Relative short_time;
73
74 /**
75  * Size of each test packet's payload
76  */
77 static size_t size_payload = sizeof (uint32_t);
78
79 /**
80  * Operation to get peer ids.
81  */
82 static struct GNUNET_TESTBED_Operation *t_op[2];
83
84 /**
85  * Peer ids.
86  */
87 static struct GNUNET_PeerIdentity *p_id[2];
88
89 /**
90  * Port ID
91  */
92 static struct GNUNET_HashCode port;
93
94 /**
95  * Peer ids counter.
96  */
97 static unsigned int p_ids;
98
99 /**
100  * Is the setup initialized?
101  */
102 static int initialized;
103
104 /**
105  * Number of payload packes sent.
106  */
107 static int data_sent;
108
109 /**
110  * Number of payload packets received.
111  */
112 static int data_received;
113
114 /**
115  * Number of payload packed acknowledgements sent.
116  */
117 static int ack_sent;
118
119 /**
120  * Number of payload packed explicitly (app level) acknowledged.
121  */
122 static int ack_received;
123
124 /**
125  * Total number of peers asked to run.
126  */
127 static unsigned int peers_requested = 2;
128
129 /**
130  * Number of currently running peers (should be same as @c peers_requested).
131  */
132 static unsigned int peers_running;
133
134 /**
135  * Test context (to shut down).
136  */
137 struct GNUNET_CADET_TEST_Context *test_ctx;
138
139 /**
140  * Task called to disconnect peers.
141  */
142 static struct GNUNET_SCHEDULER_Task *disconnect_task;
143
144 /**
145  * Task To perform tests
146  */
147 static struct GNUNET_SCHEDULER_Task *test_task;
148
149 /**
150  * Task runnining #send_next_msg().
151  */
152 static struct GNUNET_SCHEDULER_Task *send_next_msg_task;
153
154 /**
155  * Cadet handle for the root peer
156  */
157 static struct GNUNET_CADET_Handle *h1;
158
159 /**
160  * Cadet handle for the first leaf peer
161  */
162 static struct GNUNET_CADET_Handle *h2;
163
164 /**
165  * Channel handle for the root peer
166  */
167 static struct GNUNET_CADET_Channel *outgoing_ch;
168
169 /**
170  * Channel handle for the dest peer
171  */
172 static struct GNUNET_CADET_Channel *incoming_ch;
173
174 /**
175  * Time we started the data transmission (after channel has been established
176  * and initilized).
177  */
178 static struct GNUNET_TIME_Absolute start_time;
179
180 /**
181  * Peers handle.
182  */
183 static struct GNUNET_TESTBED_Peer **testbed_peers;
184
185 /**
186  * Statistics operation handle.
187  */
188 static struct GNUNET_TESTBED_Operation *stats_op;
189
190 /**
191  * Keepalives sent.
192  */
193 static unsigned int ka_sent;
194
195 /**
196  * Keepalives received.
197  */
198 static unsigned int ka_received;
199
200 /**
201  * How many messages were dropped by CADET because of full buffers?
202  */
203 static unsigned int msg_dropped;
204
205
206 /**
207  * Show the results of the test (banwidth acheived) and log them to GAUGER
208  */
209 static void
210 show_end_data (void)
211 {
212   static struct GNUNET_TIME_Absolute end_time;
213   static struct GNUNET_TIME_Relative total_time;
214
215   end_time = GNUNET_TIME_absolute_get ();
216   total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
217   FPRINTF (stderr,
218            "\nResults of test \"%s\"\n",
219            test_name);
220   FPRINTF (stderr,
221            "Test time %s\n",
222            GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES));
223   FPRINTF (stderr,
224            "Test bandwidth: %f kb/s\n",
225            4 * total_packets * 1.0 / (total_time.rel_value_us / 1000));    // 4bytes * ms
226   FPRINTF (stderr,
227            "Test throughput: %f packets/s\n\n",
228            total_packets * 1000.0 / (total_time.rel_value_us / 1000));     // packets * ms
229   GAUGER ("CADET",
230           test_name,
231           total_packets * 1000.0 / (total_time.rel_value_us / 1000),
232           "packets/s");
233 }
234
235
236 /**
237  * Shut down peergroup, clean up.
238  *
239  * @param cls Closure (unused).
240  * @param tc Task Context.
241  */
242 static void
243 shutdown_task (void *cls)
244 {
245   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
246               "Ending test.\n");
247   if (NULL != send_next_msg_task)
248   {
249     GNUNET_SCHEDULER_cancel (send_next_msg_task);
250     send_next_msg_task = NULL;
251   }
252   if (NULL != test_task)
253   {
254     GNUNET_SCHEDULER_cancel (test_task);
255     test_task = NULL;
256   }
257   for (unsigned int i = 0; i < 2; i++)
258     GNUNET_TESTBED_operation_done (t_op[i]);
259   if (NULL != outgoing_ch)
260   {
261     GNUNET_CADET_channel_destroy (outgoing_ch);
262     outgoing_ch = NULL;
263   }
264   if (NULL != incoming_ch)
265   {
266     GNUNET_CADET_channel_destroy (incoming_ch);
267     incoming_ch = NULL;
268   }
269   GNUNET_CADET_TEST_cleanup (test_ctx);
270 }
271
272
273 /**
274  * Stats callback. Finish the stats testbed operation and when all stats have
275  * been iterated, shutdown the test.
276  *
277  * @param cls Closure (line number from which termination was requested).
278  * @param op the operation that has been finished
279  * @param emsg error message in case the operation has failed; will be NULL if
280  *          operation has executed successfully.
281  */
282 static void
283 stats_cont (void *cls,
284             struct GNUNET_TESTBED_Operation *op,
285             const char *emsg)
286 {
287   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
288               "KA sent: %u, KA received: %u\n",
289               ka_sent,
290               ka_received);
291   if ((KEEPALIVE == test) && ((ka_sent < 2) || (ka_sent > ka_received + 1)))
292   {
293     GNUNET_break (0);
294     ok--;
295   }
296   GNUNET_TESTBED_operation_done (stats_op);
297
298   if (NULL != disconnect_task)
299     GNUNET_SCHEDULER_cancel (disconnect_task);
300   disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
301                                               cls);
302 }
303
304
305 /**
306  * Process statistic values.
307  *
308  * @param cls closure (line number, unused)
309  * @param peer the peer the statistic belong to
310  * @param subsystem name of subsystem that created the statistic
311  * @param name the name of the datum
312  * @param value the current value
313  * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
314  * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
315  */
316 static int
317 stats_iterator (void *cls,
318                 const struct GNUNET_TESTBED_Peer *peer,
319                 const char *subsystem,
320                 const char *name,
321                 uint64_t value,
322                 int is_persistent)
323 {
324   static const char *s_sent = "# keepalives sent";
325   static const char *s_recv = "# keepalives received";
326   static const char *rdrops = "# messages dropped due to full buffer";
327   static const char *cdrops = "# messages dropped due to slow client";
328   uint32_t i;
329
330   i = GNUNET_TESTBED_get_index (peer);
331   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "STATS PEER %u - %s [%s]: %llu\n", i,
332               subsystem, name, (unsigned long long) value);
333   if (0 == strncmp (s_sent, name, strlen (s_sent)) && 0 == i)
334     ka_sent = value;
335   if (0 == strncmp (s_recv, name, strlen (s_recv)) && peers_requested - 1 == i)
336     ka_received = value;
337   if (0 == strncmp (rdrops, name, strlen (rdrops)))
338     msg_dropped += value;
339   if (0 == strncmp (cdrops, name, strlen (cdrops)))
340     msg_dropped += value;
341
342   return GNUNET_OK;
343 }
344
345
346 /**
347  * Task to gather all statistics.
348  *
349  * @param cls Closure (line from which the task was scheduled).
350  */
351 static void
352 gather_stats_and_exit (void *cls)
353 {
354   long l = (long) cls;
355
356   disconnect_task = NULL;
357   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
358               "gathering statistics from line %ld\n",
359               l);
360   if (NULL != outgoing_ch)
361   {
362     GNUNET_CADET_channel_destroy (outgoing_ch);
363     outgoing_ch = NULL;
364   }
365   stats_op = GNUNET_TESTBED_get_statistics (peers_running,
366                                             testbed_peers,
367                                             "cadet",
368                                             NULL,
369                                             &stats_iterator,
370                                             stats_cont,
371                                             cls);
372 }
373
374
375 /**
376  * Abort test: schedule disconnect and shutdown immediately
377  *
378  * @param line Line in the code the abort is requested from (__LINE__).
379  */
380 static void
381 abort_test (long line)
382 {
383   if (NULL != disconnect_task)
384   {
385     GNUNET_SCHEDULER_cancel (disconnect_task);
386     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
387                 "Aborting test from %ld\n",
388                 line);
389     disconnect_task =
390         GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
391                                   (void *) line);
392   }
393 }
394
395
396 /**
397  * Send a message on the channel with the appropriate size and payload.
398  *
399  * Update the appropriate *_sent counter.
400  *
401  * @param channel Channel to send the message on.
402  */
403 static void
404 send_test_message (struct GNUNET_CADET_Channel *channel)
405 {
406   struct GNUNET_MQ_Envelope *env;
407   struct GNUNET_MessageHeader *msg;
408   uint32_t *data;
409   int payload;
410   int size;
411
412   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
413               "Sending test message on channel %p\n",
414               channel);
415   size = size_payload;
416   if (GNUNET_NO == initialized)
417   {
418     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending INITIALIZER\n");
419     size += 1000;
420     payload = data_sent;
421     if (SPEED_ACK == test) // FIXME unify SPEED_ACK with an initializer
422         data_sent++;
423   }
424   else if (SPEED == test || SPEED_ACK == test)
425   {
426     if (get_target_channel() == channel)
427     {
428       payload = ack_sent;
429       size += ack_sent;
430       ack_sent++;
431       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
432                   "Sending ACK %u [%d bytes]\n",
433                   payload, size);
434     }
435     else
436     {
437       payload = data_sent;
438       size += data_sent;
439       data_sent++;
440       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
441                   "Sending DATA %u [%d bytes]\n",
442                   data_sent, size);
443     }
444   }
445   else if (FORWARD == test)
446   {
447     payload = ack_sent;
448   }
449   else if (P2P_SIGNAL == test)
450   {
451     payload = data_sent;
452   }
453   else
454   {
455     GNUNET_assert (0);
456   }
457   env = GNUNET_MQ_msg_extra (msg, size, GNUNET_MESSAGE_TYPE_DUMMY);
458
459   data = (uint32_t *) &msg[1];
460   *data = htonl (payload);
461   GNUNET_MQ_send (GNUNET_CADET_get_mq (channel), env);
462 }
463
464
465 /**
466  * Task to request a new data transmission in a SPEED test, without waiting
467  * for previous messages to be sent/arrrive.
468  *
469  * @param cls Closure (unused).
470  */
471 static void
472 send_next_msg (void *cls)
473 {
474   struct GNUNET_CADET_Channel *channel;
475
476   send_next_msg_task = NULL;
477   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
478               "Sending next message: %d\n",
479               data_sent);
480
481   channel = GNUNET_YES == test_backwards ? incoming_ch : outgoing_ch;
482   GNUNET_assert (NULL != channel);
483   GNUNET_assert (SPEED == test);
484   send_test_message (channel);
485   if (data_sent < total_packets)
486   {
487     /* SPEED test: Send all messages as soon as possible */
488     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
489                 "Scheduling message %d\n",
490                 data_sent + 1);
491     send_next_msg_task =
492       GNUNET_SCHEDULER_add_delayed (SEND_INTERVAL,
493                                       &send_next_msg,
494                                       NULL);
495   }
496 }
497
498
499 /**
500  * Check if payload is sane (size contains payload).
501  *
502  * @param cls should match #ch
503  * @param message The actual message.
504  * @return #GNUNET_OK to keep the channel open,
505  *         #GNUNET_SYSERR to close it (signal serious error).
506  */
507 static int
508 check_data (void *cls,
509             const struct GNUNET_MessageHeader *message)
510 {
511   return GNUNET_OK;             /* all is well-formed */
512 }
513
514
515 /**
516  * Function is called whenever a message is received.
517  *
518  * @param cls closure (set from GNUNET_CADET_connect(), peer number)
519  * @param message the actual message
520  */
521 static void
522 handle_data (void *cls,
523              const struct GNUNET_MessageHeader *message)
524 {
525   struct CadetTestChannelWrapper *ch = cls;
526   struct GNUNET_CADET_Channel *channel = ch->ch;
527   uint32_t *data;
528   uint32_t payload;
529   int *counter;
530
531   GNUNET_CADET_receive_done (channel);
532   counter = get_target_channel () == channel ? &data_received : &ack_received;
533   if (channel == outgoing_ch)
534   {
535     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
536                 "Root client got a message.\n");
537   }
538   else if (channel == incoming_ch)
539   {
540     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
541                 "Leaf client got a message.\n");
542   }
543   else
544   {
545     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
546                 "Unknown channel %p.\n",
547                 channel);
548     GNUNET_assert (0);
549   }
550
551   data = (uint32_t *) &message[1];
552   payload = ntohl (*data);
553   if (payload == *counter)
554   {
555     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
556                 "Payload as expected: %u\n",
557                 payload);
558   }
559   else
560   {
561     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
562                 "Received payload %u, expected: %u\n",
563                 payload, *counter);
564   }
565   (*counter)++;
566   if (get_target_channel () == channel) /* Got "data" */
567   {
568     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
569                 " received data %u\n",
570                 data_received);
571     if (data_received < total_packets)
572       return;
573   }
574   else /* Got "ack" */
575   {
576     if (SPEED_ACK == test || SPEED == test)
577     {
578       GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received);
579       /* Send more data */
580       send_test_message (channel);
581       if (ack_received < total_packets && SPEED != test)
582         return;
583       if (ok == 2 && SPEED == test)
584         return;
585       show_end_data ();
586     }
587     if (test == P2P_SIGNAL)
588     {
589       GNUNET_CADET_channel_destroy (incoming_ch);
590       incoming_ch = NULL;
591     }
592     else
593     {
594       GNUNET_CADET_channel_destroy (outgoing_ch);
595       outgoing_ch = NULL;
596     }
597   }
598 }
599
600
601 /**
602  * Method called whenever a peer connects to a port in MQ-based CADET.
603  *
604  * @param cls Closure from #GNUNET_CADET_open_port (peer # as long).
605  * @param channel New handle to the channel.
606  * @param source Peer that started this channel.
607  * @return Closure for the incoming @a channel. It's given to:
608  *         - The #GNUNET_CADET_DisconnectEventHandler (given to
609  *           #GNUNET_CADET_open_port) when the channel dies.
610  *         - Each the #GNUNET_MQ_MessageCallback handlers for each message
611  *           received on the @a channel.
612  */
613 static void *
614 connect_handler (void *cls,
615                  struct GNUNET_CADET_Channel *channel,
616                  const struct GNUNET_PeerIdentity *source)
617 {
618   struct CadetTestChannelWrapper *ch;
619   long peer = (long) cls;
620
621   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
622               "Incoming channel from %s to %ld: %p\n",
623               GNUNET_i2s (source),
624               peer,
625               channel);
626   if (peer == peers_requested - 1)
627   {
628     if (NULL != incoming_ch)
629     {
630       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
631                   "Duplicate incoming channel for client %lu\n",
632                   (long) cls);
633       GNUNET_assert (0);
634     }
635     incoming_ch = channel;
636   }
637   else
638   {
639     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
640                 "Incoming channel for unexpected peer #%lu\n",
641                 (long) cls);
642     GNUNET_assert (0);
643   }
644   ch = GNUNET_new (struct CadetTestChannelWrapper);
645   ch->ch = channel;
646
647   return ch;
648 }
649
650
651 /**
652  * Function called whenever an MQ-channel is destroyed, even if the destruction
653  * was requested by #GNUNET_CADET_channel_destroy.
654  * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
655  *
656  * It should clean up any associated state, including cancelling any pending
657  * transmission on this channel.
658  *
659  * @param cls Channel closure (channel wrapper).
660  * @param channel Connection to the other end (henceforth invalid).
661  */
662 static void
663 disconnect_handler (void *cls,
664                     const struct GNUNET_CADET_Channel *channel)
665 {
666   struct CadetTestChannelWrapper *ch_w = cls;
667
668   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
669               "Channel disconnected at %d\n",
670               ok);
671   GNUNET_assert (ch_w->ch == channel);
672   if (channel == incoming_ch)
673     incoming_ch = NULL;
674   else if (outgoing_ch == channel)
675     outgoing_ch = NULL;
676   else
677     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
678                 "Disconnect on unknown channel %p\n",
679                 channel);
680   if (NULL != disconnect_task)
681     GNUNET_SCHEDULER_cancel (disconnect_task);
682   disconnect_task = GNUNET_SCHEDULER_add_now (&gather_stats_and_exit,
683                                               (void *) __LINE__);
684   GNUNET_free (ch_w);
685 }
686
687
688 /**
689  * Start the testcase, we know the peers and have handles to CADET.
690  *
691  * Testcase continues when the root receives confirmation of connected peers,
692  * on callback function ch.
693  *
694  * @param cls Closure (unused).
695  */
696 static void
697 start_test (void *cls)
698 {
699   struct GNUNET_MQ_MessageHandler handlers[] = {
700     GNUNET_MQ_hd_var_size (data,
701                            GNUNET_MESSAGE_TYPE_DUMMY,
702                            struct GNUNET_MessageHeader,
703                            NULL),
704     GNUNET_MQ_handler_end ()
705   };
706   struct CadetTestChannelWrapper *ch;
707   enum GNUNET_CADET_ChannelOption flags;
708
709   test_task = NULL;
710   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
711               "In start_test\n");
712   start_time = GNUNET_TIME_absolute_get ();
713   ch = GNUNET_new (struct CadetTestChannelWrapper);
714   outgoing_ch = GNUNET_CADET_channel_create (h1,
715                                              ch,
716                                              p_id[1],
717                                              &port,
718                                              flags,
719                                              NULL,
720                                              &disconnect_handler,
721                                              handlers);
722   ch->ch = outgoing_ch;
723   GNUNET_assert (NULL == disconnect_task);
724   disconnect_task
725     = GNUNET_SCHEDULER_add_delayed (short_time,
726                                     &gather_stats_and_exit,
727                                     (void *) __LINE__);
728   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
729               "Sending data initializer on channel %p...\n",
730               outgoing_ch);
731   send_test_message (outgoing_ch);
732 }
733
734
735 /**
736  * Callback to be called when the requested peer information is available
737  *
738  * @param cls the closure from GNUNET_TESTBED_peer_get_information()
739  * @param op the operation this callback corresponds to
740  * @param pinfo the result; will be NULL if the operation has failed
741  * @param emsg error message if the operation has failed;
742  *             NULL if the operation is successfull
743  */
744 static void
745 pi_cb (void *cls,
746        struct GNUNET_TESTBED_Operation *op,
747        const struct GNUNET_TESTBED_PeerInformation *pinfo,
748        const char *emsg)
749 {
750   long i = (long) cls;
751
752   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
753               "ID callback for %ld\n",
754               i);
755   if ( (NULL == pinfo) ||
756        (NULL != emsg) )
757   {
758     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
759                 "pi_cb: %s\n",
760                 emsg);
761     abort_test (__LINE__);
762     return;
763   }
764   p_id[i] = pinfo->result.id;
765   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
766               "id: %s\n",
767               GNUNET_i2s (p_id[i]));
768   p_ids++;
769   if (p_ids < 2)
770     return;
771   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
772               "Got all IDs, starting test\n");
773   test_task = GNUNET_SCHEDULER_add_now (&start_test,
774                                         NULL);
775 }
776
777
778 /**
779  * test main: start test when all peers are connected
780  *
781  * @param cls Closure.
782  * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
783  * @param num_peers Number of peers that are running.
784  * @param peers Array of peers.
785  * @param cadets Handle to each of the CADETs of the peers.
786  */
787 static void
788 tmain (void *cls,
789        struct GNUNET_CADET_TEST_Context *ctx,
790        unsigned int num_peers,
791        struct GNUNET_TESTBED_Peer **peers,
792        struct GNUNET_CADET_Handle **cadets)
793 {
794   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
795               "test main\n");
796   test_ctx = ctx;
797   peers_running = num_peers;
798   GNUNET_assert (peers_running == peers_requested);
799   testbed_peers = peers;
800   h1 = cadets[0];
801   h2 = cadets[num_peers - 1];
802   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
803                                  NULL);
804   p_ids = 0;
805   t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
806                                                  GNUNET_TESTBED_PIT_IDENTITY,
807                                                  &pi_cb,
808                                                  (void *) 0L);
809   t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
810                                                  GNUNET_TESTBED_PIT_IDENTITY,
811                                                  &pi_cb,
812                                                  (void *) 1L);
813   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
814               "requested peer ids\n");
815 }
816
817
818 /**
819  * Main: start test
820  */
821 int
822 main (int argc,
823       char *argv[])
824 {
825   static const struct GNUNET_HashCode *ports[2];
826   struct GNUNET_MQ_MessageHandler handlers[] = {
827     GNUNET_MQ_hd_var_size (data,
828                            GNUNET_MESSAGE_TYPE_DUMMY,
829                            struct GNUNET_MessageHeader,
830                            NULL),
831     GNUNET_MQ_handler_end ()
832   };
833   const char *config_file = "test_cadet.conf";
834   char port_id[] = "test port";
835   struct GNUNET_GETOPT_CommandLineOption options[] = {
836     GNUNET_GETOPT_option_relative_time ('t',
837                                         "time",
838                                         "short_time",
839                                         gettext_noop ("set short timeout"),
840                                         &short_time),
841     GNUNET_GETOPT_option_uint ('m',
842                                "messages",
843                                "NUM_MESSAGES",
844                                gettext_noop ("set number of messages to send"),
845                                &total_packets),
846     GNUNET_GETOPT_option_uint ('p',
847                                "peers",
848                                "NUM_PEERS",
849                                gettext_noop ("number of peers to launch"),
850                                &peers_requested),
851     GNUNET_GETOPT_OPTION_END
852   };
853
854   GNUNET_log_setup ("test-cadet-flow",
855                     "DEBUG",
856                     NULL);
857   total_packets = TOTAL_PACKETS;
858   short_time = SHORT_TIME;
859   if (-1 == GNUNET_GETOPT_run (argv[0],
860                                options,
861                                argc,
862                                argv))
863   {
864     FPRINTF (stderr,
865              "test failed: problem with CLI parameters\n");
866     return 1;
867   }
868   GNUNET_CRYPTO_hash (port_id,
869                       sizeof (port_id),
870                       &port);
871   ports[0] = &port;
872   ports[1] = NULL;
873   GNUNET_CADET_TEST_ruN ("test_cadet_flow",
874                          config_file,
875                          peers_requested,
876                          &tmain,
877                          NULL,        /* tmain cls */
878                          &connect_handler,
879                          NULL,
880                          &disconnect_handler,
881                          handlers,
882                          ports);
883   return 0;
884 }
885
886 /* end of test_cadet_flow.c */