You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

521 lines
16 KiB

  1. /*
  2. * This file is part of GNUnet
  3. * Copyright (C) 2013 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. SPDX-License-Identifier: AGPL3.0-or-later
  18. */
  19. /**
  20. * @file multicast/test_multicast_2peers.c
  21. * @brief Tests for the Multicast API with two peers doing the ping
  22. * pong test.
  23. * @author xrs
  24. */
  25. #include <inttypes.h>
  26. #include "platform.h"
  27. #include "gnunet_crypto_lib.h"
  28. #include "gnunet_common.h"
  29. #include "gnunet_util_lib.h"
  30. #include "gnunet_testbed_service.h"
  31. #include "gnunet_multicast_service.h"
  32. #define NUM_PEERS 2
  33. static struct GNUNET_TESTBED_Operation *op0;
  34. static struct GNUNET_TESTBED_Operation *op1;
  35. static struct GNUNET_TESTBED_Operation *pi_op0;
  36. static struct GNUNET_TESTBED_Operation *pi_op1;
  37. static struct GNUNET_TESTBED_Peer **peers;
  38. const struct GNUNET_PeerIdentity *peer_id[2];
  39. static struct GNUNET_SCHEDULER_Task *timeout_tid;
  40. static struct GNUNET_MULTICAST_Origin *origin;
  41. static struct GNUNET_MULTICAST_Member *member;
  42. struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
  43. struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
  44. struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key;
  45. struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
  46. /**
  47. * Global result for testcase.
  48. */
  49. static int result;
  50. /**
  51. * Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
  52. * Cleans up.
  53. */
  54. static void
  55. shutdown_task (void *cls)
  56. {
  57. if (NULL != op0)
  58. {
  59. GNUNET_TESTBED_operation_done (op0);
  60. op0 = NULL;
  61. }
  62. if (NULL != op1)
  63. {
  64. GNUNET_TESTBED_operation_done (op1);
  65. op1 = NULL;
  66. }
  67. if (NULL != pi_op0)
  68. {
  69. GNUNET_TESTBED_operation_done (pi_op0);
  70. pi_op0 = NULL;
  71. }
  72. if (NULL != pi_op1)
  73. {
  74. GNUNET_TESTBED_operation_done (pi_op1);
  75. pi_op1 = NULL;
  76. }
  77. if (NULL != timeout_tid)
  78. {
  79. GNUNET_SCHEDULER_cancel (timeout_tid);
  80. timeout_tid = NULL;
  81. }
  82. }
  83. static void
  84. timeout_task (void *cls)
  85. {
  86. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  87. "Timeout!\n");
  88. result = GNUNET_SYSERR;
  89. GNUNET_SCHEDULER_shutdown ();
  90. }
  91. static void
  92. member_join_request (void *cls,
  93. const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
  94. const struct GNUNET_MessageHeader *join_msg,
  95. struct GNUNET_MULTICAST_JoinHandle *jh)
  96. {
  97. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  98. "Member sent a join request.\n");
  99. }
  100. static int
  101. notify (void *cls,
  102. size_t *data_size,
  103. void *data)
  104. {
  105. char text[] = "ping";
  106. *data_size = strlen(text)+1;
  107. GNUNET_memcpy(data, text, *data_size);
  108. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  109. "Member sents message to origin: %s\n", text);
  110. return GNUNET_YES;
  111. }
  112. static void
  113. member_join_decision (void *cls,
  114. int is_admitted,
  115. const struct GNUNET_PeerIdentity *peer,
  116. uint16_t relay_count,
  117. const struct GNUNET_PeerIdentity *relays,
  118. const struct GNUNET_MessageHeader *join_msg)
  119. {
  120. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  121. "Member received a decision from origin: %s\n",
  122. (GNUNET_YES == is_admitted)
  123. ? "accepted"
  124. : "rejected");
  125. if (GNUNET_YES == is_admitted)
  126. {
  127. struct GNUNET_MULTICAST_MemberTransmitHandle *req;
  128. // FIXME: move to MQ-style API!
  129. req = GNUNET_MULTICAST_member_to_origin (member,
  130. 0,
  131. &notify,
  132. NULL);
  133. }
  134. }
  135. static void
  136. member_message (void *cls,
  137. const struct GNUNET_MULTICAST_MessageHeader *msg)
  138. {
  139. if (0 != strncmp ("pong", (char *)&msg[1], 4))
  140. {
  141. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "member did not receive pong\n");
  142. result = GNUNET_SYSERR;
  143. GNUNET_SCHEDULER_shutdown ();
  144. }
  145. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  146. "member receives: %s\n", (char *)&msg[1]);
  147. // Testcase ends here.
  148. result = GNUNET_YES;
  149. GNUNET_SCHEDULER_shutdown ();
  150. }
  151. static void
  152. origin_join_request (void *cls,
  153. const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
  154. const struct GNUNET_MessageHeader *join_msg,
  155. struct GNUNET_MULTICAST_JoinHandle *jh)
  156. {
  157. struct GNUNET_MessageHeader *join_resp;
  158. uint8_t data_size = ntohs (join_msg->size);
  159. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  160. "origin got a join request...\n");
  161. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  162. "origin receives: '%s'\n", (char *)&join_msg[1]);
  163. const char data[] = "Come in!";
  164. data_size = strlen (data) + 1;
  165. join_resp = GNUNET_malloc (sizeof (join_resp) + data_size);
  166. join_resp->size = htons (sizeof (join_resp) + data_size);
  167. join_resp->type = htons (123);
  168. GNUNET_memcpy (&join_resp[1], data, data_size);
  169. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  170. "origin sends: '%s'\n", data);
  171. GNUNET_MULTICAST_join_decision (jh,
  172. GNUNET_YES,
  173. 0,
  174. NULL,
  175. join_resp);
  176. GNUNET_free (join_resp);
  177. result = GNUNET_OK;
  178. }
  179. int
  180. origin_notify (void *cls,
  181. size_t *data_size,
  182. void *data)
  183. {
  184. char text[] = "pong";
  185. *data_size = strlen(text)+1;
  186. GNUNET_memcpy (data,
  187. text,
  188. *data_size);
  189. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin sends (to all): %s\n", text);
  190. return GNUNET_YES;
  191. }
  192. static void
  193. origin_request (void *cls,
  194. const struct GNUNET_MULTICAST_RequestHeader *req)
  195. {
  196. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin receives: %s\n", (char *)&req[1]);
  197. if (0 != strncmp ("ping", (char *)&req[1], 4))
  198. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "origin didn't reveice a correct request");
  199. GNUNET_MULTICAST_origin_to_all (origin,
  200. 0,
  201. 0,
  202. origin_notify,
  203. NULL);
  204. }
  205. static void
  206. origin_message (void *cls,
  207. const struct GNUNET_MULTICAST_MessageHeader *msg)
  208. {
  209. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin message msg\n");
  210. }
  211. static void
  212. service_connect1 (void *cls,
  213. struct GNUNET_TESTBED_Operation *op,
  214. void *ca_result,
  215. const char *emsg)
  216. {
  217. member = ca_result;
  218. if (NULL == member)
  219. {
  220. result = GNUNET_SYSERR;
  221. GNUNET_SCHEDULER_shutdown ();
  222. }
  223. else
  224. {
  225. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to multicast service of member\n");
  226. }
  227. }
  228. static void
  229. multicast_da1 (void *cls,
  230. void * op_result)
  231. {
  232. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  233. "Member parting from multicast group\n");
  234. GNUNET_MULTICAST_member_part (member, NULL, NULL);
  235. }
  236. static void *
  237. multicast_ca1 (void *cls,
  238. const struct GNUNET_CONFIGURATION_Handle *cfg)
  239. {
  240. struct GNUNET_MessageHeader *join_msg;
  241. void *ret;
  242. // Get members keys
  243. member_key = GNUNET_CRYPTO_ecdsa_key_create ();
  244. GNUNET_CRYPTO_ecdsa_key_get_public (member_key, &member_pub_key);
  245. char data[] = "Hi, can I enter?";
  246. uint8_t data_size = strlen (data) + 1;
  247. join_msg = GNUNET_malloc (sizeof (join_msg) + data_size);
  248. join_msg->size = htons (sizeof (join_msg) + data_size);
  249. join_msg->type = htons (123);
  250. GNUNET_memcpy (&join_msg[1], data, data_size);
  251. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  252. "Members tries to join multicast group\n");
  253. ret = GNUNET_MULTICAST_member_join (cfg,
  254. &group_pub_key,
  255. member_key,
  256. peer_id[0],
  257. 0,
  258. NULL,
  259. join_msg, /* join message */
  260. member_join_request,
  261. member_join_decision,
  262. NULL, /* no test for member_replay_frag */
  263. NULL, /* no test for member_replay_msg */
  264. member_message,
  265. NULL);
  266. GNUNET_free (join_msg);
  267. return ret;
  268. }
  269. static void
  270. peer_information_cb (void *cls,
  271. struct GNUNET_TESTBED_Operation *op,
  272. const struct GNUNET_TESTBED_PeerInformation *pinfo,
  273. const char *emsg)
  274. {
  275. int i = (int) (long) cls;
  276. if (NULL == pinfo)
  277. {
  278. result = GNUNET_SYSERR;
  279. GNUNET_SCHEDULER_shutdown ();
  280. }
  281. peer_id[i] = pinfo->result.id;
  282. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  283. "Got peer information of %s (%s)\n", (0==i)?"origin":"member" ,GNUNET_i2s(pinfo->result.id));
  284. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  285. "Create member peer\n");
  286. if (0 == i)
  287. {
  288. /* connect to multicast service of member */
  289. op1 = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */
  290. peers[1], /* The peer whose service to connect to */
  291. "multicast", /* The name of the service */
  292. service_connect1, /* callback to call after a handle to service
  293. is opened */
  294. NULL, /* closure for the above callback */
  295. multicast_ca1, /* callback to call with peer's configuration;
  296. this should open the needed service connection */
  297. multicast_da1, /* callback to be called when closing the
  298. opened service connection */
  299. NULL); /* closure for the above two callbacks */
  300. }
  301. }
  302. /**
  303. * Test logic of peer "0" being origin starts here.
  304. *
  305. * @param cls closure, for the example: NULL
  306. * @param op should be equal to "dht_op"
  307. * @param ca_result result of the connect operation, the
  308. * connection to the DHT service
  309. * @param emsg error message, if testbed somehow failed to
  310. * connect to the DHT.
  311. */
  312. static void
  313. service_connect0 (void *cls,
  314. struct GNUNET_TESTBED_Operation *op,
  315. void *ca_result,
  316. const char *emsg)
  317. {
  318. origin = ca_result;
  319. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  320. "Connected to multicast service of origin\n");
  321. // Get GNUnet identity of origin
  322. pi_op0 = GNUNET_TESTBED_peer_get_information (peers[0],
  323. GNUNET_TESTBED_PIT_IDENTITY,
  324. peer_information_cb,
  325. (void *) 0);
  326. // Get GNUnet identity of member
  327. pi_op1 = GNUNET_TESTBED_peer_get_information (peers[1],
  328. GNUNET_TESTBED_PIT_IDENTITY,
  329. peer_information_cb,
  330. (void *) 1);
  331. /* Connection to service successful. Here we'd usually do something with
  332. * the service. */
  333. result = GNUNET_OK;
  334. //GNUNET_SCHEDULER_shutdown (); /* Also kills the testbed */
  335. }
  336. /**
  337. * Function run when service multicast has started and is providing us
  338. * with a configuration file.
  339. */
  340. static void *
  341. multicast_ca0 (void *cls,
  342. const struct GNUNET_CONFIGURATION_Handle *cfg)
  343. {
  344. group_key = GNUNET_CRYPTO_eddsa_key_create ();
  345. GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key);
  346. return GNUNET_MULTICAST_origin_start (cfg,
  347. group_key,
  348. 0,
  349. origin_join_request,
  350. NULL, /* no test for origin_replay_frag */
  351. NULL, /* no test for origin_replay_msg */
  352. origin_request,
  353. origin_message,
  354. NULL);
  355. }
  356. static void
  357. multicast_da0 (void *cls,
  358. void *op_result)
  359. {
  360. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  361. "Origin closes multicast group\n");
  362. GNUNET_MULTICAST_origin_stop (origin, NULL, NULL);
  363. }
  364. /**
  365. * Main function inovked from TESTBED once all of the
  366. * peers are up and running. This one then connects
  367. * just to the multicast service of peer 0 and 1.
  368. * Peer 0 is going to be origin.
  369. * Peer 1 is going to be one member.
  370. * Origin will start a multicast group and the member will try to join it.
  371. * After that we execute some multicast test.
  372. *
  373. * @param cls closure
  374. * @param h the run handle
  375. * @param peers started peers for the test
  376. * @param num_peers size of the 'peers' array
  377. * @param links_succeeded number of links between peers that were created
  378. * @param links_failed number of links testbed was unable to establish
  379. */
  380. static void
  381. testbed_master (void *cls,
  382. struct GNUNET_TESTBED_RunHandle *h,
  383. unsigned int num_peers,
  384. struct GNUNET_TESTBED_Peer **p,
  385. unsigned int links_succeeded,
  386. unsigned int links_failed)
  387. {
  388. /* Testbed is ready with peers running and connected in a pre-defined overlay
  389. topology (FIXME) */
  390. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  391. "Connected to testbed_master()\n");
  392. peers = p;
  393. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  394. "Create origin peer\n");
  395. op0 = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */
  396. peers[0], /* The peer whose service to connect to */
  397. "multicast", /* The name of the service */
  398. service_connect0, /* callback to call after a handle to service
  399. is opened */
  400. NULL, /* closure for the above callback */
  401. multicast_ca0, /* callback to call with peer's configuration;
  402. this should open the needed service connection */
  403. multicast_da0, /* callback to be called when closing the
  404. opened service connection */
  405. NULL); /* closure for the above two callbacks */
  406. GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); /* Schedule a new task on shutdown */
  407. /* Schedule the shutdown task with a delay of a few Seconds */
  408. timeout_tid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 50),
  409. &timeout_task, NULL);
  410. }
  411. int
  412. main (int argc, char *argv[])
  413. {
  414. int ret;
  415. result = GNUNET_SYSERR;
  416. ret = GNUNET_TESTBED_test_run
  417. ("test-multicast-2peers", /* test case name */
  418. "test_multicast.conf", /* template configuration */
  419. NUM_PEERS, /* number of peers to start */
  420. 0LL, /* Event mask - set to 0 for no event notifications */
  421. NULL, /* Controller event callback */
  422. NULL, /* Closure for controller event callback */
  423. testbed_master, /* continuation callback to be called when testbed setup is complete */
  424. NULL); /* Closure for the test_master callback */
  425. if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
  426. return 1;
  427. return 0;
  428. }
  429. /* end of test_multicast_2peers.c */