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.
17 * @file multicast/test_multicast_multipeers.c
18 * @brief Tests for the Multicast API with multiple peers.
25 #include "gnunet_crypto_lib.h"
26 #include "gnunet_common.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_testbed_service.h"
29 #include "gnunet_multicast_service.h"
31 #define PEERS_REQUESTED 12
33 struct MulticastPeerContext
35 int peer; /* peer number */
36 struct GNUNET_CRYPTO_EcdsaPrivateKey *key;
37 const struct GNUNET_PeerIdentity *id;
38 struct GNUNET_TESTBED_Operation *op; /* not yet in use */
39 struct GNUNET_TESTBED_Operation *pi_op; /* not yet in use */
55 static void service_connect (void *cls,
56 struct GNUNET_TESTBED_Operation *op,
60 static struct MulticastPeerContext **multicast_peers;
61 static struct GNUNET_TESTBED_Peer **peers;
63 static struct GNUNET_TESTBED_Operation *op[PEERS_REQUESTED];
64 static struct GNUNET_TESTBED_Operation *pi_op[PEERS_REQUESTED];
66 static struct GNUNET_MULTICAST_Origin *origin;
67 static struct GNUNET_MULTICAST_Member *members[PEERS_REQUESTED]; /* first element always empty */
69 static struct GNUNET_SCHEDULER_Task *timeout_tid;
71 static struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
72 static struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
73 static struct GNUNET_HashCode group_pub_key_hash;
76 * Global result for testcase.
81 * Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
85 shutdown_task (void *cls)
87 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
89 for (int i=0;i<PEERS_REQUESTED;i++)
93 GNUNET_TESTBED_operation_done(op[i]);
98 GNUNET_TESTBED_operation_done (pi_op[i]);
103 if (NULL != multicast_peers)
105 for (int i=0; i < PEERS_REQUESTED; i++)
107 GNUNET_free_non_null (multicast_peers[i]->key);
108 GNUNET_free (multicast_peers[i]);
109 multicast_peers[i] = NULL;
111 GNUNET_free (multicast_peers);
112 multicast_peers = NULL;
115 if (NULL != timeout_tid)
117 GNUNET_SCHEDULER_cancel (timeout_tid);
124 timeout_task (void *cls)
126 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
128 result = GNUNET_SYSERR;
129 GNUNET_SCHEDULER_shutdown ();
134 member_join_request (void *cls,
135 const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
136 const struct GNUNET_MessageHeader *join_msg,
137 struct GNUNET_MULTICAST_JoinHandle *jh)
139 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
140 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
141 "Peer #%u (%s) sent a join request.\n",
143 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
152 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
154 struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg);
155 pp_msg->peer = mc_peer->peer;
158 *data_size = sizeof (struct pingpong_msg);
159 GNUNET_memcpy(data, pp_msg, *data_size);
161 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
162 "Peer #%u sents ping to origin\n", mc_peer->peer);
169 member_join_decision (void *cls,
171 const struct GNUNET_PeerIdentity *peer,
172 uint16_t relay_count,
173 const struct GNUNET_PeerIdentity *relays,
174 const struct GNUNET_MessageHeader *join_msg)
176 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
178 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
179 "Peer #%u (%s) received a decision from origin: %s\n",
181 GNUNET_i2s (multicast_peers[mc_peer->peer]->id),
182 (GNUNET_YES == is_admitted)?"accepted":"rejected");
184 if (GNUNET_YES == is_admitted)
186 GNUNET_MULTICAST_member_to_origin (members[mc_peer->peer],
196 member_replay_frag ()
198 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
199 "member replay frag...\n");
206 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
207 "member replay msg...\n");
212 origin_disconnected_cb (void *cls)
214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
215 "Origin disconnected. Shutting down.\n");
217 GNUNET_SCHEDULER_shutdown ();
222 member_disconnected_cb (void *cls)
224 for (int i = 1; i < PEERS_REQUESTED; ++i)
225 if (GNUNET_NO == multicast_peers[i]->test_ok)
227 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
228 "All member disconnected. Stopping origin.\n");
229 GNUNET_MULTICAST_origin_stop (origin, origin_disconnected_cb, cls);
234 member_message (void *cls,
235 const struct GNUNET_MULTICAST_MessageHeader *msg)
237 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
238 struct pingpong_msg *pp_msg = (struct pingpong_msg*) &(msg[1]);
240 if (PONG == pp_msg->msg && mc_peer->peer == pp_msg->peer)
242 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
243 "peer #%i (%s) receives a pong\n",
245 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
246 mc_peer->test_ok = GNUNET_OK;
247 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
248 "peer #%u (%s) parting from multicast group\n",
250 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
252 GNUNET_MULTICAST_member_part (members[mc_peer->peer], member_disconnected_cb, cls);
258 origin_join_request (void *cls,
259 const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
260 const struct GNUNET_MessageHeader *join_msg,
261 struct GNUNET_MULTICAST_JoinHandle *jh)
263 struct GNUNET_MessageHeader *join_resp;
265 uint8_t data_size = ntohs (join_msg->size);
267 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
268 "origin got a join request...\n");
269 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
270 "origin receives: '%s'\n", (char *)&join_msg[1]);
272 char data[] = "Come in!";
273 data_size = strlen (data) + 1;
274 join_resp = GNUNET_malloc (sizeof (join_resp) + data_size);
275 join_resp->size = htons (sizeof (join_resp) + data_size);
276 join_resp->type = htons (123);
277 GNUNET_memcpy (&join_resp[1], data, data_size);
279 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
280 "origin sends: '%s'\n", data);
282 GNUNET_MULTICAST_join_decision (jh,
293 origin_replay_frag (void *cls,
294 const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
295 uint64_t fragment_id,
297 struct GNUNET_MULTICAST_ReplayHandle *rh)
299 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay fraq msg\n");
304 origin_replay_msg (void *cls,
305 const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
307 uint64_t fragment_offset,
309 struct GNUNET_MULTICAST_ReplayHandle *rh)
312 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay msg\n");
317 origin_notify (void *cls,
321 struct pingpong_msg *rcv_pp_msg = (struct pingpong_msg*)cls;
322 struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg);
324 pp_msg->peer = rcv_pp_msg->peer;
326 *data_size = sizeof (struct pingpong_msg);
327 GNUNET_memcpy(data, pp_msg, *data_size);
329 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin sends pong\n");
336 origin_request (void *cls,
337 const struct GNUNET_MULTICAST_RequestHeader *req)
339 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin receives a msg\n");
342 struct pingpong_msg *pp_msg = (struct pingpong_msg *) req;
344 if (1 != pp_msg->msg) {
345 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "origin didn't reveice a correct request");
348 GNUNET_MULTICAST_origin_to_all (origin,
357 origin_message (void *cls,
358 const struct GNUNET_MULTICAST_MessageHeader *msg)
360 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin message msg\n");
365 multicast_disconnect (void *cls,
373 multicast_connect (void *cls,
374 const struct GNUNET_CONFIGURATION_Handle *cfg)
376 struct MulticastPeerContext *multicast_peer = cls;
377 struct GNUNET_MessageHeader *join_msg;
380 if (0 == multicast_peer->peer)
382 group_key = GNUNET_CRYPTO_eddsa_key_create ();
383 GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key);
385 GNUNET_CRYPTO_hash (&group_pub_key, sizeof (group_pub_key), &group_pub_key_hash);
386 origin = GNUNET_MULTICAST_origin_start (cfg,
397 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
398 "Peer #%u could not create a multicast group",
399 multicast_peer->peer);
402 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
403 "Peer #%u connected as origin to group %s\n",
404 multicast_peer->peer,
405 GNUNET_h2s (&group_pub_key_hash));
410 multicast_peer->key = GNUNET_CRYPTO_ecdsa_key_create ();
412 sprintf(data, "Hi, I am peer #%u (%s). Can I enter?",
413 multicast_peer->peer,
414 GNUNET_i2s (multicast_peers[multicast_peer->peer]->id));
415 uint8_t data_size = strlen (data) + 1;
416 join_msg = GNUNET_malloc (sizeof (join_msg) + data_size);
417 join_msg->size = htons (sizeof (join_msg) + data_size);
418 join_msg->type = htons (123);
419 GNUNET_memcpy (&join_msg[1], data, data_size);
421 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
422 "Peer #%u (%s) tries to join multicast group %s\n",
423 multicast_peer->peer,
424 GNUNET_i2s (multicast_peers[multicast_peer->peer]->id),
425 GNUNET_h2s (&group_pub_key_hash));
427 members[multicast_peer->peer] =
428 GNUNET_MULTICAST_member_join (cfg,
431 multicast_peers[0]->id,
434 join_msg, /* join message */
436 member_join_decision,
441 return members[multicast_peer->peer];
447 peer_information_cb (void *cls,
448 struct GNUNET_TESTBED_Operation *operation,
449 const struct GNUNET_TESTBED_PeerInformation *pinfo,
452 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
455 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got no peer information\n");
456 result = GNUNET_SYSERR;
457 GNUNET_SCHEDULER_shutdown ();
460 multicast_peers[mc_peer->peer]->id = pinfo->result.id;
462 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
463 "Got peer information of %s (%s)\n",
464 (0 == mc_peer->peer)? "origin" : "member",
465 GNUNET_i2s (pinfo->result.id));
467 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
468 "Create peer #%u (%s)\n",
470 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
472 if (0 != mc_peer->peer)
474 /* connect to multicast service of members */
476 GNUNET_TESTBED_service_connect (/* Closure for operation */
478 /* The peer whose service to connect to */
479 peers[mc_peer->peer],
480 /* The name of the service */
482 /* called after a handle to service is opened */
484 /* closure for the above callback */
486 /* called when opening the service connection */
488 /* called when closing the service connection */
489 multicast_disconnect,
490 /* closure for the above two callbacks */
497 service_connect (void *cls,
498 struct GNUNET_TESTBED_Operation *op,
502 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
504 if (NULL == ca_result)
506 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
507 "Connection adapter not created for peer #%u (%s)\n",
509 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
511 result = GNUNET_SYSERR;
512 GNUNET_SCHEDULER_shutdown();
515 if (0 == mc_peer->peer)
517 // Get GNUnet identity of members
518 for (int i = 0; i<PEERS_REQUESTED; i++)
520 pi_op[i] = GNUNET_TESTBED_peer_get_information (peers[i],
521 GNUNET_TESTBED_PIT_IDENTITY,
531 * Main function inovked from TESTBED once all of the
532 * peers are up and running. This one then connects
533 * just to the multicast service of peer 0 and 1.
534 * Peer 0 is going to be origin.
535 * Peer 1 is going to be one member.
536 * Origin will start a multicast group and the member will try to join it.
537 * After that we execute some multicast test.
540 * @param h the run handle
541 * @param peers started peers for the test
542 * @param PEERS_REQUESTED size of the 'peers' array
543 * @param links_succeeded number of links between peers that were created
544 * @param links_failed number of links testbed was unable to establish
547 testbed_master (void *cls,
548 struct GNUNET_TESTBED_RunHandle *h,
549 unsigned int num_peers,
550 struct GNUNET_TESTBED_Peer **p,
551 unsigned int links_succeeded,
552 unsigned int links_failed)
554 /* Testbed is ready with peers running and connected in a pre-defined overlay
557 multicast_peers = GNUNET_new_array (PEERS_REQUESTED, struct MulticastPeerContext*);
559 // Create test contexts for members
560 for (int i = 0; i<PEERS_REQUESTED; i++)
562 multicast_peers[i] = GNUNET_new (struct MulticastPeerContext);
563 multicast_peers[i]->peer = i;
564 multicast_peers[i]->test_ok = GNUNET_NO;
566 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
567 "Create origin peer\n");
569 GNUNET_TESTBED_service_connect (/* Closure for operation */
571 /* The peer whose service to connect to */
573 /* The name of the service */
575 /* called after a handle to service is opened */
577 /* closure for the above callback */
579 /* called when opening the service connection */
581 /* called when closing the service connection */
582 multicast_disconnect,
583 /* closure for the above two callbacks */
585 /* Schedule a new task on shutdown */
586 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
587 /* Schedule the shutdown task with a delay of a few Seconds */
589 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
590 (GNUNET_TIME_UNIT_SECONDS, 400),
597 main (int argc, char *argv[])
600 char const *config_file;
602 if (strstr (argv[0], "_line") != NULL)
604 config_file = "test_multicast_line.conf";
606 else if (strstr(argv[0], "_star") != NULL)
608 config_file = "test_multicast_star.conf";
612 config_file = "test_multicast_star.conf";
615 result = GNUNET_SYSERR;
617 GNUNET_TESTBED_test_run ("test-multicast-multipeer",
619 /* number of peers to start */
621 /* Event mask - set to 0 for no event notifications */
623 /* Controller event callback */
625 /* Closure for controller event callback */
627 /* called when testbed setup is complete */
629 /* Closure for the test_master callback */
631 if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
636 /* end of test_multicast_multipeer.c */