2 * This file is part of GNUnet
3 * Copyright (C) 2013 GNUnet e.V.
5 * GNUnet is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 3, or (at your
8 * option) any later version.
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 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNUnet; see the file COPYING. If not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 * @file multicast/test_multicast_multipeers.c
23 * @brief Tests for the Multicast API with multiple peers.
30 #include "gnunet_crypto_lib.h"
31 #include "gnunet_common.h"
32 #include "gnunet_util_lib.h"
33 #include "gnunet_testbed_service.h"
34 #include "gnunet_multicast_service.h"
40 int peer; /* peer number */
41 struct GNUNET_TESTBED_Operation *op; /* not yet in use */
42 struct GNUNET_TESTBED_Operation *pi_op; /* not yet in use */
46 static void service_connect (void *cls,
47 struct GNUNET_TESTBED_Operation *op,
51 static struct multicast_peer **mc_peers;
52 static struct GNUNET_TESTBED_Peer **peers;
55 static struct GNUNET_TESTBED_Operation *op[NUM_PEERS];
56 static struct GNUNET_TESTBED_Operation *pi_op[NUM_PEERS];
57 static const struct GNUNET_PeerIdentity *peer_id[NUM_PEERS];
59 static struct GNUNET_MULTICAST_Origin *origin;
60 static struct GNUNET_MULTICAST_Member *member[NUM_PEERS]; /* first element always empty */
62 static struct GNUNET_SCHEDULER_Task *timeout_tid;
64 static struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
65 static struct GNUNET_CRYPTO_EddsaPublicKey *group_pub_key;
67 static struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key[NUM_PEERS];
68 static struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key[NUM_PEERS];
72 * Global result for testcase.
77 * Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
81 shutdown_task (void *cls)
85 for (int i=0; i < NUM_PEERS; i++)
87 GNUNET_free (mc_peers[i]);
90 GNUNET_free (mc_peers);
93 for (int i=0;i<NUM_PEERS;i++)
97 GNUNET_TESTBED_operation_done(op[i]);
100 if (NULL != pi_op[i])
102 GNUNET_TESTBED_operation_done (pi_op[i]);
107 if (NULL != timeout_tid)
109 GNUNET_SCHEDULER_cancel (timeout_tid);
116 timeout_task (void *cls)
118 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
120 result = GNUNET_SYSERR;
121 GNUNET_SCHEDULER_shutdown ();
126 member_join_request (void *cls,
127 const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
128 const struct GNUNET_MessageHeader *join_msg,
129 struct GNUNET_MULTICAST_JoinHandle *jh)
131 struct multicast_peer *mc_peer = (struct multicast_peer*)cls;
132 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
133 "Peer #%u sent a join request.\n", mc_peer->peer);
143 struct multicast_peer *mc_peer = (struct multicast_peer*)cls;
145 char text[] = "ping";
146 *data_size = strlen(text)+1;
147 GNUNET_memcpy(data, text, *data_size);
149 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
150 "Peer #%u sents message to origin: %s\n", mc_peer->peer, text);
157 member_join_decision (void *cls,
159 const struct GNUNET_PeerIdentity *peer,
160 uint16_t relay_count,
161 const struct GNUNET_PeerIdentity *relays,
162 const struct GNUNET_MessageHeader *join_msg)
164 struct multicast_peer *mc_peer = (struct multicast_peer*)cls;
165 struct GNUNET_MULTICAST_MemberTransmitHandle *req;
167 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
168 "Peer #%u received a decision from origin: %s\n", mc_peer->peer, (GNUNET_YES == is_admitted)?"accepted":"rejected");
170 if (GNUNET_YES == is_admitted)
172 req = GNUNET_MULTICAST_member_to_origin (member[mc_peer->peer],
182 member_replay_frag ()
184 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
185 "member replay frag...\n");
192 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
193 "member replay msg...\n");
198 member_message (void *cls,
199 const struct GNUNET_MULTICAST_MessageHeader *msg)
201 struct multicast_peer *mc_peer = (struct multicast_peer*)cls;
203 if (0 != strncmp ("pong", (char *)&msg[1], 4))
205 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
206 "peer #%i did not receive pong\n",
209 result = GNUNET_SYSERR;
210 GNUNET_SCHEDULER_shutdown ();
213 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
214 "peer #%i receives: %s\n",
218 mc_peer->test_ok = GNUNET_OK;
220 // FIXME: ugly test function
222 for (int i=1; i<NUM_PEERS; i++)
223 if (!mc_peers[i]->test_ok)
227 GNUNET_SCHEDULER_shutdown();
233 origin_join_request (void *cls,
234 const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
235 const struct GNUNET_MessageHeader *join_msg,
236 struct GNUNET_MULTICAST_JoinHandle *jh)
238 struct GNUNET_MessageHeader *join_resp;
240 uint8_t data_size = ntohs (join_msg->size);
242 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
243 "origin got a join request...\n");
244 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
245 "origin receives: '%s'\n", (char *)&join_msg[1]);
247 char data[] = "Come in!";
248 data_size = strlen (data) + 1;
249 join_resp = GNUNET_malloc (sizeof (join_resp) + data_size);
250 join_resp->size = htons (sizeof (join_resp) + data_size);
251 join_resp->type = htons (123);
252 GNUNET_memcpy (&join_resp[1], data, data_size);
254 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
255 "origin sends: '%s'\n", data);
257 GNUNET_MULTICAST_join_decision (jh,
268 origin_replay_frag (void *cls,
269 const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
270 uint64_t fragment_id,
272 struct GNUNET_MULTICAST_ReplayHandle *rh)
274 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay fraq msg\n");
279 origin_replay_msg (void *cls,
280 const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
282 uint64_t fragment_offset,
284 struct GNUNET_MULTICAST_ReplayHandle *rh)
287 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay msg\n");
292 origin_notify (void *cls,
296 char text[] = "pong";
297 *data_size = strlen(text)+1;
298 memcpy(data, text, *data_size);
300 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin sends (to all): %s\n", text);
307 origin_request (void *cls,
308 const struct GNUNET_MULTICAST_RequestHeader *req)
310 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin receives: %s\n", (char *)&req[1]);
312 if (0 != strncmp ("ping", (char *)&req[1], 4)) {
313 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "origin didn't reveice a correct request");
316 GNUNET_MULTICAST_origin_to_all (origin,
325 origin_message (void *cls,
326 const struct GNUNET_MULTICAST_MessageHeader *msg)
328 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin message msg\n");
333 multicast_da (void *cls,
336 struct multicast_peer *mc_peer = (struct multicast_peer*)cls;
338 if (0 == mc_peer->peer)
340 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
341 "Origin closes multicast group\n");
343 GNUNET_MULTICAST_origin_stop (origin, NULL, cls);
347 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
348 "peer #%u parting from multicast group\n", mc_peer->peer);
350 GNUNET_MULTICAST_member_part (member[mc_peer->peer], NULL, cls);
356 multicast_ca (void *cls,
357 const struct GNUNET_CONFIGURATION_Handle *cfg)
359 struct multicast_peer *mc_peer = (struct multicast_peer*)cls;
360 struct GNUNET_MessageHeader *join_msg;
363 if (0 == mc_peer->peer)
365 group_pub_key = GNUNET_new (struct GNUNET_CRYPTO_EddsaPublicKey);
366 group_key = GNUNET_CRYPTO_eddsa_key_create ();
367 GNUNET_CRYPTO_eddsa_key_get_public (group_key, group_pub_key);
369 return GNUNET_MULTICAST_origin_start (cfg,
382 member_pub_key[mc_peer->peer] = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
383 member_key[mc_peer->peer] = GNUNET_CRYPTO_ecdsa_key_create ();
384 GNUNET_CRYPTO_ecdsa_key_get_public (member_key[mc_peer->peer], member_pub_key[mc_peer->peer]);
386 sprintf(data, "Hi, I am peer #%u. Can I enter?", mc_peer->peer);
387 uint8_t data_size = strlen (data) + 1;
388 join_msg = GNUNET_malloc (sizeof (join_msg) + data_size);
389 join_msg->size = htons (sizeof (join_msg) + data_size);
390 join_msg->type = htons (123);
391 GNUNET_memcpy (&join_msg[1], data, data_size);
393 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
394 "Peer #%u tries to join multicast group\n", mc_peer->peer);
396 return GNUNET_MULTICAST_member_join (cfg,
398 member_key[mc_peer->peer],
402 join_msg, /* join message */
404 member_join_decision,
414 peer_information_cb (void *cls,
415 struct GNUNET_TESTBED_Operation *operation,
416 const struct GNUNET_TESTBED_PeerInformation *pinfo,
419 struct multicast_peer *mc_peer = (struct multicast_peer*)cls;
422 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got no peer information\n");
423 result = GNUNET_SYSERR;
424 GNUNET_SCHEDULER_shutdown ();
427 peer_id[mc_peer->peer] = pinfo->result.id;
429 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
430 "Got peer information of %s (%s)\n", (0==mc_peer->peer)?"origin":"member" ,GNUNET_i2s(pinfo->result.id));
432 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
433 "Create peer #%u\n", mc_peer->peer);
435 if (0 != mc_peer->peer)
437 /* connect to multicast service of members */
438 op[mc_peer->peer] = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */
439 peers[mc_peer->peer], /* The peer whose service to connect to */
440 "multicast", /* The name of the service */
441 service_connect, /* callback to call after a handle to service
443 cls, /* closure for the above callback */
444 multicast_ca, /* callback to call with peer's configuration;
445 this should open the needed service connection */
446 multicast_da, /* callback to be called when closing the
447 opened service connection */
448 cls); /* closure for the above two callbacks */
454 service_connect (void *cls,
455 struct GNUNET_TESTBED_Operation *op,
459 struct multicast_peer *mc_peer = (struct multicast_peer*)cls;
461 if (NULL == ca_result)
463 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
464 "Connection adapter not created for peer #%u\n", mc_peer->peer);
465 result = GNUNET_SYSERR;
466 GNUNET_SCHEDULER_shutdown();
469 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
470 "Connected to multicast service of peer #%u\n", mc_peer->peer);
472 if (0 == mc_peer->peer)
476 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
477 "Connected to multicast service of origin\n");
479 // Get GNUnet identity of members
480 for (int i = 0; i<NUM_PEERS; i++)
482 pi_op[i] = GNUNET_TESTBED_peer_get_information (peers[i],
483 GNUNET_TESTBED_PIT_IDENTITY,
490 member[mc_peer->peer] = ca_result;
497 * Main function inovked from TESTBED once all of the
498 * peers are up and running. This one then connects
499 * just to the multicast service of peer 0 and 1.
500 * Peer 0 is going to be origin.
501 * Peer 1 is going to be one member.
502 * Origin will start a multicast group and the member will try to join it.
503 * After that we execute some multicast test.
506 * @param h the run handle
507 * @param peers started peers for the test
508 * @param num_peers size of the 'peers' array
509 * @param links_succeeded number of links between peers that were created
510 * @param links_failed number of links testbed was unable to establish
513 testbed_master (void *cls,
514 struct GNUNET_TESTBED_RunHandle *h,
515 unsigned int num_peers,
516 struct GNUNET_TESTBED_Peer **p,
517 unsigned int links_succeeded,
518 unsigned int links_failed)
520 /* Testbed is ready with peers running and connected in a pre-defined overlay
523 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
524 "Connected to testbed_master()\n");
528 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
529 "Create origin peer\n");
531 mc_peers = GNUNET_new_array (NUM_PEERS, struct multicast_peer*);
533 // Create test contexts for members
534 for (int i = 0; i<NUM_PEERS; i++)
536 mc_peers[i] = GNUNET_new (struct multicast_peer);
537 mc_peers[i]->peer = i;
538 mc_peers[i]->test_ok = GNUNET_NO;
541 op[0] = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */
542 peers[0], /* The peer whose service to connect to */
543 "multicast", /* The name of the service */
544 service_connect, /* callback to call after a handle to service
546 mc_peers[0], /* closure for the above callback */
547 multicast_ca, /* callback to call with peer's configuration;
548 this should open the needed service connection */
549 multicast_da, /* callback to be called when closing the
550 opened service connection */
551 mc_peers[0]); /* closure for the above two callbacks */
553 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); /* Schedule a new task on shutdown */
555 /* Schedule the shutdown task with a delay of a few Seconds */
556 timeout_tid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 80),
557 &timeout_task, NULL);
562 main (int argc, char *argv[])
566 result = GNUNET_SYSERR;
567 ret = GNUNET_TESTBED_test_run
568 ("test-multicast-multipeer", /* test case name */
569 "test_multicast.conf", /* template configuration */
570 NUM_PEERS, /* number of peers to start */
571 0LL, /* Event mask - set to 0 for no event notifications */
572 NULL, /* Controller event callback */
573 NULL, /* Closure for controller event callback */
574 testbed_master, /* continuation callback to be called when testbed setup is complete */
575 NULL); /* Closure for the test_master callback */
576 if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
581 /* end of test_multicast_multipeer.c */