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 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.
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.
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/>.
20 * @file multicast/test_multicast_multipeers.c
21 * @brief Tests for the Multicast API with multiple peers.
28 #include "gnunet_crypto_lib.h"
29 #include "gnunet_common.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_testbed_service.h"
32 #include "gnunet_multicast_service.h"
34 #define PEERS_REQUESTED 12
36 struct MulticastPeerContext
38 int peer; /* peer number */
39 struct GNUNET_CRYPTO_EcdsaPrivateKey *key;
40 const struct GNUNET_PeerIdentity *id;
41 struct GNUNET_TESTBED_Operation *op; /* not yet in use */
42 struct GNUNET_TESTBED_Operation *pi_op; /* not yet in use */
58 static void service_connect (void *cls,
59 struct GNUNET_TESTBED_Operation *op,
63 static struct MulticastPeerContext **multicast_peers;
64 static struct GNUNET_TESTBED_Peer **peers;
66 static struct GNUNET_TESTBED_Operation *op[PEERS_REQUESTED];
67 static struct GNUNET_TESTBED_Operation *pi_op[PEERS_REQUESTED];
69 static struct GNUNET_MULTICAST_Origin *origin;
70 static struct GNUNET_MULTICAST_Member *members[PEERS_REQUESTED]; /* first element always empty */
72 static struct GNUNET_SCHEDULER_Task *timeout_tid;
74 static struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
75 static struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
76 static struct GNUNET_HashCode group_pub_key_hash;
79 * Global result for testcase.
84 * Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
88 shutdown_task (void *cls)
90 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
92 for (int i=0;i<PEERS_REQUESTED;i++)
96 GNUNET_TESTBED_operation_done(op[i]);
101 GNUNET_TESTBED_operation_done (pi_op[i]);
106 if (NULL != multicast_peers)
108 for (int i=0; i < PEERS_REQUESTED; i++)
110 GNUNET_free_non_null (multicast_peers[i]->key);
111 GNUNET_free (multicast_peers[i]);
112 multicast_peers[i] = NULL;
114 GNUNET_free (multicast_peers);
115 multicast_peers = NULL;
118 if (NULL != timeout_tid)
120 GNUNET_SCHEDULER_cancel (timeout_tid);
127 timeout_task (void *cls)
129 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
131 result = GNUNET_SYSERR;
132 GNUNET_SCHEDULER_shutdown ();
137 member_join_request (void *cls,
138 const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
139 const struct GNUNET_MessageHeader *join_msg,
140 struct GNUNET_MULTICAST_JoinHandle *jh)
142 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
143 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
144 "Peer #%u (%s) sent a join request.\n",
146 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
155 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
157 struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg);
158 pp_msg->peer = mc_peer->peer;
161 *data_size = sizeof (struct pingpong_msg);
162 GNUNET_memcpy(data, pp_msg, *data_size);
163 GNUNET_free (pp_msg);
165 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
166 "Peer #%u sents ping to origin\n", mc_peer->peer);
173 member_join_decision (void *cls,
175 const struct GNUNET_PeerIdentity *peer,
176 uint16_t relay_count,
177 const struct GNUNET_PeerIdentity *relays,
178 const struct GNUNET_MessageHeader *join_msg)
180 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
182 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
183 "Peer #%u (%s) received a decision from origin: %s\n",
185 GNUNET_i2s (multicast_peers[mc_peer->peer]->id),
186 (GNUNET_YES == is_admitted)?"accepted":"rejected");
188 if (GNUNET_YES == is_admitted)
190 GNUNET_MULTICAST_member_to_origin (members[mc_peer->peer],
200 member_replay_frag ()
202 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
203 "member replay frag...\n");
210 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
211 "member replay msg...\n");
216 origin_disconnected_cb (void *cls)
218 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
219 "Origin disconnected. Shutting down.\n");
221 GNUNET_SCHEDULER_shutdown ();
226 member_disconnected_cb (void *cls)
228 for (int i = 1; i < PEERS_REQUESTED; ++i)
229 if (GNUNET_NO == multicast_peers[i]->test_ok)
231 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
232 "All member disconnected. Stopping origin.\n");
233 GNUNET_MULTICAST_origin_stop (origin, origin_disconnected_cb, cls);
238 member_message (void *cls,
239 const struct GNUNET_MULTICAST_MessageHeader *msg)
241 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
242 struct pingpong_msg *pp_msg = (struct pingpong_msg*) &(msg[1]);
244 if (PONG == pp_msg->msg && mc_peer->peer == pp_msg->peer)
246 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
247 "peer #%i (%s) receives a pong\n",
249 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
250 mc_peer->test_ok = GNUNET_OK;
251 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
252 "peer #%u (%s) parting from multicast group\n",
254 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
256 GNUNET_MULTICAST_member_part (members[mc_peer->peer], member_disconnected_cb, cls);
262 origin_join_request (void *cls,
263 const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
264 const struct GNUNET_MessageHeader *join_msg,
265 struct GNUNET_MULTICAST_JoinHandle *jh)
267 struct GNUNET_MessageHeader *join_resp;
269 uint8_t data_size = ntohs (join_msg->size);
271 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
272 "origin got a join request...\n");
273 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
274 "origin receives: '%s'\n", (char *)&join_msg[1]);
276 char data[] = "Come in!";
277 data_size = strlen (data) + 1;
278 join_resp = GNUNET_malloc (sizeof (join_resp) + data_size);
279 join_resp->size = htons (sizeof (join_resp) + data_size);
280 join_resp->type = htons (123);
281 GNUNET_memcpy (&join_resp[1], data, data_size);
283 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
284 "origin sends: '%s'\n", data);
286 GNUNET_MULTICAST_join_decision (jh,
297 origin_replay_frag (void *cls,
298 const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
299 uint64_t fragment_id,
301 struct GNUNET_MULTICAST_ReplayHandle *rh)
303 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay fraq msg\n");
308 origin_replay_msg (void *cls,
309 const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
311 uint64_t fragment_offset,
313 struct GNUNET_MULTICAST_ReplayHandle *rh)
316 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay msg\n");
321 origin_notify (void *cls,
325 struct pingpong_msg *rcv_pp_msg = (struct pingpong_msg*)cls;
326 struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg);
328 pp_msg->peer = rcv_pp_msg->peer;
330 *data_size = sizeof (struct pingpong_msg);
331 GNUNET_memcpy(data, pp_msg, *data_size);
332 GNUNET_free (pp_msg);
334 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin sends pong\n");
341 origin_request (void *cls,
342 const struct GNUNET_MULTICAST_RequestHeader *req)
344 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin receives a msg\n");
347 struct pingpong_msg *pp_msg = (struct pingpong_msg *) req;
349 if (1 != pp_msg->msg) {
350 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "origin didn't reveice a correct request");
353 GNUNET_MULTICAST_origin_to_all (origin,
362 origin_message (void *cls,
363 const struct GNUNET_MULTICAST_MessageHeader *msg)
365 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin message msg\n");
370 multicast_disconnect (void *cls,
378 multicast_connect (void *cls,
379 const struct GNUNET_CONFIGURATION_Handle *cfg)
381 struct MulticastPeerContext *multicast_peer = cls;
382 struct GNUNET_MessageHeader *join_msg;
385 if (0 == multicast_peer->peer)
387 group_key = GNUNET_CRYPTO_eddsa_key_create ();
388 GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key);
390 GNUNET_CRYPTO_hash (&group_pub_key, sizeof (group_pub_key), &group_pub_key_hash);
391 origin = GNUNET_MULTICAST_origin_start (cfg,
402 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
403 "Peer #%u could not create a multicast group",
404 multicast_peer->peer);
407 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
408 "Peer #%u connected as origin to group %s\n",
409 multicast_peer->peer,
410 GNUNET_h2s (&group_pub_key_hash));
415 multicast_peer->key = GNUNET_CRYPTO_ecdsa_key_create ();
417 sprintf(data, "Hi, I am peer #%u (%s). Can I enter?",
418 multicast_peer->peer,
419 GNUNET_i2s (multicast_peers[multicast_peer->peer]->id));
420 uint8_t data_size = strlen (data) + 1;
421 join_msg = GNUNET_malloc (sizeof (join_msg) + data_size);
422 join_msg->size = htons (sizeof (join_msg) + data_size);
423 join_msg->type = htons (123);
424 GNUNET_memcpy (&join_msg[1], data, data_size);
426 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
427 "Peer #%u (%s) tries to join multicast group %s\n",
428 multicast_peer->peer,
429 GNUNET_i2s (multicast_peers[multicast_peer->peer]->id),
430 GNUNET_h2s (&group_pub_key_hash));
432 members[multicast_peer->peer] =
433 GNUNET_MULTICAST_member_join (cfg,
436 multicast_peers[0]->id,
439 join_msg, /* join message */
441 member_join_decision,
446 return members[multicast_peer->peer];
452 peer_information_cb (void *cls,
453 struct GNUNET_TESTBED_Operation *operation,
454 const struct GNUNET_TESTBED_PeerInformation *pinfo,
457 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
460 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got no peer information\n");
461 result = GNUNET_SYSERR;
462 GNUNET_SCHEDULER_shutdown ();
465 multicast_peers[mc_peer->peer]->id = pinfo->result.id;
467 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
468 "Got peer information of %s (%s)\n",
469 (0 == mc_peer->peer)? "origin" : "member",
470 GNUNET_i2s (pinfo->result.id));
472 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
473 "Create peer #%u (%s)\n",
475 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
477 if (0 != mc_peer->peer)
479 /* connect to multicast service of members */
481 GNUNET_TESTBED_service_connect (/* Closure for operation */
483 /* The peer whose service to connect to */
484 peers[mc_peer->peer],
485 /* The name of the service */
487 /* called after a handle to service is opened */
489 /* closure for the above callback */
491 /* called when opening the service connection */
493 /* called when closing the service connection */
494 multicast_disconnect,
495 /* closure for the above two callbacks */
502 service_connect (void *cls,
503 struct GNUNET_TESTBED_Operation *op,
507 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
509 if (NULL == ca_result)
511 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
512 "Connection adapter not created for peer #%u (%s)\n",
514 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
516 result = GNUNET_SYSERR;
517 GNUNET_SCHEDULER_shutdown();
520 if (0 == mc_peer->peer)
522 // Get GNUnet identity of members
523 for (int i = 0; i<PEERS_REQUESTED; i++)
525 pi_op[i] = GNUNET_TESTBED_peer_get_information (peers[i],
526 GNUNET_TESTBED_PIT_IDENTITY,
536 * Main function inovked from TESTBED once all of the
537 * peers are up and running. This one then connects
538 * just to the multicast service of peer 0 and 1.
539 * Peer 0 is going to be origin.
540 * Peer 1 is going to be one member.
541 * Origin will start a multicast group and the member will try to join it.
542 * After that we execute some multicast test.
545 * @param h the run handle
546 * @param peers started peers for the test
547 * @param PEERS_REQUESTED size of the 'peers' array
548 * @param links_succeeded number of links between peers that were created
549 * @param links_failed number of links testbed was unable to establish
552 testbed_master (void *cls,
553 struct GNUNET_TESTBED_RunHandle *h,
554 unsigned int num_peers,
555 struct GNUNET_TESTBED_Peer **p,
556 unsigned int links_succeeded,
557 unsigned int links_failed)
559 /* Testbed is ready with peers running and connected in a pre-defined overlay
562 multicast_peers = GNUNET_new_array (PEERS_REQUESTED, struct MulticastPeerContext*);
564 // Create test contexts for members
565 for (int i = 0; i<PEERS_REQUESTED; i++)
567 multicast_peers[i] = GNUNET_new (struct MulticastPeerContext);
568 multicast_peers[i]->peer = i;
569 multicast_peers[i]->test_ok = GNUNET_NO;
571 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
572 "Create origin peer\n");
574 GNUNET_TESTBED_service_connect (/* Closure for operation */
576 /* The peer whose service to connect to */
578 /* The name of the service */
580 /* called after a handle to service is opened */
582 /* closure for the above callback */
584 /* called when opening the service connection */
586 /* called when closing the service connection */
587 multicast_disconnect,
588 /* closure for the above two callbacks */
590 /* Schedule a new task on shutdown */
591 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
592 /* Schedule the shutdown task with a delay of a few Seconds */
594 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
595 (GNUNET_TIME_UNIT_SECONDS, 400),
602 main (int argc, char *argv[])
605 char const *config_file;
607 if (strstr (argv[0], "_line") != NULL)
609 config_file = "test_multicast_line.conf";
611 else if (strstr(argv[0], "_star") != NULL)
613 config_file = "test_multicast_star.conf";
617 config_file = "test_multicast_star.conf";
620 result = GNUNET_SYSERR;
622 GNUNET_TESTBED_test_run ("test-multicast-multipeer",
624 /* number of peers to start */
626 /* Event mask - set to 0 for no event notifications */
628 /* Controller event callback */
630 /* Closure for controller event callback */
632 /* called when testbed setup is complete */
634 /* Closure for the test_master callback */
636 if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
641 /* end of test_multicast_multipeer.c */