cadet_test_lib.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2012, 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/cadet_test_lib.c
  18. * @author Bartlomiej Polot
  19. * @brief library for writing CADET tests
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "cadet_test_lib.h"
  24. #include "gnunet_cadet_service.h"
  25. /**
  26. * Test context for a CADET Test.
  27. */
  28. struct GNUNET_CADET_TEST_Context {
  29. /**
  30. * Array of running peers.
  31. */
  32. struct GNUNET_TESTBED_Peer **peers;
  33. /**
  34. * Array of handles to the CADET for each peer.
  35. */
  36. struct GNUNET_CADET_Handle **cadets;
  37. /**
  38. * Operation associated with the connection to the CADET.
  39. */
  40. struct GNUNET_TESTBED_Operation **ops;
  41. /**
  42. * Number of peers running, size of the arrays above.
  43. */
  44. unsigned int num_peers;
  45. /**
  46. * Main function of the test to run once all CADETs are available.
  47. */
  48. GNUNET_CADET_TEST_AppMain app_main;
  49. /**
  50. * Closure for 'app_main'.
  51. */
  52. void *app_main_cls;
  53. /**
  54. * Handler for incoming tunnels.
  55. */
  56. GNUNET_CADET_ConnectEventHandler connects;
  57. /**
  58. * Function called when the transmit window size changes.
  59. */
  60. GNUNET_CADET_WindowSizeEventHandler window_changes;
  61. /**
  62. * Cleaner for destroyed incoming tunnels.
  63. */
  64. GNUNET_CADET_DisconnectEventHandler disconnects;
  65. /**
  66. * Message handlers.
  67. */
  68. struct GNUNET_MQ_MessageHandler *handlers;
  69. /**
  70. * Application ports.
  71. */
  72. const struct GNUNET_HashCode **ports;
  73. /**
  74. * Number of ports in #ports.
  75. */
  76. unsigned int port_count;
  77. };
  78. /**
  79. * Context for a cadet adapter callback.
  80. */
  81. struct GNUNET_CADET_TEST_AdapterContext {
  82. /**
  83. * Peer number for the particular peer.
  84. */
  85. unsigned int peer;
  86. /**
  87. * Port handlers for open ports.
  88. */
  89. struct GNUNET_CADET_Port **ports;
  90. /**
  91. * General context.
  92. */
  93. struct GNUNET_CADET_TEST_Context *ctx;
  94. };
  95. /**
  96. * Adapter function called to establish a connection to
  97. * the CADET service.
  98. *
  99. * @param cls closure
  100. * @param cfg configuration of the peer to connect to; will be available until
  101. * GNUNET_TESTBED_operation_done() is called on the operation returned
  102. * from GNUNET_TESTBED_service_connect()
  103. * @return service handle to return in 'op_result', NULL on error
  104. */
  105. static void *
  106. cadet_connect_adapter(void *cls,
  107. const struct GNUNET_CONFIGURATION_Handle *cfg)
  108. {
  109. struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
  110. struct GNUNET_CADET_TEST_Context *ctx = actx->ctx;
  111. struct GNUNET_CADET_Handle *h;
  112. h = GNUNET_CADET_connect(cfg);
  113. if (NULL == h)
  114. {
  115. GNUNET_break(0);
  116. return NULL;
  117. }
  118. if (NULL == ctx->ports)
  119. return h;
  120. actx->ports = GNUNET_new_array(ctx->port_count,
  121. struct GNUNET_CADET_Port *);
  122. for (unsigned int i = 0; i < ctx->port_count; i++)
  123. {
  124. actx->ports[i] = GNUNET_CADET_open_port(h,
  125. ctx->ports[i],
  126. ctx->connects,
  127. (void *)(long)actx->peer,
  128. ctx->window_changes,
  129. ctx->disconnects,
  130. ctx->handlers);
  131. }
  132. return h;
  133. }
  134. /**
  135. * Adapter function called to destroy a connection to
  136. * the CADET service.
  137. *
  138. * @param cls closure
  139. * @param op_result service handle returned from the connect adapter
  140. */
  141. static void
  142. cadet_disconnect_adapter(void *cls,
  143. void *op_result)
  144. {
  145. struct GNUNET_CADET_Handle *cadet = op_result;
  146. struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
  147. if (NULL != actx->ports)
  148. {
  149. for (unsigned int i = 0; i < actx->ctx->port_count; i++)
  150. {
  151. GNUNET_CADET_close_port(actx->ports[i]);
  152. actx->ports[i] = NULL;
  153. }
  154. GNUNET_free(actx->ports);
  155. }
  156. GNUNET_free(actx);
  157. GNUNET_CADET_disconnect(cadet);
  158. }
  159. /**
  160. * Callback to be called when a service connect operation is completed.
  161. *
  162. * @param cls The callback closure from functions generating an operation.
  163. * @param op The operation that has been finished.
  164. * @param ca_result The service handle returned from
  165. * GNUNET_TESTBED_ConnectAdapter() (cadet handle).
  166. * @param emsg Error message in case the operation has failed.
  167. * NULL if operation has executed successfully.
  168. */
  169. static void
  170. cadet_connect_cb(void *cls,
  171. struct GNUNET_TESTBED_Operation *op,
  172. void *ca_result,
  173. const char *emsg)
  174. {
  175. struct GNUNET_CADET_TEST_Context *ctx = cls;
  176. if (NULL != emsg)
  177. {
  178. fprintf(stderr,
  179. "Failed to connect to CADET service: %s\n",
  180. emsg);
  181. GNUNET_SCHEDULER_shutdown();
  182. return;
  183. }
  184. for (unsigned int i = 0; i < ctx->num_peers; i++)
  185. if (op == ctx->ops[i])
  186. {
  187. ctx->cadets[i] = ca_result;
  188. GNUNET_log(GNUNET_ERROR_TYPE_INFO,
  189. "...cadet %u connected\n",
  190. i);
  191. }
  192. for (unsigned int i = 0; i < ctx->num_peers; i++)
  193. if (NULL == ctx->cadets[i])
  194. return;
  195. /* still some CADET connections missing */
  196. /* all CADET connections ready! */
  197. ctx->app_main(ctx->app_main_cls,
  198. ctx,
  199. ctx->num_peers,
  200. ctx->peers,
  201. ctx->cadets);
  202. }
  203. void
  204. GNUNET_CADET_TEST_cleanup(struct GNUNET_CADET_TEST_Context *ctx)
  205. {
  206. for (unsigned int i = 0; i < ctx->num_peers; i++)
  207. {
  208. GNUNET_assert(NULL != ctx->ops[i]);
  209. GNUNET_TESTBED_operation_done(ctx->ops[i]);
  210. ctx->ops[i] = NULL;
  211. }
  212. GNUNET_free(ctx->ops);
  213. GNUNET_free(ctx->cadets);
  214. GNUNET_free(ctx->handlers);
  215. GNUNET_free(ctx);
  216. GNUNET_SCHEDULER_shutdown();
  217. }
  218. /**
  219. * Callback run when the testbed is ready (peers running and connected to
  220. * each other)
  221. *
  222. * @param cls Closure (context).
  223. * @param h the run handle
  224. * @param num_peers Number of peers that are running.
  225. * @param peers Handles to each one of the @c num_peers peers.
  226. * @param links_succeeded the number of overlay link connection attempts that
  227. * succeeded
  228. * @param links_failed the number of overlay link connection attempts that
  229. * failed
  230. */
  231. static void
  232. cadet_test_run(void *cls,
  233. struct GNUNET_TESTBED_RunHandle *h,
  234. unsigned int num_peers,
  235. struct GNUNET_TESTBED_Peer **peers,
  236. unsigned int links_succeeded,
  237. unsigned int links_failed)
  238. {
  239. struct GNUNET_CADET_TEST_Context *ctx = cls;
  240. if (0 != links_failed)
  241. {
  242. GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
  243. "Some links failed (%u), ending\n",
  244. links_failed);
  245. exit(77);
  246. }
  247. if (num_peers != ctx->num_peers)
  248. {
  249. GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
  250. "Peers started %u/%u, ending\n",
  251. num_peers,
  252. ctx->num_peers);
  253. exit(1);
  254. }
  255. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
  256. "Testbed up, %u peers and %u links\n",
  257. num_peers,
  258. links_succeeded);
  259. ctx->peers = peers;
  260. for (unsigned int i = 0; i < num_peers; i++)
  261. {
  262. struct GNUNET_CADET_TEST_AdapterContext *newctx;
  263. newctx = GNUNET_new(struct GNUNET_CADET_TEST_AdapterContext);
  264. newctx->peer = i;
  265. newctx->ctx = ctx;
  266. GNUNET_log(GNUNET_ERROR_TYPE_INFO,
  267. "Connecting to cadet %u\n",
  268. i);
  269. ctx->ops[i] = GNUNET_TESTBED_service_connect(ctx,
  270. peers[i],
  271. "cadet",
  272. &cadet_connect_cb,
  273. ctx,
  274. &cadet_connect_adapter,
  275. &cadet_disconnect_adapter,
  276. newctx);
  277. GNUNET_log(GNUNET_ERROR_TYPE_INFO,
  278. "op handle %p\n",
  279. ctx->ops[i]);
  280. }
  281. }
  282. /**
  283. * Run a test using the given name, configuration file and number of peers.
  284. * All cadet callbacks will receive the peer number (long) as the closure.
  285. *
  286. * @param testname Name of the test (for logging).
  287. * @param cfgfile Name of the configuration file.
  288. * @param num_peers Number of peers to start.
  289. * @param tmain Main function to run once the testbed is ready.
  290. * @param tmain_cls Closure for @a tmain.
  291. * @param connects Handler for incoming channels.
  292. * @param window_changes Handler for the window size change notification.
  293. * @param disconnects Cleaner for destroyed incoming channels.
  294. * @param handlers Message handlers.
  295. * @param ports Ports the peers offer, NULL-terminated.
  296. */
  297. void
  298. GNUNET_CADET_TEST_ruN(const char *testname,
  299. const char *cfgfile,
  300. unsigned int num_peers,
  301. GNUNET_CADET_TEST_AppMain tmain,
  302. void *tmain_cls,
  303. GNUNET_CADET_ConnectEventHandler connects,
  304. GNUNET_CADET_WindowSizeEventHandler window_changes,
  305. GNUNET_CADET_DisconnectEventHandler disconnects,
  306. struct GNUNET_MQ_MessageHandler *handlers,
  307. const struct GNUNET_HashCode **ports)
  308. {
  309. struct GNUNET_CADET_TEST_Context *ctx;
  310. ctx = GNUNET_new(struct GNUNET_CADET_TEST_Context);
  311. ctx->num_peers = num_peers;
  312. ctx->ops = GNUNET_new_array(num_peers,
  313. struct GNUNET_TESTBED_Operation *);
  314. ctx->cadets = GNUNET_new_array(num_peers,
  315. struct GNUNET_CADET_Handle *);
  316. ctx->app_main = tmain;
  317. ctx->app_main_cls = tmain_cls;
  318. ctx->connects = connects;
  319. ctx->window_changes = window_changes;
  320. ctx->disconnects = disconnects;
  321. ctx->handlers = GNUNET_MQ_copy_handlers(handlers);
  322. ctx->ports = ports;
  323. ctx->port_count = 0;
  324. while (NULL != ctx->ports[ctx->port_count])
  325. ctx->port_count++;
  326. GNUNET_TESTBED_test_run(testname,
  327. cfgfile,
  328. num_peers,
  329. 0LL, NULL, NULL,
  330. &cadet_test_run,
  331. ctx);
  332. }
  333. /* end of cadet_test_lib.c */