first batch of license fixes (boring)
[oweals/gnunet.git] / src / multicast / gnunet-service-multicast.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU 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
16 /**
17  * @file multicast/gnunet-service-multicast.c
18  * @brief program that does multicast
19  * @author Christian Grothoff
20  */
21 #include "platform.h"
22 #include "gnunet_util_lib.h"
23 #include "gnunet_signatures.h"
24 #include "gnunet_applications.h"
25 #include "gnunet_statistics_service.h"
26 #include "gnunet_cadet_service.h"
27 #include "gnunet_multicast_service.h"
28 #include "multicast.h"
29
30 /**
31  * Handle to our current configuration.
32  */
33 static const struct GNUNET_CONFIGURATION_Handle *cfg;
34
35 /**
36  * Service handle.
37  */
38 static struct GNUNET_SERVICE_Handle *service;
39
40 /**
41  * CADET handle.
42  */
43 static struct GNUNET_CADET_Handle *cadet;
44
45 /**
46  * Identity of this peer.
47  */
48 static struct GNUNET_PeerIdentity this_peer;
49
50 /**
51  * Handle to the statistics service.
52  */
53 static struct GNUNET_STATISTICS_Handle *stats;
54
55 /**
56  * All connected origin clients.
57  * Group's pub_key_hash -> struct Origin * (uniq)
58  */
59 static struct GNUNET_CONTAINER_MultiHashMap *origins;
60
61 /**
62  * All connected member clients.
63  * Group's pub_key_hash -> struct Member * (multi)
64  */
65 static struct GNUNET_CONTAINER_MultiHashMap *members;
66
67 /**
68  * Connected member clients per group.
69  * Group's pub_key_hash -> Member's pub_key_hash (uniq) -> struct Member * (uniq)
70  */
71 static struct GNUNET_CONTAINER_MultiHashMap *group_members;
72
73 /**
74  * Incoming CADET channels with connected children in the tree.
75  * Group's pub_key_hash -> struct Channel * (multi)
76  */
77 static struct GNUNET_CONTAINER_MultiHashMap *channels_in;
78
79 /**
80  * Outgoing CADET channels connecting to parents in the tree.
81  * Group's pub_key_hash -> struct Channel * (multi)
82  */
83 static struct GNUNET_CONTAINER_MultiHashMap *channels_out;
84
85 /**
86  * Incoming replay requests from CADET.
87  * Group's pub_key_hash ->
88  *   H(fragment_id, message_id, fragment_offset, flags) -> struct Channel *
89  */
90 static struct GNUNET_CONTAINER_MultiHashMap *replay_req_cadet;
91
92 /**
93  * Incoming replay requests from clients.
94  * Group's pub_key_hash ->
95  *   H(fragment_id, message_id, fragment_offset, flags) -> struct GNUNET_SERVICE_Client *
96  */
97 static struct GNUNET_CONTAINER_MultiHashMap *replay_req_client;
98
99
100 /**
101  * Join status of a remote peer.
102  */
103 enum JoinStatus
104 {
105   JOIN_REFUSED  = -1,
106   JOIN_NOT_ASKED = 0,
107   JOIN_WAITING   = 1,
108   JOIN_ADMITTED  = 2,
109 };
110
111 enum ChannelDirection
112 {
113   DIR_INCOMING = 0,
114   DIR_OUTGOING = 1,
115 };
116
117
118 /**
119  * Context for a CADET channel.
120  */
121 struct Channel
122 {
123   /**
124    * Group the channel belongs to.
125    *
126    * Only set for outgoing channels.
127    */
128   struct Group *group;
129
130   /**
131    * CADET channel.
132    */
133   struct GNUNET_CADET_Channel *channel;
134
135   // FIXME: not used
136   /**
137    * CADET transmission handle.
138    */
139   struct GNUNET_CADET_TransmitHandle *tmit_handle;
140
141   /**
142    * Public key of the target group.
143    */
144   struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
145
146   /**
147    * Hash of @a group_pub_key.
148    */
149   struct GNUNET_HashCode group_pub_hash;
150
151   /**
152    * Public key of the joining member.
153    */
154   struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
155
156   /**
157    * Remote peer identity.
158    */
159   struct GNUNET_PeerIdentity peer;
160
161   /**
162    * Current window size, set by cadet_notify_window_change()
163    */
164   int32_t window_size;
165
166   /**
167    * Is the connection established?
168    */
169   int8_t is_connected;
170
171   /**
172    * Is the remote peer admitted to the group?
173    * @see enum JoinStatus
174    */
175   int8_t join_status;
176
177   /**
178    * Number of messages waiting to be sent to CADET.
179    */
180   uint8_t msgs_pending;
181
182   /**
183    * Channel direction.
184    * @see enum ChannelDirection
185    */
186   uint8_t direction;
187 };
188
189
190 /**
191  * List of connected clients.
192  */
193 struct ClientList
194 {
195   struct ClientList *prev;
196   struct ClientList *next;
197   struct GNUNET_SERVICE_Client *client;
198 };
199
200
201 /**
202  * Client context for an origin or member.
203  */
204 struct Group
205 {
206   struct ClientList *clients_head;
207   struct ClientList *clients_tail;
208
209   /**
210    * Public key of the group.
211    */
212   struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
213
214   /**
215    * Hash of @a pub_key.
216    */
217   struct GNUNET_HashCode pub_key_hash;
218
219   /**
220    * CADET port hash.
221    */
222   struct GNUNET_HashCode cadet_port_hash;
223
224   /**
225    * Is the client disconnected? #GNUNET_YES or #GNUNET_NO
226    */
227   uint8_t is_disconnected;
228
229   /**
230    * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)?
231    */
232   uint8_t is_origin;
233
234   union {
235     struct Origin *origin;
236     struct Member *member;
237   };
238 };
239
240
241 /**
242 * Client context for a group's origin.
243  */
244 struct Origin
245 {
246   struct Group group;
247
248   /**
249    * Private key of the group.
250    */
251   struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
252
253   /**
254    * CADET port.
255    */
256   struct GNUNET_CADET_Port *cadet_port;
257
258   /**
259    * Last message fragment ID sent to the group.
260    */
261   uint64_t max_fragment_id;
262 };
263
264
265 /**
266  * Client context for a group member.
267  */
268 struct Member
269 {
270   struct Group group;
271
272   /**
273    * Private key of the member.
274    */
275   struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
276
277   /**
278    * Public key of the member.
279    */
280   struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
281
282   /**
283    * Hash of @a pub_key.
284    */
285   struct GNUNET_HashCode pub_key_hash;
286
287   /**
288    * Join request sent to the origin / members.
289    */
290   struct MulticastJoinRequestMessage *join_req;
291
292   /**
293    * Join decision sent in reply to our request.
294    *
295    * Only a positive decision is stored here, in case of a negative decision the
296    * client is disconnected.
297    */
298   struct MulticastJoinDecisionMessageHeader *join_dcsn;
299
300   /**
301    * CADET channel to the origin.
302    */
303   struct Channel *origin_channel;
304
305   /**
306    * Peer identity of origin.
307    */
308   struct GNUNET_PeerIdentity origin;
309
310   /**
311    * Peer identity of relays (other members to connect).
312    */
313   struct GNUNET_PeerIdentity *relays;
314
315   /**
316    * Last request fragment ID sent to the origin.
317    */
318   uint64_t max_fragment_id;
319
320   /**
321    * Number of @a relays.
322    */
323   uint32_t relay_count;
324 };
325
326
327 /**
328  * Client context.
329  */
330 struct Client {
331   struct GNUNET_SERVICE_Client *client;
332   struct Group *group;
333 };
334
335
336 struct ReplayRequestKey
337 {
338   uint64_t fragment_id;
339   uint64_t message_id;
340   uint64_t fragment_offset;
341   uint64_t flags;
342 };
343
344
345 static struct Channel *
346 cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer);
347
348 static void
349 cadet_channel_destroy (struct Channel *chn);
350
351 static void
352 client_send_join_decision (struct Member *mem,
353                            const struct MulticastJoinDecisionMessageHeader *hdcsn);
354
355
356 /**
357  * Task run during shutdown.
358  *
359  * @param cls unused
360  */
361 static void
362 shutdown_task (void *cls)
363 {
364   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
365               "shutting down\n");
366   if (NULL != cadet)
367   {
368     GNUNET_CADET_disconnect (cadet);
369     cadet = NULL;
370   }
371   if (NULL != stats)
372   {
373     GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
374     stats = NULL;
375   }
376   /* FIXME: do more clean up here */
377 }
378
379
380 /**
381  * Clean up origin data structures after a client disconnected.
382  */
383 static void
384 cleanup_origin (struct Origin *orig)
385 {
386   struct Group *grp = &orig->group;
387   GNUNET_CONTAINER_multihashmap_remove (origins, &grp->pub_key_hash, orig);
388   if (NULL != orig->cadet_port)
389   {
390     GNUNET_CADET_close_port (orig->cadet_port);
391     orig->cadet_port = NULL;
392   }
393   GNUNET_free (orig);
394 }
395
396
397 /**
398  * Clean up member data structures after a client disconnected.
399  */
400 static void
401 cleanup_member (struct Member *mem)
402 {
403   struct Group *grp = &mem->group;
404   struct GNUNET_CONTAINER_MultiHashMap *
405     grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
406                                                  &grp->pub_key_hash);
407   GNUNET_assert (NULL != grp_mem);
408   GNUNET_CONTAINER_multihashmap_remove (grp_mem, &mem->pub_key_hash, mem);
409
410   if (0 == GNUNET_CONTAINER_multihashmap_size (grp_mem))
411   {
412     GNUNET_CONTAINER_multihashmap_remove (group_members, &grp->pub_key_hash,
413                                           grp_mem);
414     GNUNET_CONTAINER_multihashmap_destroy (grp_mem);
415   }
416   if (NULL != mem->join_dcsn)
417   {
418     GNUNET_free (mem->join_dcsn);
419     mem->join_dcsn = NULL;
420   }
421   if (NULL != mem->origin_channel)
422   {
423     GNUNET_CADET_channel_destroy (mem->origin_channel->channel);
424     mem->origin_channel = NULL;
425   }
426   GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
427   GNUNET_free (mem);
428 }
429
430
431 /**
432  * Clean up group data structures after a client disconnected.
433  */
434 static void
435 cleanup_group (struct Group *grp)
436 {
437   (GNUNET_YES == grp->is_origin)
438     ? cleanup_origin (grp->origin)
439     : cleanup_member (grp->member);
440 }
441
442
443 void
444 replay_key_hash (uint64_t fragment_id, uint64_t message_id,
445                  uint64_t fragment_offset, uint64_t flags,
446                  struct GNUNET_HashCode *key_hash)
447 {
448   struct ReplayRequestKey key = {
449     .fragment_id = fragment_id,
450     .message_id = message_id,
451     .fragment_offset = fragment_offset,
452     .flags = flags,
453   };
454   GNUNET_CRYPTO_hash (&key, sizeof (key), key_hash);
455 }
456
457
458 /**
459  * Remove channel from replay request hashmap.
460  *
461  * @param chn
462  *        Channel to remove.
463  *
464  * @return #GNUNET_YES if there are more entries to process,
465  *         #GNUNET_NO when reached end of hashmap.
466  */
467 static int
468 replay_req_remove_cadet (struct Channel *chn)
469 {
470   if (NULL == chn || NULL == chn->group)
471     return GNUNET_SYSERR;
472
473   struct GNUNET_CONTAINER_MultiHashMap *
474     grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
475                                                         &chn->group->pub_key_hash);
476   if (NULL == grp_replay_req)
477     return GNUNET_NO;
478
479   struct GNUNET_CONTAINER_MultiHashMapIterator *
480     it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
481   struct GNUNET_HashCode key;
482   const struct Channel *c;
483   while (GNUNET_YES
484          == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
485                                                          (const void **) &c))
486   {
487     if (c == chn)
488     {
489       GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, chn);
490       GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
491       return GNUNET_YES;
492     }
493   }
494   GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
495   return GNUNET_NO;
496 }
497
498
499 /**
500  * Remove client from replay request hashmap.
501  *
502  * @param client
503  *        Client to remove.
504  *
505  * @return #GNUNET_YES if there are more entries to process,
506  *         #GNUNET_NO when reached end of hashmap.
507  */
508 static int
509 replay_req_remove_client (struct Group *grp, struct GNUNET_SERVICE_Client *client)
510 {
511   struct GNUNET_CONTAINER_MultiHashMap *
512     grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
513                                                         &grp->pub_key_hash);
514   if (NULL == grp_replay_req)
515     return GNUNET_NO;
516
517   struct GNUNET_CONTAINER_MultiHashMapIterator *
518     it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
519   struct GNUNET_HashCode key;
520   const struct GNUNET_SERVICE_Client *c;
521   while (GNUNET_YES
522          == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
523                                                          (const void **) &c))
524   {
525     if (c == client)
526     {
527       GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, client);
528       GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
529       return GNUNET_YES;
530     }
531   }
532   GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
533   return GNUNET_NO;
534 }
535
536
537 /**
538  * Send message to a client.
539  */
540 static void
541 client_send (struct GNUNET_SERVICE_Client *client,
542              const struct GNUNET_MessageHeader *msg)
543 {
544   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
545               "%p Sending message to client.\n", client);
546
547   struct GNUNET_MQ_Envelope *
548     env = GNUNET_MQ_msg_copy (msg);
549
550   GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
551                   env);
552 }
553
554
555 /**
556  * Send message to all clients connected to the group.
557  */
558 static void
559 client_send_group_keep_envelope (const struct Group *grp,
560                                  struct GNUNET_MQ_Envelope *env)
561 {
562   struct ClientList *cli = grp->clients_head;
563
564   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
565               "%p Sending message to all clients of the group.\n",
566               grp);
567   while (NULL != cli)
568   {
569     GNUNET_MQ_send_copy (GNUNET_SERVICE_client_get_mq (cli->client),
570                          env);
571     cli = cli->next;
572   }
573 }
574
575
576 /**
577  * Send message to all clients connected to the group and
578  * takes care of freeing @env.
579  */
580 static void
581 client_send_group (const struct Group *grp,
582                    struct GNUNET_MQ_Envelope *env)
583 {
584   client_send_group_keep_envelope (grp, env);
585   GNUNET_MQ_discard (env);
586 }
587
588
589 /**
590  * Iterator callback for sending a message to origin clients.
591  */
592 static int
593 client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
594                        void *origin)
595 {
596   struct GNUNET_MQ_Envelope *env = cls;
597   struct Member *orig = origin;
598
599   client_send_group_keep_envelope (&orig->group, env);
600   return GNUNET_YES;
601 }
602
603
604 /**
605  * Iterator callback for sending a message to member clients.
606  */
607 static int
608 client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
609                        void *member)
610 {
611   struct GNUNET_MQ_Envelope *env = cls;
612   struct Member *mem = member;
613
614   if (NULL != mem->join_dcsn)
615   { /* Only send message to admitted members */
616     client_send_group_keep_envelope (&mem->group, env);
617   }
618   return GNUNET_YES;
619 }
620
621
622 /**
623  * Send message to all origin and member clients connected to the group.
624  *
625  * @param pub_key_hash
626  *        H(key_pub) of the group.
627  * @param msg
628  *        Message to send.
629  */
630 static int
631 client_send_all (struct GNUNET_HashCode *pub_key_hash,
632                  struct GNUNET_MQ_Envelope *env)
633 {
634   int n = 0;
635   n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
636                                                    client_send_origin_cb,
637                                                    (void *) env);
638   n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash,
639                                                    client_send_member_cb,
640                                                    (void *) env);
641   GNUNET_MQ_discard (env);
642   return n;
643 }
644
645
646 /**
647  * Send message to a random origin client or a random member client.
648  *
649  * @param grp  The group to send @a msg to.
650  * @param msg  Message to send.
651  */
652 static int
653 client_send_random (struct GNUNET_HashCode *pub_key_hash,
654                     struct GNUNET_MQ_Envelope *env)
655 {
656   int n = 0;
657   n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb,
658                                                  (void *) env);
659   if (n <= 0)
660     n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb,
661                                                    (void *) env);
662   GNUNET_MQ_discard (env);
663   return n;
664 }
665
666
667 /**
668  * Send message to all origin clients connected to the group.
669  *
670  * @param pub_key_hash
671  *        H(key_pub) of the group.
672  * @param msg
673  *        Message to send.
674  */
675 static int
676 client_send_origin (struct GNUNET_HashCode *pub_key_hash,
677                     struct GNUNET_MQ_Envelope *env)
678 {
679   int n = 0;
680   n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
681                                                    client_send_origin_cb,
682                                                    (void *) env);
683   return n;
684 }
685
686
687 /**
688  * Send fragment acknowledgement to all clients of the channel.
689  *
690  * @param pub_key_hash
691  *        H(key_pub) of the group.
692  */
693 static void
694 client_send_ack (struct GNUNET_HashCode *pub_key_hash)
695 {
696   struct GNUNET_MQ_Envelope *env;
697
698   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
699               "Sending message ACK to client.\n");
700   env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
701   client_send_all (pub_key_hash, env);
702 }
703
704
705 struct CadetTransmitClosure
706 {
707   struct Channel *chn;
708   const struct GNUNET_MessageHeader *msg;
709 };
710
711
712 /**
713  * Send a message to a CADET channel.
714  *
715  * @param chn  Channel.
716  * @param msg  Message.
717  */
718 static void
719 cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg)
720 {
721   struct GNUNET_MQ_Envelope *
722     env = GNUNET_MQ_msg_copy (msg);
723
724   GNUNET_MQ_send (GNUNET_CADET_get_mq (chn->channel), env);
725
726   if (0 < chn->window_size)
727   {
728     client_send_ack (&chn->group_pub_hash);
729   }
730   else
731   {
732     chn->msgs_pending++;
733     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
734                 "%p Queuing message. Pending messages: %u\n",
735                 chn, chn->msgs_pending);
736   }
737 }
738
739
740 /**
741  * Create CADET channel and send a join request.
742  */
743 static void
744 cadet_send_join_request (struct Member *mem)
745 {
746   mem->origin_channel = cadet_channel_create (&mem->group, &mem->origin);
747   cadet_send_channel (mem->origin_channel, &mem->join_req->header);
748
749   uint32_t i;
750   for (i = 0; i < mem->relay_count; i++)
751   {
752     struct Channel *
753       chn = cadet_channel_create (&mem->group, &mem->relays[i]);
754     cadet_send_channel (chn, &mem->join_req->header);
755   }
756 }
757
758
759 static int
760 cadet_send_join_decision_cb (void *cls,
761                              const struct GNUNET_HashCode *group_pub_hash,
762                              void *channel)
763 {
764   const struct MulticastJoinDecisionMessageHeader *hdcsn = cls;
765   struct Channel *chn = channel;
766
767   const struct MulticastJoinDecisionMessage *dcsn =
768     (struct MulticastJoinDecisionMessage *) &hdcsn[1];
769
770   if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key))
771       && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer)))
772   {
773     if (GNUNET_YES == ntohl (dcsn->is_admitted))
774     {
775       chn->join_status = JOIN_ADMITTED;
776     }
777     else
778     {
779       chn->join_status = JOIN_REFUSED;
780     }
781     cadet_send_channel (chn, &hdcsn->header);
782     return GNUNET_YES;
783   }
784
785   // return GNUNET_YES to continue the multihashmap_get iteration
786   return GNUNET_YES;
787 }
788
789
790 /**
791  * Send join decision to a remote peer.
792  */
793 static void
794 cadet_send_join_decision (struct Group *grp,
795                           const struct MulticastJoinDecisionMessageHeader *hdcsn)
796 {
797   GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, &grp->pub_key_hash,
798                                               &cadet_send_join_decision_cb,
799                                               (void *) hdcsn);
800 }
801
802
803 /**
804  * Iterator callback for sending a message to origin clients.
805  */
806 static int
807 cadet_send_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
808                void *channel)
809 {
810   const struct GNUNET_MessageHeader *msg = cls;
811   struct Channel *chn = channel;
812   if (JOIN_ADMITTED == chn->join_status)
813     cadet_send_channel (chn, msg);
814   return GNUNET_YES;
815 }
816
817
818 /**
819  * Send message to all connected children.
820  */
821 static int
822 cadet_send_children (struct GNUNET_HashCode *pub_key_hash,
823                      const struct GNUNET_MessageHeader *msg)
824 {
825   int n = 0;
826   if (channels_in != NULL)
827     n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash,
828                                                      cadet_send_cb, (void *) msg);
829   return n;
830 }
831
832
833 #if 0       // unused as yet
834 /**
835  * Send message to all connected parents.
836  */
837 static int
838 cadet_send_parents (struct GNUNET_HashCode *pub_key_hash,
839                     const struct GNUNET_MessageHeader *msg)
840 {
841   int n = 0;
842   if (channels_in != NULL)
843     n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_out, pub_key_hash,
844                                                      cadet_send_cb, (void *) msg);
845   return n;
846 }
847 #endif
848
849
850 /**
851  * CADET channel connect handler.
852  *
853  * @see GNUNET_CADET_ConnectEventHandler()
854  */
855 static void *
856 cadet_notify_connect (void *cls,
857                       struct GNUNET_CADET_Channel *channel,
858                       const struct GNUNET_PeerIdentity *source)
859 {
860   struct Channel *chn = GNUNET_malloc (sizeof (struct Channel));
861   chn->group = cls;
862   chn->channel = channel;
863   chn->direction = DIR_INCOMING;
864   chn->join_status = JOIN_NOT_ASKED;
865       
866   GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group->pub_key_hash, chn,
867                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
868   return chn;
869 }
870
871
872 /**
873  * CADET window size change handler.
874  *
875  * @see GNUNET_CADET_WindowSizeEventHandler()
876  */
877 static void
878 cadet_notify_window_change (void *cls,
879                             const struct GNUNET_CADET_Channel *channel,
880                             int window_size)
881 {
882   struct Channel *chn = cls;
883
884   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
885               "%p Window size changed to %d.  Pending messages: %u\n",
886               chn, window_size, chn->msgs_pending);
887
888   chn->is_connected = GNUNET_YES;
889   chn->window_size = (int32_t) window_size;
890
891   for (int i = 0; i < window_size; i++)
892   {
893     if (0 < chn->msgs_pending)
894     {
895       client_send_ack (&chn->group_pub_hash);
896       chn->msgs_pending--;
897     }
898     else
899     {
900       break;
901     }
902   }
903 }
904
905
906 /**
907  * CADET channel disconnect handler.
908  *
909  * @see GNUNET_CADET_DisconnectEventHandler()
910  */
911 static void
912 cadet_notify_disconnect (void *cls,
913                          const struct GNUNET_CADET_Channel *channel)
914 {
915   if (NULL == cls)
916     return;
917
918   struct Channel *chn = cls;
919   if (NULL != chn->group)
920   {
921     if (GNUNET_NO == chn->group->is_origin)
922     {
923       struct Member *mem = (struct Member *) chn->group;
924       if (chn == mem->origin_channel)
925         mem->origin_channel = NULL;
926     }
927   }
928
929   int ret;
930   do
931   {
932     ret = replay_req_remove_cadet (chn);
933   }
934   while (GNUNET_YES == ret);
935
936   GNUNET_free (chn);
937 }
938
939
940 static int
941 check_cadet_join_request (void *cls,
942                           const struct MulticastJoinRequestMessage *req)
943 {
944   struct Channel *chn = cls;
945
946   if (NULL == chn
947       || JOIN_NOT_ASKED != chn->join_status)
948   {
949     return GNUNET_SYSERR;
950   }
951
952   uint16_t size = ntohs (req->header.size);
953   if (size < sizeof (*req))
954   {
955     GNUNET_break_op (0);
956     return GNUNET_SYSERR;
957   }
958   if (ntohl (req->purpose.size) != (size
959                                     - sizeof (req->header)
960                                     - sizeof (req->reserved)
961                                     - sizeof (req->signature)))
962   {
963     GNUNET_break_op (0);
964     return GNUNET_SYSERR;
965   }
966   if (GNUNET_OK !=
967       GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
968                                   &req->purpose, &req->signature,
969                                   &req->member_pub_key))
970   {
971     GNUNET_break_op (0);
972     return GNUNET_SYSERR;
973   }
974
975   return GNUNET_OK;
976 }
977
978
979 /**
980  * Incoming join request message from CADET.
981  */
982 static void
983 handle_cadet_join_request (void *cls,
984                            const struct MulticastJoinRequestMessage *req)
985 {
986   struct Channel *chn = cls;
987   GNUNET_CADET_receive_done (chn->channel);
988
989   struct GNUNET_HashCode group_pub_hash;
990   GNUNET_CRYPTO_hash (&req->group_pub_key, sizeof (req->group_pub_key), &group_pub_hash);
991   chn->group_pub_key = req->group_pub_key;
992   chn->group_pub_hash = group_pub_hash;
993   chn->member_pub_key = req->member_pub_key;
994   chn->peer = req->peer;
995   chn->join_status = JOIN_WAITING;
996
997   client_send_all (&group_pub_hash,
998                    GNUNET_MQ_msg_copy (&req->header));
999 }
1000
1001
1002 static int
1003 check_cadet_join_decision (void *cls,
1004                            const struct MulticastJoinDecisionMessageHeader *hdcsn)
1005 {
1006   uint16_t size = ntohs (hdcsn->header.size);
1007   if (size < sizeof (struct MulticastJoinDecisionMessageHeader) +
1008              sizeof (struct MulticastJoinDecisionMessage))
1009   {
1010     GNUNET_break_op (0);
1011     return GNUNET_SYSERR;
1012   }
1013
1014   struct Channel *chn = cls;
1015   if (NULL == chn)
1016   {
1017     GNUNET_break (0);
1018     return GNUNET_SYSERR;
1019   }
1020   if (NULL == chn->group || GNUNET_NO != chn->group->is_origin)
1021   {
1022     GNUNET_break (0);
1023     return GNUNET_SYSERR;
1024   }
1025   switch (chn->join_status)
1026   {
1027   case JOIN_REFUSED:
1028     return GNUNET_SYSERR;
1029
1030   case JOIN_ADMITTED:
1031     return GNUNET_OK;
1032
1033   case JOIN_NOT_ASKED:
1034   case JOIN_WAITING:
1035     break;
1036   }
1037
1038   return GNUNET_OK;
1039 }
1040
1041
1042 /**
1043  * Incoming join decision message from CADET.
1044  */
1045 static void
1046 handle_cadet_join_decision (void *cls,
1047                             const struct MulticastJoinDecisionMessageHeader *hdcsn)
1048 {
1049   const struct MulticastJoinDecisionMessage *
1050     dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1051
1052   struct Channel *chn = cls;
1053   GNUNET_CADET_receive_done (chn->channel);
1054
1055   // FIXME: do we need to copy chn->peer or compare it with hdcsn->peer?
1056   struct Member *mem = (struct Member *) chn->group;
1057   client_send_join_decision (mem, hdcsn);
1058   if (GNUNET_YES == ntohl (dcsn->is_admitted))
1059   {
1060     chn->join_status = JOIN_ADMITTED;
1061   }
1062   else
1063   {
1064     chn->join_status = JOIN_REFUSED;
1065     cadet_channel_destroy (chn);
1066   }
1067 }
1068
1069
1070 static int
1071 check_cadet_message (void *cls,
1072                      const struct GNUNET_MULTICAST_MessageHeader *msg)
1073 {
1074   uint16_t size = ntohs (msg->header.size);
1075   if (size < sizeof (*msg))
1076   {
1077     GNUNET_break_op (0);
1078     return GNUNET_SYSERR;
1079   }
1080
1081   struct Channel *chn = cls;
1082   if (NULL == chn)
1083   {
1084     GNUNET_break (0);
1085     return GNUNET_SYSERR;
1086   }
1087   if (ntohl (msg->purpose.size) != (size
1088                                     - sizeof (msg->header)
1089                                     - sizeof (msg->hop_counter)
1090                                     - sizeof (msg->signature)))
1091   {
1092     GNUNET_break_op (0);
1093     return GNUNET_SYSERR;
1094   }
1095   if (GNUNET_OK !=
1096       GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE,
1097                                   &msg->purpose, &msg->signature,
1098                                   &chn->group_pub_key))
1099   {
1100     GNUNET_break_op (0);
1101     return GNUNET_SYSERR;
1102   }
1103
1104   return GNUNET_OK;
1105 }
1106
1107
1108 /**
1109  * Incoming multicast message from CADET.
1110  */
1111 static void
1112 handle_cadet_message (void *cls,
1113                       const struct GNUNET_MULTICAST_MessageHeader *msg)
1114 {
1115   struct Channel *chn = cls;
1116   GNUNET_CADET_receive_done (chn->channel);
1117   client_send_all (&chn->group_pub_hash,
1118                    GNUNET_MQ_msg_copy (&msg->header));
1119 }
1120
1121
1122 static int
1123 check_cadet_request (void *cls,
1124                      const struct GNUNET_MULTICAST_RequestHeader *req)
1125 {
1126   uint16_t size = ntohs (req->header.size);
1127   if (size < sizeof (*req))
1128   {
1129     GNUNET_break_op (0);
1130     return GNUNET_SYSERR;
1131   }
1132
1133   struct Channel *chn = cls;
1134   if (NULL == chn)
1135   {
1136     GNUNET_break (0);
1137     return GNUNET_SYSERR;
1138   }
1139   if (ntohl (req->purpose.size) != (size
1140                                     - sizeof (req->header)
1141                                     - sizeof (req->member_pub_key)
1142                                     - sizeof (req->signature)))
1143   {
1144     GNUNET_break_op (0);
1145     return GNUNET_SYSERR;
1146   }
1147   if (GNUNET_OK !=
1148       GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1149                                   &req->purpose, &req->signature,
1150                                   &req->member_pub_key))
1151   {
1152     GNUNET_break_op (0);
1153     return GNUNET_SYSERR;
1154   }
1155
1156   return GNUNET_OK;
1157 }
1158
1159
1160 /**
1161  * Incoming multicast request message from CADET.
1162  */
1163 static void
1164 handle_cadet_request (void *cls,
1165                       const struct GNUNET_MULTICAST_RequestHeader *req)
1166 {
1167   struct Channel *chn = cls;
1168   GNUNET_CADET_receive_done (chn->channel);
1169   client_send_origin (&chn->group_pub_hash,
1170                       GNUNET_MQ_msg_copy (&req->header));
1171 }
1172
1173
1174 // FIXME: do checks in handle_cadet_replay_request
1175 //static int
1176 //check_cadet_replay_request (void *cls,
1177 //                            const struct MulticastReplayRequestMessage *req)
1178 //{
1179 //  uint16_t size = ntohs (req->header.size);
1180 //  if (size < sizeof (*req))
1181 //  {
1182 //    GNUNET_break_op (0);
1183 //    return GNUNET_SYSERR;
1184 //  }
1185 //
1186 //  struct Channel *chn = cls;
1187 //  if (NULL == chn)
1188 //  {
1189 //    GNUNET_break_op (0);
1190 //    return GNUNET_SYSERR;
1191 //  }
1192 //
1193 //  return GNUNET_OK;
1194 //}
1195
1196
1197 /**
1198  * Incoming multicast replay request from CADET.
1199  */
1200 static void
1201 handle_cadet_replay_request (void *cls,
1202                              const struct MulticastReplayRequestMessage *req)
1203 {
1204   struct Channel *chn = cls;
1205
1206   GNUNET_CADET_receive_done (chn->channel);
1207
1208   struct MulticastReplayRequestMessage rep = *req;
1209   GNUNET_memcpy (&rep.member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key));
1210
1211   struct GNUNET_CONTAINER_MultiHashMap *
1212     grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1213                                                         &chn->group->pub_key_hash);
1214   if (NULL == grp_replay_req)
1215   {
1216     grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1217     GNUNET_CONTAINER_multihashmap_put (replay_req_cadet,
1218                                        &chn->group->pub_key_hash, grp_replay_req,
1219                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1220   }
1221   struct GNUNET_HashCode key_hash;
1222   replay_key_hash (rep.fragment_id,
1223                    rep.message_id,
1224                    rep.fragment_offset,
1225                    rep.flags,
1226                    &key_hash);
1227   GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn,
1228                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1229
1230   client_send_random (&chn->group_pub_hash,
1231                       GNUNET_MQ_msg_copy (&rep.header));
1232 }
1233
1234
1235 static int
1236 check_cadet_replay_response (void *cls,
1237                              const struct MulticastReplayResponseMessage *res)
1238 {
1239   struct Channel *chn = cls;
1240   if (NULL == chn)
1241   {
1242     GNUNET_break (0);
1243     return GNUNET_SYSERR;
1244   }
1245   return GNUNET_OK;
1246 }
1247
1248
1249 /**
1250  * Incoming multicast replay response from CADET.
1251  */
1252 static void
1253 handle_cadet_replay_response (void *cls,
1254                               const struct MulticastReplayResponseMessage *res)
1255 {
1256   struct Channel *chn = cls;
1257   GNUNET_CADET_receive_done (chn->channel);
1258
1259   /* @todo FIXME: got replay error response, send request to other members */
1260 }
1261
1262
1263 static void
1264 group_set_cadet_port_hash (struct Group *grp)
1265 {
1266   struct CadetPort {
1267     struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
1268     uint32_t app_type;
1269   } port = {
1270     grp->pub_key,
1271     GNUNET_APPLICATION_TYPE_MULTICAST,
1272   };
1273   GNUNET_CRYPTO_hash (&port, sizeof (port), &grp->cadet_port_hash);
1274 }
1275
1276
1277
1278 /**
1279  * Create new outgoing CADET channel.
1280  *
1281  * @param peer
1282  *        Peer to connect to.
1283  * @param group_pub_key
1284  *        Public key of group the channel belongs to.
1285  * @param group_pub_hash
1286  *        Hash of @a group_pub_key.
1287  *
1288  * @return Channel.
1289  */
1290 static struct Channel *
1291 cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer)
1292 {
1293   struct Channel *chn = GNUNET_malloc (sizeof (*chn));
1294   chn->group = grp;
1295   chn->group_pub_key = grp->pub_key;
1296   chn->group_pub_hash = grp->pub_key_hash;
1297   chn->peer = *peer;
1298   chn->direction = DIR_OUTGOING;
1299   chn->is_connected = GNUNET_NO;
1300   chn->join_status = JOIN_WAITING;
1301
1302   struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1303     GNUNET_MQ_hd_var_size (cadet_message,
1304                            GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
1305                            struct GNUNET_MULTICAST_MessageHeader,
1306                            chn),
1307
1308     GNUNET_MQ_hd_var_size (cadet_join_decision,
1309                            GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
1310                            struct MulticastJoinDecisionMessageHeader,
1311                            chn),
1312
1313     GNUNET_MQ_hd_fixed_size (cadet_replay_request,
1314                              GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1315                              struct MulticastReplayRequestMessage,
1316                              chn),
1317
1318     GNUNET_MQ_hd_var_size (cadet_replay_response,
1319                            GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
1320                            struct MulticastReplayResponseMessage,
1321                            chn),
1322
1323     GNUNET_MQ_handler_end ()
1324   };
1325
1326   chn->channel = GNUNET_CADET_channel_create (cadet, chn, &chn->peer,
1327                                               &grp->cadet_port_hash,
1328                                               GNUNET_CADET_OPTION_RELIABLE,
1329                                               cadet_notify_window_change,
1330                                               cadet_notify_disconnect,
1331                                               cadet_handlers);
1332   GNUNET_CONTAINER_multihashmap_put (channels_out, &chn->group_pub_hash, chn,
1333                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1334   return chn;
1335 }
1336
1337
1338 /**
1339  * Destroy outgoing CADET channel.
1340  */
1341 static void
1342 cadet_channel_destroy (struct Channel *chn)
1343 {
1344   GNUNET_CADET_channel_destroy (chn->channel);
1345   GNUNET_CONTAINER_multihashmap_remove_all (channels_out, &chn->group_pub_hash);
1346   GNUNET_free (chn);
1347 }
1348
1349 /**
1350  * Handle a connecting client starting an origin.
1351  */
1352 static void
1353 handle_client_origin_start (void *cls,
1354                             const struct MulticastOriginStartMessage *msg)
1355 {
1356   struct Client *c = cls;
1357   struct GNUNET_SERVICE_Client *client = c->client;
1358
1359   struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
1360   struct GNUNET_HashCode pub_key_hash;
1361
1362   GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key);
1363   GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
1364
1365   struct Origin *
1366     orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash);
1367   struct Group *grp;
1368
1369   if (NULL == orig)
1370   {
1371     orig = GNUNET_new (struct Origin);
1372     orig->priv_key = msg->group_key;
1373     orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
1374
1375     grp = c->group = &orig->group;
1376     grp->origin = orig;
1377     grp->is_origin = GNUNET_YES;
1378     grp->pub_key = pub_key;
1379     grp->pub_key_hash = pub_key_hash;
1380     grp->is_disconnected = GNUNET_NO;
1381
1382     GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
1383                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1384
1385     group_set_cadet_port_hash (grp);
1386
1387     struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1388       GNUNET_MQ_hd_var_size (cadet_message,
1389                              GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
1390                              struct GNUNET_MULTICAST_MessageHeader,
1391                              grp),
1392
1393       GNUNET_MQ_hd_var_size (cadet_request,
1394                              GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
1395                              struct GNUNET_MULTICAST_RequestHeader,
1396                              grp),
1397
1398       GNUNET_MQ_hd_var_size (cadet_join_request,
1399                              GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST,
1400                              struct MulticastJoinRequestMessage,
1401                              grp),
1402
1403       GNUNET_MQ_hd_fixed_size (cadet_replay_request,
1404                                GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1405                                struct MulticastReplayRequestMessage,
1406                                grp),
1407
1408       GNUNET_MQ_hd_var_size (cadet_replay_response,
1409                              GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
1410                              struct MulticastReplayResponseMessage,
1411                              grp),
1412
1413       GNUNET_MQ_handler_end ()
1414     };
1415
1416
1417     orig->cadet_port = GNUNET_CADET_open_port (cadet,
1418                                                &grp->cadet_port_hash,
1419                                                cadet_notify_connect,
1420                                                grp,
1421                                                cadet_notify_window_change,
1422                                                cadet_notify_disconnect,
1423                                                cadet_handlers);
1424   }
1425   else
1426   {
1427     grp = &orig->group;
1428   }
1429
1430   struct ClientList *cl = GNUNET_new (struct ClientList);
1431   cl->client = client;
1432   GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1433
1434   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1435               "%p Client connected as origin to group %s.\n",
1436               orig, GNUNET_h2s (&grp->pub_key_hash));
1437   GNUNET_SERVICE_client_continue (client);
1438 }
1439
1440
1441 static int
1442 check_client_member_join (void *cls,
1443                           const struct MulticastMemberJoinMessage *msg)
1444 {
1445   uint16_t msg_size = ntohs (msg->header.size);
1446   struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1447   uint32_t relay_count = ntohl (msg->relay_count);
1448   if (UINT32_MAX / relay_count < sizeof (*relays)){
1449       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1450                     "relay_count (%lu) * sizeof (*relays)  (%lu) exceeds UINT32_MAX!\n",
1451               (unsigned long)relay_count,
1452               sizeof (*relays));
1453       return GNUNET_SYSERR;
1454   }
1455   uint32_t relay_size = relay_count * sizeof (*relays);
1456   struct GNUNET_MessageHeader *join_msg = NULL;
1457   uint16_t join_msg_size = 0;
1458   if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1459       <= msg_size)
1460   {
1461     join_msg = (struct GNUNET_MessageHeader *)
1462       (((char *) &msg[1]) + relay_size);
1463     join_msg_size = ntohs (join_msg->size);
1464     if (UINT16_MAX - join_msg_size < sizeof (struct MulticastJoinRequestMessage)){
1465         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1466                     "join_msg_size (%u) + sizeof (struct MulticastJoinRequestMessage) (%lu) exceeds UINT16_MAX!\n",
1467                 (unsigned)join_msg_size,
1468                 (unsigned long)sizeof (struct MulticastJoinRequestMessage));
1469         return GNUNET_SYSERR;
1470     } 
1471   }
1472   if (msg_size != (sizeof (*msg) + relay_size + join_msg_size)){
1473       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1474                     "msg_size does not match real size of message!\n");
1475       return GNUNET_SYSERR;
1476   }else{
1477       return GNUNET_OK;
1478   }
1479 }
1480
1481
1482 /**
1483  * Handle a connecting client joining a group.
1484  */
1485 static void
1486 handle_client_member_join (void *cls,
1487                            const struct MulticastMemberJoinMessage *msg)
1488 {
1489   struct Client *c = cls;
1490   struct GNUNET_SERVICE_Client *client = c->client;
1491
1492   uint16_t msg_size = ntohs (msg->header.size);
1493
1494   struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key;
1495   struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
1496
1497   GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key);
1498   GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
1499   GNUNET_CRYPTO_hash (&msg->group_pub_key, sizeof (msg->group_pub_key), &pub_key_hash);
1500   
1501   struct GNUNET_CONTAINER_MultiHashMap *
1502     grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash);
1503   struct Member *mem = NULL;
1504   struct Group *grp;
1505
1506   if (NULL != grp_mem)
1507   {
1508     mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
1509   }
1510   
1511   if (NULL == mem)
1512   {
1513     mem = GNUNET_new (struct Member);
1514     mem->origin = msg->origin;
1515     mem->priv_key = msg->member_key;
1516     mem->pub_key = mem_pub_key;
1517     mem->pub_key_hash = mem_pub_key_hash;
1518     mem->max_fragment_id = 0; // FIXME
1519
1520     grp = c->group = &mem->group;
1521     grp->member = mem;
1522     grp->is_origin = GNUNET_NO;
1523     grp->pub_key = msg->group_pub_key;
1524     grp->pub_key_hash = pub_key_hash;
1525     grp->is_disconnected = GNUNET_NO;
1526     group_set_cadet_port_hash (grp);
1527   
1528     if (NULL == grp_mem)
1529     {
1530       grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1531       GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, grp_mem,
1532                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1533     }
1534     GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
1535                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1536    
1537     // FIXME: should the members hash map have option UNIQUE_FAST?
1538     GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
1539                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1540   }
1541   else
1542   {
1543     grp = &mem->group;
1544   }
1545
1546   struct ClientList *cl = GNUNET_new (struct ClientList);
1547   cl->client = client;
1548   GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1549
1550   char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
1551   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1552               "Client connected to group %s as member %s (%s). size = %d\n",
1553               GNUNET_h2s (&grp->pub_key_hash),
1554               GNUNET_h2s2 (&mem->pub_key_hash),
1555               str,
1556               GNUNET_CONTAINER_multihashmap_size (members));
1557   GNUNET_free (str);
1558
1559   if (NULL != mem->join_dcsn)
1560   { /* Already got a join decision, send it to client. */
1561     struct GNUNET_MQ_Envelope *
1562       env = GNUNET_MQ_msg_copy (&mem->join_dcsn->header);
1563
1564     GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1565                     env);
1566   }
1567   else
1568   { /* First client of the group, send join request. */
1569     struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1570     uint32_t relay_count = ntohl (msg->relay_count);
1571     uint16_t relay_size = relay_count * sizeof (*relays);
1572     struct GNUNET_MessageHeader *join_msg = NULL;
1573     uint16_t join_msg_size = 0;
1574     if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1575         <= msg_size)
1576     {
1577       join_msg = (struct GNUNET_MessageHeader *)
1578         (((char *) &msg[1]) + relay_size);
1579       join_msg_size = ntohs (join_msg->size);
1580     }
1581
1582     uint16_t req_msg_size = sizeof (struct MulticastJoinRequestMessage) + join_msg_size;
1583     struct MulticastJoinRequestMessage *
1584       req = GNUNET_malloc (req_msg_size);
1585     req->header.size = htons (req_msg_size);
1586     req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
1587     req->group_pub_key = grp->pub_key;
1588     req->peer = this_peer;
1589     GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_pub_key);
1590     if (0 < join_msg_size)
1591       GNUNET_memcpy (&req[1], join_msg, join_msg_size);
1592
1593     req->member_pub_key = mem->pub_key;
1594     req->purpose.size = htonl (req_msg_size
1595                                - sizeof (req->header)
1596                                - sizeof (req->reserved)
1597                                - sizeof (req->signature));
1598     req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1599
1600     if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose,
1601                                                &req->signature))
1602     {
1603       /* FIXME: handle error */
1604       GNUNET_assert (0);
1605     }
1606
1607     if (NULL != mem->join_req)
1608       GNUNET_free (mem->join_req);
1609     mem->join_req = req;
1610
1611     if (0 ==
1612         client_send_origin (&grp->pub_key_hash,
1613                             GNUNET_MQ_msg_copy (&mem->join_req->header)))
1614     { /* No local origins, send to remote origin */
1615       cadet_send_join_request (mem);
1616     }
1617   }
1618   GNUNET_SERVICE_client_continue (client);
1619 }
1620
1621
1622 static void
1623 client_send_join_decision (struct Member *mem,
1624                            const struct MulticastJoinDecisionMessageHeader *hdcsn)
1625 {
1626   client_send_group (&mem->group, GNUNET_MQ_msg_copy (&hdcsn->header));
1627
1628   const struct MulticastJoinDecisionMessage *
1629     dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1630   if (GNUNET_YES == ntohl (dcsn->is_admitted))
1631   { /* Member admitted, store join_decision. */
1632     uint16_t dcsn_size = ntohs (dcsn->header.size);
1633     mem->join_dcsn = GNUNET_malloc (dcsn_size);
1634     GNUNET_memcpy (mem->join_dcsn, dcsn, dcsn_size);
1635   }
1636   else
1637   { /* Refused entry, but replay would be still possible for past members. */
1638   }
1639 }
1640
1641
1642 static int
1643 check_client_join_decision (void *cls,
1644                             const struct MulticastJoinDecisionMessageHeader *hdcsn)
1645 {
1646   return GNUNET_OK;
1647 }
1648
1649
1650 /**
1651  * Join decision from client.
1652  */
1653 static void
1654 handle_client_join_decision (void *cls,
1655                              const struct MulticastJoinDecisionMessageHeader *hdcsn)
1656 {
1657   struct Client *c = cls;
1658   struct GNUNET_SERVICE_Client *client = c->client;
1659   struct Group *grp = c->group;
1660
1661   if (NULL == grp)
1662   {
1663     GNUNET_break (0);
1664     GNUNET_SERVICE_client_drop (client);
1665     return;
1666   }
1667   GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1668   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1669               "%p got join decision from client for group %s..\n",
1670               grp, GNUNET_h2s (&grp->pub_key_hash));
1671
1672   struct GNUNET_CONTAINER_MultiHashMap *
1673     grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
1674                                                  &grp->pub_key_hash);
1675   struct Member *mem = NULL;
1676   if (NULL != grp_mem)
1677   {
1678     struct GNUNET_HashCode member_key_hash;
1679     GNUNET_CRYPTO_hash (&hdcsn->member_pub_key, sizeof (hdcsn->member_pub_key),
1680                         &member_key_hash);
1681     mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
1682     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1683                 "%p ..and member %s: %p\n",
1684                 grp, GNUNET_h2s (&member_key_hash), mem);
1685   }
1686   
1687   if (NULL != mem) 
1688   { /* Found local member */
1689     client_send_join_decision (mem, hdcsn);
1690   }
1691   else
1692   { /* Look for remote member */
1693     cadet_send_join_decision (grp, hdcsn);
1694   }
1695   GNUNET_SERVICE_client_continue (client);
1696 }
1697
1698
1699 static void
1700 handle_client_part_request (void *cls,
1701                             const struct GNUNET_MessageHeader *msg)
1702 {
1703   struct Client *c = cls;
1704   struct GNUNET_SERVICE_Client *client = c->client;
1705   struct Group *grp = c->group;
1706   struct GNUNET_MQ_Envelope *env;
1707
1708   if (NULL == grp)
1709   {
1710     GNUNET_break (0);
1711     GNUNET_SERVICE_client_drop (client);
1712     return;
1713   }
1714   GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1715   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1716               "%p got part request from client for group %s.\n",
1717               grp, GNUNET_h2s (&grp->pub_key_hash));
1718   grp->is_disconnected = GNUNET_YES;
1719   env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK);
1720   client_send_group (grp, env);
1721   GNUNET_SERVICE_client_continue (client);
1722 }
1723
1724
1725 static int
1726 check_client_multicast_message (void *cls,
1727                                 const struct GNUNET_MULTICAST_MessageHeader *msg)
1728 {
1729   return GNUNET_OK;
1730 }
1731
1732
1733 /**
1734  * Incoming message from a client.
1735  */
1736 static void
1737 handle_client_multicast_message (void *cls,
1738                                  const struct GNUNET_MULTICAST_MessageHeader *msg)
1739 {
1740   // FIXME: what if GNUNET_YES == grp->is_disconnected? Do we allow sending messages?
1741   struct Client *c = cls;
1742   struct GNUNET_SERVICE_Client *client = c->client;
1743   struct Group *grp = c->group;
1744
1745   if (NULL == grp)
1746   {
1747     GNUNET_break (0);
1748     GNUNET_SERVICE_client_drop (client);
1749     return;
1750   }
1751   GNUNET_assert (GNUNET_YES == grp->is_origin);
1752   struct Origin *orig = grp->origin;
1753
1754   // FIXME: use GNUNET_MQ_msg_copy
1755   /* FIXME: yucky, should use separate message structs for P2P and CS! */
1756   struct GNUNET_MULTICAST_MessageHeader *
1757     out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (&msg->header);
1758   out->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
1759   out->purpose.size = htonl (ntohs (out->header.size)
1760                              - sizeof (out->header)
1761                              - sizeof (out->hop_counter)
1762                              - sizeof (out->signature));
1763   out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE);
1764
1765   if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &out->purpose,
1766                                              &out->signature))
1767   {
1768     GNUNET_assert (0);
1769   }
1770
1771   client_send_all (&grp->pub_key_hash, GNUNET_MQ_msg_copy (&out->header));
1772   cadet_send_children (&grp->pub_key_hash, &out->header);
1773   client_send_ack (&grp->pub_key_hash);
1774   GNUNET_free (out);
1775
1776   GNUNET_SERVICE_client_continue (client);
1777 }
1778
1779
1780 static int
1781 check_client_multicast_request (void *cls,
1782                                 const struct GNUNET_MULTICAST_RequestHeader *req)
1783 {
1784   return GNUNET_OK;
1785 }
1786
1787
1788 /**
1789  * Incoming request from a client.
1790  */
1791 static void
1792 handle_client_multicast_request (void *cls,
1793                                  const struct GNUNET_MULTICAST_RequestHeader *req)
1794 {
1795   struct Client *c = cls;
1796   struct GNUNET_SERVICE_Client *client = c->client;
1797   struct Group *grp = c->group;
1798
1799   if (NULL == grp)
1800   {
1801     GNUNET_break (0);
1802     GNUNET_SERVICE_client_drop (client);
1803     return;
1804   }
1805   GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1806   GNUNET_assert (GNUNET_NO == grp->is_origin);
1807   struct Member *mem = grp->member;
1808
1809   /* FIXME: yucky, should use separate message structs for P2P and CS! */
1810   struct GNUNET_MULTICAST_RequestHeader *
1811     out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (&req->header);
1812   out->member_pub_key = mem->pub_key;
1813   out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
1814   out->purpose.size = htonl (ntohs (out->header.size)
1815                              - sizeof (out->header)
1816                              - sizeof (out->member_pub_key)
1817                              - sizeof (out->signature));
1818   out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1819
1820   if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &out->purpose,
1821                                              &out->signature))
1822   {
1823     GNUNET_assert (0);
1824   }
1825
1826   uint8_t send_ack = GNUNET_YES;
1827   if (0 ==
1828       client_send_origin (&grp->pub_key_hash,
1829                           GNUNET_MQ_msg_copy (&out->header)))
1830   { /* No local origins, send to remote origin */
1831     if (NULL != mem->origin_channel)
1832     {
1833       cadet_send_channel (mem->origin_channel, &out->header);
1834       send_ack = GNUNET_NO;
1835     }
1836     else
1837     {
1838       /* FIXME: not yet connected to origin */
1839       GNUNET_SERVICE_client_drop (client);
1840       GNUNET_free (out);
1841       return;
1842     }
1843   }
1844   if (GNUNET_YES == send_ack)
1845   {
1846     client_send_ack (&grp->pub_key_hash);
1847   }
1848   GNUNET_free (out);
1849   GNUNET_SERVICE_client_continue (client);
1850 }
1851
1852
1853 /**
1854  * Incoming replay request from a client.
1855  */
1856 static void
1857 handle_client_replay_request (void *cls,
1858                               const struct MulticastReplayRequestMessage *rep)
1859 {
1860   struct Client *c = cls;
1861   struct GNUNET_SERVICE_Client *client = c->client;
1862   struct Group *grp = c->group;
1863
1864   if (NULL == grp)
1865   {
1866     GNUNET_break (0);
1867     GNUNET_SERVICE_client_drop (client);
1868     return;
1869   }
1870   GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1871   GNUNET_assert (GNUNET_NO == grp->is_origin);
1872   struct Member *mem = grp->member;
1873
1874   struct GNUNET_CONTAINER_MultiHashMap *
1875     grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1876                                                         &grp->pub_key_hash);
1877   if (NULL == grp_replay_req)
1878   {
1879     grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1880     GNUNET_CONTAINER_multihashmap_put (replay_req_client,
1881                                        &grp->pub_key_hash, grp_replay_req,
1882                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1883   }
1884
1885   struct GNUNET_HashCode key_hash;
1886   replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset,
1887                    rep->flags, &key_hash);
1888   GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
1889                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1890
1891   if (0 ==
1892       client_send_origin (&grp->pub_key_hash,
1893                           GNUNET_MQ_msg_copy (&rep->header)))
1894   { /* No local origin, replay from remote members / origin. */
1895     if (NULL != mem->origin_channel)
1896     {
1897       cadet_send_channel (mem->origin_channel, &rep->header);
1898     }
1899     else
1900     {
1901       /* FIXME: not yet connected to origin */
1902       
1903       GNUNET_assert (0);
1904       GNUNET_SERVICE_client_drop (client);
1905       return;
1906     }
1907   }
1908   GNUNET_SERVICE_client_continue (client);
1909 }
1910
1911
1912 static int
1913 cadet_send_replay_response_cb (void *cls,
1914                                const struct GNUNET_HashCode *key_hash,
1915                                void *value)
1916 {
1917   struct Channel *chn = value;
1918   struct GNUNET_MessageHeader *msg = cls;
1919
1920   cadet_send_channel (chn, msg);
1921   return GNUNET_OK;
1922 }
1923
1924
1925 static int
1926 client_send_replay_response_cb (void *cls,
1927                                 const struct GNUNET_HashCode *key_hash,
1928                                 void *value)
1929 {
1930   struct GNUNET_SERVICE_Client *client = value;
1931   struct GNUNET_MessageHeader *msg = cls;
1932
1933   client_send (client, msg);
1934   return GNUNET_OK;
1935 }
1936
1937
1938 static int
1939 check_client_replay_response_end (void *cls,
1940                                   const struct MulticastReplayResponseMessage *res)
1941 {
1942   return GNUNET_OK;
1943 }
1944
1945
1946 /**
1947  * End of replay response from a client.
1948  */
1949 static void
1950 handle_client_replay_response_end (void *cls,
1951                                    const struct MulticastReplayResponseMessage *res)
1952 {
1953   struct Client *c = cls;
1954   struct GNUNET_SERVICE_Client *client = c->client;
1955   struct Group *grp = c->group;
1956
1957   if (NULL == grp)
1958   {
1959     GNUNET_break (0);
1960     GNUNET_SERVICE_client_drop (client);
1961     return;
1962   }
1963   GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1964
1965   struct GNUNET_HashCode key_hash;
1966   replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1967                    res->flags, &key_hash);
1968
1969   struct GNUNET_CONTAINER_MultiHashMap *
1970     grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1971                                                               &grp->pub_key_hash);
1972   if (NULL != grp_replay_req_cadet)
1973   {
1974     GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash);
1975   }
1976   struct GNUNET_CONTAINER_MultiHashMap *
1977     grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1978                                                                &grp->pub_key_hash);
1979   if (NULL != grp_replay_req_client)
1980   {
1981     GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash);
1982   }
1983   GNUNET_SERVICE_client_continue (client);
1984 }
1985
1986
1987 static int
1988 check_client_replay_response (void *cls,
1989                               const struct MulticastReplayResponseMessage *res)
1990 {
1991   const struct GNUNET_MessageHeader *msg;
1992   if (GNUNET_MULTICAST_REC_OK == res->error_code)
1993   {
1994     msg = GNUNET_MQ_extract_nested_mh (res);
1995     if (NULL == msg)
1996     {
1997       return GNUNET_SYSERR;
1998     }
1999   }
2000   return GNUNET_OK;
2001 }
2002
2003
2004 /**
2005  * Incoming replay response from a client.
2006  *
2007  * Respond with a multicast message on success, or otherwise with an error code.
2008  */
2009 static void
2010 handle_client_replay_response (void *cls,
2011                                const struct MulticastReplayResponseMessage *res)
2012 {
2013   struct Client *c = cls;
2014   struct GNUNET_SERVICE_Client *client = c->client;
2015   struct Group *grp = c->group;
2016
2017   if (NULL == grp)
2018   {
2019     GNUNET_break (0);
2020     GNUNET_SERVICE_client_drop (client);
2021     return;
2022   }
2023   GNUNET_assert (GNUNET_NO == grp->is_disconnected);
2024
2025   const struct GNUNET_MessageHeader *msg = &res->header;
2026   if (GNUNET_MULTICAST_REC_OK == res->error_code)
2027   {
2028     msg = GNUNET_MQ_extract_nested_mh (res);
2029   }
2030
2031   struct GNUNET_HashCode key_hash;
2032   replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
2033                    res->flags, &key_hash);
2034
2035   struct GNUNET_CONTAINER_MultiHashMap *
2036     grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
2037                                                               &grp->pub_key_hash);
2038   if (NULL != grp_replay_req_cadet)
2039   {
2040     GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash,
2041                                                 cadet_send_replay_response_cb,
2042                                                 (void *) msg);
2043   }
2044   if (GNUNET_MULTICAST_REC_OK == res->error_code)
2045   {
2046     struct GNUNET_CONTAINER_MultiHashMap *
2047       grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
2048                                                                  &grp->pub_key_hash);
2049     if (NULL != grp_replay_req_client)
2050     {
2051       GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash,
2052                                                   client_send_replay_response_cb,
2053                                                   (void *) msg);
2054     }
2055   }
2056   else
2057   {
2058     handle_client_replay_response_end (c, res);
2059     return;
2060   }
2061   GNUNET_SERVICE_client_continue (client);
2062 }
2063
2064
2065 /**
2066  * A new client connected.
2067  *
2068  * @param cls NULL
2069  * @param client client to add
2070  * @param mq message queue for @a client
2071  * @return @a client
2072  */
2073 static void *
2074 client_notify_connect (void *cls,
2075                        struct GNUNET_SERVICE_Client *client,
2076                        struct GNUNET_MQ_Handle *mq)
2077 {
2078   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
2079   /* FIXME: send connect ACK */
2080
2081   struct Client *c = GNUNET_new (struct Client);
2082   c->client = client;
2083
2084   return c;
2085 }
2086
2087
2088 /**
2089  * Called whenever a client is disconnected.
2090  * Frees our resources associated with that client.
2091  *
2092  * @param cls closure
2093  * @param client identification of the client
2094  * @param app_ctx must match @a client
2095  */
2096 static void
2097 client_notify_disconnect (void *cls,
2098                           struct GNUNET_SERVICE_Client *client,
2099                           void *app_ctx)
2100 {
2101   struct Client *c = app_ctx;
2102   struct Group *grp = c->group;
2103   GNUNET_free (c);
2104
2105   if (NULL == grp)
2106   {
2107     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2108                 "%p User context is NULL in client_disconnect()\n", grp);
2109     GNUNET_break (0);
2110     return;
2111   }
2112
2113   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2114               "%p Client (%s) disconnected from group %s\n",
2115               grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
2116               GNUNET_h2s (&grp->pub_key_hash));
2117
2118   // FIXME (due to protocol change): here we must not remove all clients,
2119   // only the one we were notified about!
2120   struct ClientList *cl = grp->clients_head;
2121   while (NULL != cl)
2122   {
2123     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2124                 "iterating clients for group %p\n",
2125                 grp);
2126     if (cl->client == client)
2127     {
2128       GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
2129       GNUNET_free (cl);
2130       break;
2131     }
2132     cl = cl->next;
2133   }
2134
2135   while (GNUNET_YES == replay_req_remove_client (grp, client));
2136
2137   if (NULL == grp->clients_head)
2138   { /* Last client disconnected. */
2139     cleanup_group (grp);
2140   }
2141 }
2142
2143
2144 /**
2145  * Service started.
2146  *
2147  * @param cls closure
2148  * @param server the initialized server
2149  * @param cfg configuration to use
2150  */
2151 static void
2152 run (void *cls,
2153      const struct GNUNET_CONFIGURATION_Handle *c,
2154      struct GNUNET_SERVICE_Handle *svc)
2155 {
2156   cfg = c;
2157   service = svc;
2158   GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
2159
2160   stats = GNUNET_STATISTICS_create ("multicast", cfg);
2161   origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2162   members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2163   group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2164   channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2165   channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2166   replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2167   replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2168
2169   cadet = GNUNET_CADET_connect (cfg);
2170
2171   GNUNET_assert (NULL != cadet);
2172
2173   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
2174                                  NULL);
2175 }
2176
2177
2178 /**
2179  * Define "main" method using service macro.
2180  */
2181 GNUNET_SERVICE_MAIN
2182 ("multicast",
2183  GNUNET_SERVICE_OPTION_NONE,
2184  &run,
2185  &client_notify_connect,
2186  &client_notify_disconnect,
2187  NULL,
2188  GNUNET_MQ_hd_fixed_size (client_origin_start,
2189                           GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START,
2190                           struct MulticastOriginStartMessage,
2191                           NULL),
2192  GNUNET_MQ_hd_var_size (client_member_join,
2193                         GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN,
2194                         struct MulticastMemberJoinMessage,
2195                         NULL),
2196  GNUNET_MQ_hd_var_size (client_join_decision,
2197                         GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
2198                         struct MulticastJoinDecisionMessageHeader,
2199                         NULL),
2200  GNUNET_MQ_hd_fixed_size (client_part_request,
2201                           GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST,
2202                           struct GNUNET_MessageHeader,
2203                           NULL),
2204  GNUNET_MQ_hd_var_size (client_multicast_message,
2205                         GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
2206                         struct GNUNET_MULTICAST_MessageHeader,
2207                         NULL),
2208  GNUNET_MQ_hd_var_size (client_multicast_request,
2209                         GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
2210                         struct GNUNET_MULTICAST_RequestHeader,
2211                         NULL),
2212  GNUNET_MQ_hd_fixed_size (client_replay_request,
2213                           GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
2214                           struct MulticastReplayRequestMessage,
2215                           NULL),
2216  GNUNET_MQ_hd_var_size (client_replay_response,
2217                         GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
2218                         struct MulticastReplayResponseMessage,
2219                         NULL),
2220  GNUNET_MQ_hd_var_size (client_replay_response_end,
2221                         GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END,
2222                         struct MulticastReplayResponseMessage,
2223                         NULL));
2224
2225 /* end of gnunet-service-multicast.c */