test_cadet_flow.c 24 KB

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