multicast: use CADET port hash derived from group key
[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
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/gnunet-service-multicast.c
23  * @brief program that does multicast
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_signatures.h"
29 #include "gnunet_applications.h"
30 #include "gnunet_statistics_service.h"
31 #include "gnunet_core_service.h"
32 #include "gnunet_cadet_service.h"
33 #include "gnunet_multicast_service.h"
34 #include "multicast.h"
35
36 /**
37  * Handle to our current configuration.
38  */
39 static const struct GNUNET_CONFIGURATION_Handle *cfg;
40
41 /**
42  * Server handle.
43  */
44 static struct GNUNET_SERVER_Handle *server;
45
46 /**
47  * Core handle.
48  * Only used during initialization.
49  */
50 static struct GNUNET_CORE_Handle *core;
51
52 /**
53  * CADET handle.
54  */
55 static struct GNUNET_CADET_Handle *cadet;
56
57 /**
58  * Identity of this peer.
59  */
60 static struct GNUNET_PeerIdentity this_peer;
61
62 /**
63  * Handle to the statistics service.
64  */
65 static struct GNUNET_STATISTICS_Handle *stats;
66
67 /**
68  * Notification context, simplifies client broadcasts.
69  */
70 static struct GNUNET_SERVER_NotificationContext *nc;
71
72 /**
73  * All connected origin clients.
74  * Group's pub_key_hash -> struct Origin * (uniq)
75  */
76 static struct GNUNET_CONTAINER_MultiHashMap *origins;
77
78 /**
79  * All connected member clients.
80  * Group's pub_key_hash -> struct Member * (multi)
81  */
82 static struct GNUNET_CONTAINER_MultiHashMap *members;
83
84 /**
85  * Connected member clients per group.
86  * Group's pub_key_hash -> Member's pub_key_hash (uniq) -> struct Member * (uniq)
87  */
88 static struct GNUNET_CONTAINER_MultiHashMap *group_members;
89
90 /**
91  * Incoming CADET channels with connected children in the tree.
92  * Group's pub_key_hash -> struct Channel * (multi)
93  */
94 static struct GNUNET_CONTAINER_MultiHashMap *channels_in;
95
96 /**
97  * Outgoing CADET channels connecting to parents in the tree.
98  * Group's pub_key_hash -> struct Channel * (multi)
99  */
100 static struct GNUNET_CONTAINER_MultiHashMap *channels_out;
101
102 /**
103  * Incoming replay requests from CADET.
104  * Group's pub_key_hash ->
105  *   H(fragment_id, message_id, fragment_offset, flags) -> struct Channel *
106  */
107 static struct GNUNET_CONTAINER_MultiHashMap *replay_req_cadet;
108
109 /**
110  * Incoming replay requests from clients.
111  * Group's pub_key_hash ->
112  *   H(fragment_id, message_id, fragment_offset, flags) -> struct GNUNET_SERVER_Client *
113  */
114 static struct GNUNET_CONTAINER_MultiHashMap *replay_req_client;
115
116
117 /**
118  * Join status of a remote peer.
119  */
120 enum JoinStatus
121 {
122   JOIN_REFUSED  = -1,
123   JOIN_NOT_ASKED = 0,
124   JOIN_WAITING   = 1,
125   JOIN_ADMITTED  = 2,
126 };
127
128 enum ChannelDirection
129 {
130   DIR_INCOMING = 0,
131   DIR_OUTGOING = 1,
132 };
133
134
135 /**
136  * Context for a CADET channel.
137  */
138 struct Channel
139 {
140   /**
141    * Group the channel belongs to.
142    *
143    * Only set for outgoing channels.
144    */
145   struct Group *grp;
146
147   /**
148    * CADET channel.
149    */
150   struct GNUNET_CADET_Channel *channel;
151
152   /**
153    * CADET transmission handle.
154    */
155   struct GNUNET_CADET_TransmitHandle *tmit_handle;
156
157   /**
158    * Public key of the target group.
159    */
160   struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
161
162   /**
163    * Hash of @a group_pub_key.
164    */
165   struct GNUNET_HashCode group_pub_hash;
166
167   /**
168    * Public key of the joining member.
169    */
170   struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
171
172   /**
173    * Remote peer identity.
174    */
175   struct GNUNET_PeerIdentity peer;
176
177   /**
178    * Is the remote peer admitted to the group?
179    * @see enum JoinStatus
180    */
181   int8_t join_status;
182
183   /**
184    * Number of messages waiting to be sent to CADET.
185    */
186   uint8_t msgs_pending;
187
188   /**
189    * Channel direction.
190    * @see enum ChannelDirection
191    */
192   uint8_t direction;
193 };
194
195
196 /**
197  * List of connected clients.
198  */
199 struct ClientList
200 {
201   struct ClientList *prev;
202   struct ClientList *next;
203   struct GNUNET_SERVER_Client *client;
204 };
205
206 /**
207  * Common part of the client context for both an origin and member.
208  */
209 struct Group
210 {
211   struct ClientList *clients_head;
212   struct ClientList *clients_tail;
213
214   /**
215    * Public key of the group.
216    */
217   struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
218
219   /**
220    * Hash of @a pub_key.
221    */
222   struct GNUNET_HashCode pub_key_hash;
223
224   /**
225    * CADET port hash.
226    */
227   struct GNUNET_HashCode cadet_port_hash;
228
229   /**
230    * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)?
231    */
232   uint8_t is_origin;
233
234   /**
235    * Is the client disconnected? #GNUNET_YES or #GNUNET_NO
236    */
237   uint8_t disconnected;
238 };
239
240
241 /**
242  * Client context for a group's origin.
243  */
244 struct Origin
245 {
246   struct Group grp;
247
248   /**
249    * Private key of the group.
250    */
251   struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
252
253   /**
254    * Last message fragment ID sent to the group.
255    */
256   uint64_t max_fragment_id;
257 };
258
259
260 /**
261  * Client context for a group member.
262  */
263 struct Member
264 {
265   struct Group grp;
266
267   /**
268    * Private key of the member.
269    */
270   struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
271
272   /**
273    * Public key of the member.
274    */
275   struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
276
277   /**
278    * Hash of @a pub_key.
279    */
280   struct GNUNET_HashCode pub_key_hash;
281
282   /**
283    * Join request sent to the origin / members.
284    */
285   struct MulticastJoinRequestMessage *join_req;
286
287   /**
288    * Join decision sent in reply to our request.
289    *
290    * Only a positive decision is stored here, in case of a negative decision the
291    * client is disconnected.
292    */
293   struct MulticastJoinDecisionMessageHeader *join_dcsn;
294
295   /**
296    * CADET channel to the origin.
297    */
298   struct Channel *origin_channel;
299
300   /**
301    * Peer identity of origin.
302    */
303   struct GNUNET_PeerIdentity origin;
304
305   /**
306    * Peer identity of relays (other members to connect).
307    */
308   struct GNUNET_PeerIdentity *relays;
309
310   /**
311    * Last request fragment ID sent to the origin.
312    */
313   uint64_t max_fragment_id;
314
315   /**
316    * Number of @a relays.
317    */
318   uint32_t relay_count;
319 };
320
321
322 struct ReplayRequestKey
323 {
324   uint64_t fragment_id;
325   uint64_t message_id;
326   uint64_t fragment_offset;
327   uint64_t flags;
328 };
329
330
331 /**
332  * Task run during shutdown.
333  *
334  * @param cls unused
335  */
336 static void
337 shutdown_task (void *cls)
338 {
339   if (NULL != core)
340   {
341     GNUNET_CORE_disconnecT (core);
342     core = NULL;
343   }
344   if (NULL != cadet)
345   {
346     GNUNET_CADET_disconnect (cadet);
347     cadet = NULL;
348   }
349   if (NULL != stats)
350   {
351     GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
352     stats = NULL;
353   }
354   /* FIXME: do more clean up here */
355 }
356
357
358 /**
359  * Clean up origin data structures after a client disconnected.
360  */
361 static void
362 cleanup_origin (struct Origin *orig)
363 {
364   struct Group *grp = &orig->grp;
365   GNUNET_CONTAINER_multihashmap_remove (origins, &grp->pub_key_hash, orig);
366 }
367
368
369 /**
370  * Clean up member data structures after a client disconnected.
371  */
372 static void
373 cleanup_member (struct Member *mem)
374 {
375   struct Group *grp = &mem->grp;
376   struct GNUNET_CONTAINER_MultiHashMap *
377     grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
378                                                  &grp->pub_key_hash);
379   GNUNET_assert (NULL != grp_mem);
380   GNUNET_CONTAINER_multihashmap_remove (grp_mem, &mem->pub_key_hash, mem);
381
382   if (0 == GNUNET_CONTAINER_multihashmap_size (grp_mem))
383   {
384     GNUNET_CONTAINER_multihashmap_remove (group_members, &grp->pub_key_hash,
385                                           grp_mem);
386     GNUNET_CONTAINER_multihashmap_destroy (grp_mem);
387   }
388   if (NULL != mem->join_dcsn)
389   {
390     GNUNET_free (mem->join_dcsn);
391     mem->join_dcsn = NULL;
392   }
393   GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
394 }
395
396
397 /**
398  * Clean up group data structures after a client disconnected.
399  */
400 static void
401 cleanup_group (struct Group *grp)
402 {
403   (GNUNET_YES == grp->is_origin)
404     ? cleanup_origin ((struct Origin *) grp)
405     : cleanup_member ((struct Member *) grp);
406
407   GNUNET_free (grp);
408 }
409
410
411 void
412 replay_key_hash (uint64_t fragment_id, uint64_t message_id,
413                  uint64_t fragment_offset, uint64_t flags,
414                  struct GNUNET_HashCode *key_hash)
415 {
416   struct ReplayRequestKey key = {
417     .fragment_id = fragment_id,
418     .message_id = message_id,
419     .fragment_offset = fragment_offset,
420     .flags = flags,
421   };
422   GNUNET_CRYPTO_hash (&key, sizeof (key), key_hash);
423 }
424
425
426 /**
427  * Remove channel from replay request hashmap.
428  *
429  * @param chn
430  *        Channel to remove.
431  *
432  * @return #GNUNET_YES if there are more entries to process,
433  *         #GNUNET_NO when reached end of hashmap.
434  */
435 static int
436 replay_req_remove_cadet (struct Channel *chn)
437 {
438   struct GNUNET_CONTAINER_MultiHashMap *
439     grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
440                                                         &chn->grp->pub_key_hash);
441   if (NULL == grp_replay_req)
442     return GNUNET_NO;
443
444   struct GNUNET_CONTAINER_MultiHashMapIterator *
445     it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
446   struct GNUNET_HashCode key;
447   const struct Channel *c;
448   while (GNUNET_YES
449          == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
450                                                          (const void **) &c))
451   {
452     if (c == chn)
453     {
454       GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, chn);
455       GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
456       return GNUNET_YES;
457     }
458   }
459   GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
460   return GNUNET_NO;
461 }
462
463
464 /**
465  * Remove client from replay request hashmap.
466  *
467  * @param client
468  *        Client to remove.
469  *
470  * @return #GNUNET_YES if there are more entries to process,
471  *         #GNUNET_NO when reached end of hashmap.
472  */
473 static int
474 replay_req_remove_client (struct Group *grp, struct GNUNET_SERVER_Client *client)
475 {
476   struct GNUNET_CONTAINER_MultiHashMap *
477     grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
478                                                         &grp->pub_key_hash);
479   if (NULL == grp_replay_req)
480     return GNUNET_NO;
481
482   struct GNUNET_CONTAINER_MultiHashMapIterator *
483     it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
484   struct GNUNET_HashCode key;
485   const struct GNUNET_SERVER_Client *c;
486   while (GNUNET_YES
487          == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
488                                                          (const void **) &c))
489   {
490     if (c == client)
491     {
492       GNUNET_CONTAINER_multihashmap_remove (replay_req_client, &key, client);
493       GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
494       return GNUNET_YES;
495     }
496   }
497   GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
498   return GNUNET_NO;
499 }
500
501
502 /**
503  * Called whenever a client is disconnected.
504  *
505  * Frees our resources associated with that client.
506  *
507  * @param cls  Closure.
508  * @param client  Client handle.
509  */
510 static void
511 client_notify_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
512 {
513   if (NULL == client)
514     return;
515
516   struct Group *grp
517     = GNUNET_SERVER_client_get_user_context (client, struct Group);
518
519   if (NULL == grp)
520   {
521     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
522                 "%p User context is NULL in client_disconnect()\n", grp);
523     GNUNET_break (0);
524     return;
525   }
526
527   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
528               "%p Client (%s) disconnected from group %s\n",
529               grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
530               GNUNET_h2s (&grp->pub_key_hash));
531
532   struct ClientList *cl = grp->clients_head;
533   while (NULL != cl)
534   {
535     if (cl->client == client)
536     {
537       GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
538       GNUNET_free (cl);
539       break;
540     }
541     cl = cl->next;
542   }
543
544   while (GNUNET_YES == replay_req_remove_client (grp, client));
545
546   if (NULL == grp->clients_head)
547   { /* Last client disconnected. */
548 #if FIXME
549     if (NULL != grp->tmit_head)
550     { /* Send pending messages via CADET before cleanup. */
551       transmit_message (grp);
552     }
553     else
554 #endif
555     {
556       cleanup_group (grp);
557     }
558   }
559 }
560
561
562 /**
563  * Send message to a client.
564  */
565 static void
566 client_send (struct GNUNET_SERVER_Client *client,
567              const struct GNUNET_MessageHeader *msg)
568 {
569   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
570               "%p Sending message to client.\n", client);
571
572   GNUNET_SERVER_notification_context_add (nc, client);
573   GNUNET_SERVER_notification_context_unicast (nc, client, msg, GNUNET_NO);
574 }
575
576
577 /**
578  * Send message to all clients connected to the group.
579  */
580 static void
581 client_send_group (const struct Group *grp,
582                    const struct GNUNET_MessageHeader *msg)
583 {
584   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
585               "%p Sending message to all clients of the group.\n", grp);
586
587   struct ClientList *cl = grp->clients_head;
588   while (NULL != cl)
589   {
590     GNUNET_SERVER_notification_context_add (nc, cl->client);
591     GNUNET_SERVER_notification_context_unicast (nc, cl->client, msg, GNUNET_NO);
592     cl = cl->next;
593   }
594 }
595
596
597 /**
598  * Iterator callback for sending a message to origin clients.
599  */
600 static int
601 client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
602                        void *origin)
603 {
604   const struct GNUNET_MessageHeader *msg = cls;
605   struct Member *orig = origin;
606
607   client_send_group (&orig->grp, msg);
608   return GNUNET_YES;
609 }
610
611
612 /**
613  * Iterator callback for sending a message to member clients.
614  */
615 static int
616 client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
617                        void *member)
618 {
619   const struct GNUNET_MessageHeader *msg = cls;
620   struct Member *mem = member;
621
622   if (NULL != mem->join_dcsn)
623   { /* Only send message to admitted members */
624     client_send_group (&mem->grp, msg);
625   }
626   return GNUNET_YES;
627 }
628
629
630 /**
631  * Send message to all origin and member clients connected to the group.
632  *
633  * @param pub_key_hash
634  *        H(key_pub) of the group.
635  * @param msg
636  *        Message to send.
637  */
638 static int
639 client_send_all (struct GNUNET_HashCode *pub_key_hash,
640                  const struct GNUNET_MessageHeader *msg)
641 {
642   int n = 0;
643   n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
644                                                    client_send_origin_cb,
645                                                    (void *) msg);
646   n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash,
647                                                    client_send_member_cb,
648                                                    (void *) msg);
649   return n;
650 }
651
652
653 /**
654  * Send message to a random origin client or a random member client.
655  *
656  * @param grp  The group to send @a msg to.
657  * @param msg  Message to send.
658  */
659 static int
660 client_send_random (struct GNUNET_HashCode *pub_key_hash,
661                     const struct GNUNET_MessageHeader *msg)
662 {
663   int n = 0;
664   n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb,
665                                                  (void *) msg);
666   if (n <= 0)
667     n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb,
668                                                    (void *) msg);
669   return n;
670 }
671
672
673 /**
674  * Send message to all origin clients connected to the group.
675  *
676  * @param pub_key_hash
677  *        H(key_pub) of the group.
678  * @param msg
679  *        Message to send.
680  */
681 static int
682 client_send_origin (struct GNUNET_HashCode *pub_key_hash,
683                     const struct GNUNET_MessageHeader *msg)
684 {
685   int n = 0;
686   n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
687                                                    client_send_origin_cb,
688                                                    (void *) msg);
689   return n;
690 }
691
692
693 /**
694  * Send fragment acknowledgement to all clients of the channel.
695  *
696  * @param pub_key_hash
697  *        H(key_pub) of the group.
698  */
699 static void
700 client_send_ack (struct GNUNET_HashCode *pub_key_hash)
701 {
702   static struct GNUNET_MessageHeader *msg = NULL;
703   if (NULL == msg)
704   {
705     msg = GNUNET_malloc (sizeof (*msg));
706     msg->type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
707     msg->size = htons (sizeof (*msg));
708   }
709   client_send_all (pub_key_hash, msg);
710 }
711
712
713 struct CadetTransmitClosure
714 {
715   struct Channel *chn;
716   const struct GNUNET_MessageHeader *msg;
717 };
718
719
720 /**
721  * CADET is ready to transmit a message.
722  */
723 size_t
724 cadet_notify_transmit_ready (void *cls, size_t buf_size, void *buf)
725 {
726   if (0 == buf_size)
727   {
728     /* FIXME: connection closed */
729     return 0;
730   }
731   struct CadetTransmitClosure *tcls = cls;
732   struct Channel *chn = tcls->chn;
733   uint16_t msg_size = ntohs (tcls->msg->size);
734   GNUNET_assert (msg_size <= buf_size);
735   GNUNET_memcpy (buf, tcls->msg, msg_size);
736   GNUNET_free (tcls);
737
738   if (0 == chn->msgs_pending)
739   {
740     GNUNET_break (0);
741   }
742   else if (0 == --chn->msgs_pending)
743   {
744     client_send_ack (&chn->group_pub_hash);
745   }
746   return msg_size;
747 }
748
749
750 /**
751  * Send a message to a CADET channel.
752  *
753  * @param chn  Channel.
754  * @param msg  Message.
755  */
756 static void
757 cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg)
758 {
759   struct CadetTransmitClosure *tcls = GNUNET_malloc (sizeof (*tcls));
760   tcls->chn = chn;
761   tcls->msg = msg;
762
763   chn->msgs_pending++;
764   chn->tmit_handle
765     = GNUNET_CADET_notify_transmit_ready (chn->channel, GNUNET_NO,
766                                           GNUNET_TIME_UNIT_FOREVER_REL,
767                                           ntohs (msg->size),
768                                           &cadet_notify_transmit_ready,
769                                           tcls);
770   GNUNET_assert (NULL != chn->tmit_handle);
771 }
772
773
774 /**
775  * Create new outgoing CADET channel.
776  *
777  * @param peer
778  *        Peer to connect to.
779  * @param group_pub_key
780  *        Public key of group the channel belongs to.
781  * @param group_pub_hash
782  *        Hash of @a group_pub_key.
783  *
784  * @return Channel.
785  */
786 static struct Channel *
787 cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer)
788 {
789   struct Channel *chn = GNUNET_malloc (sizeof (*chn));
790   chn->grp = grp;
791   chn->group_pub_key = grp->pub_key;
792   chn->group_pub_hash = grp->pub_key_hash;
793   chn->peer = *peer;
794   chn->direction = DIR_OUTGOING;
795   chn->join_status = JOIN_WAITING;
796   chn->channel = GNUNET_CADET_channel_create (cadet, chn, &chn->peer,
797                                               &grp->cadet_port_hash,
798                                               GNUNET_CADET_OPTION_RELIABLE);
799   GNUNET_CONTAINER_multihashmap_put (channels_out, &chn->group_pub_hash, chn,
800                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
801   return chn;
802 }
803
804
805 /**
806  * Create CADET channel and send a join request.
807  */
808 static void
809 cadet_send_join_request (struct Member *mem)
810 {
811   mem->origin_channel = cadet_channel_create (&mem->grp, &mem->origin);
812   cadet_send_channel (mem->origin_channel, &mem->join_req->header);
813
814   uint32_t i;
815   for (i = 0; i < mem->relay_count; i++)
816   {
817     struct Channel *
818       chn = cadet_channel_create (&mem->grp, &mem->relays[i]);
819     cadet_send_channel (chn, &mem->join_req->header);
820   }
821 }
822
823
824 static int
825 cadet_send_join_decision_cb (void *cls,
826                              const struct GNUNET_HashCode *group_pub_hash,
827                              void *channel)
828 {
829   const struct MulticastJoinDecisionMessageHeader *hdcsn = cls;
830   struct Channel *chn = channel;
831
832   if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key))
833       && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer)))
834   {
835     cadet_send_channel (chn, &hdcsn->header);
836     return GNUNET_NO;
837   }
838   return GNUNET_YES;
839 }
840
841
842 /**
843  * Send join decision to a remote peer.
844  */
845 static void
846 cadet_send_join_decision (struct Group *grp,
847                           const struct MulticastJoinDecisionMessageHeader *hdcsn)
848 {
849   GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, &grp->pub_key_hash,
850                                               &cadet_send_join_decision_cb,
851                                               (void *) hdcsn);
852 }
853
854
855 /**
856  * Iterator callback for sending a message to origin clients.
857  */
858 static int
859 cadet_send_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
860                void *channel)
861 {
862   const struct GNUNET_MessageHeader *msg = cls;
863   struct Channel *chn = channel;
864   if (JOIN_ADMITTED == chn->join_status)
865     cadet_send_channel (chn, msg);
866   return GNUNET_YES;
867 }
868
869
870 /**
871  * Send message to all connected children.
872  */
873 static int
874 cadet_send_children (struct GNUNET_HashCode *pub_key_hash,
875                      const struct GNUNET_MessageHeader *msg)
876 {
877   int n = 0;
878   if (channels_in != NULL)
879     n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash,
880                                                      cadet_send_cb, (void *) msg);
881   return n;
882 }
883
884
885 #if 0       // unused as yet
886 /**
887  * Send message to all connected parents.
888  */
889 static int
890 cadet_send_parents (struct GNUNET_HashCode *pub_key_hash,
891                     const struct GNUNET_MessageHeader *msg)
892 {
893   int n = 0;
894   if (channels_in != NULL)
895     n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_out, pub_key_hash,
896                                                      cadet_send_cb, (void *) msg);
897   return n;
898 }
899 #endif
900
901
902 /**
903  * New incoming CADET channel.
904  */
905 static void *
906 cadet_notify_channel_new (void *cls,
907                           struct GNUNET_CADET_Channel *channel,
908                           const struct GNUNET_PeerIdentity *initiator,
909                           const struct GNUNET_HashCode *port,
910                           enum GNUNET_CADET_ChannelOption options)
911 {
912   return NULL;
913 }
914
915
916 /**
917  * CADET channel is being destroyed.
918  */
919 static void
920 cadet_notify_channel_end (void *cls,
921                           const struct GNUNET_CADET_Channel *channel,
922                           void *ctx)
923 {
924   if (NULL == ctx)
925     return;
926
927   struct Channel *chn = ctx;
928   if (NULL != chn->grp)
929   {
930     if (GNUNET_NO == chn->grp->is_origin)
931     {
932       struct Member *mem = (struct Member *) chn->grp;
933       if (chn == mem->origin_channel)
934         mem->origin_channel = NULL;
935     }
936   }
937
938   while (GNUNET_YES == replay_req_remove_cadet (chn));
939
940   GNUNET_free (chn);
941 }
942
943
944 static void
945 group_set_cadet_port_hash (struct Group *grp)
946 {
947   struct CadetPort {
948     struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
949     uint32_t app_type;
950   } port = {
951     grp->pub_key,
952     GNUNET_APPLICATION_TYPE_MULTICAST,
953   };
954
955   GNUNET_CRYPTO_hash (&port, sizeof (port), &grp->cadet_port_hash);
956 }
957
958
959 /**
960  * Handle a connecting client starting an origin.
961  */
962 static void
963 client_recv_origin_start (void *cls, struct GNUNET_SERVER_Client *client,
964                           const struct GNUNET_MessageHeader *m)
965 {
966   const struct MulticastOriginStartMessage *
967     msg = (const struct MulticastOriginStartMessage *) m;
968
969   struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
970   struct GNUNET_HashCode pub_key_hash;
971
972   GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key);
973   GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
974
975   struct Origin *
976     orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash);
977   struct Group *grp;
978
979   if (NULL == orig)
980   {
981     orig = GNUNET_new (struct Origin);
982     orig->priv_key = msg->group_key;
983     orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
984     grp = &orig->grp;
985     grp->is_origin = GNUNET_YES;
986     grp->pub_key = pub_key;
987     grp->pub_key_hash = pub_key_hash;
988
989     GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
990                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
991     group_set_cadet_port_hash (grp);
992     GNUNET_CADET_open_port (cadet, &grp->cadet_port_hash,
993                             cadet_notify_channel_new, NULL);
994
995   }
996   else
997   {
998     grp = &orig->grp;
999   }
1000
1001   struct ClientList *cl = GNUNET_new (struct ClientList);
1002   cl->client = client;
1003   GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1004
1005   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1006               "%p Client connected as origin to group %s.\n",
1007               orig, GNUNET_h2s (&grp->pub_key_hash));
1008
1009   GNUNET_SERVER_client_set_user_context (client, grp);
1010   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1011 }
1012
1013
1014 /**
1015  * Handle a connecting client joining a group.
1016  */
1017 static void
1018 client_recv_member_join (void *cls, struct GNUNET_SERVER_Client *client,
1019                          const struct GNUNET_MessageHeader *m)
1020 {
1021   const struct MulticastMemberJoinMessage *
1022     msg = (const struct MulticastMemberJoinMessage *) m;
1023   uint16_t msg_size = ntohs (msg->header.size);
1024
1025   struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key;
1026   struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
1027
1028   GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key);
1029   GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
1030   GNUNET_CRYPTO_hash (&msg->group_pub_key, sizeof (msg->group_pub_key), &pub_key_hash);
1031
1032   struct GNUNET_CONTAINER_MultiHashMap *
1033     grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash);
1034   struct Member *mem = NULL;
1035   struct Group *grp;
1036
1037   if (NULL != grp_mem)
1038   {
1039     mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
1040   }
1041   if (NULL == mem)
1042   {
1043     mem = GNUNET_new (struct Member);
1044     mem->priv_key = msg->member_key;
1045     mem->pub_key = mem_pub_key;
1046     mem->pub_key_hash = mem_pub_key_hash;
1047     mem->max_fragment_id = 0; // FIXME
1048
1049     grp = &mem->grp;
1050     grp->is_origin = GNUNET_NO;
1051     grp->pub_key = msg->group_pub_key;
1052     grp->pub_key_hash = pub_key_hash;
1053     group_set_cadet_port_hash (grp);
1054
1055     if (NULL == grp_mem)
1056     {
1057       grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1058       GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, grp_mem,
1059                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1060     }
1061     GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
1062                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1063     GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
1064                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1065   }
1066   else
1067   {
1068     grp = &mem->grp;
1069   }
1070
1071   struct ClientList *cl = GNUNET_new (struct ClientList);
1072   cl->client = client;
1073   GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1074
1075   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1076               "%p Client connected to group %s..\n",
1077               mem, GNUNET_h2s (&grp->pub_key_hash));
1078   char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
1079   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1080               "%p ..as member %s (%s).\n",
1081               mem, GNUNET_h2s (&mem->pub_key_hash), str);
1082   GNUNET_free (str);
1083
1084   GNUNET_SERVER_client_set_user_context (client, grp);
1085
1086   if (NULL != mem->join_dcsn)
1087   { /* Already got a join decision, send it to client. */
1088     GNUNET_SERVER_notification_context_add (nc, client);
1089     GNUNET_SERVER_notification_context_unicast (nc, client,
1090                                                 (struct GNUNET_MessageHeader *)
1091                                                 mem->join_dcsn,
1092                                                 GNUNET_NO);
1093   }
1094   else
1095   { /* First client of the group, send join request. */
1096     struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1097     uint32_t relay_count = ntohl (msg->relay_count);
1098     uint16_t relay_size = relay_count * sizeof (*relays);
1099     struct GNUNET_MessageHeader *join_msg = NULL;
1100     uint16_t join_msg_size = 0;
1101     if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1102         <= msg_size)
1103     {
1104       join_msg = (struct GNUNET_MessageHeader *)
1105         (((char *) &msg[1]) + relay_size);
1106       join_msg_size = ntohs (join_msg->size);
1107     }
1108     if (sizeof (*msg) + relay_size + join_msg_size != msg_size)
1109     {
1110       GNUNET_break (0);
1111       GNUNET_SERVER_client_disconnect (client);
1112       return;
1113     }
1114
1115     struct MulticastJoinRequestMessage *
1116       req = GNUNET_malloc (sizeof (*req) + join_msg_size);
1117     req->header.size = htons (sizeof (*req) + join_msg_size);
1118     req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
1119     req->group_pub_key = grp->pub_key;
1120     req->peer = this_peer;
1121     GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_pub_key);
1122     if (0 < join_msg_size)
1123       GNUNET_memcpy (&req[1], join_msg, join_msg_size);
1124
1125     req->member_pub_key = mem->pub_key;
1126     req->purpose.size = htonl (msg_size
1127                                - sizeof (req->header)
1128                                - sizeof (req->reserved)
1129                                - sizeof (req->signature));
1130     req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1131
1132     if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose,
1133                                                &req->signature))
1134     {
1135       /* FIXME: handle error */
1136       GNUNET_assert (0);
1137     }
1138
1139     if (NULL != mem->join_req)
1140       GNUNET_free (mem->join_req);
1141     mem->join_req = req;
1142
1143     if (0 == client_send_origin (&grp->pub_key_hash, &mem->join_req->header))
1144     { /* No local origins, send to remote origin */
1145       cadet_send_join_request (mem);
1146     }
1147   }
1148   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1149 }
1150
1151
1152 static void
1153 client_send_join_decision (struct Member *mem,
1154                            const struct MulticastJoinDecisionMessageHeader *hdcsn)
1155 {
1156   client_send_group (&mem->grp, &hdcsn->header);
1157
1158   const struct MulticastJoinDecisionMessage *
1159     dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1160   if (GNUNET_YES == ntohl (dcsn->is_admitted))
1161   { /* Member admitted, store join_decision. */
1162     uint16_t dcsn_size = ntohs (dcsn->header.size);
1163     mem->join_dcsn = GNUNET_malloc (dcsn_size);
1164     GNUNET_memcpy (mem->join_dcsn, dcsn, dcsn_size);
1165   }
1166   else
1167   { /* Refused entry, but replay would be still possible for past members. */
1168   }
1169 }
1170
1171
1172 /**
1173  * Join decision from client.
1174  */
1175 static void
1176 client_recv_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
1177                            const struct GNUNET_MessageHeader *m)
1178 {
1179   struct Group *
1180     grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1181   const struct MulticastJoinDecisionMessageHeader *
1182     hdcsn = (const struct MulticastJoinDecisionMessageHeader *) m;
1183
1184   if (NULL == grp)
1185   {
1186     GNUNET_break (0);
1187     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1188     return;
1189   }
1190   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1191               "%p Got join decision from client for group %s..\n",
1192               grp, GNUNET_h2s (&grp->pub_key_hash));
1193
1194   struct GNUNET_CONTAINER_MultiHashMap *
1195     grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
1196                                                  &grp->pub_key_hash);
1197   struct Member *mem = NULL;
1198   if (NULL != grp_mem)
1199   {
1200     struct GNUNET_HashCode member_key_hash;
1201     GNUNET_CRYPTO_hash (&hdcsn->member_pub_key, sizeof (hdcsn->member_pub_key),
1202                         &member_key_hash);
1203     mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
1204     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1205                 "%p ..and member %s: %p\n",
1206                 grp, GNUNET_h2s (&member_key_hash), mem);
1207   }
1208   if (NULL != mem)
1209   { /* Found local member */
1210     client_send_join_decision (mem, hdcsn);
1211   }
1212   else
1213   { /* Look for remote member */
1214     cadet_send_join_decision (grp, hdcsn);
1215   }
1216   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1217 }
1218
1219
1220 /**
1221  * Incoming message from a client.
1222  */
1223 static void
1224 client_recv_multicast_message (void *cls, struct GNUNET_SERVER_Client *client,
1225                                const struct GNUNET_MessageHeader *m)
1226 {
1227   struct Group *
1228     grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1229   struct GNUNET_MULTICAST_MessageHeader *out;
1230   struct Origin *orig;
1231
1232   if (NULL == grp)
1233   {
1234     GNUNET_break (0);
1235     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1236     return;
1237   }
1238   GNUNET_assert (GNUNET_YES == grp->is_origin);
1239   orig = (struct Origin *) grp;
1240
1241   /* FIXME: yucky, should use separate message structs for P2P and CS! */
1242   out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (m);
1243   out->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
1244   out->purpose.size = htonl (ntohs (out->header.size)
1245                              - sizeof (out->header)
1246                              - sizeof (out->hop_counter)
1247                              - sizeof (out->signature));
1248   out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE);
1249
1250   if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &out->purpose,
1251                                              &out->signature))
1252   {
1253     GNUNET_assert (0);
1254   }
1255
1256   client_send_all (&grp->pub_key_hash, &out->header);
1257   if (0 == cadet_send_children (&grp->pub_key_hash, &out->header))
1258   {
1259     client_send_ack (&grp->pub_key_hash);
1260   }
1261   GNUNET_free (out);
1262
1263   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1264 }
1265
1266
1267 /**
1268  * Incoming request from a client.
1269  */
1270 static void
1271 client_recv_multicast_request (void *cls, struct GNUNET_SERVER_Client *client,
1272                                const struct GNUNET_MessageHeader *m)
1273 {
1274   struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1275   struct Member *mem;
1276   struct GNUNET_MULTICAST_RequestHeader *out;
1277   if (NULL == grp)
1278   {
1279     GNUNET_break (0);
1280     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1281     return;
1282   }
1283   GNUNET_assert (GNUNET_NO == grp->is_origin);
1284   mem = (struct Member *) grp;
1285
1286   /* FIXME: yucky, should use separate message structs for P2P and CS! */
1287   out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (m);
1288   out->member_pub_key = mem->pub_key;
1289   out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
1290   out->purpose.size = htonl (ntohs (out->header.size)
1291                              - sizeof (out->header)
1292                              - sizeof (out->member_pub_key)
1293                              - sizeof (out->signature));
1294   out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1295
1296   if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &out->purpose,
1297                                              &out->signature))
1298   {
1299     GNUNET_assert (0);
1300   }
1301
1302   uint8_t send_ack = GNUNET_YES;
1303   if (0 == client_send_origin (&grp->pub_key_hash, &out->header))
1304   { /* No local origins, send to remote origin */
1305     if (NULL != mem->origin_channel)
1306     {
1307       cadet_send_channel (mem->origin_channel, &out->header);
1308       send_ack = GNUNET_NO;
1309     }
1310     else
1311     {
1312       /* FIXME: not yet connected to origin */
1313       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1314       GNUNET_free (out);
1315       return;
1316     }
1317   }
1318   if (GNUNET_YES == send_ack)
1319   {
1320     client_send_ack (&grp->pub_key_hash);
1321   }
1322   GNUNET_free (out);
1323   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1324 }
1325
1326
1327 /**
1328  * Incoming replay request from a client.
1329  */
1330 static void
1331 client_recv_replay_request (void *cls, struct GNUNET_SERVER_Client *client,
1332                             const struct GNUNET_MessageHeader *m)
1333 {
1334   struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1335   struct Member *mem;
1336   if (NULL == grp)
1337   {
1338     GNUNET_break (0);
1339     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1340     return;
1341   }
1342   GNUNET_assert (GNUNET_NO == grp->is_origin);
1343   mem = (struct Member *) grp;
1344
1345   struct GNUNET_CONTAINER_MultiHashMap *
1346     grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1347                                                         &grp->pub_key_hash);
1348   if (NULL == grp_replay_req)
1349   {
1350     grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1351     GNUNET_CONTAINER_multihashmap_put (replay_req_client,
1352                                        &grp->pub_key_hash, grp_replay_req,
1353                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1354   }
1355   struct MulticastReplayRequestMessage *
1356     rep = (struct MulticastReplayRequestMessage *) m;
1357   struct GNUNET_HashCode key_hash;
1358   replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset,
1359                    rep->flags, &key_hash);
1360   GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
1361                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1362
1363   if (0 == client_send_origin (&grp->pub_key_hash, m))
1364   { /* No local origin, replay from remote members / origin. */
1365     if (NULL != mem->origin_channel)
1366     {
1367       cadet_send_channel (mem->origin_channel, m);
1368     }
1369     else
1370     {
1371       /* FIXME: not yet connected to origin */
1372       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1373       return;
1374     }
1375   }
1376   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1377 }
1378
1379
1380 static int
1381 cadet_send_replay_response_cb (void *cls,
1382                                const struct GNUNET_HashCode *key_hash,
1383                                void *value)
1384 {
1385   struct Channel *chn = value;
1386   struct GNUNET_MessageHeader *msg = cls;
1387
1388   cadet_send_channel (chn, msg);
1389   return GNUNET_OK;
1390 }
1391
1392
1393 static int
1394 client_send_replay_response_cb (void *cls,
1395                                 const struct GNUNET_HashCode *key_hash,
1396                                 void *value)
1397 {
1398   struct GNUNET_SERVER_Client *client = value;
1399   struct GNUNET_MessageHeader *msg = cls;
1400
1401   client_send (client, msg);
1402   return GNUNET_OK;
1403 }
1404
1405
1406 /**
1407  * End of replay response from a client.
1408  */
1409 static void
1410 client_recv_replay_response_end (void *cls, struct GNUNET_SERVER_Client *client,
1411                                  const struct GNUNET_MessageHeader *m)
1412 {
1413   struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1414   if (NULL == grp)
1415   {
1416     GNUNET_break (0);
1417     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1418     return;
1419   }
1420
1421   struct MulticastReplayResponseMessage *
1422     res = (struct MulticastReplayResponseMessage *) m;
1423
1424   struct GNUNET_HashCode key_hash;
1425   replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1426                    res->flags, &key_hash);
1427
1428   struct GNUNET_CONTAINER_MultiHashMap *
1429     grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1430                                                                 &grp->pub_key_hash);
1431   if (NULL != grp_replay_req_cadet)
1432   {
1433     GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash);
1434   }
1435   struct GNUNET_CONTAINER_MultiHashMap *
1436     grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1437                                                                &grp->pub_key_hash);
1438   if (NULL != grp_replay_req_client)
1439   {
1440     GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash);
1441   }
1442   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1443 }
1444
1445
1446 /**
1447  * Incoming replay response from a client.
1448  *
1449  * Respond with a multicast message on success, or otherwise with an error code.
1450  */
1451 static void
1452 client_recv_replay_response (void *cls, struct GNUNET_SERVER_Client *client,
1453                              const struct GNUNET_MessageHeader *m)
1454 {
1455   struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1456   if (NULL == grp)
1457   {
1458     GNUNET_break (0);
1459     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1460     return;
1461   }
1462
1463   struct MulticastReplayResponseMessage *
1464     res = (struct MulticastReplayResponseMessage *) m;
1465
1466   const struct GNUNET_MessageHeader *msg = m;
1467   if (GNUNET_MULTICAST_REC_OK == res->error_code)
1468   {
1469     msg = (struct GNUNET_MessageHeader *) &res[1];
1470   }
1471
1472   struct GNUNET_HashCode key_hash;
1473   replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1474                    res->flags, &key_hash);
1475
1476   struct GNUNET_CONTAINER_MultiHashMap *
1477     grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1478                                                               &grp->pub_key_hash);
1479   if (NULL != grp_replay_req_cadet)
1480   {
1481     GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash,
1482                                                 cadet_send_replay_response_cb,
1483                                                 (void *) msg);
1484   }
1485   if (GNUNET_MULTICAST_REC_OK == res->error_code)
1486   {
1487     struct GNUNET_CONTAINER_MultiHashMap *
1488       grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1489                                                                  &grp->pub_key_hash);
1490     if (NULL != grp_replay_req_client)
1491     {
1492       GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash,
1493                                                   client_send_replay_response_cb,
1494                                                   (void *) msg);
1495     }
1496   }
1497   else
1498   {
1499     client_recv_replay_response_end (cls, client, m);
1500     return;
1501   }
1502   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1503 }
1504
1505
1506 /**
1507  * A new client connected.
1508  */
1509 static void
1510 client_notify_connect (void *cls, struct GNUNET_SERVER_Client *client)
1511 {
1512   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
1513   /* FIXME: send connect ACK */
1514 }
1515
1516
1517 /**
1518  * Message handlers for the server.
1519  */
1520 static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1521   { client_recv_origin_start, NULL,
1522     GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START, 0 },
1523
1524   { client_recv_member_join, NULL,
1525     GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN, 0 },
1526
1527   { client_recv_join_decision, NULL,
1528     GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 0 },
1529
1530   { client_recv_multicast_message, NULL,
1531     GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
1532
1533   { client_recv_multicast_request, NULL,
1534     GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 },
1535
1536   { client_recv_replay_request, NULL,
1537     GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 0 },
1538
1539   { client_recv_replay_response, NULL,
1540     GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 0 },
1541
1542   { client_recv_replay_response_end, NULL,
1543     GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END, 0 },
1544
1545   { NULL, NULL, 0, 0 }
1546 };
1547
1548
1549 /**
1550  * Incoming join request message from CADET.
1551  */
1552 int
1553 cadet_recv_join_request (void *cls,
1554                          struct GNUNET_CADET_Channel *channel,
1555                          void **ctx,
1556                          const struct GNUNET_MessageHeader *m)
1557 {
1558   const struct MulticastJoinRequestMessage *
1559     req = (const struct MulticastJoinRequestMessage *) m;
1560   uint16_t size = ntohs (m->size);
1561   if (size < sizeof (*req))
1562   {
1563     GNUNET_break_op (0);
1564     return GNUNET_SYSERR;
1565   }
1566   if (NULL != *ctx)
1567   {
1568     GNUNET_break_op (0);
1569     return GNUNET_SYSERR;
1570   }
1571   if (ntohl (req->purpose.size) != (size
1572                                     - sizeof (req->header)
1573                                     - sizeof (req->reserved)
1574                                     - sizeof (req->signature)))
1575   {
1576     GNUNET_break_op (0);
1577     return GNUNET_SYSERR;
1578   }
1579   if (GNUNET_OK !=
1580       GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1581                                   &req->purpose, &req->signature,
1582                                   &req->member_pub_key))
1583   {
1584     GNUNET_break_op (0);
1585     return GNUNET_SYSERR;
1586   }
1587
1588   struct GNUNET_HashCode group_pub_hash;
1589   GNUNET_CRYPTO_hash (&req->group_pub_key, sizeof (req->group_pub_key), &group_pub_hash);
1590
1591   struct Channel *chn = GNUNET_malloc (sizeof *chn);
1592   chn->channel = channel;
1593   chn->group_pub_key = req->group_pub_key;
1594   chn->group_pub_hash = group_pub_hash;
1595   chn->member_pub_key = req->member_pub_key;
1596   chn->peer = req->peer;
1597   chn->join_status = JOIN_WAITING;
1598   GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group_pub_hash, chn,
1599                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1600
1601   client_send_all (&group_pub_hash, m);
1602   return GNUNET_OK;
1603 }
1604
1605
1606 /**
1607  * Incoming join decision message from CADET.
1608  */
1609 int
1610 cadet_recv_join_decision (void *cls,
1611                           struct GNUNET_CADET_Channel *channel,
1612                           void **ctx,
1613                           const struct GNUNET_MessageHeader *m)
1614 {
1615   const struct MulticastJoinDecisionMessage *
1616     dcsn = (const struct MulticastJoinDecisionMessage *) m;
1617   uint16_t size = ntohs (m->size);
1618   if (size < sizeof (*dcsn))
1619   {
1620     GNUNET_break_op (0);
1621     return GNUNET_SYSERR;
1622   }
1623   struct Channel *chn = *ctx;
1624   if (NULL == chn)
1625   {
1626     GNUNET_break_op (0);
1627     return GNUNET_SYSERR;
1628   }
1629   if (NULL == chn->grp || GNUNET_NO != chn->grp->is_origin)
1630   {
1631     GNUNET_break_op (0);
1632     return GNUNET_SYSERR;
1633   }
1634   switch (chn->join_status)
1635   {
1636   case JOIN_REFUSED:
1637     return GNUNET_SYSERR;
1638
1639   case JOIN_ADMITTED:
1640     return GNUNET_OK;
1641
1642   case JOIN_NOT_ASKED:
1643   case JOIN_WAITING:
1644     break;
1645   }
1646
1647   struct MulticastJoinDecisionMessageHeader *
1648     hdcsn = GNUNET_malloc (sizeof (*hdcsn) + size);
1649   hdcsn->peer = chn->peer;
1650   GNUNET_memcpy (&hdcsn[1], dcsn, sizeof (*hdcsn) + size);
1651
1652   struct Member *mem = (struct Member *) chn->grp;
1653   client_send_join_decision (mem, hdcsn);
1654   GNUNET_free (hdcsn);
1655   if (GNUNET_YES == ntohs (dcsn->is_admitted))
1656   {
1657     chn->join_status = JOIN_ADMITTED;
1658     return GNUNET_OK;
1659   }
1660   else
1661   {
1662     chn->join_status = JOIN_REFUSED;
1663     return GNUNET_SYSERR;
1664   }
1665 }
1666
1667 /**
1668  * Incoming multicast message from CADET.
1669  */
1670 int
1671 cadet_recv_message (void *cls,
1672                     struct GNUNET_CADET_Channel *channel,
1673                     void **ctx,
1674                     const struct GNUNET_MessageHeader *m)
1675 {
1676   const struct GNUNET_MULTICAST_MessageHeader *
1677     msg = (const struct GNUNET_MULTICAST_MessageHeader *) m;
1678   uint16_t size = ntohs (m->size);
1679   if (size < sizeof (*msg))
1680   {
1681     GNUNET_break_op (0);
1682     return GNUNET_SYSERR;
1683   }
1684   struct Channel *chn = *ctx;
1685   if (NULL == chn)
1686   {
1687     GNUNET_break_op (0);
1688     return GNUNET_SYSERR;
1689   }
1690   if (ntohl (msg->purpose.size) != (size
1691                                     - sizeof (msg->header)
1692                                     - sizeof (msg->hop_counter)
1693                                     - sizeof (msg->signature)))
1694   {
1695     GNUNET_break_op (0);
1696     return GNUNET_SYSERR;
1697   }
1698   if (GNUNET_OK !=
1699       GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE,
1700                                   &msg->purpose, &msg->signature,
1701                                   &chn->group_pub_key))
1702   {
1703     GNUNET_break_op (0);
1704     return GNUNET_SYSERR;
1705   }
1706
1707   client_send_all (&chn->group_pub_hash, m);
1708   return GNUNET_OK;
1709 }
1710
1711
1712 /**
1713  * Incoming multicast request message from CADET.
1714  */
1715 int
1716 cadet_recv_request (void *cls,
1717                     struct GNUNET_CADET_Channel *channel,
1718                     void **ctx,
1719                     const struct GNUNET_MessageHeader *m)
1720 {
1721   const struct GNUNET_MULTICAST_RequestHeader *
1722     req = (const struct GNUNET_MULTICAST_RequestHeader *) m;
1723   uint16_t size = ntohs (m->size);
1724   if (size < sizeof (*req))
1725   {
1726     GNUNET_break_op (0);
1727     return GNUNET_SYSERR;
1728   }
1729   struct Channel *chn = *ctx;
1730   if (NULL == chn)
1731   {
1732     GNUNET_break_op (0);
1733     return GNUNET_SYSERR;
1734   }
1735   if (ntohl (req->purpose.size) != (size
1736                                     - sizeof (req->header)
1737                                     - sizeof (req->member_pub_key)
1738                                     - sizeof (req->signature)))
1739   {
1740     GNUNET_break_op (0);
1741     return GNUNET_SYSERR;
1742   }
1743   if (GNUNET_OK !=
1744       GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1745                                   &req->purpose, &req->signature,
1746                                   &req->member_pub_key))
1747   {
1748     GNUNET_break_op (0);
1749     return GNUNET_SYSERR;
1750   }
1751
1752   client_send_origin (&chn->group_pub_hash, m);
1753   return GNUNET_OK;
1754 }
1755
1756
1757 /**
1758  * Incoming multicast replay request from CADET.
1759  */
1760 int
1761 cadet_recv_replay_request (void *cls,
1762                            struct GNUNET_CADET_Channel *channel,
1763                            void **ctx,
1764                            const struct GNUNET_MessageHeader *m)
1765 {
1766   struct MulticastReplayRequestMessage rep;
1767   uint16_t size = ntohs (m->size);
1768   if (size < sizeof (rep))
1769   {
1770     GNUNET_break_op (0);
1771     return GNUNET_SYSERR;
1772   }
1773   struct Channel *chn = *ctx;
1774
1775   GNUNET_memcpy (&rep, m, sizeof (rep));
1776   GNUNET_memcpy (&rep.member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key));
1777
1778   struct GNUNET_CONTAINER_MultiHashMap *
1779     grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1780                                                         &chn->grp->pub_key_hash);
1781   if (NULL == grp_replay_req)
1782   {
1783     grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1784     GNUNET_CONTAINER_multihashmap_put (replay_req_cadet,
1785                                        &chn->grp->pub_key_hash, grp_replay_req,
1786                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1787   }
1788   struct GNUNET_HashCode key_hash;
1789   replay_key_hash (rep.fragment_id, rep.message_id, rep.fragment_offset,
1790                    rep.flags, &key_hash);
1791   GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn,
1792                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1793
1794   client_send_random (&chn->group_pub_hash, &rep.header);
1795   return GNUNET_OK;
1796 }
1797
1798
1799 /**
1800  * Incoming multicast replay response from CADET.
1801  */
1802 int
1803 cadet_recv_replay_response (void *cls,
1804                             struct GNUNET_CADET_Channel *channel,
1805                             void **ctx,
1806                             const struct GNUNET_MessageHeader *m)
1807 {
1808   //struct Channel *chn = *ctx;
1809
1810   /* @todo FIXME: got replay error response, send request to other members */
1811
1812   return GNUNET_OK;
1813 }
1814
1815
1816 /**
1817  * Message handlers for CADET.
1818  */
1819 static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
1820   { cadet_recv_join_request,
1821     GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, 0 },
1822
1823   { cadet_recv_message,
1824     GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
1825
1826   { cadet_recv_request,
1827     GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 },
1828
1829   { cadet_recv_replay_request,
1830     GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 0 },
1831
1832   { cadet_recv_replay_response,
1833     GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 0 },
1834
1835   { NULL, 0, 0 }
1836 };
1837
1838
1839 /**
1840  * Connected to core service.
1841  */
1842 static void
1843 core_connected_cb  (void *cls, const struct GNUNET_PeerIdentity *my_identity)
1844 {
1845   this_peer = *my_identity;
1846
1847   stats = GNUNET_STATISTICS_create ("multicast", cfg);
1848   origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1849   members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1850   group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1851   channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1852   channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1853   replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1854   replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1855
1856   cadet = GNUNET_CADET_connect (cfg, NULL,
1857                                 &cadet_notify_channel_end,
1858                                 cadet_handlers);
1859   GNUNET_assert (NULL != cadet);
1860
1861   nc = GNUNET_SERVER_notification_context_create (server, 1);
1862   GNUNET_SERVER_add_handlers (server, server_handlers);
1863   GNUNET_SERVER_disconnect_notify (server,
1864                                    &client_notify_disconnect, NULL);
1865   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1866                                  NULL);
1867 }
1868
1869
1870 /**
1871  * Service started.
1872  *
1873  * @param cls closure
1874  * @param server the initialized server
1875  * @param cfg configuration to use
1876  */
1877 static void
1878 run (void *cls,
1879      struct GNUNET_SERVER_Handle *srv,
1880      const struct GNUNET_CONFIGURATION_Handle *c)
1881 {
1882   cfg = c;
1883   server = srv;
1884   GNUNET_SERVER_connect_notify (server, &client_notify_connect, NULL);
1885   core = GNUNET_CORE_connecT (cfg, NULL, &core_connected_cb, NULL, NULL, NULL);
1886 }
1887
1888
1889 /**
1890  * The main function for the multicast service.
1891  *
1892  * @param argc number of arguments from the command line
1893  * @param argv command line arguments
1894  * @return 0 ok, 1 on error
1895  */
1896 int
1897 main (int argc, char *const *argv)
1898 {
1899   return (GNUNET_OK ==
1900           GNUNET_SERVICE_run (argc, argv, "multicast",
1901                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
1902 }
1903
1904 /* end of gnunet-service-multicast.c */