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