Merge branch 'master' of gnunet.org:gnunet
[oweals/gnunet.git] / src / multicast / test_multicast.c
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
19 /**
20  * @file multicast/test_multicast.c
21  * @brief Tests for the Multicast API.
22  * @author Gabor X Toth
23  */
24
25 #include <inttypes.h>
26
27 #include "platform.h"
28 #include "gnunet_crypto_lib.h"
29 #include "gnunet_common.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_testing_lib.h"
32 #include "gnunet_multicast_service.h"
33
34 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
35
36 /**
37  * Return value from 'main'.
38  */
39 static int res;
40
41 /**
42  * Handle for task for timeout termination.
43  */
44 static struct GNUNET_SCHEDULER_Task * end_badly_task;
45
46 static const struct GNUNET_CONFIGURATION_Handle *cfg;
47
48 struct GNUNET_PeerIdentity this_peer;
49
50 struct GNUNET_MULTICAST_Origin *origin;
51 struct GNUNET_MULTICAST_Member *member;
52
53 struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
54 struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
55
56 struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key;
57 struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
58
59 struct TransmitClosure {
60   struct GNUNET_MULTICAST_OriginTransmitHandle *orig_tmit;
61   struct GNUNET_MULTICAST_MemberTransmitHandle *mem_tmit;
62   char * data[16];
63   uint8_t data_delay[16];
64   uint8_t data_count;
65   uint8_t paused;
66   uint8_t n;
67 } tmit_cls;
68
69 struct OriginClosure {
70   uint8_t msgs_expected;
71   uint8_t n;
72 } origin_cls;
73
74 struct MemberClosure {
75   uint8_t msgs_expected;
76   size_t n;
77 } member_cls;
78
79 struct GNUNET_MessageHeader *join_req, *join_resp;
80
81 enum
82 {
83   TEST_NONE                = 0,
84   TEST_ORIGIN_START        = 1,
85   TEST_MEMBER_JOIN_REFUSE  = 2,
86   TEST_MEMBER_JOIN_ADMIT   = 3,
87   TEST_ORIGIN_TO_ALL       = 4,
88   TEST_ORIGIN_TO_ALL_RECV  = 5,
89   TEST_MEMBER_TO_ORIGIN    = 6,
90   TEST_MEMBER_REPLAY_ERROR = 7,
91   TEST_MEMBER_REPLAY_OK    = 8,
92   TEST_MEMBER_PART         = 9,
93   TEST_ORIGIN_STOP        = 10,
94 } test;
95
96 uint64_t replay_fragment_id;
97 uint64_t replay_flags;
98
99 static void
100 member_join (int t);
101
102
103 /**
104  * Clean up all resources used.
105  */
106 static void
107 cleanup ()
108 {
109   if (NULL != member)
110   {
111     GNUNET_MULTICAST_member_part (member, NULL, NULL);
112     member = NULL;
113   }
114   if (NULL != origin)
115   {
116     GNUNET_MULTICAST_origin_stop (origin, NULL, NULL);
117     origin = NULL;
118   }
119 }
120
121
122 /**
123  * Terminate the test case (failure).
124  *
125  * @param cls NULL
126  */
127 static void
128 end_badly (void *cls)
129 {
130   res = 1;
131   cleanup ();
132   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test FAILED.\n");
133 }
134
135
136 /**
137  * Terminate the test case (success).
138  *
139  * @param cls NULL
140  */
141 static void
142 end_normally (void *cls)
143 {
144   res = 0;
145   cleanup ();
146   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test PASSED.\n");
147 }
148
149
150 /**
151  * Finish the test case (successfully).
152  */
153 static void
154 end ()
155 {
156   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending tests.\n");
157
158   if (end_badly_task != NULL)
159   {
160     GNUNET_SCHEDULER_cancel (end_badly_task);
161     end_badly_task = NULL;
162   }
163   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
164                                 &end_normally, NULL);
165 }
166
167
168 static void
169 tmit_resume (void *cls)
170 {
171   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission resumed.\n");
172   struct TransmitClosure *tmit = cls;
173   if (NULL != tmit->orig_tmit)
174     GNUNET_MULTICAST_origin_to_all_resume (tmit->orig_tmit);
175   else if (NULL != tmit->mem_tmit)
176     GNUNET_MULTICAST_member_to_origin_resume (tmit->mem_tmit);
177 }
178
179
180 static int
181 tmit_notify (void *cls, size_t *data_size, void *data)
182 {
183   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
184               "Test #%u: origin_tmit_notify()\n", test);
185   struct TransmitClosure *tmit = cls;
186
187   if (0 == tmit->data_count)
188   {
189     *data_size = 0;
190     return GNUNET_YES;
191   }
192
193   uint16_t size = strlen (tmit->data[tmit->n]);
194   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
195               "Transmit notify data: %u bytes available, processing fragment %u/%u (size %u).\n",
196               (unsigned int) *data_size,
197               tmit->n + 1,
198               tmit->data_count,
199               size);
200   if (*data_size < size)
201   {
202     *data_size = 0;
203     GNUNET_assert (0);
204     return GNUNET_SYSERR;
205   }
206
207   if (GNUNET_YES != tmit->paused && 0 < tmit->data_delay[tmit->n])
208   {
209     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission paused.\n");
210     tmit->paused = GNUNET_YES;
211     GNUNET_SCHEDULER_add_delayed (
212       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
213                                      tmit->data_delay[tmit->n]),
214       tmit_resume, tmit);
215     *data_size = 0;
216     return GNUNET_NO;
217   }
218   tmit->paused = GNUNET_NO;
219
220   *data_size = size;
221   GNUNET_memcpy (data, tmit->data[tmit->n], size);
222
223   return ++tmit->n < tmit->data_count ? GNUNET_NO : GNUNET_YES;
224 }
225
226
227 static void
228 member_recv_join_request (void *cls,
229                           const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
230                           const struct GNUNET_MessageHeader *join_msg,
231                           struct GNUNET_MULTICAST_JoinHandle *jh)
232 {
233   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
234               "Test #%u: member_recv_join_request()\n", test);
235 }
236
237
238 static void
239 origin_stopped (void *cls)
240 {
241   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
242               "Test #%u: origin_stopped()\n", test);
243   end ();
244 }
245
246
247 static void
248 schedule_origin_stop (void *cls)
249 {
250   test = TEST_ORIGIN_STOP;
251   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
252               "Test #%u: origin_stop()\n", test);
253   GNUNET_MULTICAST_origin_stop (origin, origin_stopped, NULL);
254   origin = NULL;
255 }
256
257
258 static void
259 member_parted (void *cls)
260 {
261   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
262               "Test #%u: member_parted()\n", test);
263   member = NULL;
264
265   switch (test)
266   {
267   case TEST_MEMBER_JOIN_REFUSE:
268     // Test 3 starts here
269     member_join (TEST_MEMBER_JOIN_ADMIT);
270     break;
271
272   case TEST_MEMBER_PART:
273     GNUNET_SCHEDULER_add_now (&schedule_origin_stop, NULL);
274     break;
275
276   default:
277     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
278                 "Invalid test #%d in member_parted()\n", test);
279     GNUNET_assert (0);
280   }
281 }
282
283
284 static void
285 schedule_member_part (void *cls)
286 {
287   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
288               "Test #%u: schedule_member_part()\n", test);
289   GNUNET_MULTICAST_member_part (member, member_parted, NULL);
290 }
291
292
293 static void
294 member_part ()
295 {
296   test = TEST_MEMBER_PART;
297   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
298               "Test #%u: member_part()\n", test);
299   // Test 10 starts here
300   GNUNET_SCHEDULER_add_now (&schedule_member_part, NULL);
301 }
302
303
304 static void
305 member_replay_ok ()
306 {
307   // Execution of test 8 here
308   test = TEST_MEMBER_REPLAY_OK;
309   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
310               "Test #%u: member_replay_ok()\n", test);
311   replay_fragment_id = 1;
312   replay_flags = 1 | 1<<11;
313   GNUNET_MULTICAST_member_replay_fragment (member, replay_fragment_id,
314                                            replay_flags);
315 }
316
317
318 static void
319 member_replay_error ()
320 {
321   test = TEST_MEMBER_REPLAY_ERROR;
322   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
323               "Test #%u: member_replay_error()\n", test);
324   replay_fragment_id = 1234;
325   replay_flags = 11 | 1<<11;
326   GNUNET_MULTICAST_member_replay_fragment (member, replay_fragment_id,
327                                            replay_flags);
328 }
329
330
331 static void
332 origin_recv_replay_msg (void *cls,
333                         const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
334                         uint64_t message_id,
335                         uint64_t fragment_offset,
336                         uint64_t flags,
337                         struct GNUNET_MULTICAST_ReplayHandle *rh)
338 {
339   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
340               "Test #%u: origin_recv_replay_msg()\n", test);
341   GNUNET_assert (0);
342 }
343
344
345 static void
346 member_recv_replay_msg (void *cls,
347                         const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
348                         uint64_t message_id,
349                         uint64_t fragment_offset,
350                         uint64_t flags,
351                         struct GNUNET_MULTICAST_ReplayHandle *rh)
352 {
353   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
354               "Test #%u: member_recv_replay_msg()\n", test);
355   GNUNET_assert (0);
356 }
357
358
359 static void
360 origin_recv_replay_frag (void *cls,
361                          const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
362                          uint64_t fragment_id,
363                          uint64_t flags,
364                          struct GNUNET_MULTICAST_ReplayHandle *rh)
365 {
366   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
367               "Test #%u: origin_recv_replay_frag()"
368               " - fragment_id=%" PRIu64 " flags=%" PRIu64 "\n",
369               test, fragment_id, flags);
370   GNUNET_assert (replay_fragment_id == fragment_id && replay_flags == flags);
371   switch (test)
372   {
373   case TEST_MEMBER_REPLAY_ERROR:
374     // Test 8 starts here
375     GNUNET_MULTICAST_replay_response (rh, NULL, GNUNET_SYSERR);
376     member_replay_ok ();
377     break;
378
379   case TEST_MEMBER_REPLAY_OK:
380   {
381     struct GNUNET_MULTICAST_MessageHeader mmsg = {
382       .header = {
383         .type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE),
384         .size = htons (sizeof (mmsg)),
385       },
386       .fragment_id = GNUNET_htonll (1),
387       .message_id = GNUNET_htonll (1),
388       .fragment_offset = 0,
389       .group_generation = GNUNET_htonll (1),
390       .flags = 0,
391     };
392     member_cls.n = 0;
393     member_cls.msgs_expected = 1;
394     GNUNET_MULTICAST_replay_response (rh, &mmsg.header, GNUNET_MULTICAST_REC_OK);
395     GNUNET_MULTICAST_replay_response_end (rh);
396     break;
397   }
398
399   default:
400     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
401                 "Invalid test #%d in origin_recv_replay_frag()\n", test);
402     GNUNET_assert (0);
403   }
404 }
405
406
407 static void
408 member_recv_replay_frag (void *cls,
409                          const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
410                          uint64_t fragment_id,
411                          uint64_t flags,
412                          struct GNUNET_MULTICAST_ReplayHandle *rh)
413 {
414   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
415               "Test #%u: member_recv_replay_frag()\n", test);
416   GNUNET_assert (0);
417 }
418
419
420 static void
421 origin_recv_request (void *cls,
422                      const struct GNUNET_MULTICAST_RequestHeader *req)
423 {
424   struct OriginClosure *ocls = cls;
425   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
426               "Test #%u: origin_recv_request()\n", test);
427   if (++ocls->n != ocls->msgs_expected)
428     return;
429
430   GNUNET_assert (0 == memcmp (&req->member_pub_key,
431                               &member_pub_key, sizeof (member_pub_key)));
432
433   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
434               "Test #%u: verify message content, take first 3 bytes: %.3s\n",
435               test, (char *)&req[1]);
436   GNUNET_assert (0 == memcmp (&req[1], "abc", 3));
437
438   // Test 7 starts here
439   member_replay_error ();
440 }
441
442
443 static void
444 member_to_origin ()
445 {
446   test = TEST_MEMBER_TO_ORIGIN;
447   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
448               "Test #%u: member_to_origin()\n", test);
449
450   struct TransmitClosure *tmit = &tmit_cls;
451   *tmit = (struct TransmitClosure) {};
452   tmit->data[0] = "abc def";
453   tmit->data[1] = "ghi jkl mno";
454   tmit->data_delay[1] = 2;
455   tmit->data[2] = "pqr stuw xyz";
456   tmit->data_count = 3;
457
458   origin_cls.n = 0;
459   origin_cls.msgs_expected = 1;
460
461   tmit->mem_tmit = GNUNET_MULTICAST_member_to_origin (member, 1,
462                                                       tmit_notify, tmit);
463 }
464
465
466 static void
467 member_recv_message (void *cls,
468                      const struct GNUNET_MULTICAST_MessageHeader *msg)
469 {
470   struct MemberClosure *mcls = cls;
471
472   // Test 5 starts here after message has been received from origin
473   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
474               "Test #%u: member_recv_message() %u/%u\n",
475               test,
476               (unsigned int) (mcls->n + 1),
477               mcls->msgs_expected);
478   if (++mcls->n != mcls->msgs_expected)
479     return;
480
481   // FIXME: check message content
482
483   switch (test)
484   {
485   case TEST_ORIGIN_TO_ALL:
486     test = TEST_ORIGIN_TO_ALL_RECV;
487     break;
488
489   case TEST_ORIGIN_TO_ALL_RECV:
490     // Test 6 starts here
491     member_to_origin ();
492     break;
493
494   case TEST_MEMBER_REPLAY_OK:
495     // Test 9 starts here
496     GNUNET_assert (replay_fragment_id == GNUNET_ntohll (msg->fragment_id));
497     member_part ();
498     break;
499
500   default:
501     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
502                 "Invalid test #%d in origin_recv_message()\n", test);
503     GNUNET_assert (0);
504   }
505 }
506
507
508 static void
509 origin_recv_message (void *cls,
510                      const struct GNUNET_MULTICAST_MessageHeader *msg)
511 {
512   struct OriginClosure *ocls = cls;
513   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
514               "Test #%u: origin_recv_message() %u/%u\n",
515               test, ocls->n + 1, ocls->msgs_expected);
516   if (++ocls->n != ocls->msgs_expected)
517     return;
518
519   // FIXME: check message content
520
521   switch (test)
522   {
523   case TEST_ORIGIN_TO_ALL:
524     // Prepare to execute test 5
525     test = TEST_ORIGIN_TO_ALL_RECV;
526     break;
527
528   case TEST_ORIGIN_TO_ALL_RECV:
529     // Test 6 starts here
530     member_to_origin ();
531     break;
532
533   default:
534     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
535                 "Invalid test #%d in origin_recv_message()\n", test);
536     GNUNET_assert (0);
537   }
538 }
539
540
541 static void
542 origin_to_all ()
543 {
544   test = TEST_ORIGIN_TO_ALL;
545   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
546               "Test #%u: origin_to_all()\n", test);
547
548   struct TransmitClosure *tmit = &tmit_cls;
549   *tmit = (struct TransmitClosure) {};
550   tmit->data[0] = "ABC DEF";
551   tmit->data[1] =  GNUNET_malloc (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD + 1);
552   uint16_t i;
553   for (i = 0; i < GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD; i++)
554     tmit->data[1][i] = (0 == i % 10000) ? '0' + i / 10000 : '_';
555   tmit->data[2] = "GHI JKL MNO";
556   tmit->data_delay[2] = 2;
557   tmit->data[3] = "PQR STUW XYZ";
558   tmit->data_count = 4;
559
560   origin_cls.n = member_cls.n = 0;
561   origin_cls.msgs_expected = member_cls.msgs_expected = tmit->data_count;
562
563   tmit->orig_tmit = GNUNET_MULTICAST_origin_to_all (origin, 1, 1,
564                                                     tmit_notify, tmit);
565 }
566
567
568 static void
569 member_recv_join_decision (void *cls,
570                            int is_admitted,
571                            const struct GNUNET_PeerIdentity *peer,
572                            uint16_t relay_count,
573                            const struct GNUNET_PeerIdentity *relays,
574                            const struct GNUNET_MessageHeader *join_msg)
575 {
576   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
577               "Test #%u: member_recv_join_decision() - is_admitted: %d\n",
578               test, is_admitted);
579
580   GNUNET_assert (join_msg->size == join_resp->size);
581   GNUNET_assert (join_msg->type == join_resp->type);
582   GNUNET_assert (0 == memcmp (join_msg, join_resp, ntohs (join_resp->size)));
583
584   switch (test)
585   {
586   case TEST_MEMBER_JOIN_REFUSE:
587     GNUNET_assert (0 == relay_count);
588     // Test 3 starts here
589     GNUNET_SCHEDULER_add_now (&schedule_member_part, NULL);
590     break;
591
592   case TEST_MEMBER_JOIN_ADMIT:
593     GNUNET_assert (1 == relay_count);
594     GNUNET_assert (0 == memcmp (relays, &this_peer, sizeof (this_peer)));
595     // Test 4 starts here
596     origin_to_all ();
597     break;
598
599   default:
600     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
601                 "Invalid test #%d in member_recv_join_decision()\n", test);
602     GNUNET_assert (0);
603   }
604 }
605
606 /**
607  * Test: origin receives join request
608  */
609 static void
610 origin_recv_join_request (void *cls,
611                           const struct GNUNET_CRYPTO_EcdsaPublicKey *mem_key,
612                           const struct GNUNET_MessageHeader *join_msg,
613                           struct GNUNET_MULTICAST_JoinHandle *jh)
614 {
615   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
616               "Test #%u: origin_recv_join_request()\n", test);
617
618   GNUNET_assert (0 == memcmp (mem_key, &member_pub_key, sizeof (member_pub_key)));
619   GNUNET_assert (join_msg->size == join_req->size);
620   GNUNET_assert (join_msg->type == join_req->type);
621   GNUNET_assert (0 == memcmp (join_msg, join_req, ntohs (join_req->size)));
622
623   char data[] = "here's the decision";
624   uint8_t data_size = strlen (data) + 1;
625   join_resp = GNUNET_malloc (sizeof (join_resp) + data_size);
626   join_resp->size = htons (sizeof (join_resp) + data_size);
627   join_resp->type = htons (456);
628   GNUNET_memcpy (&join_resp[1], data, data_size);
629
630   switch (test)
631   {
632   case TEST_MEMBER_JOIN_REFUSE:
633     // Test 3 starts here
634     GNUNET_MULTICAST_join_decision (jh, GNUNET_NO, 0, NULL, join_resp);
635     break;
636
637   case TEST_MEMBER_JOIN_ADMIT:
638     // Test 3 is running
639     GNUNET_MULTICAST_join_decision (jh, GNUNET_YES, 1, &this_peer, join_resp);
640     break;
641
642   default:
643     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
644                 "Invalid test #%d in origin_recv_join_request()\n", test);
645     GNUNET_assert (0);
646     break;
647   }
648 }
649
650 /**
651  * Test: member joins multicast group
652  */
653 static void
654 member_join (int t)
655 {
656   test = t;
657   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
658               "Test #%u: member_join()\n", test);
659
660   member_key = GNUNET_CRYPTO_ecdsa_key_create ();
661   GNUNET_CRYPTO_ecdsa_key_get_public (member_key, &member_pub_key);
662
663   if (NULL != join_req)
664     GNUNET_free (join_req);
665
666   char data[] = "let me in!";
667   uint8_t data_size = strlen (data) + 1;
668   join_req = GNUNET_malloc (sizeof (join_req) + data_size);
669   join_req->size = htons (sizeof (join_req) + data_size);
670   join_req->type = htons (123);
671   GNUNET_memcpy (&join_req[1], data, data_size);
672
673   member = GNUNET_MULTICAST_member_join (cfg, &group_pub_key, member_key,
674                                          &this_peer, 1, &this_peer, join_req,
675                                          member_recv_join_request,
676                                          member_recv_join_decision,
677                                          member_recv_replay_frag,
678                                          member_recv_replay_msg,
679                                          member_recv_message,
680                                          &member_cls);
681 }
682
683 /**
684  * Test: Start a multicast group as origin
685  */
686 static void
687 origin_start ()
688 {
689   test = TEST_ORIGIN_START;
690   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
691               "Test #%u: origin_start()\n", test);
692
693   group_key = GNUNET_CRYPTO_eddsa_key_create ();
694   GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key);
695
696   origin = GNUNET_MULTICAST_origin_start (cfg, group_key, 0,
697                                           origin_recv_join_request,
698                                           origin_recv_replay_frag,
699                                           origin_recv_replay_msg,
700                                           origin_recv_request,
701                                           origin_recv_message,
702                                           &origin_cls);
703   // Test 2 starts here
704   member_join (TEST_MEMBER_JOIN_REFUSE);
705 }
706
707
708 /**
709  * Main function of the test, run from scheduler.
710  *
711  * @param cls NULL
712  * @param cfg configuration we use (also to connect to Multicast service)
713  * @param peer handle to access more of the peer (not used)
714  */
715 static void
716 #if DEBUG_TEST_MULTICAST
717 run (void *cls,
718      char *const *args,
719      const char *cfgfile,
720      const struct GNUNET_CONFIGURATION_Handle *c)
721 #else
722 run (void *cls,
723      const struct GNUNET_CONFIGURATION_Handle *c,
724      struct GNUNET_TESTING_Peer *peer)
725 #endif
726 {
727   cfg = c;
728   end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
729                                                  &end_badly, NULL);
730   GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
731
732   // Test 1 starts here
733   origin_start ();
734 }
735
736
737 int
738 main (int argc, char *argv[])
739 {
740   res = 1;
741 #if DEBUG_TEST_MULTICAST
742   const struct GNUNET_GETOPT_CommandLineOption opts[] = {
743     GNUNET_GETOPT_OPTION_END
744   };
745   if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-multicast",
746                                        "test-multicast [options]",
747                                        opts, &run, NULL))
748     return 1;
749 #else
750   if (0 != GNUNET_TESTING_peer_run ("test-multicast", "test_multicast.conf", &run, NULL))
751     return 1;
752 #endif
753   return res;
754 }
755
756 /* end of test_multicast.c */