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.
 
 
 
 

644 lines
20 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_multipeers.c
  21. * @brief Tests for the Multicast API with multiple peers.
  22. * @author xrs
  23. */
  24. #include <inttypes.h>
  25. #include "platform.h"
  26. #include "gnunet_crypto_lib.h"
  27. #include "gnunet_common.h"
  28. #include "gnunet_util_lib.h"
  29. #include "gnunet_testbed_service.h"
  30. #include "gnunet_multicast_service.h"
  31. #define PEERS_REQUESTED 12
  32. struct MulticastPeerContext
  33. {
  34. int peer; /* peer number */
  35. struct GNUNET_CRYPTO_EcdsaPrivateKey *key;
  36. const struct GNUNET_PeerIdentity *id;
  37. struct GNUNET_TESTBED_Operation *op; /* not yet in use */
  38. struct GNUNET_TESTBED_Operation *pi_op; /* not yet in use */
  39. int test_ok;
  40. };
  41. enum pingpong
  42. {
  43. PING = 1,
  44. PONG = 2
  45. };
  46. struct pingpong_msg
  47. {
  48. int peer;
  49. enum pingpong msg;
  50. };
  51. static void service_connect (void *cls,
  52. struct GNUNET_TESTBED_Operation *op,
  53. void *ca_result,
  54. const char *emsg);
  55. static struct MulticastPeerContext **multicast_peers;
  56. static struct GNUNET_TESTBED_Peer **peers;
  57. static struct GNUNET_TESTBED_Operation *op[PEERS_REQUESTED];
  58. static struct GNUNET_TESTBED_Operation *pi_op[PEERS_REQUESTED];
  59. static struct GNUNET_MULTICAST_Origin *origin;
  60. static struct GNUNET_MULTICAST_Member *members[PEERS_REQUESTED]; /* first element always empty */
  61. static struct GNUNET_SCHEDULER_Task *timeout_tid;
  62. static struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
  63. static struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
  64. static struct GNUNET_HashCode group_pub_key_hash;
  65. /**
  66. * Global result for testcase.
  67. */
  68. static int result;
  69. /**
  70. * Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
  71. * Cleans up.
  72. */
  73. static void
  74. shutdown_task (void *cls)
  75. {
  76. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  77. "shutdown_task!\n");
  78. for (int i=0;i<PEERS_REQUESTED;i++)
  79. {
  80. if (NULL != op[i])
  81. {
  82. GNUNET_TESTBED_operation_done(op[i]);
  83. op[i] = NULL;
  84. }
  85. if (NULL != pi_op[i])
  86. {
  87. GNUNET_TESTBED_operation_done (pi_op[i]);
  88. pi_op[i] = NULL;
  89. }
  90. }
  91. if (NULL != multicast_peers)
  92. {
  93. for (int i=0; i < PEERS_REQUESTED; i++)
  94. {
  95. GNUNET_free_non_null (multicast_peers[i]->key);
  96. GNUNET_free (multicast_peers[i]);
  97. multicast_peers[i] = NULL;
  98. }
  99. GNUNET_free (multicast_peers);
  100. multicast_peers = NULL;
  101. }
  102. if (NULL != timeout_tid)
  103. {
  104. GNUNET_SCHEDULER_cancel (timeout_tid);
  105. timeout_tid = NULL;
  106. }
  107. }
  108. static void
  109. timeout_task (void *cls)
  110. {
  111. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  112. "Timeout!\n");
  113. result = GNUNET_SYSERR;
  114. GNUNET_SCHEDULER_shutdown ();
  115. }
  116. static void
  117. member_join_request (void *cls,
  118. const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
  119. const struct GNUNET_MessageHeader *join_msg,
  120. struct GNUNET_MULTICAST_JoinHandle *jh)
  121. {
  122. struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
  123. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  124. "Peer #%u (%s) sent a join request.\n",
  125. mc_peer->peer,
  126. GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
  127. }
  128. static int
  129. notify (void *cls,
  130. size_t *data_size,
  131. void *data)
  132. {
  133. struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
  134. struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg);
  135. pp_msg->peer = mc_peer->peer;
  136. pp_msg->msg = PING;
  137. *data_size = sizeof (struct pingpong_msg);
  138. GNUNET_memcpy(data, pp_msg, *data_size);
  139. GNUNET_free (pp_msg);
  140. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  141. "Peer #%u sents ping to origin\n", mc_peer->peer);
  142. return GNUNET_YES;
  143. }
  144. static void
  145. member_join_decision (void *cls,
  146. int is_admitted,
  147. const struct GNUNET_PeerIdentity *peer,
  148. uint16_t relay_count,
  149. const struct GNUNET_PeerIdentity *relays,
  150. const struct GNUNET_MessageHeader *join_msg)
  151. {
  152. struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
  153. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  154. "Peer #%u (%s) received a decision from origin: %s\n",
  155. mc_peer->peer,
  156. GNUNET_i2s (multicast_peers[mc_peer->peer]->id),
  157. (GNUNET_YES == is_admitted)?"accepted":"rejected");
  158. if (GNUNET_YES == is_admitted)
  159. {
  160. GNUNET_MULTICAST_member_to_origin (members[mc_peer->peer],
  161. 0,
  162. notify,
  163. cls);
  164. }
  165. }
  166. static void
  167. member_replay_frag ()
  168. {
  169. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  170. "member replay frag...\n");
  171. }
  172. static void
  173. member_replay_msg ()
  174. {
  175. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  176. "member replay msg...\n");
  177. }
  178. static void
  179. origin_disconnected_cb (void *cls)
  180. {
  181. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  182. "Origin disconnected. Shutting down.\n");
  183. result = GNUNET_YES;
  184. GNUNET_SCHEDULER_shutdown ();
  185. }
  186. static void
  187. member_disconnected_cb (void *cls)
  188. {
  189. for (int i = 1; i < PEERS_REQUESTED; ++i)
  190. if (GNUNET_NO == multicast_peers[i]->test_ok)
  191. return;
  192. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  193. "All member disconnected. Stopping origin.\n");
  194. GNUNET_MULTICAST_origin_stop (origin, origin_disconnected_cb, cls);
  195. }
  196. static void
  197. member_message (void *cls,
  198. const struct GNUNET_MULTICAST_MessageHeader *msg)
  199. {
  200. struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
  201. struct pingpong_msg *pp_msg = (struct pingpong_msg*) &(msg[1]);
  202. if (PONG == pp_msg->msg && mc_peer->peer == pp_msg->peer)
  203. {
  204. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  205. "peer #%i (%s) receives a pong\n",
  206. mc_peer->peer,
  207. GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
  208. mc_peer->test_ok = GNUNET_OK;
  209. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  210. "peer #%u (%s) parting from multicast group\n",
  211. mc_peer->peer,
  212. GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
  213. GNUNET_MULTICAST_member_part (members[mc_peer->peer], member_disconnected_cb, cls);
  214. }
  215. }
  216. static void
  217. origin_join_request (void *cls,
  218. const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
  219. const struct GNUNET_MessageHeader *join_msg,
  220. struct GNUNET_MULTICAST_JoinHandle *jh)
  221. {
  222. struct GNUNET_MessageHeader *join_resp;
  223. uint8_t data_size = ntohs (join_msg->size);
  224. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  225. "origin got a join request...\n");
  226. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  227. "origin receives: '%s'\n", (char *)&join_msg[1]);
  228. char data[] = "Come in!";
  229. data_size = strlen (data) + 1;
  230. join_resp = GNUNET_malloc (sizeof (join_resp) + data_size);
  231. join_resp->size = htons (sizeof (join_resp) + data_size);
  232. join_resp->type = htons (123);
  233. GNUNET_memcpy (&join_resp[1], data, data_size);
  234. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  235. "origin sends: '%s'\n", data);
  236. GNUNET_MULTICAST_join_decision (jh,
  237. GNUNET_YES,
  238. 0,
  239. NULL,
  240. join_resp);
  241. result = GNUNET_OK;
  242. }
  243. static void
  244. origin_replay_frag (void *cls,
  245. const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
  246. uint64_t fragment_id,
  247. uint64_t flags,
  248. struct GNUNET_MULTICAST_ReplayHandle *rh)
  249. {
  250. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay fraq msg\n");
  251. }
  252. static void
  253. origin_replay_msg (void *cls,
  254. const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
  255. uint64_t message_id,
  256. uint64_t fragment_offset,
  257. uint64_t flags,
  258. struct GNUNET_MULTICAST_ReplayHandle *rh)
  259. {
  260. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay msg\n");
  261. }
  262. static int
  263. origin_notify (void *cls,
  264. size_t *data_size,
  265. void *data)
  266. {
  267. struct pingpong_msg *rcv_pp_msg = (struct pingpong_msg*)cls;
  268. struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg);
  269. pp_msg->peer = rcv_pp_msg->peer;
  270. pp_msg->msg = PONG;
  271. *data_size = sizeof (struct pingpong_msg);
  272. GNUNET_memcpy(data, pp_msg, *data_size);
  273. GNUNET_free (pp_msg);
  274. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin sends pong\n");
  275. return GNUNET_YES;
  276. }
  277. static void
  278. origin_request (void *cls,
  279. const struct GNUNET_MULTICAST_RequestHeader *req)
  280. {
  281. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin receives a msg\n");
  282. req++;
  283. struct pingpong_msg *pp_msg = (struct pingpong_msg *) req;
  284. if (1 != pp_msg->msg) {
  285. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "origin didn't reveice a correct request");
  286. }
  287. GNUNET_MULTICAST_origin_to_all (origin,
  288. 0,
  289. 0,
  290. origin_notify,
  291. pp_msg);
  292. }
  293. static void
  294. origin_message (void *cls,
  295. const struct GNUNET_MULTICAST_MessageHeader *msg)
  296. {
  297. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin message msg\n");
  298. }
  299. static void
  300. multicast_disconnect (void *cls,
  301. void *op_result)
  302. {
  303. }
  304. static void *
  305. multicast_connect (void *cls,
  306. const struct GNUNET_CONFIGURATION_Handle *cfg)
  307. {
  308. struct MulticastPeerContext *multicast_peer = cls;
  309. struct GNUNET_MessageHeader *join_msg;
  310. char data[64];
  311. if (0 == multicast_peer->peer)
  312. {
  313. group_key = GNUNET_CRYPTO_eddsa_key_create ();
  314. GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key);
  315. GNUNET_CRYPTO_hash (&group_pub_key, sizeof (group_pub_key), &group_pub_key_hash);
  316. origin = GNUNET_MULTICAST_origin_start (cfg,
  317. group_key,
  318. 0,
  319. origin_join_request,
  320. origin_replay_frag,
  321. origin_replay_msg,
  322. origin_request,
  323. origin_message,
  324. cls);
  325. if (NULL == origin)
  326. {
  327. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  328. "Peer #%u could not create a multicast group",
  329. multicast_peer->peer);
  330. return NULL;
  331. }
  332. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  333. "Peer #%u connected as origin to group %s\n",
  334. multicast_peer->peer,
  335. GNUNET_h2s (&group_pub_key_hash));
  336. return origin;
  337. }
  338. else
  339. {
  340. multicast_peer->key = GNUNET_CRYPTO_ecdsa_key_create ();
  341. sprintf(data, "Hi, I am peer #%u (%s). Can I enter?",
  342. multicast_peer->peer,
  343. GNUNET_i2s (multicast_peers[multicast_peer->peer]->id));
  344. uint8_t data_size = strlen (data) + 1;
  345. join_msg = GNUNET_malloc (sizeof (join_msg) + data_size);
  346. join_msg->size = htons (sizeof (join_msg) + data_size);
  347. join_msg->type = htons (123);
  348. GNUNET_memcpy (&join_msg[1], data, data_size);
  349. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  350. "Peer #%u (%s) tries to join multicast group %s\n",
  351. multicast_peer->peer,
  352. GNUNET_i2s (multicast_peers[multicast_peer->peer]->id),
  353. GNUNET_h2s (&group_pub_key_hash));
  354. members[multicast_peer->peer] =
  355. GNUNET_MULTICAST_member_join (cfg,
  356. &group_pub_key,
  357. multicast_peer->key,
  358. multicast_peers[0]->id,
  359. 0,
  360. NULL,
  361. join_msg, /* join message */
  362. member_join_request,
  363. member_join_decision,
  364. member_replay_frag,
  365. member_replay_msg,
  366. member_message,
  367. cls);
  368. return members[multicast_peer->peer];
  369. }
  370. }
  371. static void
  372. peer_information_cb (void *cls,
  373. struct GNUNET_TESTBED_Operation *operation,
  374. const struct GNUNET_TESTBED_PeerInformation *pinfo,
  375. const char *emsg)
  376. {
  377. struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
  378. if (NULL == pinfo) {
  379. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got no peer information\n");
  380. result = GNUNET_SYSERR;
  381. GNUNET_SCHEDULER_shutdown ();
  382. }
  383. multicast_peers[mc_peer->peer]->id = pinfo->result.id;
  384. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  385. "Got peer information of %s (%s)\n",
  386. (0 == mc_peer->peer)? "origin" : "member",
  387. GNUNET_i2s (pinfo->result.id));
  388. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  389. "Create peer #%u (%s)\n",
  390. mc_peer->peer,
  391. GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
  392. if (0 != mc_peer->peer)
  393. {
  394. /* connect to multicast service of members */
  395. op[mc_peer->peer] =
  396. GNUNET_TESTBED_service_connect (/* Closure for operation */
  397. NULL,
  398. /* The peer whose service to connect to */
  399. peers[mc_peer->peer],
  400. /* The name of the service */
  401. "multicast",
  402. /* called after a handle to service is opened */
  403. service_connect,
  404. /* closure for the above callback */
  405. cls,
  406. /* called when opening the service connection */
  407. multicast_connect,
  408. /* called when closing the service connection */
  409. multicast_disconnect,
  410. /* closure for the above two callbacks */
  411. cls);
  412. }
  413. }
  414. static void
  415. service_connect (void *cls,
  416. struct GNUNET_TESTBED_Operation *op,
  417. void *ca_result,
  418. const char *emsg)
  419. {
  420. struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
  421. if (NULL == ca_result)
  422. {
  423. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  424. "Connection adapter not created for peer #%u (%s)\n",
  425. mc_peer->peer,
  426. GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
  427. result = GNUNET_SYSERR;
  428. GNUNET_SCHEDULER_shutdown();
  429. }
  430. if (0 == mc_peer->peer)
  431. {
  432. // Get GNUnet identity of members
  433. for (int i = 0; i<PEERS_REQUESTED; i++)
  434. {
  435. pi_op[i] = GNUNET_TESTBED_peer_get_information (peers[i],
  436. GNUNET_TESTBED_PIT_IDENTITY,
  437. peer_information_cb,
  438. multicast_peers[i]);
  439. }
  440. }
  441. }
  442. /**
  443. * Main function inovked from TESTBED once all of the
  444. * peers are up and running. This one then connects
  445. * just to the multicast service of peer 0 and 1.
  446. * Peer 0 is going to be origin.
  447. * Peer 1 is going to be one member.
  448. * Origin will start a multicast group and the member will try to join it.
  449. * After that we execute some multicast test.
  450. *
  451. * @param cls closure
  452. * @param h the run handle
  453. * @param peers started peers for the test
  454. * @param PEERS_REQUESTED size of the 'peers' array
  455. * @param links_succeeded number of links between peers that were created
  456. * @param links_failed number of links testbed was unable to establish
  457. */
  458. static void
  459. testbed_master (void *cls,
  460. struct GNUNET_TESTBED_RunHandle *h,
  461. unsigned int num_peers,
  462. struct GNUNET_TESTBED_Peer **p,
  463. unsigned int links_succeeded,
  464. unsigned int links_failed)
  465. {
  466. /* Testbed is ready with peers running and connected in a pre-defined overlay
  467. topology (FIXME) */
  468. peers = p;
  469. multicast_peers = GNUNET_new_array (PEERS_REQUESTED, struct MulticastPeerContext*);
  470. // Create test contexts for members
  471. for (int i = 0; i<PEERS_REQUESTED; i++)
  472. {
  473. multicast_peers[i] = GNUNET_new (struct MulticastPeerContext);
  474. multicast_peers[i]->peer = i;
  475. multicast_peers[i]->test_ok = GNUNET_NO;
  476. }
  477. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  478. "Create origin peer\n");
  479. op[0] =
  480. GNUNET_TESTBED_service_connect (/* Closure for operation */
  481. NULL,
  482. /* The peer whose service to connect to */
  483. peers[0],
  484. /* The name of the service */
  485. "multicast",
  486. /* called after a handle to service is opened */
  487. service_connect,
  488. /* closure for the above callback */
  489. multicast_peers[0],
  490. /* called when opening the service connection */
  491. multicast_connect,
  492. /* called when closing the service connection */
  493. multicast_disconnect,
  494. /* closure for the above two callbacks */
  495. multicast_peers[0]);
  496. /* Schedule a new task on shutdown */
  497. GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
  498. /* Schedule the shutdown task with a delay of a few Seconds */
  499. timeout_tid =
  500. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
  501. (GNUNET_TIME_UNIT_SECONDS, 400),
  502. &timeout_task,
  503. NULL);
  504. }
  505. int
  506. main (int argc, char *argv[])
  507. {
  508. int ret;
  509. char const *config_file;
  510. if (strstr (argv[0], "_line") != NULL)
  511. {
  512. config_file = "test_multicast_line.conf";
  513. }
  514. else if (strstr(argv[0], "_star") != NULL)
  515. {
  516. config_file = "test_multicast_star.conf";
  517. }
  518. else
  519. {
  520. config_file = "test_multicast_star.conf";
  521. }
  522. result = GNUNET_SYSERR;
  523. ret =
  524. GNUNET_TESTBED_test_run ("test-multicast-multipeer",
  525. config_file,
  526. /* number of peers to start */
  527. PEERS_REQUESTED,
  528. /* Event mask - set to 0 for no event notifications */
  529. 0LL,
  530. /* Controller event callback */
  531. NULL,
  532. /* Closure for controller event callback */
  533. NULL,
  534. /* called when testbed setup is complete */
  535. testbed_master,
  536. /* Closure for the test_master callback */
  537. NULL);
  538. if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
  539. return 1;
  540. return 0;
  541. }
  542. /* end of test_multicast_multipeer.c */