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